summaryrefslogtreecommitdiff
path: root/vendor/rustls
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustls')
-rw-r--r--vendor/rustls/.cargo-checksum.json1
-rw-r--r--vendor/rustls/Cargo.lock1131
-rw-r--r--vendor/rustls/Cargo.toml233
-rw-r--r--vendor/rustls/LICENSE-APACHE201
-rw-r--r--vendor/rustls/LICENSE-ISC15
-rw-r--r--vendor/rustls/LICENSE-MIT25
-rw-r--r--vendor/rustls/README.md222
-rw-r--r--vendor/rustls/benches/benchmarks.rs20
-rw-r--r--vendor/rustls/build.rs13
-rw-r--r--vendor/rustls/examples/internal/test_ca.rs352
-rw-r--r--vendor/rustls/src/bs_debug.rs80
-rw-r--r--vendor/rustls/src/builder.rs290
-rw-r--r--vendor/rustls/src/check.rs70
-rw-r--r--vendor/rustls/src/client/builder.rs186
-rw-r--r--vendor/rustls/src/client/client_conn.rs1062
-rw-r--r--vendor/rustls/src/client/common.rs119
-rw-r--r--vendor/rustls/src/client/ech.rs899
-rw-r--r--vendor/rustls/src/client/handy.rs390
-rw-r--r--vendor/rustls/src/client/hs.rs1178
-rw-r--r--vendor/rustls/src/client/test.rs712
-rw-r--r--vendor/rustls/src/client/tls12.rs1372
-rw-r--r--vendor/rustls/src/client/tls13.rs1700
-rw-r--r--vendor/rustls/src/common_state.rs1049
-rw-r--r--vendor/rustls/src/compress.rs677
-rw-r--r--vendor/rustls/src/conn.rs1280
-rw-r--r--vendor/rustls/src/conn/kernel.rs268
-rw-r--r--vendor/rustls/src/conn/unbuffered.rs613
-rw-r--r--vendor/rustls/src/crypto/aws_lc_rs/hpke.rs1191
-rw-r--r--vendor/rustls/src/crypto/aws_lc_rs/mod.rs318
-rw-r--r--vendor/rustls/src/crypto/aws_lc_rs/pq/hybrid.rs205
-rw-r--r--vendor/rustls/src/crypto/aws_lc_rs/pq/mlkem.rs103
-rw-r--r--vendor/rustls/src/crypto/aws_lc_rs/pq/mod.rs48
-rw-r--r--vendor/rustls/src/crypto/aws_lc_rs/sign.rs876
-rw-r--r--vendor/rustls/src/crypto/aws_lc_rs/ticketer.rs397
-rw-r--r--vendor/rustls/src/crypto/aws_lc_rs/tls12.rs465
-rw-r--r--vendor/rustls/src/crypto/aws_lc_rs/tls13.rs425
-rw-r--r--vendor/rustls/src/crypto/cipher.rs350
-rw-r--r--vendor/rustls/src/crypto/hash.rs81
-rw-r--r--vendor/rustls/src/crypto/hmac.rs73
-rw-r--r--vendor/rustls/src/crypto/hpke.rs145
-rw-r--r--vendor/rustls/src/crypto/mod.rs756
-rw-r--r--vendor/rustls/src/crypto/ring/hash.rs60
-rw-r--r--vendor/rustls/src/crypto/ring/hmac.rs48
-rw-r--r--vendor/rustls/src/crypto/ring/kx.rs188
-rw-r--r--vendor/rustls/src/crypto/ring/mod.rs203
-rw-r--r--vendor/rustls/src/crypto/ring/quic.rs416
-rw-r--r--vendor/rustls/src/crypto/ring/sign.rs822
-rw-r--r--vendor/rustls/src/crypto/ring/ticketer.rs366
-rw-r--r--vendor/rustls/src/crypto/ring/tls12.rs406
-rw-r--r--vendor/rustls/src/crypto/ring/tls13.rs336
-rw-r--r--vendor/rustls/src/crypto/signer.rs233
-rw-r--r--vendor/rustls/src/crypto/tls12.rs169
-rw-r--r--vendor/rustls/src/crypto/tls13.rs406
-rw-r--r--vendor/rustls/src/enums.rs691
-rw-r--r--vendor/rustls/src/error.rs1387
-rw-r--r--vendor/rustls/src/hash_hs.rs347
-rw-r--r--vendor/rustls/src/key_log.rs61
-rw-r--r--vendor/rustls/src/key_log_file.rs162
-rw-r--r--vendor/rustls/src/lib.rs715
-rw-r--r--vendor/rustls/src/limited_cache.rs250
-rw-r--r--vendor/rustls/src/lock.rs89
-rw-r--r--vendor/rustls/src/manual/defaults.rs71
-rw-r--r--vendor/rustls/src/manual/features.rs100
-rw-r--r--vendor/rustls/src/manual/fips.rs62
-rw-r--r--vendor/rustls/src/manual/howto.rs124
-rw-r--r--vendor/rustls/src/manual/implvulns.rs104
-rw-r--r--vendor/rustls/src/manual/mod.rs34
-rw-r--r--vendor/rustls/src/manual/tlsvulns.rs175
-rw-r--r--vendor/rustls/src/msgs/alert.rs26
-rw-r--r--vendor/rustls/src/msgs/base.rs238
-rw-r--r--vendor/rustls/src/msgs/ccs.rs23
-rw-r--r--vendor/rustls/src/msgs/codec.rs404
-rw-r--r--vendor/rustls/src/msgs/deframer/buffers.rs296
-rw-r--r--vendor/rustls/src/msgs/deframer/handshake.rs525
-rw-r--r--vendor/rustls/src/msgs/deframer/mod.rs238
-rw-r--r--vendor/rustls/src/msgs/enums.rs510
-rw-r--r--vendor/rustls/src/msgs/ffdhe_groups.rs323
-rw-r--r--vendor/rustls/src/msgs/fragmenter.rs232
-rw-r--r--vendor/rustls/src/msgs/handshake.rs3210
-rw-r--r--vendor/rustls/src/msgs/handshake_test.rs1051
-rw-r--r--vendor/rustls/src/msgs/macros.rs313
-rw-r--r--vendor/rustls/src/msgs/message/inbound.rs161
-rw-r--r--vendor/rustls/src/msgs/message/mod.rs262
-rw-r--r--vendor/rustls/src/msgs/message/outbound.rs422
-rw-r--r--vendor/rustls/src/msgs/message_test.rs124
-rw-r--r--vendor/rustls/src/msgs/mod.rs74
-rw-r--r--vendor/rustls/src/msgs/persist.rs492
-rw-r--r--vendor/rustls/src/polyfill.rs9
-rw-r--r--vendor/rustls/src/quic.rs1022
-rw-r--r--vendor/rustls/src/rand.rs34
-rw-r--r--vendor/rustls/src/record_layer.rs336
-rw-r--r--vendor/rustls/src/server/builder.rs127
-rw-r--r--vendor/rustls/src/server/common.rs35
-rw-r--r--vendor/rustls/src/server/handy.rs356
-rw-r--r--vendor/rustls/src/server/hs.rs763
-rw-r--r--vendor/rustls/src/server/server_conn.rs1288
-rw-r--r--vendor/rustls/src/server/test.rs369
-rw-r--r--vendor/rustls/src/server/tls12.rs1003
-rw-r--r--vendor/rustls/src/server/tls13.rs1535
-rw-r--r--vendor/rustls/src/stream.rs282
-rw-r--r--vendor/rustls/src/suites.rs272
-rw-r--r--vendor/rustls/src/test_macros.rs71
-rw-r--r--vendor/rustls/src/ticketer.rs365
-rw-r--r--vendor/rustls/src/time_provider.rs30
-rw-r--r--vendor/rustls/src/tls12/mod.rs380
-rw-r--r--vendor/rustls/src/tls13/key_schedule.rs1308
-rw-r--r--vendor/rustls/src/tls13/mod.rs125
-rw-r--r--vendor/rustls/src/vecbuf.rs374
-rw-r--r--vendor/rustls/src/verify.rs382
-rw-r--r--vendor/rustls/src/verifybench.rs244
-rw-r--r--vendor/rustls/src/versions.rs97
-rw-r--r--vendor/rustls/src/webpki/anchors.rs143
-rw-r--r--vendor/rustls/src/webpki/client_verifier.rs665
-rw-r--r--vendor/rustls/src/webpki/mod.rs313
-rw-r--r--vendor/rustls/src/webpki/server_verifier.rs448
-rw-r--r--vendor/rustls/src/webpki/verify.rs289
-rw-r--r--vendor/rustls/src/x509.rs147
117 files changed, 0 insertions, 49352 deletions
diff --git a/vendor/rustls/.cargo-checksum.json b/vendor/rustls/.cargo-checksum.json
deleted file mode 100644
index 441dc8f0..00000000
--- a/vendor/rustls/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.lock":"16463c44989ca7b3256ddb327730574dd03fa25ba4c117e92c26884a00f23ec9","Cargo.toml":"46f1cf9ca064bd16baf3416b8efff9a0d8f6e88935495dbd21cddf4c798f142a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-ISC":"7cfafc877eccc46c0e346ccbaa5c51bb6b894d2b818e617d970211e232785ad4","LICENSE-MIT":"709e3175b4212f7b13aa93971c9f62ff8c69ec45ad8c6532a7e0c41d7a7d6f8c","README.md":"1f3cec2c07d17bf1c3860fa6a692953fd456315134a1abe79ae4cc0c8cc1ca35","benches/benchmarks.rs":"251ec5926d31af7087308224ac3bcf2a58b3fb1965083da1c75779957e30cedf","build.rs":"380b9a051325baa7d4957bd9a4f1a637c27a663610b1b502f9524530f6995f4d","examples/internal/test_ca.rs":"bcb952d082cc46e53e8ef0ac547cda0cd990e7d36f0e9512448aa5ef4dd5e056","src/bs_debug.rs":"4e4ff4ee2d1db612ba7367e88ee587d525a973167c87b28bb2b35555a9eda27b","src/builder.rs":"3cfebc1faeb5e2b7fbb8ede68aca1240c7ba69061f3381a1a4ded87f11bf5d6a","src/check.rs":"8e5b8a35aebe931c60afa009159a398cf81f300c21898d2002fec88b42d13ad7","src/client/builder.rs":"dedb310e92f9bf837f2500bb9bc8bb3f02975477682232bc91801fe891a2048f","src/client/client_conn.rs":"beb8e4d6720370ab6696f082aede044e62e47e69246b044f5d1101691149b4ef","src/client/common.rs":"c745f89b8fd2381118dda319ab69c71a410212d879d380fb8205aa74ece52b48","src/client/ech.rs":"622eeccb85ea350b01e597821bc92fee8939f87c30c028cf043133a663cb9d89","src/client/handy.rs":"7137eeea1cbd8df5a8620e5934a2c3a6889d992caf45c5b13f33072c46ddefb1","src/client/hs.rs":"0b48abf24f0fc6093fe17b628a3d3989f6f35018e322d63d0b90c2066319d2a9","src/client/test.rs":"ca72f595d0f2c9ee713bf68ad647bbfaf402bfa19d7a6e610e98f57464b34221","src/client/tls12.rs":"39b2fd1c88d5b764cfc7f183f6dda7dcf38cf7384a17adfa3e26a5a5ff2d325d","src/client/tls13.rs":"e5db6db56ca31dbe270a4bfe7cf7c99929d05babb3760484baef8c9e1acad35e","src/common_state.rs":"d60d2790e97aee52667e8b9f18d25f3b6066cbcc6bed2e6153d2932525b6d0d5","src/compress.rs":"b3d5d65cd16f8ae98d0398697a4d86fbfb9a5a0db8243b553ea1d763992b5544","src/conn.rs":"72fad622038e07436da895faf2eaadc5a9b5e4fd2a1ac4d68d73ef47959da37c","src/conn/kernel.rs":"ecdbb41cd6e4aa95c33a16584723befe6b310754452174cee9ab201917ffb87e","src/conn/unbuffered.rs":"843c2eaa532cdce077cb6f33972d9da5149de0558d4aab86dddb7f5c59aa9d92","src/crypto/aws_lc_rs/hpke.rs":"9786831e6b839d52b91b5ba1b1bfc77cb1c859489e19ccfa7f84940dfc5c706e","src/crypto/aws_lc_rs/mod.rs":"e566e21c3a8f7aac1eba68ca195f51dea16127f79eb37b9f883eec1d2df7d32f","src/crypto/aws_lc_rs/pq/hybrid.rs":"a1ac53e228fe7bb6851b3a73b1ba4aa64f09bdbc77a09053f59ae89c8ea152b8","src/crypto/aws_lc_rs/pq/mlkem.rs":"c6b18343b1fb337e95994fb5d3ea473785bd681d383a215e81a232d46f6d5ef5","src/crypto/aws_lc_rs/pq/mod.rs":"4848bbd5780a2061c0bd0837312061a8bef131a1db1af8c025eb0195dba8a866","src/crypto/aws_lc_rs/sign.rs":"972f4deb09c5b64091bc9e16bd8062e39aceffb94bad5cc77ab58af066e35543","src/crypto/aws_lc_rs/ticketer.rs":"a16431d3ac21b944e6b43a78f930e13bd82603483b85cfa823f43f2a86eb0e32","src/crypto/aws_lc_rs/tls12.rs":"9e3a9220b68ce2a340d2289d376107bf4b75bc73319d1562c2800c5c01476d28","src/crypto/aws_lc_rs/tls13.rs":"e9998aa39049aa886c34c7ffb0da3b8d74388ce823bd310d07e1cd83b3559857","src/crypto/cipher.rs":"e2551ee5086adecd749e1cedc794398299104323ec14027b66e6d17c127f5ece","src/crypto/hash.rs":"eaa21b2d8f11afb9f5e41794e3461bcc18c950c53153d1fc37dfd23e3bdc1094","src/crypto/hmac.rs":"82ac9b1da0295b0ab70adec4ce321fb87d7873f530652a8b86397655042d035b","src/crypto/hpke.rs":"b65ace9c09cc0f83888c000b369376d8b8ca8a49e016d1aa0a9691c7921fdfbc","src/crypto/mod.rs":"d375a0ddf9da06669436fde13d9593e1dd400043348d0709466220bde0b73b6b","src/crypto/ring/hash.rs":"d4b594369971c8e8dc275a85beea83b51f5134174a4b37f620e130a51266d6ea","src/crypto/ring/hmac.rs":"7df8a4c33176c4e53306c23285ed965c9e35e0aebcc6fd03f1cd68759122ae94","src/crypto/ring/kx.rs":"d385431f42e76b7aa8bd0749ea256da268239d762114b40a37bee8306b07229d","src/crypto/ring/mod.rs":"b43827457ae0248f1ec3888464d40875f80e60b2d785e38517c79dda819b7675","src/crypto/ring/quic.rs":"73ced30aa8e5cf01578ca71f5546075557123d1dd7a73deb9579e93153f35a9c","src/crypto/ring/sign.rs":"6bb88454d5751ce1262d68c670ba41a52f88cd152b75d0740743ef603a43f650","src/crypto/ring/ticketer.rs":"2ec1193097d3032fc31dda08277cfb0fcb8defc6667af09d4ff1bd16be95eba4","src/crypto/ring/tls12.rs":"a3a65ebd7cf6fe7157dd19500d35ac7a948970fc64f94909ec4cc22e889e3a44","src/crypto/ring/tls13.rs":"2d093ce74d9ad824ed15f0a18abf5d845fd701a5b8de2d7db088e706dd49ab62","src/crypto/signer.rs":"3d99f11b9472eb7b316312cf94157edeb5d21ac189ed114450219f5bd60123f9","src/crypto/tls12.rs":"b729e02f64415570ba68fdde0a17cfaa60062f4d694001658b0467672a4e626d","src/crypto/tls13.rs":"feec69f36dcc738ccf735bc69e12a767857d8b52ad9af139b2b8584990b651d3","src/enums.rs":"807d39e7720ab3be31b7064fa2a67593d7246598edf6fe012f80a363afca417c","src/error.rs":"d85c232735d313be3661d564c2858fe26ebe72b203a127c3a681ef44d3c95ffd","src/hash_hs.rs":"6a03da8c8aea2f44f162843bc803a0dfb683b4b99137e5e5f5a6dd7978b02849","src/key_log.rs":"6aeb8c45365e6d53c51246fe8773243096b8c6806274cdcc3ffd1bb82fe360e9","src/key_log_file.rs":"9e781ef5e267b56afa0e70f7aeced53e5060814c71d4175741f076d5aa55fa4d","src/lib.rs":"1e1e14d37121fc3b2f3ddce24ae51f7f911d67b93a0fc968fde0db025a941eb8","src/limited_cache.rs":"a53eb38036ab1db04fe7c561d804076690631dedb17040eaa006f1264cfed097","src/lock.rs":"a4d9befd9a53e7dfbd7fb5d30ca16bcdd54e61f3fc9b353992cd45928818d70e","src/manual/defaults.rs":"71e854184d355b71a96280d82f3e83224491300e861655916d76f44325bf626a","src/manual/features.rs":"a7fecd590287388215fa6bcc6403f425897f3d4ea4f44b72a5dee9bfa2ee8345","src/manual/fips.rs":"50881a17d61c65cd855c1295572cd9b6381cf60008555b841b5e3bfca93dc712","src/manual/howto.rs":"df03dcc9abd0e8c11c13573680d43c84fd92876e4b128fb8bd881a58e07a0ae2","src/manual/implvulns.rs":"b42abb13ce142e83da012f7fa47759091c43216628abd46563de9910748efe5b","src/manual/mod.rs":"45e5d510140d668553030695a45e6ad50da2274e097e3e8fa8900446944a7576","src/manual/tlsvulns.rs":"9d2dc1d4f8f5703b67eb159d698325788863795848a246e36bef779dbba252be","src/msgs/alert.rs":"cf85febb6f1bd2719dd4767f6dea61468e2cee211f507956e93cfe79a9139afc","src/msgs/base.rs":"b6bb842fcfdf2d800e0594cb63c574663e335d4725dc870ee5fb26256f9eba64","src/msgs/ccs.rs":"61117e8e8cc2fb7b030360f959b66d6392d34a601f4ae1dc7276bb444462a742","src/msgs/codec.rs":"fa53201ef4387a453c626c37138a6a2de2d2ff13d85c0ec34f8b13ee20daeeaf","src/msgs/deframer/buffers.rs":"48bb18eff4e5859ec56aba8910488a791457afabc79feba0b09375e11bcca459","src/msgs/deframer/handshake.rs":"e7309acb70aa406dbd6c2c35c17e9d8fe036e9d24e4d29b362b37aa59bae9944","src/msgs/deframer/mod.rs":"bab59c49aa59b4d44e49928ab3aa6b58a5d167412585017bdae88cd32ce23847","src/msgs/enums.rs":"2366725846e1daa22481cfe5351d68199f833e88eb8d12095c00bc78fc77eb18","src/msgs/ffdhe_groups.rs":"22a2abdede92e082300998e0b0d49cc915a995713db2cdd811b4ff3502c1c619","src/msgs/fragmenter.rs":"c324f9ac144999ec36673736d0ef026122be9d4f6eb1f2908c01461cebe1122d","src/msgs/handshake.rs":"08219f5e36f75163f2c64e3dbf1a4506ef0d1266a42791e33863609225f0c3c8","src/msgs/handshake_test.rs":"bb73da98b08bfeea59762441c56a5aa0d9a17f30468ef5f6f87d8feb6cc1ef28","src/msgs/macros.rs":"2d4efa38989d480f8d36015d4487beedf9ec5e16aeacd3f9980d9ec61720890c","src/msgs/message/inbound.rs":"85c75ca765f5f7ce70b2f1afbb4d7a1568c1098e7be5267a16a4cb20b50b7ed5","src/msgs/message/mod.rs":"f1bdfa1ee08e31e54c85dd1c47d090afee672bd50bb6074aaa9c51d08feae3bf","src/msgs/message/outbound.rs":"fb214090aff53ea7228519feeac4444fa4b0f389c9af6dc062bf6efbe6c8a8ff","src/msgs/message_test.rs":"b3889ee3db6b8a28241fc1795209e2202f942445d8ec8ed0b08424ad6ad56dd0","src/msgs/mod.rs":"39c54a233a8bd46497c27b3e2626d8aee173d4c41ec8670386bb8c1f19249d07","src/msgs/persist.rs":"33ae762fe42981379082622bd66b2133e224cbaef012535834a4f2eeeaef9a72","src/polyfill.rs":"a6c6dcb5c42aa481099e60b85fd16d84559daa68bbef215c5cb02f93d5c65bec","src/quic.rs":"7bc4e28e1173b223b3242e8915383be0ae5476d73ad623280cd96cd00181a258","src/rand.rs":"c0c55d130516c8415836187c9050ecb5269ed7b51f65d70b40305f05f9ba57fb","src/record_layer.rs":"299c725f5bb3e032ecb17e9d1b228a1fa6fc580714c1470d5ff93c54592dc97d","src/server/builder.rs":"53cc5765fd1646c675a239f442fc212e8081369e0dfb1795aaed972d3e02a4a7","src/server/common.rs":"aef13bfc295f17218aa9b157f69c6fdfb9802ee90263acd43e880465a707bb20","src/server/handy.rs":"85ce7ea135eb5582703cb41eb8a5ec7d1d6b9266a130935d291eb71c1327394d","src/server/hs.rs":"5cfe9298ddf83d22786870460dd22b803d450ae4f0cc13e1e83c67512a24838f","src/server/server_conn.rs":"6ae7036a0ffe9c9d4c579e4aea33fa2be7ebf8056b9ad0417f31a64996559be6","src/server/test.rs":"c51e092a1e0bb8721bc66dc2a6de33ba173603f1cb51dab6b422f24c6b0d8f1c","src/server/tls12.rs":"4db5408886f09341063bde2d143f3bc29c2e4456c942fd1d16309dd4bcd3371c","src/server/tls13.rs":"a399e36edbda2f10d2b1e000d30555a4d8e23a40969d3121895bcb2f2be9758c","src/stream.rs":"00e4d9671226311ee50840a00a9e70d0921838a8a780aca6b78e4e208822d5e4","src/suites.rs":"82f697a876e4dcd720d2317d2ffd807c2ff79c081a4de3f2acf3fdf850b18980","src/test_macros.rs":"e5f98aa388375cc195cef7bae2cdba8b33c795ce48e8ff228fbfef153a493c47","src/ticketer.rs":"b722e6be43f8920ca495e4a3cbd624a4e69d61e1ad7584cfae0d8bc06429290a","src/time_provider.rs":"cdc75369bb353ca1edfb1d700a6467e42779c1c0cba5d5bd7d9f67f392ea92b1","src/tls12/mod.rs":"159fb6a519534986e1d1fd2326d30ffa0422650d9fe636c3dac8a5bd113c7c8b","src/tls13/key_schedule.rs":"dfe3a46dc72f4b175c70f0e0504819697a4876eed1e68715348d3f30585185cf","src/tls13/mod.rs":"f22e73dd261d1cc94076a9d3e0147352d7aa4c86872566bb79c93a8ad9f1c1a7","src/vecbuf.rs":"e8941e43ff21527ca3e8f6c9a9dc8526fab2e9a2676acb29065f075f98b622d6","src/verify.rs":"ba9dbc12548b0a1d3813e5c51b54ce2073fe6a87aaca9f6368185fb452add659","src/verifybench.rs":"5e4bd4bc5e2b93e4ee2f7f15b552e10c1c2f4bde7e60d44f426a0fc97f7b5d71","src/versions.rs":"125d9981b8c02ed6dcbabfdd76721fef3537f41d424ac1fb79e088331061fb22","src/webpki/anchors.rs":"82011d21d85376f695044157dbb0659ac42bbf8dcbf671e6c19e6e6bc355c9b7","src/webpki/client_verifier.rs":"c6051e79858a70ce746fb55208751a429c691c1bb76bcaca238be310ae11d652","src/webpki/mod.rs":"96075da2044ee4d89ba5647d832bfad06a35a2aa628924e9ed3570d06bc56e2f","src/webpki/server_verifier.rs":"1678d02f7fa352b990915de691959e1d90309ba631b714992afd1e98600cb301","src/webpki/verify.rs":"fcbc90dc30793cbe7f15f363fda793d6e08a132a82d003c1f9e88019a6e1f2b4","src/x509.rs":"e036e80ceb688d1b7ff2ff82a63e99545678b262cf5af0c331fbebc714db4444"},"package":"2491382039b29b9b11ff08b76ff6c97cf287671dbb74f0be44bda389fffe9bd1"} \ No newline at end of file
diff --git a/vendor/rustls/Cargo.lock b/vendor/rustls/Cargo.lock
deleted file mode 100644
index 29fb7bfa..00000000
--- a/vendor/rustls/Cargo.lock
+++ /dev/null
@@ -1,1131 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "aho-corasick"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "alloc-no-stdlib"
-version = "2.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
-
-[[package]]
-name = "alloc-stdlib"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
-dependencies = [
- "alloc-no-stdlib",
-]
-
-[[package]]
-name = "anstream"
-version = "0.6.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
-dependencies = [
- "anstyle",
- "anstyle-parse",
- "anstyle-query",
- "anstyle-wincon",
- "colorchoice",
- "is_terminal_polyfill",
- "utf8parse",
-]
-
-[[package]]
-name = "anstyle"
-version = "1.0.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
-
-[[package]]
-name = "anstyle-parse"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
-dependencies = [
- "utf8parse",
-]
-
-[[package]]
-name = "anstyle-query"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
-dependencies = [
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "anstyle-wincon"
-version = "3.0.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
-dependencies = [
- "anstyle",
- "once_cell_polyfill",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "asn1-rs"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56624a96882bb8c26d61312ae18cb45868e5a9992ea73c58e45c3101e56a1e60"
-dependencies = [
- "asn1-rs-derive",
- "asn1-rs-impl",
- "displaydoc",
- "nom",
- "num-traits",
- "rusticata-macros",
- "thiserror",
- "time",
-]
-
-[[package]]
-name = "asn1-rs-derive"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "asn1-rs-impl"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "autocfg"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
-
-[[package]]
-name = "aws-lc-fips-sys"
-version = "0.13.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e99d74bb793a19f542ae870a6edafbc5ecf0bc0ba01d4636b7f7e0aba9ee9bd3"
-dependencies = [
- "bindgen",
- "cc",
- "cmake",
- "dunce",
- "fs_extra",
- "regex",
-]
-
-[[package]]
-name = "aws-lc-rs"
-version = "1.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93fcc8f365936c834db5514fc45aee5b1202d677e6b40e48468aaaa8183ca8c7"
-dependencies = [
- "aws-lc-fips-sys",
- "aws-lc-sys",
- "zeroize",
-]
-
-[[package]]
-name = "aws-lc-sys"
-version = "0.29.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61b1d86e7705efe1be1b569bab41d4fa1e14e220b60a160f78de2db687add079"
-dependencies = [
- "bindgen",
- "cc",
- "cmake",
- "dunce",
- "fs_extra",
-]
-
-[[package]]
-name = "base64"
-version = "0.22.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
-
-[[package]]
-name = "bencher"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7dfdb4953a096c551ce9ace855a604d702e6e62d77fac690575ae347571717f5"
-
-[[package]]
-name = "bindgen"
-version = "0.69.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
-dependencies = [
- "bitflags",
- "cexpr",
- "clang-sys",
- "itertools",
- "lazy_static",
- "lazycell",
- "log",
- "prettyplease",
- "proc-macro2",
- "quote",
- "regex",
- "rustc-hash",
- "shlex",
- "syn",
- "which",
-]
-
-[[package]]
-name = "bitflags"
-version = "2.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
-
-[[package]]
-name = "brotli"
-version = "8.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d"
-dependencies = [
- "alloc-no-stdlib",
- "alloc-stdlib",
- "brotli-decompressor",
-]
-
-[[package]]
-name = "brotli-decompressor"
-version = "5.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03"
-dependencies = [
- "alloc-no-stdlib",
- "alloc-stdlib",
-]
-
-[[package]]
-name = "cc"
-version = "1.2.26"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac"
-dependencies = [
- "jobserver",
- "libc",
- "shlex",
-]
-
-[[package]]
-name = "cexpr"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
-dependencies = [
- "nom",
-]
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "clang-sys"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
-dependencies = [
- "glob",
- "libc",
- "libloading",
-]
-
-[[package]]
-name = "cmake"
-version = "0.1.54"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0"
-dependencies = [
- "cc",
-]
-
-[[package]]
-name = "colorchoice"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
-
-[[package]]
-name = "data-encoding"
-version = "2.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
-
-[[package]]
-name = "der-parser"
-version = "10.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6"
-dependencies = [
- "asn1-rs",
- "displaydoc",
- "nom",
- "num-bigint",
- "num-traits",
- "rusticata-macros",
-]
-
-[[package]]
-name = "deranged"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
-dependencies = [
- "powerfmt",
-]
-
-[[package]]
-name = "displaydoc"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "dunce"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
-
-[[package]]
-name = "either"
-version = "1.15.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
-
-[[package]]
-name = "env_filter"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
-dependencies = [
- "log",
- "regex",
-]
-
-[[package]]
-name = "env_logger"
-version = "0.11.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f"
-dependencies = [
- "anstream",
- "anstyle",
- "env_filter",
- "jiff",
- "log",
-]
-
-[[package]]
-name = "errno"
-version = "0.3.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18"
-dependencies = [
- "libc",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "foldhash"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
-
-[[package]]
-name = "fs_extra"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
-
-[[package]]
-name = "getrandom"
-version = "0.2.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi 0.11.0+wasi-snapshot-preview1",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
-dependencies = [
- "cfg-if",
- "libc",
- "r-efi",
- "wasi 0.14.2+wasi-0.2.4",
-]
-
-[[package]]
-name = "glob"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
-
-[[package]]
-name = "hashbrown"
-version = "0.15.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3"
-dependencies = [
- "foldhash",
-]
-
-[[package]]
-name = "hex"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
-
-[[package]]
-name = "home"
-version = "0.5.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
-dependencies = [
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "is_terminal_polyfill"
-version = "1.70.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
-
-[[package]]
-name = "itertools"
-version = "0.10.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
-dependencies = [
- "either",
-]
-
-[[package]]
-name = "itoa"
-version = "1.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
-
-[[package]]
-name = "jiff"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93"
-dependencies = [
- "jiff-static",
- "log",
- "portable-atomic",
- "portable-atomic-util",
- "serde",
-]
-
-[[package]]
-name = "jiff-static"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "jobserver"
-version = "0.1.33"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
-dependencies = [
- "getrandom 0.3.3",
- "libc",
-]
-
-[[package]]
-name = "lazy_static"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
-
-[[package]]
-name = "lazycell"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
-
-[[package]]
-name = "libc"
-version = "0.2.172"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
-
-[[package]]
-name = "libloading"
-version = "0.8.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
-dependencies = [
- "cfg-if",
- "windows-targets",
-]
-
-[[package]]
-name = "linux-raw-sys"
-version = "0.4.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
-
-[[package]]
-name = "log"
-version = "0.4.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
-
-[[package]]
-name = "macro_rules_attribute"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65049d7923698040cd0b1ddcced9b0eb14dd22c5f86ae59c3740eab64a676520"
-dependencies = [
- "macro_rules_attribute-proc_macro",
- "paste",
-]
-
-[[package]]
-name = "macro_rules_attribute-proc_macro"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "670fdfda89751bc4a84ac13eaa63e205cf0fd22b4c9a5fbfa085b63c1f1d3a30"
-
-[[package]]
-name = "memchr"
-version = "2.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
-
-[[package]]
-name = "minimal-lexical"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
-
-[[package]]
-name = "nom"
-version = "7.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
-dependencies = [
- "memchr",
- "minimal-lexical",
-]
-
-[[package]]
-name = "num-bigint"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
-dependencies = [
- "num-integer",
- "num-traits",
-]
-
-[[package]]
-name = "num-conv"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
-
-[[package]]
-name = "num-integer"
-version = "0.1.46"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
-dependencies = [
- "num-traits",
-]
-
-[[package]]
-name = "num-traits"
-version = "0.2.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "oid-registry"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7"
-dependencies = [
- "asn1-rs",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.21.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
-
-[[package]]
-name = "once_cell_polyfill"
-version = "1.70.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
-
-[[package]]
-name = "paste"
-version = "1.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
-
-[[package]]
-name = "pem"
-version = "3.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3"
-dependencies = [
- "base64",
- "serde",
-]
-
-[[package]]
-name = "portable-atomic"
-version = "1.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
-
-[[package]]
-name = "portable-atomic-util"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
-dependencies = [
- "portable-atomic",
-]
-
-[[package]]
-name = "powerfmt"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
-
-[[package]]
-name = "prettyplease"
-version = "0.2.33"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9dee91521343f4c5c6a63edd65e54f31f5c92fe8978c40a4282f8372194c6a7d"
-dependencies = [
- "proc-macro2",
- "syn",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.95"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "r-efi"
-version = "5.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
-
-[[package]]
-name = "rcgen"
-version = "0.14.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "218a7fbb357f6da42c9fd3610b1a5128d087d460e5386eaa5040705c464611dc"
-dependencies = [
- "aws-lc-rs",
- "pem",
- "rustls-pki-types",
- "time",
- "yasna",
-]
-
-[[package]]
-name = "regex"
-version = "1.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-automata",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.4.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
-
-[[package]]
-name = "ring"
-version = "0.17.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
-dependencies = [
- "cc",
- "cfg-if",
- "getrandom 0.2.16",
- "libc",
- "untrusted",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "rustc-hash"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
-
-[[package]]
-name = "rusticata-macros"
-version = "4.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632"
-dependencies = [
- "nom",
-]
-
-[[package]]
-name = "rustix"
-version = "0.38.44"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
-dependencies = [
- "bitflags",
- "errno",
- "libc",
- "linux-raw-sys",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "rustls"
-version = "0.23.29"
-dependencies = [
- "aws-lc-rs",
- "base64",
- "bencher",
- "brotli",
- "brotli-decompressor",
- "env_logger",
- "hashbrown",
- "hex",
- "log",
- "macro_rules_attribute",
- "num-bigint",
- "once_cell",
- "rcgen",
- "ring",
- "rustls-pki-types",
- "rustls-webpki",
- "rustversion",
- "serde",
- "serde_json",
- "subtle",
- "time",
- "webpki-roots",
- "x509-parser",
- "zeroize",
- "zlib-rs",
-]
-
-[[package]]
-name = "rustls-pki-types"
-version = "1.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79"
-dependencies = [
- "zeroize",
-]
-
-[[package]]
-name = "rustls-webpki"
-version = "0.103.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc"
-dependencies = [
- "aws-lc-rs",
- "ring",
- "rustls-pki-types",
- "untrusted",
-]
-
-[[package]]
-name = "rustversion"
-version = "1.0.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
-
-[[package]]
-name = "ryu"
-version = "1.0.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
-
-[[package]]
-name = "serde"
-version = "1.0.219"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.219"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.140"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
-dependencies = [
- "itoa",
- "memchr",
- "ryu",
- "serde",
-]
-
-[[package]]
-name = "shlex"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
-
-[[package]]
-name = "subtle"
-version = "2.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
-
-[[package]]
-name = "syn"
-version = "2.0.101"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "synstructure"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "thiserror"
-version = "2.0.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
-dependencies = [
- "thiserror-impl",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "2.0.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "time"
-version = "0.3.41"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
-dependencies = [
- "deranged",
- "itoa",
- "num-conv",
- "powerfmt",
- "serde",
- "time-core",
- "time-macros",
-]
-
-[[package]]
-name = "time-core"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
-
-[[package]]
-name = "time-macros"
-version = "0.2.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
-dependencies = [
- "num-conv",
- "time-core",
-]
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
-
-[[package]]
-name = "untrusted"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
-
-[[package]]
-name = "utf8parse"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
-
-[[package]]
-name = "wasi"
-version = "0.11.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
-
-[[package]]
-name = "wasi"
-version = "0.14.2+wasi-0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
-dependencies = [
- "wit-bindgen-rt",
-]
-
-[[package]]
-name = "webpki-roots"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb"
-dependencies = [
- "rustls-pki-types",
-]
-
-[[package]]
-name = "which"
-version = "4.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
-dependencies = [
- "either",
- "home",
- "once_cell",
- "rustix",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
-dependencies = [
- "windows-targets",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.59.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
-dependencies = [
- "windows-targets",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
-dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_gnullvm",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
-]
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
-
-[[package]]
-name = "windows_i686_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
-
-[[package]]
-name = "wit-bindgen-rt"
-version = "0.39.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "x509-parser"
-version = "0.17.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4569f339c0c402346d4a75a9e39cf8dad310e287eef1ff56d4c68e5067f53460"
-dependencies = [
- "asn1-rs",
- "data-encoding",
- "der-parser",
- "lazy_static",
- "nom",
- "oid-registry",
- "rusticata-macros",
- "thiserror",
- "time",
-]
-
-[[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.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
-
-[[package]]
-name = "zlib-rs"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "626bd9fa9734751fc50d6060752170984d7053f5a39061f524cda68023d4db8a"
diff --git a/vendor/rustls/Cargo.toml b/vendor/rustls/Cargo.toml
deleted file mode 100644
index a7504ff5..00000000
--- a/vendor/rustls/Cargo.toml
+++ /dev/null
@@ -1,233 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies.
-#
-# If you are reading this file be aware that the original Cargo.toml
-# will likely look very different (and much more reasonable).
-# See Cargo.toml.orig for the original contents.
-
-[package]
-edition = "2021"
-rust-version = "1.71"
-name = "rustls"
-version = "0.23.29"
-build = "build.rs"
-exclude = [
- "src/testdata",
- "tests/**",
-]
-autolib = false
-autobins = false
-autoexamples = false
-autotests = false
-autobenches = false
-description = "Rustls is a modern TLS library written in Rust."
-homepage = "https://github.com/rustls/rustls"
-readme = "README.md"
-categories = [
- "network-programming",
- "cryptography",
-]
-license = "Apache-2.0 OR ISC OR MIT"
-repository = "https://github.com/rustls/rustls"
-
-[package.metadata.cargo-semver-checks.lints]
-enum_no_repr_variant_discriminant_changed = "warn"
-
-[package.metadata.cargo_check_external_types]
-allowed_external_types = [
- "rustls_pki_types",
- "rustls_pki_types::*",
-]
-
-[package.metadata.docs.rs]
-features = [
- "read_buf",
- "ring",
-]
-rustdoc-args = [
- "--cfg",
- "docsrs",
-]
-
-[features]
-aws-lc-rs = ["aws_lc_rs"]
-aws_lc_rs = [
- "dep:aws-lc-rs",
- "webpki/aws-lc-rs",
- "aws-lc-rs/aws-lc-sys",
- "aws-lc-rs/prebuilt-nasm",
-]
-brotli = [
- "dep:brotli",
- "dep:brotli-decompressor",
- "std",
-]
-custom-provider = []
-default = [
- "aws_lc_rs",
- "logging",
- "prefer-post-quantum",
- "std",
- "tls12",
-]
-fips = [
- "aws_lc_rs",
- "aws-lc-rs?/fips",
- "webpki/aws-lc-rs-fips",
-]
-logging = ["log"]
-prefer-post-quantum = ["aws_lc_rs"]
-read_buf = [
- "rustversion",
- "std",
-]
-ring = [
- "dep:ring",
- "webpki/ring",
-]
-std = [
- "webpki/std",
- "pki-types/std",
- "once_cell/std",
-]
-tls12 = []
-zlib = ["dep:zlib-rs"]
-
-[lib]
-name = "rustls"
-path = "src/lib.rs"
-
-[[example]]
-name = "test_ca"
-path = "examples/internal/test_ca.rs"
-
-[[bench]]
-name = "benchmarks"
-path = "benches/benchmarks.rs"
-harness = false
-required-features = ["ring"]
-
-[dependencies.aws-lc-rs]
-version = "1.12"
-optional = true
-default-features = false
-
-[dependencies.brotli]
-version = "8"
-features = ["std"]
-optional = true
-default-features = false
-
-[dependencies.brotli-decompressor]
-version = "5.0.0"
-optional = true
-
-[dependencies.hashbrown]
-version = "0.15"
-features = [
- "default-hasher",
- "inline-more",
-]
-optional = true
-default-features = false
-
-[dependencies.log]
-version = "0.4.8"
-optional = true
-
-[dependencies.once_cell]
-version = "1.16"
-features = [
- "alloc",
- "race",
-]
-default-features = false
-
-[dependencies.pki-types]
-version = "1.12"
-features = ["alloc"]
-package = "rustls-pki-types"
-
-[dependencies.ring]
-version = "0.17"
-optional = true
-
-[dependencies.subtle]
-version = "2.5.0"
-default-features = false
-
-[dependencies.webpki]
-version = "0.103.4"
-features = ["alloc"]
-default-features = false
-package = "rustls-webpki"
-
-[dependencies.zeroize]
-version = "1.7"
-
-[dependencies.zlib-rs]
-version = "0.5"
-optional = true
-
-[dev-dependencies.base64]
-version = "0.22"
-
-[dev-dependencies.bencher]
-version = "0.1.5"
-
-[dev-dependencies.env_logger]
-version = "0.11"
-
-[dev-dependencies.hex]
-version = "0.4"
-
-[dev-dependencies.log]
-version = "0.4.8"
-
-[dev-dependencies.macro_rules_attribute]
-version = "0.2"
-
-[dev-dependencies.num-bigint]
-version = "0.4.4"
-
-[dev-dependencies.rcgen]
-version = "0.14"
-features = [
- "pem",
- "aws_lc_rs",
-]
-default-features = false
-
-[dev-dependencies.serde]
-version = "1"
-features = ["derive"]
-
-[dev-dependencies.serde_json]
-version = "1"
-
-[dev-dependencies.time]
-version = "0.3.6"
-default-features = false
-
-[dev-dependencies.webpki-roots]
-version = "1"
-
-[dev-dependencies.x509-parser]
-version = "0.17"
-
-[build-dependencies.rustversion]
-version = "1.0.6"
-optional = true
-
-[lints.rust.unexpected_cfgs]
-level = "warn"
-priority = 0
-check-cfg = [
- "cfg(bench)",
- "cfg(coverage_nightly)",
- "cfg(read_buf)",
-]
diff --git a/vendor/rustls/LICENSE-APACHE b/vendor/rustls/LICENSE-APACHE
deleted file mode 100644
index 16fe87b0..00000000
--- a/vendor/rustls/LICENSE-APACHE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/vendor/rustls/LICENSE-ISC b/vendor/rustls/LICENSE-ISC
deleted file mode 100644
index 03acf1bd..00000000
--- a/vendor/rustls/LICENSE-ISC
+++ /dev/null
@@ -1,15 +0,0 @@
-ISC License (ISC)
-Copyright (c) 2016, Joseph Birr-Pixton <jpixton@gmail.com>
-
-Permission to use, copy, modify, and/or distribute this software for
-any purpose with or without fee is hereby granted, provided that the
-above copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
-WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
-AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
-DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
-PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
-THIS SOFTWARE.
diff --git a/vendor/rustls/LICENSE-MIT b/vendor/rustls/LICENSE-MIT
deleted file mode 100644
index ef480e6f..00000000
--- a/vendor/rustls/LICENSE-MIT
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2016 Joseph Birr-Pixton <jpixton@gmail.com>
-
-Permission is hereby granted, free of charge, to any
-person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without
-limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/vendor/rustls/README.md b/vendor/rustls/README.md
deleted file mode 100644
index 5b8f0124..00000000
--- a/vendor/rustls/README.md
+++ /dev/null
@@ -1,222 +0,0 @@
-<p align="center">
- <img width="460" height="300" src="https://raw.githubusercontent.com/rustls/rustls/main/admin/rustls-logo-web.png">
-</p>
-
-<p align="center">
-Rustls is a modern TLS library written in Rust.
-</p>
-
-# Status
-
-Rustls is used in production at many organizations and projects. We aim to maintain
-reasonable API surface stability but the API may evolve as we make changes to accommodate
-new features or performance improvements.
-
-We have a [roadmap](ROADMAP.md) for our future plans. We also have [benchmarks](BENCHMARKING.md) to
-prevent performance regressions and to let you evaluate rustls on your target hardware.
-
-If you'd like to help out, please see [CONTRIBUTING.md](CONTRIBUTING.md).
-
-[![Build Status](https://github.com/rustls/rustls/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/rustls/rustls/actions/workflows/build.yml?query=branch%3Amain)
-[![Coverage Status (codecov.io)](https://codecov.io/gh/rustls/rustls/branch/main/graph/badge.svg)](https://codecov.io/gh/rustls/rustls/)
-[![Documentation](https://docs.rs/rustls/badge.svg)](https://docs.rs/rustls/)
-[![Chat](https://img.shields.io/discord/976380008299917365?logo=discord)](https://discord.gg/MCSB76RU96)
-[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/9034/badge)](https://www.bestpractices.dev/projects/9034)
-
-## Changelog
-
-The detailed list of changes in each release can be found at
-https://github.com/rustls/rustls/releases.
-
-# Documentation
-
-https://docs.rs/rustls/
-
-# Approach
-
-Rustls is a TLS library that aims to provide a good level of cryptographic security,
-requires no configuration to achieve that security, and provides no unsafe features or
-obsolete cryptography by default.
-
-Rustls implements TLS1.2 and TLS1.3 for both clients and servers. See [the full
-list of protocol features](https://docs.rs/rustls/latest/rustls/manual/_04_features/index.html).
-
-### Platform support
-
-While Rustls itself is platform independent, by default it uses [`aws-lc-rs`] for implementing
-the cryptography in TLS. See [the aws-lc-rs FAQ][aws-lc-rs-platforms-faq] for more details of the
-platform/architecture support constraints in aws-lc-rs.
-
-[`ring`] is also available via the `ring` crate feature: see
-[the supported `ring` target platforms][ring-target-platforms].
-
-By providing a custom instance of the [`crypto::CryptoProvider`] struct, you
-can replace all cryptography dependencies of rustls. This is a route to being portable
-to a wider set of architectures and environments, or compliance requirements. See the
-[`crypto::CryptoProvider`] documentation for more details.
-
-Specifying `default-features = false` when depending on rustls will remove the implicit
-dependency on aws-lc-rs.
-
-Rustls requires Rust 1.71 or later. It has an optional dependency on zlib-rs which requires 1.75 or later.
-
-[ring-target-platforms]: https://github.com/briansmith/ring/blob/2e8363b433fa3b3962c877d9ed2e9145612f3160/include/ring-core/target.h#L18-L64
-[`crypto::CryptoProvider`]: https://docs.rs/rustls/latest/rustls/crypto/struct.CryptoProvider.html
-[`ring`]: https://crates.io/crates/ring
-[aws-lc-rs-platforms-faq]: https://aws.github.io/aws-lc-rs/faq.html#can-i-run-aws-lc-rs-on-x-platform-or-architecture
-[`aws-lc-rs`]: https://crates.io/crates/aws-lc-rs
-
-### Cryptography providers
-
-Since Rustls 0.22 it has been possible to choose the provider of the cryptographic primitives
-that Rustls uses. This may be appealing if you have specific platform, compliance or feature
-requirements that aren't met by the default provider, [`aws-lc-rs`].
-
-Users that wish to customize the provider in use can do so when constructing `ClientConfig`
-and `ServerConfig` instances using the `with_crypto_provider` method on the respective config
-builder types. See the [`crypto::CryptoProvider`] documentation for more details.
-
-#### Built-in providers
-
-Rustls ships with two built-in providers controlled by associated crate features:
-
-* [`aws-lc-rs`] - enabled by default, available with the `aws_lc_rs` crate feature enabled.
-* [`ring`] - available with the `ring` crate feature enabled.
-
-See the documentation for [`crypto::CryptoProvider`] for details on how providers are
-selected.
-
-#### Third-party providers
-
-The community has also started developing third-party providers for Rustls:
-
-* [`boring-rustls-provider`] - a work-in-progress provider that uses [`boringssl`] for
-cryptography.
-* [`rustls-graviola`] - a provider that uses [`graviola`] for cryptography.
-* [`rustls-mbedtls-provider`] - a provider that uses [`mbedtls`] for cryptography.
-* [`rustls-openssl`] - a provider that uses [OpenSSL] for cryptography.
-* [`rustls-rustcrypto`] - an experimental provider that uses the crypto primitives
-from [`RustCrypto`] for cryptography.
-* [`rustls-symcrypt`] - a provider that uses Microsoft's [SymCrypt] library.
-* [`rustls-wolfcrypt-provider`] - a work-in-progress provider that uses [`wolfCrypt`] for cryptography.
-
-[`rustls-graviola`]: https://crates.io/crates/rustls-graviola
-[`graviola`]: https://github.com/ctz/graviola
-[`rustls-mbedtls-provider`]: https://github.com/fortanix/rustls-mbedtls-provider
-[`mbedtls`]: https://github.com/Mbed-TLS/mbedtls
-[`rustls-openssl`]: https://github.com/tofay/rustls-openssl
-[OpenSSL]: https://openssl-library.org/
-[`rustls-symcrypt`]: https://github.com/microsoft/rustls-symcrypt
-[SymCrypt]: https://github.com/microsoft/SymCrypt
-[`boring-rustls-provider`]: https://github.com/janrueth/boring-rustls-provider
-[`boringssl`]: https://github.com/google/boringssl
-[`rustls-rustcrypto`]: https://github.com/RustCrypto/rustls-rustcrypto
-[`RustCrypto`]: https://github.com/RustCrypto
-[`rustls-wolfcrypt-provider`]: https://github.com/wolfSSL/rustls-wolfcrypt-provider
-[`wolfCrypt`]: https://www.wolfssl.com/products/wolfcrypt
-
-#### Custom provider
-
-We also provide a simple example of writing your own provider in the [custom provider example].
-This example implements a minimal provider using parts of the [`RustCrypto`] ecosystem.
-
-See the [Making a custom CryptoProvider] section of the documentation for more information
-on this topic.
-
-[custom provider example]: https://github.com/rustls/rustls/tree/main/provider-example/
-[`RustCrypto`]: https://github.com/RustCrypto
-[Making a custom CryptoProvider]: https://docs.rs/rustls/latest/rustls/crypto/struct.CryptoProvider.html#making-a-custom-cryptoprovider
-
-# Example code
-
-Our [examples] directory contains demos that show how to handle I/O using the
-[`stream::Stream`] helper, as well as more complex asynchronous I/O using [`mio`].
-If you're already using Tokio for an async runtime you may prefer to use
-[`tokio-rustls`] instead of interacting with rustls directly.
-
-The [`mio`] based examples are the most complete, and discussed below. Users
-new to Rustls may prefer to look at the simple client/server examples before
-diving in to the more complex MIO examples.
-
-[examples]: examples/
-[`stream::Stream`]: https://docs.rs/rustls/latest/rustls/struct.Stream.html
-[`mio`]: https://docs.rs/mio/latest/mio/
-[`tokio-rustls`]: https://docs.rs/tokio-rustls/latest/tokio_rustls/
-
-## Client example program
-
-The MIO client example program is named `tlsclient-mio`.
-
-Some sample runs:
-
-```
-$ cargo run --bin tlsclient-mio -- --http mozilla-modern.badssl.com
-HTTP/1.1 200 OK
-Server: nginx/1.6.2 (Ubuntu)
-Date: Wed, 01 Jun 2016 18:44:00 GMT
-Content-Type: text/html
-Content-Length: 644
-(...)
-```
-
-or
-
-```
-$ cargo run --bin tlsclient-mio -- --http expired.badssl.com
-TLS error: InvalidCertificate(Expired)
-Connection closed
-```
-
-Run `cargo run --bin tlsclient-mio -- --help` for more options.
-
-## Server example program
-
-The MIO server example program is named `tlsserver-mio`.
-
-Here's a sample run; we start a TLS echo server, then connect to it with
-`openssl` and `tlsclient-mio`:
-
-```
-$ cargo run --bin tlsserver-mio -- --certs test-ca/rsa-2048/end.fullchain --key test-ca/rsa-2048/end.key -p 8443 echo &
-$ echo hello world | openssl s_client -ign_eof -quiet -connect localhost:8443
-depth=2 CN = ponytown RSA CA
-verify error:num=19:self signed certificate in certificate chain
-hello world
-^C
-$ echo hello world | cargo run --bin tlsclient-mio -- --cafile test-ca/rsa-2048/ca.cert --port 8443 localhost
-hello world
-^C
-```
-
-Run `cargo run --bin tlsserver-mio -- --help` for more options.
-
-# License
-
-Rustls is distributed under the following three licenses:
-
-- Apache License version 2.0.
-- MIT license.
-- ISC license.
-
-These are included as LICENSE-APACHE, LICENSE-MIT and LICENSE-ISC
-respectively. You may use this software under the terms of any
-of these licenses, at your option.
-
-# Project Membership
-
-- Joe Birr-Pixton ([@ctz], Project Founder - full-time funded by [Prossimo])
-- Dirkjan Ochtman ([@djc], Co-maintainer)
-- Daniel McCarney ([@cpu], Co-maintainer)
-- Josh Aas ([@bdaehlie], Project Management)
-
-[@ctz]: https://github.com/ctz
-[@djc]: https://github.com/djc
-[@cpu]: https://github.com/cpu
-[@bdaehlie]: https://github.com/bdaehlie
-[Prossimo]: https://www.memorysafety.org/initiative/rustls/
-
-# Code of conduct
-
-This project adopts the [Rust Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct).
-Please email rustls-mod@googlegroups.com to report any instance of misconduct, or if you
-have any comments or questions on the Code of Conduct.
diff --git a/vendor/rustls/benches/benchmarks.rs b/vendor/rustls/benches/benchmarks.rs
deleted file mode 100644
index 5aebc995..00000000
--- a/vendor/rustls/benches/benchmarks.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-#![cfg(feature = "ring")]
-#![allow(clippy::disallowed_types)]
-
-use std::io;
-use std::sync::Arc;
-
-use bencher::{Bencher, benchmark_group, benchmark_main};
-use rustls::ServerConnection;
-use rustls::crypto::ring as provider;
-use rustls_test::{FailsReads, KeyType, make_server_config};
-
-fn bench_ewouldblock(c: &mut Bencher) {
- let server_config = make_server_config(KeyType::Rsa2048, &provider::default_provider());
- let mut server = ServerConnection::new(Arc::new(server_config)).unwrap();
- let mut read_ewouldblock = FailsReads::new(io::ErrorKind::WouldBlock);
- c.iter(|| server.read_tls(&mut read_ewouldblock));
-}
-
-benchmark_group!(benches, bench_ewouldblock);
-benchmark_main!(benches);
diff --git a/vendor/rustls/build.rs b/vendor/rustls/build.rs
deleted file mode 100644
index 8c0bd2aa..00000000
--- a/vendor/rustls/build.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-//! This build script allows us to enable the `read_buf` language feature only
-//! for Rust Nightly.
-//!
-//! See the comment in lib.rs to understand why we need this.
-
-#[cfg_attr(feature = "read_buf", rustversion::not(nightly))]
-fn main() {}
-
-#[cfg(feature = "read_buf")]
-#[rustversion::nightly]
-fn main() {
- println!("cargo:rustc-cfg=read_buf");
-}
diff --git a/vendor/rustls/examples/internal/test_ca.rs b/vendor/rustls/examples/internal/test_ca.rs
deleted file mode 100644
index 1df38484..00000000
--- a/vendor/rustls/examples/internal/test_ca.rs
+++ /dev/null
@@ -1,352 +0,0 @@
-use std::collections::HashMap;
-use std::env;
-use std::fs::{self, File};
-use std::io::Write;
-use std::net::IpAddr;
-use std::path::PathBuf;
-use std::str::FromStr;
-use std::sync::atomic::{AtomicU64, Ordering};
-use std::time::Duration;
-
-use rcgen::string::Ia5String;
-use rcgen::{
- BasicConstraints, Certificate, CertificateParams, CertificateRevocationListParams,
- DistinguishedName, DnType, ExtendedKeyUsagePurpose, IsCa, Issuer, KeyIdMethod, KeyPair,
- KeyUsagePurpose, PKCS_ECDSA_P256_SHA256, PKCS_ECDSA_P384_SHA384, PKCS_ECDSA_P521_SHA512,
- PKCS_ED25519, PKCS_RSA_SHA256, PKCS_RSA_SHA384, PKCS_RSA_SHA512, RevocationReason,
- RevokedCertParams, RsaKeySize, SanType, SerialNumber, SignatureAlgorithm,
-};
-use time::OffsetDateTime;
-
-fn main() -> Result<(), Box<dyn std::error::Error>> {
- let mut certified_keys = HashMap::<
- (Role, &'static SignatureAlgorithm),
- (Issuer<'static, KeyPair>, Certificate),
- >::with_capacity(ROLES.len() * SIG_ALGS.len());
-
- for role in ROLES {
- for alg in SIG_ALGS {
- // Generate a key pair and serialize it to a PEM encoded file.
- let key_pair = alg.key_pair();
- let mut key_pair_file = File::create(role.key_file_path(alg))?;
- key_pair_file.write_all(key_pair.serialize_pem().as_bytes())?;
-
- // Issue a certificate for the key pair. For trust anchors, this will be self-signed.
- // Otherwise we dig out the issuer and issuer_key for the issuer, which should have
- // been produced in earlier iterations based on the careful ordering of roles.
- let (params, cert) = match role {
- Role::TrustAnchor => {
- let params = role.params(alg);
- let cert = params.self_signed(&key_pair)?;
- (params, cert)
- }
- Role::Intermediate => {
- let issuer = certified_keys
- .get(&(Role::TrustAnchor, alg.inner))
- .unwrap();
- let params = role.params(alg);
- let cert = params.signed_by(&key_pair, &issuer.0)?;
- (params, cert)
- }
- Role::EndEntity | Role::Client => {
- let issuer = certified_keys
- .get(&(Role::Intermediate, alg.inner))
- .unwrap();
- let params = role.params(alg);
- let cert = params.signed_by(&key_pair, &issuer.0)?;
- (params, cert)
- }
- };
-
- // Serialize the issued certificate to a PEM encoded file.
- let mut cert_file = File::create(role.cert_pem_file_path(alg))?;
- cert_file.write_all(cert.pem().as_bytes())?;
- // And to a DER encoded file.
- let mut cert_file = File::create(role.cert_der_file_path(alg))?;
- cert_file.write_all(cert.der())?;
-
- // If we're not a trust anchor, generate a CRL for the certificate we just issued.
- if role != Role::TrustAnchor {
- // The CRL will be signed by the issuer of the certificate being revoked. For
- // intermediates this will be the trust anchor, and for client/EE certs this will
- // be the intermediate.
- let issuer = match role {
- Role::Intermediate => certified_keys
- .get(&(Role::TrustAnchor, alg.inner))
- .unwrap(),
- Role::EndEntity | Role::Client => certified_keys
- .get(&(Role::Intermediate, alg.inner))
- .unwrap(),
- _ => panic!("unexpected role for CRL generation: {role:?}"),
- };
-
- let revoked_crl =
- crl_for_serial(params.serial_number.clone().unwrap()).signed_by(&issuer.0)?;
- let mut revoked_crl_file = File::create(
- alg.output_directory()
- .join(format!("{}.revoked.crl.pem", role.label())),
- )?;
- revoked_crl_file.write_all(revoked_crl.pem().unwrap().as_bytes())?;
-
- let expired_crl = expired_crl().signed_by(&issuer.0)?;
- let mut expired_crl_file = File::create(
- alg.output_directory()
- .join(format!("{}.expired.crl.pem", role.label())),
- )?;
- expired_crl_file.write_all(expired_crl.pem().unwrap().as_bytes())?;
- }
-
- // When we're issuing end entity or client certs we have a bit of extra work to do
- // now that we have full chains in hand.
- if matches!(role, Role::EndEntity | Role::Client) {
- let root = &certified_keys
- .get(&(Role::TrustAnchor, alg.inner))
- .unwrap()
- .1;
- let intermediate = &certified_keys
- .get(&(Role::Intermediate, alg.inner))
- .unwrap()
- .1;
-
- // Write the PEM chain and full chain files for the end entity and client certs.
- // Chain files include the intermediate and root certs, while full chain files include
- // the end entity or client cert as well.
- for f in [
- ("chain", &[intermediate, root][..]),
- ("fullchain", &[&cert, intermediate, root][..]),
- ] {
- let mut chain_file = File::create(alg.output_directory().join(format!(
- "{}.{}",
- role.label(),
- f.0
- )))?;
- for cert in f.1 {
- chain_file.write_all(cert.pem().as_bytes())?;
- }
- }
-
- // Write the PEM public key for the end entity and client.
- let mut raw_public_key_file = File::create(
- alg.output_directory()
- .join(format!("{}.spki.pem", role.label())),
- )?;
- raw_public_key_file.write_all(key_pair.public_key_pem().as_bytes())?;
- }
-
- certified_keys.insert((role, alg.inner), (Issuer::new(params, key_pair), cert));
- }
- }
-
- Ok(())
-}
-
-fn crl_for_serial(serial_number: SerialNumber) -> CertificateRevocationListParams {
- let now = OffsetDateTime::now_utc();
- CertificateRevocationListParams {
- this_update: now,
- next_update: now + Duration::from_secs(60 * 60 * 24 * 365 * 100), // 100 years
- crl_number: SerialNumber::from(1234),
- issuing_distribution_point: None,
- revoked_certs: vec![RevokedCertParams {
- serial_number,
- revocation_time: now,
- reason_code: Some(RevocationReason::KeyCompromise),
- invalidity_date: None,
- }],
- key_identifier_method: KeyIdMethod::Sha256,
- }
-}
-
-fn expired_crl() -> CertificateRevocationListParams {
- let now = OffsetDateTime::now_utc();
- CertificateRevocationListParams {
- this_update: now - Duration::from_secs(60),
- next_update: now,
- crl_number: SerialNumber::from(1234),
- issuing_distribution_point: None,
- revoked_certs: vec![],
- key_identifier_method: KeyIdMethod::Sha256,
- }
-}
-
-// Note: these are ordered such that the data dependencies for issuance are satisfied.
-const ROLES: [Role; 4] = [
- Role::TrustAnchor,
- Role::Intermediate,
- Role::EndEntity,
- Role::Client,
-];
-
-#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
-enum Role {
- Client,
- EndEntity,
- Intermediate,
- TrustAnchor,
-}
-
-impl Role {
- fn params(&self, alg: &'static SigAlgContext) -> CertificateParams {
- let mut params = CertificateParams::default();
- params.distinguished_name = self.common_name(alg);
- params.use_authority_key_identifier_extension = true;
- let serial = SERIAL_NUMBER.fetch_add(1, Ordering::SeqCst);
- params.serial_number = Some(SerialNumber::from_slice(&serial.to_be_bytes()[..]));
-
- match self {
- Self::TrustAnchor | Self::Intermediate => {
- params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained);
- params.key_usages = ISSUER_KEY_USAGES.to_vec();
- params.extended_key_usages = ISSUER_EXTENDED_KEY_USAGES.to_vec();
- }
- Self::EndEntity | Self::Client => {
- params.is_ca = IsCa::NoCa;
- params.key_usages = EE_KEY_USAGES.to_vec();
- params.subject_alt_names = vec![
- SanType::DnsName(Ia5String::try_from("testserver.com".to_string()).unwrap()),
- SanType::DnsName(
- Ia5String::try_from("second.testserver.com".to_string()).unwrap(),
- ),
- SanType::DnsName(Ia5String::try_from("localhost".to_string()).unwrap()),
- SanType::IpAddress(IpAddr::from_str("198.51.100.1").unwrap()),
- SanType::IpAddress(IpAddr::from_str("2001:db8::1").unwrap()),
- ];
- }
- }
-
- // Client certificates additionally get the client auth EKU.
- if *self == Self::Client {
- params.extended_key_usages = vec![ExtendedKeyUsagePurpose::ClientAuth];
- }
-
- params
- }
-
- fn common_name(&self, alg: &'static SigAlgContext) -> DistinguishedName {
- let mut distinguished_name = DistinguishedName::new();
- distinguished_name.push(
- DnType::CommonName,
- match self {
- Self::Client => "ponytown client".to_owned(),
- Self::EndEntity => "testserver.com".to_owned(),
- Self::Intermediate => {
- format!("ponytown {} level 2 intermediate", alg.issuer_cn)
- }
- Self::TrustAnchor => format!("ponytown {} CA", alg.issuer_cn),
- },
- );
- distinguished_name
- }
-
- fn key_file_path(&self, alg: &'static SigAlgContext) -> PathBuf {
- alg.output_directory()
- .join(format!("{}.key", self.label()))
- }
-
- fn cert_pem_file_path(&self, alg: &'static SigAlgContext) -> PathBuf {
- alg.output_directory()
- .join(format!("{}.cert", self.label()))
- }
-
- fn cert_der_file_path(&self, alg: &'static SigAlgContext) -> PathBuf {
- alg.output_directory()
- .join(format!("{}.der", self.label()))
- }
-
- fn label(&self) -> &'static str {
- match self {
- Self::Client => "client",
- Self::EndEntity => "end",
- Self::Intermediate => "inter",
- Self::TrustAnchor => "ca",
- }
- }
-}
-
-// Note: for convenience we use the RSA sigalg digest algorithm to inform the RSA modulus
-// size, mapping SHA256 to RSA 2048, SHA384 to RSA 3072, and SHA512 to RSA 4096.
-static SIG_ALGS: &[SigAlgContext] = &[
- SigAlgContext {
- inner: &PKCS_RSA_SHA256,
- issuer_cn: "RSA 2048",
- },
- SigAlgContext {
- inner: &PKCS_RSA_SHA384,
- issuer_cn: "RSA 3072",
- },
- SigAlgContext {
- inner: &PKCS_RSA_SHA512,
- issuer_cn: "RSA 4096",
- },
- SigAlgContext {
- inner: &PKCS_ECDSA_P256_SHA256,
- issuer_cn: "ECDSA p256",
- },
- SigAlgContext {
- inner: &PKCS_ECDSA_P384_SHA384,
- issuer_cn: "ECDSA p384",
- },
- SigAlgContext {
- inner: &PKCS_ECDSA_P521_SHA512,
- issuer_cn: "ECDSA p521",
- },
- SigAlgContext {
- inner: &PKCS_ED25519,
- issuer_cn: "EdDSA",
- },
-];
-
-struct SigAlgContext {
- pub(crate) inner: &'static SignatureAlgorithm,
- pub(crate) issuer_cn: &'static str,
-}
-
-impl SigAlgContext {
- fn output_directory(&self) -> PathBuf {
- let output_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap())
- .join("../")
- .join("test-ca")
- .join(
- self.issuer_cn
- .to_lowercase()
- .replace(' ', "-"),
- );
- fs::create_dir_all(&output_dir).unwrap();
- output_dir
- }
-
- fn key_pair(&self) -> KeyPair {
- if *self.inner == PKCS_RSA_SHA256 {
- KeyPair::generate_rsa_for(&PKCS_RSA_SHA256, RsaKeySize::_2048)
- } else if *self.inner == PKCS_RSA_SHA384 {
- KeyPair::generate_rsa_for(&PKCS_RSA_SHA384, RsaKeySize::_3072)
- } else if *self.inner == PKCS_RSA_SHA512 {
- KeyPair::generate_rsa_for(&PKCS_RSA_SHA512, RsaKeySize::_4096)
- } else {
- KeyPair::generate_for(self.inner)
- }
- .unwrap()
- }
-}
-
-const ISSUER_KEY_USAGES: &[KeyUsagePurpose; 7] = &[
- KeyUsagePurpose::CrlSign,
- KeyUsagePurpose::KeyCertSign,
- KeyUsagePurpose::DigitalSignature,
- KeyUsagePurpose::ContentCommitment,
- KeyUsagePurpose::KeyEncipherment,
- KeyUsagePurpose::DataEncipherment,
- KeyUsagePurpose::KeyAgreement,
-];
-
-const ISSUER_EXTENDED_KEY_USAGES: &[ExtendedKeyUsagePurpose; 2] = &[
- ExtendedKeyUsagePurpose::ServerAuth,
- ExtendedKeyUsagePurpose::ClientAuth,
-];
-
-const EE_KEY_USAGES: &[KeyUsagePurpose; 2] = &[
- KeyUsagePurpose::DigitalSignature,
- KeyUsagePurpose::ContentCommitment,
-];
-
-static SERIAL_NUMBER: AtomicU64 = AtomicU64::new(1);
diff --git a/vendor/rustls/src/bs_debug.rs b/vendor/rustls/src/bs_debug.rs
deleted file mode 100644
index eac4149f..00000000
--- a/vendor/rustls/src/bs_debug.rs
+++ /dev/null
@@ -1,80 +0,0 @@
-use core::fmt;
-
-/// Alternative implementation of `fmt::Debug` for byte slice.
-///
-/// Standard `Debug` implementation for `[u8]` is comma separated
-/// list of numbers. Since large amount of byte strings are in fact
-/// ASCII strings or contain a lot of ASCII strings (e. g. HTTP),
-/// it is convenient to print strings as ASCII when possible.
-///
-/// This struct wraps `&[u8]` just to override `fmt::Debug`.
-///
-/// `BsDebug` is not a part of public API of bytes crate.
-pub(crate) struct BsDebug<'a>(pub(crate) &'a [u8]);
-
-impl fmt::Debug for BsDebug<'_> {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
- write!(fmt, "b\"")?;
- for &c in self.0 {
- // https://doc.rust-lang.org/reference.html#byte-escapes
- if c == b'\n' {
- write!(fmt, "\\n")?;
- } else if c == b'\r' {
- write!(fmt, "\\r")?;
- } else if c == b'\t' {
- write!(fmt, "\\t")?;
- } else if c == b'\\' || c == b'"' {
- write!(fmt, "\\{}", c as char)?;
- } else if c == b'\0' {
- write!(fmt, "\\0")?;
- // ASCII printable
- } else if (0x20..0x7f).contains(&c) {
- write!(fmt, "{}", c as char)?;
- } else {
- write!(fmt, "\\x{c:02x}")?;
- }
- }
- write!(fmt, "\"")?;
- Ok(())
- }
-}
-
-#[cfg(test)]
-mod tests {
- use std::format;
- use std::prelude::v1::*;
-
- use super::BsDebug;
-
- #[test]
- fn debug() {
- let vec: Vec<_> = (0..0x100).map(|b| b as u8).collect();
-
- let expected = "b\"\
- \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\
- \\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\
- \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\
- \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\
- \x20!\\\"#$%&'()*+,-./0123456789:;<=>?\
- @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_\
- `abcdefghijklmnopqrstuvwxyz{|}~\\x7f\
- \\x80\\x81\\x82\\x83\\x84\\x85\\x86\\x87\
- \\x88\\x89\\x8a\\x8b\\x8c\\x8d\\x8e\\x8f\
- \\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97\
- \\x98\\x99\\x9a\\x9b\\x9c\\x9d\\x9e\\x9f\
- \\xa0\\xa1\\xa2\\xa3\\xa4\\xa5\\xa6\\xa7\
- \\xa8\\xa9\\xaa\\xab\\xac\\xad\\xae\\xaf\
- \\xb0\\xb1\\xb2\\xb3\\xb4\\xb5\\xb6\\xb7\
- \\xb8\\xb9\\xba\\xbb\\xbc\\xbd\\xbe\\xbf\
- \\xc0\\xc1\\xc2\\xc3\\xc4\\xc5\\xc6\\xc7\
- \\xc8\\xc9\\xca\\xcb\\xcc\\xcd\\xce\\xcf\
- \\xd0\\xd1\\xd2\\xd3\\xd4\\xd5\\xd6\\xd7\
- \\xd8\\xd9\\xda\\xdb\\xdc\\xdd\\xde\\xdf\
- \\xe0\\xe1\\xe2\\xe3\\xe4\\xe5\\xe6\\xe7\
- \\xe8\\xe9\\xea\\xeb\\xec\\xed\\xee\\xef\
- \\xf0\\xf1\\xf2\\xf3\\xf4\\xf5\\xf6\\xf7\
- \\xf8\\xf9\\xfa\\xfb\\xfc\\xfd\\xfe\\xff\"";
-
- assert_eq!(expected, format!("{:?}", BsDebug(&vec)));
- }
-}
diff --git a/vendor/rustls/src/builder.rs b/vendor/rustls/src/builder.rs
deleted file mode 100644
index f8ff6140..00000000
--- a/vendor/rustls/src/builder.rs
+++ /dev/null
@@ -1,290 +0,0 @@
-use alloc::format;
-use alloc::vec::Vec;
-use core::fmt;
-use core::marker::PhantomData;
-
-use crate::client::EchMode;
-use crate::crypto::CryptoProvider;
-use crate::error::Error;
-use crate::msgs::handshake::ALL_KEY_EXCHANGE_ALGORITHMS;
-use crate::sync::Arc;
-use crate::time_provider::TimeProvider;
-use crate::versions;
-#[cfg(doc)]
-use crate::{ClientConfig, ServerConfig};
-
-/// A [builder] for [`ServerConfig`] or [`ClientConfig`] values.
-///
-/// To get one of these, call [`ServerConfig::builder()`] or [`ClientConfig::builder()`].
-///
-/// To build a config, you must make at least two decisions (in order):
-///
-/// - How should this client or server verify certificates provided by its peer?
-/// - What certificates should this client or server present to its peer?
-///
-/// For settings besides these, see the fields of [`ServerConfig`] and [`ClientConfig`].
-///
-/// The usual choice for protocol primitives is to call
-/// [`ClientConfig::builder`]/[`ServerConfig::builder`]
-/// which will use rustls' default cryptographic provider and safe defaults for ciphersuites and
-/// supported protocol versions.
-///
-/// ```
-/// # #[cfg(feature = "aws_lc_rs")] {
-/// # rustls::crypto::aws_lc_rs::default_provider().install_default();
-/// use rustls::{ClientConfig, ServerConfig};
-/// ClientConfig::builder()
-/// // ...
-/// # ;
-///
-/// ServerConfig::builder()
-/// // ...
-/// # ;
-/// # }
-/// ```
-///
-/// You may also override the choice of protocol versions:
-///
-/// ```no_run
-/// # #[cfg(feature = "aws_lc_rs")] {
-/// # rustls::crypto::aws_lc_rs::default_provider().install_default();
-/// # use rustls::ServerConfig;
-/// ServerConfig::builder_with_protocol_versions(&[&rustls::version::TLS13])
-/// // ...
-/// # ;
-/// # }
-/// ```
-///
-/// Overriding the default cryptographic provider introduces a `Result` that must be unwrapped,
-/// because the config builder checks for consistency of the choices made. For instance, it's an error to
-/// configure only TLS 1.2 cipher suites while specifying that TLS 1.3 should be the only supported protocol
-/// version.
-///
-/// If you configure a smaller set of protocol primitives than the default, you may get a smaller binary,
-/// since the code for the unused ones can be optimized away at link time.
-///
-/// After choosing protocol primitives, you must choose (a) how to verify certificates and (b) what certificates
-/// (if any) to send to the peer. The methods to do this are specific to whether you're building a ClientConfig
-/// or a ServerConfig, as tracked by the [`ConfigSide`] type parameter on the various impls of ConfigBuilder.
-///
-/// # ClientConfig certificate configuration
-///
-/// For a client, _certificate verification_ must be configured either by calling one of:
-/// - [`ConfigBuilder::with_root_certificates`] or
-/// - [`ConfigBuilder::dangerous()`] and [`DangerousClientConfigBuilder::with_custom_certificate_verifier`]
-///
-/// Next, _certificate sending_ (also known as "client authentication", "mutual TLS", or "mTLS") must be configured
-/// or disabled using one of:
-/// - [`ConfigBuilder::with_no_client_auth`] - to not send client authentication (most common)
-/// - [`ConfigBuilder::with_client_auth_cert`] - to always send a specific certificate
-/// - [`ConfigBuilder::with_client_cert_resolver`] - to send a certificate chosen dynamically
-///
-/// For example:
-///
-/// ```
-/// # #[cfg(feature = "aws_lc_rs")] {
-/// # rustls::crypto::aws_lc_rs::default_provider().install_default();
-/// # use rustls::ClientConfig;
-/// # let root_certs = rustls::RootCertStore::empty();
-/// ClientConfig::builder()
-/// .with_root_certificates(root_certs)
-/// .with_no_client_auth();
-/// # }
-/// ```
-///
-/// # ServerConfig certificate configuration
-///
-/// For a server, _certificate verification_ must be configured by calling one of:
-/// - [`ConfigBuilder::with_no_client_auth`] - to not require client authentication (most common)
-/// - [`ConfigBuilder::with_client_cert_verifier`] - to use a custom verifier
-///
-/// Next, _certificate sending_ must be configured by calling one of:
-/// - [`ConfigBuilder::with_single_cert`] - to send a specific certificate
-/// - [`ConfigBuilder::with_single_cert_with_ocsp`] - to send a specific certificate, plus stapled OCSP
-/// - [`ConfigBuilder::with_cert_resolver`] - to send a certificate chosen dynamically
-///
-/// For example:
-///
-/// ```no_run
-/// # #[cfg(feature = "aws_lc_rs")] {
-/// # rustls::crypto::aws_lc_rs::default_provider().install_default();
-/// # use rustls::ServerConfig;
-/// # let certs = vec![];
-/// # let private_key = pki_types::PrivateKeyDer::from(
-/// # pki_types::PrivatePkcs8KeyDer::from(vec![])
-/// # );
-/// ServerConfig::builder()
-/// .with_no_client_auth()
-/// .with_single_cert(certs, private_key)
-/// .expect("bad certificate/key");
-/// # }
-/// ```
-///
-/// # Types
-///
-/// ConfigBuilder uses the [typestate] pattern to ensure at compile time that each required
-/// configuration item is provided exactly once. This is tracked in the `State` type parameter,
-/// which can have these values:
-///
-/// - [`WantsVersions`]
-/// - [`WantsVerifier`]
-/// - [`WantsClientCert`]
-/// - [`WantsServerCert`]
-///
-/// The other type parameter is `Side`, which is either `ServerConfig` or `ClientConfig`
-/// depending on whether the ConfigBuilder was built with [`ServerConfig::builder()`] or
-/// [`ClientConfig::builder()`].
-///
-/// You won't need to write out either of these type parameters explicitly. If you write a
-/// correct chain of configuration calls they will be used automatically. If you write an
-/// incorrect chain of configuration calls you will get an error message from the compiler
-/// mentioning some of these types.
-///
-/// Additionally, ServerConfig and ClientConfig carry a private field containing a
-/// [`CryptoProvider`], from [`ClientConfig::builder_with_provider()`] or
-/// [`ServerConfig::builder_with_provider()`]. This determines which cryptographic backend
-/// is used. The default is [the process-default provider](`CryptoProvider::get_default`).
-///
-/// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html
-/// [typestate]: http://cliffle.com/blog/rust-typestate/
-/// [`ServerConfig`]: crate::ServerConfig
-/// [`ServerConfig::builder`]: crate::ServerConfig::builder
-/// [`ClientConfig`]: crate::ClientConfig
-/// [`ClientConfig::builder()`]: crate::ClientConfig::builder()
-/// [`ServerConfig::builder()`]: crate::ServerConfig::builder()
-/// [`ClientConfig::builder_with_provider()`]: crate::ClientConfig::builder_with_provider()
-/// [`ServerConfig::builder_with_provider()`]: crate::ServerConfig::builder_with_provider()
-/// [`ConfigBuilder<ClientConfig, WantsVerifier>`]: struct.ConfigBuilder.html#impl-3
-/// [`ConfigBuilder<ServerConfig, WantsVerifier>`]: struct.ConfigBuilder.html#impl-6
-/// [`WantsClientCert`]: crate::client::WantsClientCert
-/// [`WantsServerCert`]: crate::server::WantsServerCert
-/// [`CryptoProvider::get_default`]: crate::crypto::CryptoProvider::get_default
-/// [`DangerousClientConfigBuilder::with_custom_certificate_verifier`]: crate::client::danger::DangerousClientConfigBuilder::with_custom_certificate_verifier
-#[derive(Clone)]
-pub struct ConfigBuilder<Side: ConfigSide, State> {
- pub(crate) state: State,
- pub(crate) provider: Arc<CryptoProvider>,
- pub(crate) time_provider: Arc<dyn TimeProvider>,
- pub(crate) side: PhantomData<Side>,
-}
-
-impl<Side: ConfigSide, State> ConfigBuilder<Side, State> {
- /// Return the crypto provider used to construct this builder.
- pub fn crypto_provider(&self) -> &Arc<CryptoProvider> {
- &self.provider
- }
-}
-
-impl<Side: ConfigSide, State: fmt::Debug> fmt::Debug for ConfigBuilder<Side, State> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let side_name = core::any::type_name::<Side>();
- let (ty, _) = side_name
- .split_once('<')
- .unwrap_or((side_name, ""));
- let (_, name) = ty.rsplit_once("::").unwrap_or(("", ty));
-
- f.debug_struct(&format!("ConfigBuilder<{name}, _>",))
- .field("state", &self.state)
- .finish()
- }
-}
-
-/// Config builder state where the caller must supply TLS protocol versions.
-///
-/// For more information, see the [`ConfigBuilder`] documentation.
-#[derive(Clone, Debug)]
-pub struct WantsVersions {}
-
-impl<S: ConfigSide> ConfigBuilder<S, WantsVersions> {
- /// Accept the default protocol versions: both TLS1.2 and TLS1.3 are enabled.
- pub fn with_safe_default_protocol_versions(
- self,
- ) -> Result<ConfigBuilder<S, WantsVerifier>, Error> {
- self.with_protocol_versions(versions::DEFAULT_VERSIONS)
- }
-
- /// Use a specific set of protocol versions.
- pub fn with_protocol_versions(
- self,
- versions: &[&'static versions::SupportedProtocolVersion],
- ) -> Result<ConfigBuilder<S, WantsVerifier>, Error> {
- let mut any_usable_suite = false;
- for suite in &self.provider.cipher_suites {
- if versions.contains(&suite.version()) {
- any_usable_suite = true;
- break;
- }
- }
-
- if !any_usable_suite {
- return Err(Error::General("no usable cipher suites configured".into()));
- }
-
- if self.provider.kx_groups.is_empty() {
- return Err(Error::General("no kx groups configured".into()));
- }
-
- // verifying cipher suites have matching kx groups
- let mut supported_kx_algos = Vec::with_capacity(ALL_KEY_EXCHANGE_ALGORITHMS.len());
- for group in self.provider.kx_groups.iter() {
- let kx = group.name().key_exchange_algorithm();
- if !supported_kx_algos.contains(&kx) {
- supported_kx_algos.push(kx);
- }
- // Small optimization. We don't need to go over other key exchange groups
- // if we already cover all supported key exchange algorithms
- if supported_kx_algos.len() == ALL_KEY_EXCHANGE_ALGORITHMS.len() {
- break;
- }
- }
-
- for cs in self.provider.cipher_suites.iter() {
- let cs_kx = cs.key_exchange_algorithms();
- if cs_kx
- .iter()
- .any(|kx| supported_kx_algos.contains(kx))
- {
- continue;
- }
- let suite_name = cs.common().suite;
- return Err(Error::General(alloc::format!(
- "Ciphersuite {suite_name:?} requires {cs_kx:?} key exchange, but no {cs_kx:?}-compatible \
- key exchange groups were present in `CryptoProvider`'s `kx_groups` field",
- )));
- }
-
- Ok(ConfigBuilder {
- state: WantsVerifier {
- versions: versions::EnabledVersions::new(versions),
- client_ech_mode: None,
- },
- provider: self.provider,
- time_provider: self.time_provider,
- side: self.side,
- })
- }
-}
-
-/// Config builder state where the caller must supply a verifier.
-///
-/// For more information, see the [`ConfigBuilder`] documentation.
-#[derive(Clone, Debug)]
-pub struct WantsVerifier {
- pub(crate) versions: versions::EnabledVersions,
- pub(crate) client_ech_mode: Option<EchMode>,
-}
-
-/// Helper trait to abstract [`ConfigBuilder`] over building a [`ClientConfig`] or [`ServerConfig`].
-///
-/// [`ClientConfig`]: crate::ClientConfig
-/// [`ServerConfig`]: crate::ServerConfig
-pub trait ConfigSide: sealed::Sealed {}
-
-impl ConfigSide for crate::ClientConfig {}
-impl ConfigSide for crate::ServerConfig {}
-
-mod sealed {
- pub trait Sealed {}
- impl Sealed for crate::ClientConfig {}
- impl Sealed for crate::ServerConfig {}
-}
diff --git a/vendor/rustls/src/check.rs b/vendor/rustls/src/check.rs
deleted file mode 100644
index 9875bc8b..00000000
--- a/vendor/rustls/src/check.rs
+++ /dev/null
@@ -1,70 +0,0 @@
-use crate::enums::{ContentType, HandshakeType};
-use crate::error::Error;
-use crate::log::warn;
-use crate::msgs::message::MessagePayload;
-
-/// For a Message $m, and a HandshakePayload enum member $payload_type,
-/// return Ok(payload) if $m is both a handshake message and one that
-/// has the given $payload_type. If not, return Err(rustls::Error) quoting
-/// $handshake_type as the expected handshake type.
-macro_rules! require_handshake_msg(
- ( $m:expr, $handshake_type:path, $payload_type:path ) => (
- match &$m.payload {
- MessagePayload::Handshake { parsed: $crate::msgs::handshake::HandshakeMessagePayload(
- $payload_type(hm),
- ), .. } => Ok(hm),
- payload => Err($crate::check::inappropriate_handshake_message(
- payload,
- &[$crate::ContentType::Handshake],
- &[$handshake_type]))
- }
- )
-);
-
-/// Like require_handshake_msg, but moves the payload out of $m.
-macro_rules! require_handshake_msg_move(
- ( $m:expr, $handshake_type:path, $payload_type:path ) => (
- match $m.payload {
- MessagePayload::Handshake { parsed: $crate::msgs::handshake::HandshakeMessagePayload(
- $payload_type(hm),
- ), .. } => Ok(hm),
- payload =>
- Err($crate::check::inappropriate_handshake_message(
- &payload,
- &[$crate::ContentType::Handshake],
- &[$handshake_type]))
- }
- )
-);
-
-pub(crate) fn inappropriate_message(
- payload: &MessagePayload<'_>,
- content_types: &[ContentType],
-) -> Error {
- warn!(
- "Received a {:?} message while expecting {content_types:?}",
- payload.content_type(),
- );
- Error::InappropriateMessage {
- expect_types: content_types.to_vec(),
- got_type: payload.content_type(),
- }
-}
-
-pub(crate) fn inappropriate_handshake_message(
- payload: &MessagePayload<'_>,
- content_types: &[ContentType],
- handshake_types: &[HandshakeType],
-) -> Error {
- match payload {
- MessagePayload::Handshake { parsed, .. } => {
- let got_type = parsed.0.handshake_type();
- warn!("Received a {got_type:?} handshake message while expecting {handshake_types:?}",);
- Error::InappropriateHandshakeMessage {
- expect_types: handshake_types.to_vec(),
- got_type,
- }
- }
- payload => inappropriate_message(payload, content_types),
- }
-}
diff --git a/vendor/rustls/src/client/builder.rs b/vendor/rustls/src/client/builder.rs
deleted file mode 100644
index b301e750..00000000
--- a/vendor/rustls/src/client/builder.rs
+++ /dev/null
@@ -1,186 +0,0 @@
-use alloc::vec::Vec;
-use core::marker::PhantomData;
-
-use pki_types::{CertificateDer, PrivateKeyDer};
-
-use super::client_conn::Resumption;
-use crate::builder::{ConfigBuilder, WantsVerifier};
-use crate::client::{ClientConfig, EchMode, ResolvesClientCert, handy};
-use crate::error::Error;
-use crate::key_log::NoKeyLog;
-use crate::sign::{CertifiedKey, SingleCertAndKey};
-use crate::sync::Arc;
-use crate::versions::TLS13;
-use crate::webpki::{self, WebPkiServerVerifier};
-use crate::{WantsVersions, compress, verify, versions};
-
-impl ConfigBuilder<ClientConfig, WantsVersions> {
- /// Enable Encrypted Client Hello (ECH) in the given mode.
- ///
- /// This implicitly selects TLS 1.3 as the only supported protocol version to meet the
- /// requirement to support ECH.
- ///
- /// The `ClientConfig` that will be produced by this builder will be specific to the provided
- /// [`crate::client::EchConfig`] and may not be appropriate for all connections made by the program.
- /// In this case the configuration should only be shared by connections intended for domains
- /// that offer the provided [`crate::client::EchConfig`] in their DNS zone.
- pub fn with_ech(
- self,
- mode: EchMode,
- ) -> Result<ConfigBuilder<ClientConfig, WantsVerifier>, Error> {
- let mut res = self.with_protocol_versions(&[&TLS13][..])?;
- res.state.client_ech_mode = Some(mode);
- Ok(res)
- }
-}
-
-impl ConfigBuilder<ClientConfig, WantsVerifier> {
- /// Choose how to verify server certificates.
- ///
- /// Using this function does not configure revocation. If you wish to
- /// configure revocation, instead use:
- ///
- /// ```diff
- /// - .with_root_certificates(root_store)
- /// + .with_webpki_verifier(
- /// + WebPkiServerVerifier::builder_with_provider(root_store, crypto_provider)
- /// + .with_crls(...)
- /// + .build()?
- /// + )
- /// ```
- pub fn with_root_certificates(
- self,
- root_store: impl Into<Arc<webpki::RootCertStore>>,
- ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
- let algorithms = self
- .provider
- .signature_verification_algorithms;
- self.with_webpki_verifier(
- WebPkiServerVerifier::new_without_revocation(root_store, algorithms).into(),
- )
- }
-
- /// Choose how to verify server certificates using a webpki verifier.
- ///
- /// See [`webpki::WebPkiServerVerifier::builder`] and
- /// [`webpki::WebPkiServerVerifier::builder_with_provider`] for more information.
- pub fn with_webpki_verifier(
- self,
- verifier: Arc<WebPkiServerVerifier>,
- ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
- ConfigBuilder {
- state: WantsClientCert {
- versions: self.state.versions,
- verifier,
- client_ech_mode: self.state.client_ech_mode,
- },
- provider: self.provider,
- time_provider: self.time_provider,
- side: PhantomData,
- }
- }
-
- /// Access configuration options whose use is dangerous and requires
- /// extra care.
- pub fn dangerous(self) -> danger::DangerousClientConfigBuilder {
- danger::DangerousClientConfigBuilder { cfg: self }
- }
-}
-
-/// Container for unsafe APIs
-pub(super) mod danger {
- use core::marker::PhantomData;
-
- use crate::client::WantsClientCert;
- use crate::sync::Arc;
- use crate::{ClientConfig, ConfigBuilder, WantsVerifier, verify};
-
- /// Accessor for dangerous configuration options.
- #[derive(Debug)]
- pub struct DangerousClientConfigBuilder {
- /// The underlying ClientConfigBuilder
- pub cfg: ConfigBuilder<ClientConfig, WantsVerifier>,
- }
-
- impl DangerousClientConfigBuilder {
- /// Set a custom certificate verifier.
- pub fn with_custom_certificate_verifier(
- self,
- verifier: Arc<dyn verify::ServerCertVerifier>,
- ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
- ConfigBuilder {
- state: WantsClientCert {
- versions: self.cfg.state.versions,
- verifier,
- client_ech_mode: self.cfg.state.client_ech_mode,
- },
- provider: self.cfg.provider,
- time_provider: self.cfg.time_provider,
- side: PhantomData,
- }
- }
- }
-}
-
-/// A config builder state where the caller needs to supply whether and how to provide a client
-/// certificate.
-///
-/// For more information, see the [`ConfigBuilder`] documentation.
-#[derive(Clone)]
-pub struct WantsClientCert {
- versions: versions::EnabledVersions,
- verifier: Arc<dyn verify::ServerCertVerifier>,
- client_ech_mode: Option<EchMode>,
-}
-
-impl ConfigBuilder<ClientConfig, WantsClientCert> {
- /// Sets a single certificate chain and matching private key for use
- /// in client authentication.
- ///
- /// `cert_chain` is a vector of DER-encoded certificates.
- /// `key_der` is a DER-encoded private key as PKCS#1, PKCS#8, or SEC1. The
- /// `aws-lc-rs` and `ring` [`CryptoProvider`][crate::CryptoProvider]s support
- /// all three encodings, but other `CryptoProviders` may not.
- ///
- /// This function fails if `key_der` is invalid.
- pub fn with_client_auth_cert(
- self,
- cert_chain: Vec<CertificateDer<'static>>,
- key_der: PrivateKeyDer<'static>,
- ) -> Result<ClientConfig, Error> {
- let certified_key = CertifiedKey::from_der(cert_chain, key_der, &self.provider)?;
- Ok(self.with_client_cert_resolver(Arc::new(SingleCertAndKey::from(certified_key))))
- }
-
- /// Do not support client auth.
- pub fn with_no_client_auth(self) -> ClientConfig {
- self.with_client_cert_resolver(Arc::new(handy::FailResolveClientCert {}))
- }
-
- /// Sets a custom [`ResolvesClientCert`].
- pub fn with_client_cert_resolver(
- self,
- client_auth_cert_resolver: Arc<dyn ResolvesClientCert>,
- ) -> ClientConfig {
- ClientConfig {
- provider: self.provider,
- alpn_protocols: Vec::new(),
- resumption: Resumption::default(),
- max_fragment_size: None,
- client_auth_cert_resolver,
- versions: self.state.versions,
- enable_sni: true,
- verifier: self.state.verifier,
- key_log: Arc::new(NoKeyLog {}),
- enable_secret_extraction: false,
- enable_early_data: false,
- #[cfg(feature = "tls12")]
- require_ems: cfg!(feature = "fips"),
- time_provider: self.time_provider,
- cert_compressors: compress::default_cert_compressors().to_vec(),
- cert_compression_cache: Arc::new(compress::CompressionCache::default()),
- cert_decompressors: compress::default_cert_decompressors().to_vec(),
- ech_mode: self.state.client_ech_mode,
- }
- }
-}
diff --git a/vendor/rustls/src/client/client_conn.rs b/vendor/rustls/src/client/client_conn.rs
deleted file mode 100644
index d214c2a1..00000000
--- a/vendor/rustls/src/client/client_conn.rs
+++ /dev/null
@@ -1,1062 +0,0 @@
-use alloc::vec::Vec;
-use core::marker::PhantomData;
-use core::ops::{Deref, DerefMut};
-use core::{fmt, mem};
-
-use pki_types::{ServerName, UnixTime};
-
-use super::handy::NoClientSessionStorage;
-use super::hs::{self, ClientHelloInput};
-#[cfg(feature = "std")]
-use crate::WantsVerifier;
-use crate::builder::ConfigBuilder;
-use crate::client::{EchMode, EchStatus};
-use crate::common_state::{CommonState, Protocol, Side};
-use crate::conn::{ConnectionCore, UnbufferedConnectionCommon};
-use crate::crypto::{CryptoProvider, SupportedKxGroup};
-use crate::enums::{CipherSuite, ProtocolVersion, SignatureScheme};
-use crate::error::Error;
-use crate::kernel::KernelConnection;
-use crate::log::trace;
-use crate::msgs::enums::NamedGroup;
-use crate::msgs::handshake::ClientExtensionsInput;
-use crate::msgs::persist;
-use crate::suites::{ExtractedSecrets, SupportedCipherSuite};
-use crate::sync::Arc;
-#[cfg(feature = "std")]
-use crate::time_provider::DefaultTimeProvider;
-use crate::time_provider::TimeProvider;
-use crate::unbuffered::{EncryptError, TransmitTlsData};
-#[cfg(doc)]
-use crate::{DistinguishedName, crypto};
-use crate::{KeyLog, WantsVersions, compress, sign, verify, versions};
-
-/// A trait for the ability to store client session data, so that sessions
-/// can be resumed in future connections.
-///
-/// Generally all data in this interface should be treated as
-/// **highly sensitive**, containing enough key material to break all security
-/// of the corresponding session.
-///
-/// `set_`, `insert_`, `remove_` and `take_` operations are mutating; this isn't
-/// expressed in the type system to allow implementations freedom in
-/// how to achieve interior mutability. `Mutex` is a common choice.
-pub trait ClientSessionStore: fmt::Debug + Send + Sync {
- /// Remember what `NamedGroup` the given server chose.
- fn set_kx_hint(&self, server_name: ServerName<'static>, group: NamedGroup);
-
- /// This should return the value most recently passed to `set_kx_hint`
- /// for the given `server_name`.
- ///
- /// If `None` is returned, the caller chooses the first configured group,
- /// and an extra round trip might happen if that choice is unsatisfactory
- /// to the server.
- fn kx_hint(&self, server_name: &ServerName<'_>) -> Option<NamedGroup>;
-
- /// Remember a TLS1.2 session.
- ///
- /// At most one of these can be remembered at a time, per `server_name`.
- fn set_tls12_session(
- &self,
- server_name: ServerName<'static>,
- value: persist::Tls12ClientSessionValue,
- );
-
- /// Get the most recently saved TLS1.2 session for `server_name` provided to `set_tls12_session`.
- fn tls12_session(
- &self,
- server_name: &ServerName<'_>,
- ) -> Option<persist::Tls12ClientSessionValue>;
-
- /// Remove and forget any saved TLS1.2 session for `server_name`.
- fn remove_tls12_session(&self, server_name: &ServerName<'static>);
-
- /// Remember a TLS1.3 ticket that might be retrieved later from `take_tls13_ticket`, allowing
- /// resumption of this session.
- ///
- /// This can be called multiple times for a given session, allowing multiple independent tickets
- /// to be valid at once. The number of times this is called is controlled by the server, so
- /// implementations of this trait should apply a reasonable bound of how many items are stored
- /// simultaneously.
- fn insert_tls13_ticket(
- &self,
- server_name: ServerName<'static>,
- value: persist::Tls13ClientSessionValue,
- );
-
- /// Return a TLS1.3 ticket previously provided to `add_tls13_ticket`.
- ///
- /// Implementations of this trait must return each value provided to `add_tls13_ticket` _at most once_.
- fn take_tls13_ticket(
- &self,
- server_name: &ServerName<'static>,
- ) -> Option<persist::Tls13ClientSessionValue>;
-}
-
-/// A trait for the ability to choose a certificate chain and
-/// private key for the purposes of client authentication.
-pub trait ResolvesClientCert: fmt::Debug + Send + Sync {
- /// Resolve a client certificate chain/private key to use as the client's
- /// identity.
- ///
- /// `root_hint_subjects` is an optional list of certificate authority
- /// subject distinguished names that the client can use to help
- /// decide on a client certificate the server is likely to accept. If
- /// the list is empty, the client should send whatever certificate it
- /// has. The hints are expected to be DER-encoded X.500 distinguished names,
- /// per [RFC 5280 A.1]. See [`DistinguishedName`] for more information
- /// on decoding with external crates like `x509-parser`.
- ///
- /// `sigschemes` is the list of the [`SignatureScheme`]s the server
- /// supports.
- ///
- /// Return `None` to continue the handshake without any client
- /// authentication. The server may reject the handshake later
- /// if it requires authentication.
- ///
- /// [RFC 5280 A.1]: https://www.rfc-editor.org/rfc/rfc5280#appendix-A.1
- fn resolve(
- &self,
- root_hint_subjects: &[&[u8]],
- sigschemes: &[SignatureScheme],
- ) -> Option<Arc<sign::CertifiedKey>>;
-
- /// Return true if the client only supports raw public keys.
- ///
- /// See [RFC 7250](https://www.rfc-editor.org/rfc/rfc7250).
- fn only_raw_public_keys(&self) -> bool {
- false
- }
-
- /// Return true if any certificates at all are available.
- fn has_certs(&self) -> bool;
-}
-
-/// Common configuration for (typically) all connections made by a program.
-///
-/// Making one of these is cheap, though one of the inputs may be expensive: gathering trust roots
-/// from the operating system to add to the [`RootCertStore`] passed to `with_root_certificates()`
-/// (the rustls-native-certs crate is often used for this) may take on the order of a few hundred
-/// milliseconds.
-///
-/// These must be created via the [`ClientConfig::builder()`] or [`ClientConfig::builder_with_provider()`]
-/// function.
-///
-/// Note that using [`ConfigBuilder<ClientConfig, WantsVersions>::with_ech()`] will produce a common
-/// configuration specific to the provided [`crate::client::EchConfig`] that may not be appropriate
-/// for all connections made by the program. In this case the configuration should only be shared
-/// by connections intended for domains that offer the provided [`crate::client::EchConfig`] in
-/// their DNS zone.
-///
-/// # Defaults
-///
-/// * [`ClientConfig::max_fragment_size`]: the default is `None` (meaning 16kB).
-/// * [`ClientConfig::resumption`]: supports resumption with up to 256 server names, using session
-/// ids or tickets, with a max of eight tickets per server.
-/// * [`ClientConfig::alpn_protocols`]: the default is empty -- no ALPN protocol is negotiated.
-/// * [`ClientConfig::key_log`]: key material is not logged.
-/// * [`ClientConfig::cert_decompressors`]: depends on the crate features, see [`compress::default_cert_decompressors()`].
-/// * [`ClientConfig::cert_compressors`]: depends on the crate features, see [`compress::default_cert_compressors()`].
-/// * [`ClientConfig::cert_compression_cache`]: caches the most recently used 4 compressions
-///
-/// [`RootCertStore`]: crate::RootCertStore
-#[derive(Clone, Debug)]
-pub struct ClientConfig {
- /// Which ALPN protocols we include in our client hello.
- /// If empty, no ALPN extension is sent.
- pub alpn_protocols: Vec<Vec<u8>>,
-
- /// How and when the client can resume a previous session.
- ///
- /// # Sharing `resumption` between `ClientConfig`s
- /// In a program using many `ClientConfig`s it may improve resumption rates
- /// (which has a significant impact on connection performance) if those
- /// configs share a single `Resumption`.
- ///
- /// However, resumption is only allowed between two `ClientConfig`s if their
- /// `client_auth_cert_resolver` (ie, potential client authentication credentials)
- /// and `verifier` (ie, server certificate verification settings) are
- /// the same (according to `Arc::ptr_eq`).
- ///
- /// To illustrate, imagine two `ClientConfig`s `A` and `B`. `A` fully validates
- /// the server certificate, `B` does not. If `A` and `B` shared a resumption store,
- /// it would be possible for a session originated by `B` to be inserted into the
- /// store, and then resumed by `A`. This would give a false impression to the user
- /// of `A` that the server certificate is fully validated.
- pub resumption: Resumption,
-
- /// The maximum size of plaintext input to be emitted in a single TLS record.
- /// A value of None is equivalent to the [TLS maximum] of 16 kB.
- ///
- /// rustls enforces an arbitrary minimum of 32 bytes for this field.
- /// Out of range values are reported as errors from [ClientConnection::new].
- ///
- /// Setting this value to a little less than the TCP MSS may improve latency
- /// for stream-y workloads.
- ///
- /// [TLS maximum]: https://datatracker.ietf.org/doc/html/rfc8446#section-5.1
- /// [ClientConnection::new]: crate::client::ClientConnection::new
- pub max_fragment_size: Option<usize>,
-
- /// How to decide what client auth certificate/keys to use.
- pub client_auth_cert_resolver: Arc<dyn ResolvesClientCert>,
-
- /// Whether to send the Server Name Indication (SNI) extension
- /// during the client handshake.
- ///
- /// The default is true.
- pub enable_sni: bool,
-
- /// How to output key material for debugging. The default
- /// does nothing.
- pub key_log: Arc<dyn KeyLog>,
-
- /// Allows traffic secrets to be extracted after the handshake,
- /// e.g. for kTLS setup.
- pub enable_secret_extraction: bool,
-
- /// Whether to send data on the first flight ("early data") in
- /// TLS 1.3 handshakes.
- ///
- /// The default is false.
- pub enable_early_data: bool,
-
- /// If set to `true`, requires the server to support the extended
- /// master secret extraction method defined in [RFC 7627].
- ///
- /// The default is `true` if the `fips` crate feature is enabled,
- /// `false` otherwise.
- ///
- /// It must be set to `true` to meet FIPS requirement mentioned in section
- /// **D.Q Transition of the TLS 1.2 KDF to Support the Extended Master
- /// Secret** from [FIPS 140-3 IG.pdf].
- ///
- /// [RFC 7627]: https://datatracker.ietf.org/doc/html/rfc7627
- /// [FIPS 140-3 IG.pdf]: https://csrc.nist.gov/csrc/media/Projects/cryptographic-module-validation-program/documents/fips%20140-3/FIPS%20140-3%20IG.pdf
- #[cfg(feature = "tls12")]
- pub require_ems: bool,
-
- /// Provides the current system time
- pub time_provider: Arc<dyn TimeProvider>,
-
- /// Source of randomness and other crypto.
- pub(super) provider: Arc<CryptoProvider>,
-
- /// Supported versions, in no particular order. The default
- /// is all supported versions.
- pub(super) versions: versions::EnabledVersions,
-
- /// How to verify the server certificate chain.
- pub(super) verifier: Arc<dyn verify::ServerCertVerifier>,
-
- /// How to decompress the server's certificate chain.
- ///
- /// If this is non-empty, the [RFC8779] certificate compression
- /// extension is offered, and any compressed certificates are
- /// transparently decompressed during the handshake.
- ///
- /// This only applies to TLS1.3 connections. It is ignored for
- /// TLS1.2 connections.
- ///
- /// [RFC8779]: https://datatracker.ietf.org/doc/rfc8879/
- pub cert_decompressors: Vec<&'static dyn compress::CertDecompressor>,
-
- /// How to compress the client's certificate chain.
- ///
- /// If a server supports this extension, and advertises support
- /// for one of the compression algorithms included here, the
- /// client certificate will be compressed according to [RFC8779].
- ///
- /// This only applies to TLS1.3 connections. It is ignored for
- /// TLS1.2 connections.
- ///
- /// [RFC8779]: https://datatracker.ietf.org/doc/rfc8879/
- pub cert_compressors: Vec<&'static dyn compress::CertCompressor>,
-
- /// Caching for compressed certificates.
- ///
- /// This is optional: [`compress::CompressionCache::Disabled`] gives
- /// a cache that does no caching.
- pub cert_compression_cache: Arc<compress::CompressionCache>,
-
- /// How to offer Encrypted Client Hello (ECH). The default is to not offer ECH.
- pub(super) ech_mode: Option<EchMode>,
-}
-
-impl ClientConfig {
- /// Create a builder for a client configuration with
- /// [the process-default `CryptoProvider`][CryptoProvider#using-the-per-process-default-cryptoprovider]
- /// and safe protocol version defaults.
- ///
- /// For more information, see the [`ConfigBuilder`] documentation.
- #[cfg(feature = "std")]
- pub fn builder() -> ConfigBuilder<Self, WantsVerifier> {
- Self::builder_with_protocol_versions(versions::DEFAULT_VERSIONS)
- }
-
- /// Create a builder for a client configuration with
- /// [the process-default `CryptoProvider`][CryptoProvider#using-the-per-process-default-cryptoprovider]
- /// and the provided protocol versions.
- ///
- /// Panics if
- /// - the supported versions are not compatible with the provider (eg.
- /// the combination of ciphersuites supported by the provider and supported
- /// versions lead to zero cipher suites being usable),
- /// - if a `CryptoProvider` cannot be resolved using a combination of
- /// the crate features and process default.
- ///
- /// For more information, see the [`ConfigBuilder`] documentation.
- #[cfg(feature = "std")]
- pub fn builder_with_protocol_versions(
- versions: &[&'static versions::SupportedProtocolVersion],
- ) -> ConfigBuilder<Self, WantsVerifier> {
- // Safety assumptions:
- // 1. that the provider has been installed (explicitly or implicitly)
- // 2. that the process-level default provider is usable with the supplied protocol versions.
- Self::builder_with_provider(
- CryptoProvider::get_default_or_install_from_crate_features().clone(),
- )
- .with_protocol_versions(versions)
- .unwrap()
- }
-
- /// Create a builder for a client configuration with a specific [`CryptoProvider`].
- ///
- /// This will use the provider's configured ciphersuites. You must additionally choose
- /// which protocol versions to enable, using `with_protocol_versions` or
- /// `with_safe_default_protocol_versions` and handling the `Result` in case a protocol
- /// version is not supported by the provider's ciphersuites.
- ///
- /// For more information, see the [`ConfigBuilder`] documentation.
- #[cfg(feature = "std")]
- pub fn builder_with_provider(
- provider: Arc<CryptoProvider>,
- ) -> ConfigBuilder<Self, WantsVersions> {
- ConfigBuilder {
- state: WantsVersions {},
- provider,
- time_provider: Arc::new(DefaultTimeProvider),
- side: PhantomData,
- }
- }
- /// Create a builder for a client configuration with no default implementation details.
- ///
- /// This API must be used by `no_std` users.
- ///
- /// You must provide a specific [`TimeProvider`].
- ///
- /// You must provide a specific [`CryptoProvider`].
- ///
- /// This will use the provider's configured ciphersuites. You must additionally choose
- /// which protocol versions to enable, using `with_protocol_versions` or
- /// `with_safe_default_protocol_versions` and handling the `Result` in case a protocol
- /// version is not supported by the provider's ciphersuites.
- ///
- /// For more information, see the [`ConfigBuilder`] documentation.
- pub fn builder_with_details(
- provider: Arc<CryptoProvider>,
- time_provider: Arc<dyn TimeProvider>,
- ) -> ConfigBuilder<Self, WantsVersions> {
- ConfigBuilder {
- state: WantsVersions {},
- provider,
- time_provider,
- side: PhantomData,
- }
- }
-
- /// Return true if connections made with this `ClientConfig` will
- /// operate in FIPS mode.
- ///
- /// This is different from [`CryptoProvider::fips()`]: [`CryptoProvider::fips()`]
- /// is concerned only with cryptography, whereas this _also_ covers TLS-level
- /// configuration that NIST recommends, as well as ECH HPKE suites if applicable.
- pub fn fips(&self) -> bool {
- let mut is_fips = self.provider.fips();
-
- #[cfg(feature = "tls12")]
- {
- is_fips = is_fips && self.require_ems
- }
-
- if let Some(ech_mode) = &self.ech_mode {
- is_fips = is_fips && ech_mode.fips();
- }
-
- is_fips
- }
-
- /// Return the crypto provider used to construct this client configuration.
- pub fn crypto_provider(&self) -> &Arc<CryptoProvider> {
- &self.provider
- }
-
- /// Access configuration options whose use is dangerous and requires
- /// extra care.
- pub fn dangerous(&mut self) -> danger::DangerousClientConfig<'_> {
- danger::DangerousClientConfig { cfg: self }
- }
-
- pub(super) fn needs_key_share(&self) -> bool {
- self.supports_version(ProtocolVersion::TLSv1_3)
- }
-
- /// We support a given TLS version if it's quoted in the configured
- /// versions *and* at least one ciphersuite for this version is
- /// also configured.
- pub(crate) fn supports_version(&self, v: ProtocolVersion) -> bool {
- self.versions.contains(v)
- && self
- .provider
- .cipher_suites
- .iter()
- .any(|cs| cs.version().version == v)
- }
-
- #[cfg(feature = "std")]
- pub(crate) fn supports_protocol(&self, proto: Protocol) -> bool {
- self.provider
- .cipher_suites
- .iter()
- .any(|cs| cs.usable_for_protocol(proto))
- }
-
- pub(super) fn find_cipher_suite(&self, suite: CipherSuite) -> Option<SupportedCipherSuite> {
- self.provider
- .cipher_suites
- .iter()
- .copied()
- .find(|&scs| scs.suite() == suite)
- }
-
- pub(super) fn find_kx_group(
- &self,
- group: NamedGroup,
- version: ProtocolVersion,
- ) -> Option<&'static dyn SupportedKxGroup> {
- self.provider
- .kx_groups
- .iter()
- .copied()
- .find(|skxg| skxg.usable_for_version(version) && skxg.name() == group)
- }
-
- pub(super) fn current_time(&self) -> Result<UnixTime, Error> {
- self.time_provider
- .current_time()
- .ok_or(Error::FailedToGetCurrentTime)
- }
-}
-
-/// Configuration for how/when a client is allowed to resume a previous session.
-#[derive(Clone, Debug)]
-pub struct Resumption {
- /// How we store session data or tickets. The default is to use an in-memory
- /// [super::handy::ClientSessionMemoryCache].
- pub(super) store: Arc<dyn ClientSessionStore>,
-
- /// What mechanism is used for resuming a TLS 1.2 session.
- pub(super) tls12_resumption: Tls12Resumption,
-}
-
-impl Resumption {
- /// Create a new `Resumption` that stores data for the given number of sessions in memory.
- ///
- /// This is the default `Resumption` choice, and enables resuming a TLS 1.2 session with
- /// a session id or RFC 5077 ticket.
- #[cfg(feature = "std")]
- pub fn in_memory_sessions(num: usize) -> Self {
- Self {
- store: Arc::new(super::handy::ClientSessionMemoryCache::new(num)),
- tls12_resumption: Tls12Resumption::SessionIdOrTickets,
- }
- }
-
- /// Use a custom [`ClientSessionStore`] implementation to store sessions.
- ///
- /// By default, enables resuming a TLS 1.2 session with a session id or RFC 5077 ticket.
- pub fn store(store: Arc<dyn ClientSessionStore>) -> Self {
- Self {
- store,
- tls12_resumption: Tls12Resumption::SessionIdOrTickets,
- }
- }
-
- /// Disable all use of session resumption.
- pub fn disabled() -> Self {
- Self {
- store: Arc::new(NoClientSessionStorage),
- tls12_resumption: Tls12Resumption::Disabled,
- }
- }
-
- /// Configure whether TLS 1.2 sessions may be resumed, and by what mechanism.
- ///
- /// This is meaningless if you've disabled resumption entirely, which is the case in `no-std`
- /// contexts.
- pub fn tls12_resumption(mut self, tls12: Tls12Resumption) -> Self {
- self.tls12_resumption = tls12;
- self
- }
-}
-
-impl Default for Resumption {
- /// Create an in-memory session store resumption with up to 256 server names, allowing
- /// a TLS 1.2 session to resume with a session id or RFC 5077 ticket.
- fn default() -> Self {
- #[cfg(feature = "std")]
- let ret = Self::in_memory_sessions(256);
-
- #[cfg(not(feature = "std"))]
- let ret = Self::disabled();
-
- ret
- }
-}
-
-/// What mechanisms to support for resuming a TLS 1.2 session.
-#[derive(Clone, Copy, Debug, PartialEq)]
-pub enum Tls12Resumption {
- /// Disable 1.2 resumption.
- Disabled,
- /// Support 1.2 resumption using session ids only.
- SessionIdOnly,
- /// Support 1.2 resumption using session ids or RFC 5077 tickets.
- ///
- /// See[^1] for why you might like to disable RFC 5077 by instead choosing the `SessionIdOnly`
- /// option. Note that TLS 1.3 tickets do not have those issues.
- ///
- /// [^1]: <https://words.filippo.io/we-need-to-talk-about-session-tickets/>
- SessionIdOrTickets,
-}
-
-/// Container for unsafe APIs
-pub(super) mod danger {
- use super::ClientConfig;
- use super::verify::ServerCertVerifier;
- use crate::sync::Arc;
-
- /// Accessor for dangerous configuration options.
- #[derive(Debug)]
- pub struct DangerousClientConfig<'a> {
- /// The underlying ClientConfig
- pub cfg: &'a mut ClientConfig,
- }
-
- impl DangerousClientConfig<'_> {
- /// Overrides the default `ServerCertVerifier` with something else.
- pub fn set_certificate_verifier(&mut self, verifier: Arc<dyn ServerCertVerifier>) {
- self.cfg.verifier = verifier;
- }
- }
-}
-
-#[derive(Debug, PartialEq)]
-enum EarlyDataState {
- Disabled,
- Ready,
- Accepted,
- AcceptedFinished,
- Rejected,
-}
-
-#[derive(Debug)]
-pub(super) struct EarlyData {
- state: EarlyDataState,
- left: usize,
-}
-
-impl EarlyData {
- fn new() -> Self {
- Self {
- left: 0,
- state: EarlyDataState::Disabled,
- }
- }
-
- pub(super) fn is_enabled(&self) -> bool {
- matches!(self.state, EarlyDataState::Ready | EarlyDataState::Accepted)
- }
-
- #[cfg(feature = "std")]
- fn is_accepted(&self) -> bool {
- matches!(
- self.state,
- EarlyDataState::Accepted | EarlyDataState::AcceptedFinished
- )
- }
-
- pub(super) fn enable(&mut self, max_data: usize) {
- assert_eq!(self.state, EarlyDataState::Disabled);
- self.state = EarlyDataState::Ready;
- self.left = max_data;
- }
-
- pub(super) fn rejected(&mut self) {
- trace!("EarlyData rejected");
- self.state = EarlyDataState::Rejected;
- }
-
- pub(super) fn accepted(&mut self) {
- trace!("EarlyData accepted");
- assert_eq!(self.state, EarlyDataState::Ready);
- self.state = EarlyDataState::Accepted;
- }
-
- pub(super) fn finished(&mut self) {
- trace!("EarlyData finished");
- self.state = match self.state {
- EarlyDataState::Accepted => EarlyDataState::AcceptedFinished,
- _ => panic!("bad EarlyData state"),
- }
- }
-
- fn check_write_opt(&mut self, sz: usize) -> Option<usize> {
- match self.state {
- EarlyDataState::Disabled => unreachable!(),
- EarlyDataState::Ready | EarlyDataState::Accepted => {
- let take = if self.left < sz {
- mem::replace(&mut self.left, 0)
- } else {
- self.left -= sz;
- sz
- };
-
- Some(take)
- }
- EarlyDataState::Rejected | EarlyDataState::AcceptedFinished => None,
- }
- }
-}
-
-#[cfg(feature = "std")]
-mod connection {
- use alloc::vec::Vec;
- use core::fmt;
- use core::ops::{Deref, DerefMut};
- use std::io;
-
- use pki_types::ServerName;
-
- use super::{ClientConnectionData, ClientExtensionsInput};
- use crate::ClientConfig;
- use crate::client::EchStatus;
- use crate::common_state::Protocol;
- use crate::conn::{ConnectionCommon, ConnectionCore};
- use crate::error::Error;
- use crate::suites::ExtractedSecrets;
- use crate::sync::Arc;
-
- /// Stub that implements io::Write and dispatches to `write_early_data`.
- pub struct WriteEarlyData<'a> {
- sess: &'a mut ClientConnection,
- }
-
- impl<'a> WriteEarlyData<'a> {
- fn new(sess: &'a mut ClientConnection) -> Self {
- WriteEarlyData { sess }
- }
-
- /// How many bytes you may send. Writes will become short
- /// once this reaches zero.
- pub fn bytes_left(&self) -> usize {
- self.sess
- .inner
- .core
- .data
- .early_data
- .bytes_left()
- }
- }
-
- impl io::Write for WriteEarlyData<'_> {
- fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- self.sess.write_early_data(buf)
- }
-
- fn flush(&mut self) -> io::Result<()> {
- Ok(())
- }
- }
-
- impl super::EarlyData {
- fn check_write(&mut self, sz: usize) -> io::Result<usize> {
- self.check_write_opt(sz)
- .ok_or_else(|| io::Error::from(io::ErrorKind::InvalidInput))
- }
-
- fn bytes_left(&self) -> usize {
- self.left
- }
- }
-
- /// This represents a single TLS client connection.
- pub struct ClientConnection {
- inner: ConnectionCommon<ClientConnectionData>,
- }
-
- impl fmt::Debug for ClientConnection {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("ClientConnection")
- .finish()
- }
- }
-
- impl ClientConnection {
- /// Make a new ClientConnection. `config` controls how
- /// we behave in the TLS protocol, `name` is the
- /// name of the server we want to talk to.
- pub fn new(config: Arc<ClientConfig>, name: ServerName<'static>) -> Result<Self, Error> {
- Self::new_with_alpn(config.clone(), name, config.alpn_protocols.clone())
- }
-
- /// Make a new ClientConnection with custom ALPN protocols.
- pub fn new_with_alpn(
- config: Arc<ClientConfig>,
- name: ServerName<'static>,
- alpn_protocols: Vec<Vec<u8>>,
- ) -> Result<Self, Error> {
- Ok(Self {
- inner: ConnectionCommon::from(ConnectionCore::for_client(
- config,
- name,
- ClientExtensionsInput::from_alpn(alpn_protocols),
- Protocol::Tcp,
- )?),
- })
- }
- /// Returns an `io::Write` implementer you can write bytes to
- /// to send TLS1.3 early data (a.k.a. "0-RTT data") to the server.
- ///
- /// This returns None in many circumstances when the capability to
- /// send early data is not available, including but not limited to:
- ///
- /// - The server hasn't been talked to previously.
- /// - The server does not support resumption.
- /// - The server does not support early data.
- /// - The resumption data for the server has expired.
- ///
- /// The server specifies a maximum amount of early data. You can
- /// learn this limit through the returned object, and writes through
- /// it will process only this many bytes.
- ///
- /// The server can choose not to accept any sent early data --
- /// in this case the data is lost but the connection continues. You
- /// can tell this happened using `is_early_data_accepted`.
- pub fn early_data(&mut self) -> Option<WriteEarlyData<'_>> {
- if self
- .inner
- .core
- .data
- .early_data
- .is_enabled()
- {
- Some(WriteEarlyData::new(self))
- } else {
- None
- }
- }
-
- /// Returns True if the server signalled it will process early data.
- ///
- /// If you sent early data and this returns false at the end of the
- /// handshake then the server will not process the data. This
- /// is not an error, but you may wish to resend the data.
- pub fn is_early_data_accepted(&self) -> bool {
- self.inner.core.is_early_data_accepted()
- }
-
- /// Extract secrets, so they can be used when configuring kTLS, for example.
- /// Should be used with care as it exposes secret key material.
- pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
- self.inner.dangerous_extract_secrets()
- }
-
- /// Return the connection's Encrypted Client Hello (ECH) status.
- pub fn ech_status(&self) -> EchStatus {
- self.inner.core.data.ech_status
- }
-
- /// Returns the number of TLS1.3 tickets that have been received.
- pub fn tls13_tickets_received(&self) -> u32 {
- self.inner.tls13_tickets_received
- }
-
- /// Return true if the connection was made with a `ClientConfig` that is FIPS compatible.
- ///
- /// This is different from [`crate::crypto::CryptoProvider::fips()`]:
- /// it is concerned only with cryptography, whereas this _also_ covers TLS-level
- /// configuration that NIST recommends, as well as ECH HPKE suites if applicable.
- pub fn fips(&self) -> bool {
- self.inner.core.common_state.fips
- }
-
- fn write_early_data(&mut self, data: &[u8]) -> io::Result<usize> {
- self.inner
- .core
- .data
- .early_data
- .check_write(data.len())
- .map(|sz| {
- self.inner
- .send_early_plaintext(&data[..sz])
- })
- }
- }
-
- impl Deref for ClientConnection {
- type Target = ConnectionCommon<ClientConnectionData>;
-
- fn deref(&self) -> &Self::Target {
- &self.inner
- }
- }
-
- impl DerefMut for ClientConnection {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.inner
- }
- }
-
- #[doc(hidden)]
- impl<'a> TryFrom<&'a mut crate::Connection> for &'a mut ClientConnection {
- type Error = ();
-
- fn try_from(value: &'a mut crate::Connection) -> Result<Self, Self::Error> {
- use crate::Connection::*;
- match value {
- Client(conn) => Ok(conn),
- Server(_) => Err(()),
- }
- }
- }
-
- impl From<ClientConnection> for crate::Connection {
- fn from(conn: ClientConnection) -> Self {
- Self::Client(conn)
- }
- }
-}
-#[cfg(feature = "std")]
-pub use connection::{ClientConnection, WriteEarlyData};
-
-impl ConnectionCore<ClientConnectionData> {
- pub(crate) fn for_client(
- config: Arc<ClientConfig>,
- name: ServerName<'static>,
- extra_exts: ClientExtensionsInput<'static>,
- proto: Protocol,
- ) -> Result<Self, Error> {
- let mut common_state = CommonState::new(Side::Client);
- common_state.set_max_fragment_size(config.max_fragment_size)?;
- common_state.protocol = proto;
- common_state.enable_secret_extraction = config.enable_secret_extraction;
- common_state.fips = config.fips();
- let mut data = ClientConnectionData::new();
-
- let mut cx = hs::ClientContext {
- common: &mut common_state,
- data: &mut data,
- // `start_handshake` won't produce plaintext
- sendable_plaintext: None,
- };
-
- let input = ClientHelloInput::new(name, &extra_exts, &mut cx, config)?;
- let state = input.start_handshake(extra_exts, &mut cx)?;
- Ok(Self::new(state, data, common_state))
- }
-
- #[cfg(feature = "std")]
- pub(crate) fn is_early_data_accepted(&self) -> bool {
- self.data.early_data.is_accepted()
- }
-}
-
-/// Unbuffered version of `ClientConnection`
-///
-/// See the [`crate::unbuffered`] module docs for more details
-pub struct UnbufferedClientConnection {
- inner: UnbufferedConnectionCommon<ClientConnectionData>,
-}
-
-impl UnbufferedClientConnection {
- /// Make a new ClientConnection. `config` controls how we behave in the TLS protocol, `name` is
- /// the name of the server we want to talk to.
- pub fn new(config: Arc<ClientConfig>, name: ServerName<'static>) -> Result<Self, Error> {
- Self::new_with_extensions(
- config.clone(),
- name,
- ClientExtensionsInput::from_alpn(config.alpn_protocols.clone()),
- )
- }
-
- /// Make a new UnbufferedClientConnection with custom ALPN protocols.
- pub fn new_with_alpn(
- config: Arc<ClientConfig>,
- name: ServerName<'static>,
- alpn_protocols: Vec<Vec<u8>>,
- ) -> Result<Self, Error> {
- Self::new_with_extensions(
- config,
- name,
- ClientExtensionsInput::from_alpn(alpn_protocols),
- )
- }
-
- fn new_with_extensions(
- config: Arc<ClientConfig>,
- name: ServerName<'static>,
- extensions: ClientExtensionsInput<'static>,
- ) -> Result<Self, Error> {
- Ok(Self {
- inner: UnbufferedConnectionCommon::from(ConnectionCore::for_client(
- config,
- name,
- extensions,
- Protocol::Tcp,
- )?),
- })
- }
-
- /// Extract secrets, so they can be used when configuring kTLS, for example.
- /// Should be used with care as it exposes secret key material.
- #[deprecated = "dangerous_extract_secrets() does not support session tickets or \
- key updates, use dangerous_into_kernel_connection() instead"]
- pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
- self.inner.dangerous_extract_secrets()
- }
-
- /// Extract secrets and a [`KernelConnection`] object.
- ///
- /// This allows you use rustls to manage keys and then manage encryption and
- /// decryption yourself (e.g. for kTLS).
- ///
- /// Should be used with care as it exposes secret key material.
- ///
- /// See the [`crate::kernel`] documentations for details on prerequisites
- /// for calling this method.
- pub fn dangerous_into_kernel_connection(
- self,
- ) -> Result<(ExtractedSecrets, KernelConnection<ClientConnectionData>), Error> {
- self.inner
- .core
- .dangerous_into_kernel_connection()
- }
-
- /// Returns the number of TLS1.3 tickets that have been received.
- pub fn tls13_tickets_received(&self) -> u32 {
- self.inner.tls13_tickets_received
- }
-}
-
-impl Deref for UnbufferedClientConnection {
- type Target = UnbufferedConnectionCommon<ClientConnectionData>;
-
- fn deref(&self) -> &Self::Target {
- &self.inner
- }
-}
-
-impl DerefMut for UnbufferedClientConnection {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.inner
- }
-}
-
-impl TransmitTlsData<'_, ClientConnectionData> {
- /// returns an adapter that allows encrypting early (RTT-0) data before transmitting the
- /// already encoded TLS data
- ///
- /// IF allowed by the protocol
- pub fn may_encrypt_early_data(&mut self) -> Option<MayEncryptEarlyData<'_>> {
- if self
- .conn
- .core
- .data
- .early_data
- .is_enabled()
- {
- Some(MayEncryptEarlyData { conn: self.conn })
- } else {
- None
- }
- }
-}
-
-/// Allows encrypting early (RTT-0) data
-pub struct MayEncryptEarlyData<'c> {
- conn: &'c mut UnbufferedConnectionCommon<ClientConnectionData>,
-}
-
-impl MayEncryptEarlyData<'_> {
- /// Encrypts `application_data` into the `outgoing_tls` buffer
- ///
- /// returns the number of bytes that were written into `outgoing_tls`, or an error if
- /// the provided buffer was too small. In the error case, `outgoing_tls` is not modified
- pub fn encrypt(
- &mut self,
- early_data: &[u8],
- outgoing_tls: &mut [u8],
- ) -> Result<usize, EarlyDataError> {
- let Some(allowed) = self
- .conn
- .core
- .data
- .early_data
- .check_write_opt(early_data.len())
- else {
- return Err(EarlyDataError::ExceededAllowedEarlyData);
- };
-
- self.conn
- .core
- .common_state
- .write_plaintext(early_data[..allowed].into(), outgoing_tls)
- .map_err(|e| e.into())
- }
-}
-
-/// Errors that may arise when encrypting early (RTT-0) data
-#[derive(Debug)]
-pub enum EarlyDataError {
- /// Cannot encrypt more early data due to imposed limits
- ExceededAllowedEarlyData,
- /// Encryption error
- Encrypt(EncryptError),
-}
-
-impl From<EncryptError> for EarlyDataError {
- fn from(v: EncryptError) -> Self {
- Self::Encrypt(v)
- }
-}
-
-impl fmt::Display for EarlyDataError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::ExceededAllowedEarlyData => f.write_str("cannot send any more early data"),
- Self::Encrypt(e) => fmt::Display::fmt(e, f),
- }
- }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for EarlyDataError {}
-
-/// State associated with a client connection.
-#[derive(Debug)]
-pub struct ClientConnectionData {
- pub(super) early_data: EarlyData,
- pub(super) ech_status: EchStatus,
-}
-
-impl ClientConnectionData {
- fn new() -> Self {
- Self {
- early_data: EarlyData::new(),
- ech_status: EchStatus::NotOffered,
- }
- }
-}
-
-impl crate::conn::SideData for ClientConnectionData {}
diff --git a/vendor/rustls/src/client/common.rs b/vendor/rustls/src/client/common.rs
deleted file mode 100644
index 9afa0c34..00000000
--- a/vendor/rustls/src/client/common.rs
+++ /dev/null
@@ -1,119 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec::Vec;
-
-use super::ResolvesClientCert;
-use crate::log::{debug, trace};
-use crate::msgs::enums::ExtensionType;
-use crate::msgs::handshake::{CertificateChain, DistinguishedName, ProtocolName, ServerExtensions};
-use crate::sync::Arc;
-use crate::{SignatureScheme, compress, sign};
-
-#[derive(Debug)]
-pub(super) struct ServerCertDetails<'a> {
- pub(super) cert_chain: CertificateChain<'a>,
- pub(super) ocsp_response: Vec<u8>,
-}
-
-impl<'a> ServerCertDetails<'a> {
- pub(super) fn new(cert_chain: CertificateChain<'a>, ocsp_response: Vec<u8>) -> Self {
- Self {
- cert_chain,
- ocsp_response,
- }
- }
-
- pub(super) fn into_owned(self) -> ServerCertDetails<'static> {
- let Self {
- cert_chain,
- ocsp_response,
- } = self;
- ServerCertDetails {
- cert_chain: cert_chain.into_owned(),
- ocsp_response,
- }
- }
-}
-
-pub(super) struct ClientHelloDetails {
- pub(super) alpn_protocols: Vec<ProtocolName>,
- pub(super) sent_extensions: Vec<ExtensionType>,
- pub(super) extension_order_seed: u16,
- pub(super) offered_cert_compression: bool,
-}
-
-impl ClientHelloDetails {
- pub(super) fn new(alpn_protocols: Vec<ProtocolName>, extension_order_seed: u16) -> Self {
- Self {
- alpn_protocols,
- sent_extensions: Vec::new(),
- extension_order_seed,
- offered_cert_compression: false,
- }
- }
-
- pub(super) fn server_sent_unsolicited_extensions(
- &self,
- received_exts: &ServerExtensions<'_>,
- allowed_unsolicited: &[ExtensionType],
- ) -> bool {
- let mut extensions = received_exts.collect_used();
- extensions.extend(
- received_exts
- .unknown_extensions
- .iter()
- .map(|ext| ExtensionType::from(*ext)),
- );
- for ext_type in extensions {
- if !self.sent_extensions.contains(&ext_type) && !allowed_unsolicited.contains(&ext_type)
- {
- trace!("Unsolicited extension {ext_type:?}");
- return true;
- }
- }
-
- false
- }
-}
-
-pub(super) enum ClientAuthDetails {
- /// Send an empty `Certificate` and no `CertificateVerify`.
- Empty { auth_context_tls13: Option<Vec<u8>> },
- /// Send a non-empty `Certificate` and a `CertificateVerify`.
- Verify {
- certkey: Arc<sign::CertifiedKey>,
- signer: Box<dyn sign::Signer>,
- auth_context_tls13: Option<Vec<u8>>,
- compressor: Option<&'static dyn compress::CertCompressor>,
- },
-}
-
-impl ClientAuthDetails {
- pub(super) fn resolve(
- resolver: &dyn ResolvesClientCert,
- canames: Option<&[DistinguishedName]>,
- sigschemes: &[SignatureScheme],
- auth_context_tls13: Option<Vec<u8>>,
- compressor: Option<&'static dyn compress::CertCompressor>,
- ) -> Self {
- let acceptable_issuers = canames
- .unwrap_or_default()
- .iter()
- .map(|p| p.as_ref())
- .collect::<Vec<&[u8]>>();
-
- if let Some(certkey) = resolver.resolve(&acceptable_issuers, sigschemes) {
- if let Some(signer) = certkey.key.choose_scheme(sigschemes) {
- debug!("Attempting client auth");
- return Self::Verify {
- certkey,
- signer,
- auth_context_tls13,
- compressor,
- };
- }
- }
-
- debug!("Client auth requested but no cert/sigscheme available");
- Self::Empty { auth_context_tls13 }
- }
-}
diff --git a/vendor/rustls/src/client/ech.rs b/vendor/rustls/src/client/ech.rs
deleted file mode 100644
index 616ebbfc..00000000
--- a/vendor/rustls/src/client/ech.rs
+++ /dev/null
@@ -1,899 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec;
-use alloc::vec::Vec;
-
-use pki_types::{DnsName, EchConfigListBytes, ServerName};
-use subtle::ConstantTimeEq;
-
-use crate::CipherSuite::TLS_EMPTY_RENEGOTIATION_INFO_SCSV;
-use crate::client::tls13;
-use crate::crypto::SecureRandom;
-use crate::crypto::hash::Hash;
-use crate::crypto::hpke::{EncapsulatedSecret, Hpke, HpkePublicKey, HpkeSealer, HpkeSuite};
-use crate::hash_hs::{HandshakeHash, HandshakeHashBuffer};
-use crate::log::{debug, trace, warn};
-use crate::msgs::base::{Payload, PayloadU16};
-use crate::msgs::codec::{Codec, Reader};
-use crate::msgs::enums::{ExtensionType, HpkeKem};
-use crate::msgs::handshake::{
- ClientExtensions, ClientHelloPayload, EchConfigContents, EchConfigPayload, Encoding,
- EncryptedClientHello, EncryptedClientHelloOuter, HandshakeMessagePayload, HandshakePayload,
- HelloRetryRequest, HpkeKeyConfig, HpkeSymmetricCipherSuite, PresharedKeyBinder,
- PresharedKeyOffer, Random, ServerHelloPayload, ServerNamePayload,
-};
-use crate::msgs::message::{Message, MessagePayload};
-use crate::msgs::persist;
-use crate::msgs::persist::Retrieved;
-use crate::tls13::key_schedule::{
- KeyScheduleEarly, KeyScheduleHandshakeStart, server_ech_hrr_confirmation_secret,
-};
-use crate::{
- AlertDescription, ClientConfig, CommonState, EncryptedClientHelloError, Error,
- PeerIncompatible, PeerMisbehaved, ProtocolVersion, Tls13CipherSuite,
-};
-
-/// Controls how Encrypted Client Hello (ECH) is used in a client handshake.
-#[derive(Clone, Debug)]
-pub enum EchMode {
- /// ECH is enabled and the ClientHello will be encrypted based on the provided
- /// configuration.
- Enable(EchConfig),
-
- /// No ECH configuration is available but the client should act as though it were.
- ///
- /// This is an anti-ossification measure, sometimes referred to as "GREASE"[^0].
- /// [^0]: <https://www.rfc-editor.org/rfc/rfc8701>
- Grease(EchGreaseConfig),
-}
-
-impl EchMode {
- /// Returns true if the ECH mode will use a FIPS approved HPKE suite.
- pub fn fips(&self) -> bool {
- match self {
- Self::Enable(ech_config) => ech_config.suite.fips(),
- Self::Grease(grease_config) => grease_config.suite.fips(),
- }
- }
-}
-
-impl From<EchConfig> for EchMode {
- fn from(config: EchConfig) -> Self {
- Self::Enable(config)
- }
-}
-
-impl From<EchGreaseConfig> for EchMode {
- fn from(config: EchGreaseConfig) -> Self {
- Self::Grease(config)
- }
-}
-
-/// Configuration for performing encrypted client hello.
-///
-/// Note: differs from the protocol-encoded EchConfig (`EchConfigMsg`).
-#[derive(Clone, Debug)]
-pub struct EchConfig {
- /// The selected EchConfig.
- pub(crate) config: EchConfigPayload,
-
- /// An HPKE instance corresponding to a suite from the `config` we have selected as
- /// a compatible choice.
- pub(crate) suite: &'static dyn Hpke,
-}
-
-impl EchConfig {
- /// Construct an EchConfig by selecting a ECH config from the provided bytes that is compatible
- /// with one of the given HPKE suites.
- ///
- /// The config list bytes should be sourced from a DNS-over-HTTPS lookup resolving the `HTTPS`
- /// resource record for the host name of the server you wish to connect via ECH,
- /// and extracting the ECH configuration from the `ech` parameter. The extracted bytes should
- /// be base64 decoded to yield the `EchConfigListBytes` you provide to rustls.
- ///
- /// One of the provided ECH configurations must be compatible with the HPKE provider's supported
- /// suites or an error will be returned.
- ///
- /// See the [`ech-client.rs`] example for a complete example of fetching ECH configs from DNS.
- ///
- /// [`ech-client.rs`]: https://github.com/rustls/rustls/blob/main/examples/src/bin/ech-client.rs
- pub fn new(
- ech_config_list: EchConfigListBytes<'_>,
- hpke_suites: &[&'static dyn Hpke],
- ) -> Result<Self, Error> {
- let ech_configs = Vec::<EchConfigPayload>::read(&mut Reader::init(&ech_config_list))
- .map_err(|_| {
- Error::InvalidEncryptedClientHello(EncryptedClientHelloError::InvalidConfigList)
- })?;
-
- // Note: we name the index var _i because if the log feature is disabled
- // it is unused.
- #[cfg_attr(not(feature = "logging"), allow(clippy::unused_enumerate_index))]
- for (_i, config) in ech_configs.iter().enumerate() {
- let contents = match config {
- EchConfigPayload::V18(contents) => contents,
- EchConfigPayload::Unknown {
- version: _version, ..
- } => {
- warn!(
- "ECH config {} has unsupported version {:?}",
- _i + 1,
- _version
- );
- continue; // Unsupported version.
- }
- };
-
- if contents.has_unknown_mandatory_extension() || contents.has_duplicate_extension() {
- warn!("ECH config has duplicate, or unknown mandatory extensions: {contents:?}",);
- continue; // Unsupported, or malformed extensions.
- }
-
- let key_config = &contents.key_config;
- for cipher_suite in &key_config.symmetric_cipher_suites {
- if cipher_suite.aead_id.tag_len().is_none() {
- continue; // Unsupported EXPORT_ONLY AEAD cipher suite.
- }
-
- let suite = HpkeSuite {
- kem: key_config.kem_id,
- sym: *cipher_suite,
- };
- if let Some(hpke) = hpke_suites
- .iter()
- .find(|hpke| hpke.suite() == suite)
- {
- debug!(
- "selected ECH config ID {:?} suite {:?} public_name {:?}",
- key_config.config_id, suite, contents.public_name
- );
- return Ok(Self {
- config: config.clone(),
- suite: *hpke,
- });
- }
- }
- }
-
- Err(EncryptedClientHelloError::NoCompatibleConfig.into())
- }
-
- pub(super) fn state(
- &self,
- server_name: ServerName<'static>,
- config: &ClientConfig,
- ) -> Result<EchState, Error> {
- EchState::new(
- self,
- server_name.clone(),
- config
- .client_auth_cert_resolver
- .has_certs(),
- config.provider.secure_random,
- config.enable_sni,
- )
- }
-
- /// Compute the HPKE `SetupBaseS` `info` parameter for this ECH configuration.
- ///
- /// See <https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-17#section-6.1>.
- pub(crate) fn hpke_info(&self) -> Vec<u8> {
- let mut info = Vec::with_capacity(128);
- // "tls ech" || 0x00 || ECHConfig
- info.extend_from_slice(b"tls ech\0");
- self.config.encode(&mut info);
- info
- }
-}
-
-/// Configuration for GREASE Encrypted Client Hello.
-#[derive(Clone, Debug)]
-pub struct EchGreaseConfig {
- pub(crate) suite: &'static dyn Hpke,
- pub(crate) placeholder_key: HpkePublicKey,
-}
-
-impl EchGreaseConfig {
- /// Construct a GREASE ECH configuration.
- ///
- /// This configuration is used when the client wishes to offer ECH to prevent ossification,
- /// but doesn't have a real ECH configuration to use for the remote server. In this case
- /// a placeholder or "GREASE"[^0] extension is used.
- ///
- /// Returns an error if the HPKE provider does not support the given suite.
- ///
- /// [^0]: <https://www.rfc-editor.org/rfc/rfc8701>
- pub fn new(suite: &'static dyn Hpke, placeholder_key: HpkePublicKey) -> Self {
- Self {
- suite,
- placeholder_key,
- }
- }
-
- /// Build a GREASE ECH extension based on the placeholder configuration.
- ///
- /// See <https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#name-grease-ech> for
- /// more information.
- pub(crate) fn grease_ext(
- &self,
- secure_random: &'static dyn SecureRandom,
- inner_name: ServerName<'static>,
- outer_hello: &ClientHelloPayload,
- ) -> Result<EncryptedClientHello, Error> {
- trace!("Preparing GREASE ECH extension");
-
- // Pick a random config id.
- let mut config_id: [u8; 1] = [0; 1];
- secure_random.fill(&mut config_id[..])?;
-
- let suite = self.suite.suite();
-
- // Construct a dummy ECH state - we don't have a real ECH config from a server since
- // this is for GREASE.
- let mut grease_state = EchState::new(
- &EchConfig {
- config: EchConfigPayload::V18(EchConfigContents {
- key_config: HpkeKeyConfig {
- config_id: config_id[0],
- kem_id: HpkeKem::DHKEM_P256_HKDF_SHA256,
- public_key: PayloadU16::new(self.placeholder_key.0.clone()),
- symmetric_cipher_suites: vec![suite.sym],
- },
- maximum_name_length: 0,
- public_name: DnsName::try_from("filler").unwrap(),
- extensions: Vec::default(),
- }),
- suite: self.suite,
- },
- inner_name,
- false,
- secure_random,
- false, // Does not matter if we enable/disable SNI here. Inner hello is not used.
- )?;
-
- // Construct an inner hello using the outer hello - this allows us to know the size of
- // dummy payload we should use for the GREASE extension.
- let encoded_inner_hello = grease_state.encode_inner_hello(outer_hello, None, &None);
-
- // Generate a payload of random data equivalent in length to a real inner hello.
- let payload_len = encoded_inner_hello.len()
- + suite
- .sym
- .aead_id
- .tag_len()
- // Safety: we have confirmed the AEAD is supported when building the config. All
- // supported AEADs have a tag length.
- .unwrap();
- let mut payload = vec![0; payload_len];
- secure_random.fill(&mut payload)?;
-
- // Return the GREASE extension.
- Ok(EncryptedClientHello::Outer(EncryptedClientHelloOuter {
- cipher_suite: suite.sym,
- config_id: config_id[0],
- enc: PayloadU16::new(grease_state.enc.0),
- payload: PayloadU16::new(payload),
- }))
- }
-}
-
-/// An enum representing ECH offer status.
-#[derive(Debug, Clone, Copy, Eq, PartialEq)]
-pub enum EchStatus {
- /// ECH was not offered - it is a normal TLS handshake.
- NotOffered,
- /// GREASE ECH was sent. This is not considered offering ECH.
- Grease,
- /// ECH was offered but we do not yet know whether the offer was accepted or rejected.
- Offered,
- /// ECH was offered and the server accepted.
- Accepted,
- /// ECH was offered and the server rejected.
- Rejected,
-}
-
-/// Contextual data for a TLS client handshake that has offered encrypted client hello (ECH).
-pub(crate) struct EchState {
- // The public DNS name from the ECH configuration we've chosen - this is included as the SNI
- // value for the "outer" client hello. It can only be a DnsName, not an IP address.
- pub(crate) outer_name: DnsName<'static>,
- // If we're resuming in the inner hello, this is the early key schedule to use for encrypting
- // early data if the ECH offer is accepted.
- pub(crate) early_data_key_schedule: Option<KeyScheduleEarly>,
- // A random value we use for the inner hello.
- pub(crate) inner_hello_random: Random,
- // A transcript buffer maintained for the inner hello. Once ECH is confirmed we switch to
- // using this transcript for the handshake.
- pub(crate) inner_hello_transcript: HandshakeHashBuffer,
- // A source of secure random data.
- secure_random: &'static dyn SecureRandom,
- // An HPKE sealer context that can be used for encrypting ECH data.
- sender: Box<dyn HpkeSealer>,
- // The ID of the ECH configuration we've chosen - this is included in the outer ECH extension.
- config_id: u8,
- // The private server name we'll use for the inner protected hello.
- inner_name: ServerName<'static>,
- // The advertised maximum name length from the ECH configuration we've chosen - this is used
- // for padding calculations.
- maximum_name_length: u8,
- // A supported symmetric cipher suite from the ECH configuration we've chosen - this is
- // included in the outer ECH extension.
- cipher_suite: HpkeSymmetricCipherSuite,
- // A secret encapsulated to the public key of the remote server. This is included in the
- // outer ECH extension for non-retry outer hello messages.
- enc: EncapsulatedSecret,
- // Whether the inner client hello should contain a server name indication (SNI) extension.
- enable_sni: bool,
- // The extensions sent in the inner hello.
- sent_extensions: Vec<ExtensionType>,
-}
-
-impl EchState {
- pub(crate) fn new(
- config: &EchConfig,
- inner_name: ServerName<'static>,
- client_auth_enabled: bool,
- secure_random: &'static dyn SecureRandom,
- enable_sni: bool,
- ) -> Result<Self, Error> {
- let EchConfigPayload::V18(config_contents) = &config.config else {
- // the public EchConfig::new() constructor ensures we only have supported
- // configurations.
- unreachable!("ECH config version mismatch");
- };
- let key_config = &config_contents.key_config;
-
- // Encapsulate a secret for the server's public key, and set up a sender context
- // we can use to seal messages.
- let (enc, sender) = config.suite.setup_sealer(
- &config.hpke_info(),
- &HpkePublicKey(key_config.public_key.0.clone()),
- )?;
-
- // Start a new transcript buffer for the inner hello.
- let mut inner_hello_transcript = HandshakeHashBuffer::new();
- if client_auth_enabled {
- inner_hello_transcript.set_client_auth_enabled();
- }
-
- Ok(Self {
- secure_random,
- sender,
- config_id: key_config.config_id,
- inner_name,
- outer_name: config_contents.public_name.clone(),
- maximum_name_length: config_contents.maximum_name_length,
- cipher_suite: config.suite.suite().sym,
- enc,
- inner_hello_random: Random::new(secure_random)?,
- inner_hello_transcript,
- early_data_key_schedule: None,
- enable_sni,
- sent_extensions: Vec::new(),
- })
- }
-
- /// Construct a ClientHelloPayload offering ECH.
- ///
- /// An outer hello, with a protected inner hello for the `inner_name` will be returned, and the
- /// ECH context will be updated to reflect the inner hello that was offered.
- ///
- /// If `retry_req` is `Some`, then the outer hello will be constructed for a hello retry request.
- ///
- /// If `resuming` is `Some`, then the inner hello will be constructed for a resumption handshake.
- pub(crate) fn ech_hello(
- &mut self,
- mut outer_hello: ClientHelloPayload,
- retry_req: Option<&HelloRetryRequest>,
- resuming: &Option<Retrieved<&persist::Tls13ClientSessionValue>>,
- ) -> Result<ClientHelloPayload, Error> {
- trace!(
- "Preparing ECH offer {}",
- if retry_req.is_some() { "for retry" } else { "" }
- );
-
- // Construct the encoded inner hello and update the transcript.
- let encoded_inner_hello = self.encode_inner_hello(&outer_hello, retry_req, resuming);
-
- // Complete the ClientHelloOuterAAD with an ech extension, the payload should be a placeholder
- // of size L, all zeroes. L == length of encrypting encoded client hello inner w/ the selected
- // HPKE AEAD. (sum of plaintext + tag length, typically).
- let payload_len = encoded_inner_hello.len()
- + self
- .cipher_suite
- .aead_id
- .tag_len()
- // Safety: we've already verified this AEAD is supported when loading the config
- // that was used to create the ECH context. All supported AEADs have a tag length.
- .unwrap();
-
- // Outer hello's created in response to a hello retry request omit the enc value.
- let enc = match retry_req.is_some() {
- true => Vec::default(),
- false => self.enc.0.clone(),
- };
-
- fn outer_hello_ext(ctx: &EchState, enc: Vec<u8>, payload: Vec<u8>) -> EncryptedClientHello {
- EncryptedClientHello::Outer(EncryptedClientHelloOuter {
- cipher_suite: ctx.cipher_suite,
- config_id: ctx.config_id,
- enc: PayloadU16::new(enc),
- payload: PayloadU16::new(payload),
- })
- }
-
- // The outer handshake is not permitted to resume a session. If we're resuming in the
- // inner handshake we remove the PSK extension from the outer hello, replacing it
- // with a GREASE PSK to implement the "ClientHello Malleability Mitigation" mentioned
- // in 10.12.3.
- if let Some(psk_offer) = outer_hello.preshared_key_offer.as_mut() {
- self.grease_psk(psk_offer)?;
- }
-
- // To compute the encoded AAD we add a placeholder extension with an empty payload.
- outer_hello.encrypted_client_hello =
- Some(outer_hello_ext(self, enc.clone(), vec![0; payload_len]));
-
- // Next we compute the proper extension payload.
- let payload = self
- .sender
- .seal(&outer_hello.get_encoding(), &encoded_inner_hello)?;
-
- // And then we replace the placeholder extension with the real one.
- outer_hello.encrypted_client_hello = Some(outer_hello_ext(self, enc, payload));
-
- Ok(outer_hello)
- }
-
- /// Confirm whether an ECH offer was accepted based on examining the server hello.
- pub(crate) fn confirm_acceptance(
- self,
- ks: &mut KeyScheduleHandshakeStart,
- server_hello: &ServerHelloPayload,
- server_hello_encoded: &Payload<'_>,
- hash: &'static dyn Hash,
- ) -> Result<Option<EchAccepted>, Error> {
- // Start the inner transcript hash now that we know the hash algorithm to use.
- let inner_transcript = self
- .inner_hello_transcript
- .start_hash(hash);
-
- // Fork the transcript that we've started with the inner hello to use for a confirmation step.
- // We need to preserve the original inner_transcript to use if this confirmation succeeds.
- let mut confirmation_transcript = inner_transcript.clone();
-
- // Add the server hello confirmation - this is computed by altering the received
- // encoding rather than reencoding it.
- confirmation_transcript
- .add_message(&Self::server_hello_conf(server_hello, server_hello_encoded));
-
- // Derive a confirmation secret from the inner hello random and the confirmation transcript.
- let derived = ks.server_ech_confirmation_secret(
- self.inner_hello_random.0.as_ref(),
- confirmation_transcript.current_hash(),
- );
-
- // Check that first 8 digits of the derived secret match the last 8 digits of the original
- // server random. This match signals that the server accepted the ECH offer.
- // Indexing safety: Random is [0; 32] by construction.
-
- match ConstantTimeEq::ct_eq(derived.as_ref(), server_hello.random.0[24..].as_ref()).into() {
- true => {
- trace!("ECH accepted by server");
- Ok(Some(EchAccepted {
- transcript: inner_transcript,
- random: self.inner_hello_random,
- sent_extensions: self.sent_extensions,
- }))
- }
- false => {
- trace!("ECH rejected by server");
- Ok(None)
- }
- }
- }
-
- pub(crate) fn confirm_hrr_acceptance(
- &self,
- hrr: &HelloRetryRequest,
- cs: &Tls13CipherSuite,
- common: &mut CommonState,
- ) -> Result<bool, Error> {
- // The client checks for the "encrypted_client_hello" extension.
- let ech_conf = match &hrr.encrypted_client_hello {
- // If none is found, the server has implicitly rejected ECH.
- None => return Ok(false),
- // Otherwise, if it has a length other than 8, the client aborts the
- // handshake with a "decode_error" alert.
- Some(ech_conf) if ech_conf.bytes().len() != 8 => {
- return Err({
- common.send_fatal_alert(
- AlertDescription::DecodeError,
- PeerMisbehaved::IllegalHelloRetryRequestWithInvalidEch,
- )
- });
- }
- Some(ech_conf) => ech_conf,
- };
-
- // Otherwise the client computes hrr_accept_confirmation as described in Section
- // 7.2.1
- let confirmation_transcript = self.inner_hello_transcript.clone();
- let mut confirmation_transcript =
- confirmation_transcript.start_hash(cs.common.hash_provider);
- confirmation_transcript.rollup_for_hrr();
- confirmation_transcript.add_message(&Self::hello_retry_request_conf(hrr));
-
- let derived = server_ech_hrr_confirmation_secret(
- cs.hkdf_provider,
- &self.inner_hello_random.0,
- confirmation_transcript.current_hash(),
- );
-
- match ConstantTimeEq::ct_eq(derived.as_ref(), ech_conf.bytes()).into() {
- true => {
- trace!("ECH accepted by server in hello retry request");
- Ok(true)
- }
- false => {
- trace!("ECH rejected by server in hello retry request");
- Ok(false)
- }
- }
- }
-
- /// Update the ECH context inner hello transcript based on a received hello retry request message.
- ///
- /// This will start the in-progress transcript using the given `hash`, convert it into an HRR
- /// buffer, and then add the hello retry message `m`.
- pub(crate) fn transcript_hrr_update(&mut self, hash: &'static dyn Hash, m: &Message<'_>) {
- trace!("Updating ECH inner transcript for HRR");
-
- let inner_transcript = self
- .inner_hello_transcript
- .clone()
- .start_hash(hash);
-
- let mut inner_transcript_buffer = inner_transcript.into_hrr_buffer();
- inner_transcript_buffer.add_message(m);
- self.inner_hello_transcript = inner_transcript_buffer;
- }
-
- // 5.1 "Encoding the ClientHelloInner"
- fn encode_inner_hello(
- &mut self,
- outer_hello: &ClientHelloPayload,
- retryreq: Option<&HelloRetryRequest>,
- resuming: &Option<Retrieved<&persist::Tls13ClientSessionValue>>,
- ) -> Vec<u8> {
- // Start building an inner hello using the outer_hello as a template.
- let mut inner_hello = ClientHelloPayload {
- // Some information is copied over as-is.
- client_version: outer_hello.client_version,
- session_id: outer_hello.session_id,
- compression_methods: outer_hello.compression_methods.clone(),
-
- // We will build up the included extensions ourselves.
- extensions: Box::new(ClientExtensions::default()),
-
- // Set the inner hello random to the one we generated when creating the ECH state.
- // We hold on to the inner_hello_random in the ECH state to use later for confirming
- // whether ECH was accepted or not.
- random: self.inner_hello_random,
-
- // We remove the empty renegotiation info SCSV from the outer hello's ciphersuite.
- // Similar to the TLS 1.2 specific extensions we will filter out, this is seen as a
- // TLS 1.2 only feature by bogo.
- cipher_suites: outer_hello
- .cipher_suites
- .iter()
- .filter(|cs| **cs != TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
- .cloned()
- .collect(),
- };
-
- inner_hello.order_seed = outer_hello.order_seed;
-
- // The inner hello will always have an inner variant of the ECH extension added.
- // See Section 6.1 rule 4.
- inner_hello.encrypted_client_hello = Some(EncryptedClientHello::Inner);
-
- let inner_sni = match &self.inner_name {
- // The inner hello only gets a SNI value if enable_sni is true and the inner name
- // is a domain name (not an IP address).
- ServerName::DnsName(dns_name) if self.enable_sni => Some(dns_name),
- _ => None,
- };
-
- // Now we consider each of the outer hello's extensions - we can either:
- // 1. Omit the extension if it isn't appropriate (e.g. is a TLS 1.2 extension).
- // 2. Add the extension to the inner hello as-is.
- // 3. Compress the extension, by collecting it into a list of to-be-compressed
- // extensions we'll handle separately.
- let outer_extensions = outer_hello.used_extensions_in_encoding_order();
- let mut compressed_exts = Vec::with_capacity(outer_extensions.len());
- for ext in outer_extensions {
- // Some outer hello extensions are only useful in the context where a TLS 1.3
- // connection allows TLS 1.2. This isn't the case for ECH so we skip adding them
- // to the inner hello.
- if matches!(
- ext,
- ExtensionType::ExtendedMasterSecret
- | ExtensionType::SessionTicket
- | ExtensionType::ECPointFormats
- ) {
- continue;
- }
-
- if ext == ExtensionType::ServerName {
- // We may want to replace the outer hello SNI with our own inner hello specific SNI.
- if let Some(sni_value) = inner_sni {
- inner_hello.server_name = Some(ServerNamePayload::from(sni_value));
- }
- // We don't want to add, or compress, the SNI from the outer hello.
- continue;
- }
-
- // Compressed extensions need to be put aside to include in one contiguous block.
- // Uncompressed extensions get added directly to the inner hello.
- if ext.ech_compress() {
- compressed_exts.push(ext);
- }
-
- inner_hello.clone_one(outer_hello, ext);
- }
-
- // We've added all the uncompressed extensions. Now we need to add the contiguous
- // block of to-be-compressed extensions.
- inner_hello.contiguous_extensions = compressed_exts.clone();
-
- // Note which extensions we're sending in the inner hello. This may differ from
- // the outer hello (e.g. the inner hello may omit SNI while the outer hello will
- // always have the ECH cover name in SNI).
- self.sent_extensions = inner_hello.collect_used();
-
- // If we're resuming, we need to update the PSK binder in the inner hello.
- if let Some(resuming) = resuming.as_ref() {
- let mut chp = HandshakeMessagePayload(HandshakePayload::ClientHello(inner_hello));
-
- // Retain the early key schedule we get from processing the binder.
- self.early_data_key_schedule = Some(tls13::fill_in_psk_binder(
- resuming,
- &self.inner_hello_transcript,
- &mut chp,
- ));
-
- // fill_in_psk_binder works on an owned HandshakeMessagePayload, so we need to
- // extract our inner hello back out of it to retain ownership.
- inner_hello = match chp.0 {
- HandshakePayload::ClientHello(chp) => chp,
- // Safety: we construct the HMP above and know its type unconditionally.
- _ => unreachable!(),
- };
- }
-
- trace!("ECH Inner Hello: {inner_hello:#?}");
-
- // Encode the inner hello according to the rules required for ECH. This differs
- // from the standard encoding in several ways. Notably this is where we will
- // replace the block of contiguous to-be-compressed extensions with a marker.
- let mut encoded_hello = inner_hello.ech_inner_encoding(compressed_exts);
-
- // Calculate padding
- // max_name_len = L
- let max_name_len = self.maximum_name_length;
- let max_name_len = if max_name_len > 0 { max_name_len } else { 255 };
-
- let padding_len = match &self.inner_name {
- ServerName::DnsName(name) => {
- // name.len() = D
- // max(0, L - D)
- core::cmp::max(
- 0,
- max_name_len.saturating_sub(name.as_ref().len() as u8) as usize,
- )
- }
- _ => {
- // L + 9
- // "This is the length of a "server_name" extension with an L-byte name."
- // We widen to usize here to avoid overflowing u8 + u8.
- max_name_len as usize + 9
- }
- };
-
- // Let L be the length of the EncodedClientHelloInner with all the padding computed so far
- // Let N = 31 - ((L - 1) % 32) and add N bytes of padding.
- let padding_len = 31 - ((encoded_hello.len() + padding_len - 1) % 32);
- encoded_hello.extend(vec![0; padding_len]);
-
- // Construct the inner hello message that will be used for the transcript.
- let inner_hello_msg = Message {
- version: match retryreq {
- // <https://datatracker.ietf.org/doc/html/rfc8446#section-5.1>:
- // "This value MUST be set to 0x0303 for all records generated
- // by a TLS 1.3 implementation ..."
- Some(_) => ProtocolVersion::TLSv1_2,
- // "... other than an initial ClientHello (i.e., one not
- // generated after a HelloRetryRequest), where it MAY also be
- // 0x0301 for compatibility purposes"
- //
- // (retryreq == None means we're in the "initial ClientHello" case)
- None => ProtocolVersion::TLSv1_0,
- },
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::ClientHello(inner_hello),
- )),
- };
-
- // Update the inner transcript buffer with the inner hello message.
- self.inner_hello_transcript
- .add_message(&inner_hello_msg);
-
- encoded_hello
- }
-
- // See https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#name-grease-psk
- fn grease_psk(&self, psk_offer: &mut PresharedKeyOffer) -> Result<(), Error> {
- for ident in psk_offer.identities.iter_mut() {
- // "For each PSK identity advertised in the ClientHelloInner, the
- // client generates a random PSK identity with the same length."
- self.secure_random
- .fill(&mut ident.identity.0)?;
- // "It also generates a random, 32-bit, unsigned integer to use as
- // the obfuscated_ticket_age."
- let mut ticket_age = [0_u8; 4];
- self.secure_random
- .fill(&mut ticket_age)?;
- ident.obfuscated_ticket_age = u32::from_be_bytes(ticket_age);
- }
-
- // "Likewise, for each inner PSK binder, the client generates a random string
- // of the same length."
- psk_offer.binders = psk_offer
- .binders
- .iter()
- .map(|old_binder| {
- // We can't access the wrapped binder PresharedKeyBinder's PayloadU8 mutably,
- // so we construct new PresharedKeyBinder's from scratch with the same length.
- let mut new_binder = vec![0; old_binder.as_ref().len()];
- self.secure_random
- .fill(&mut new_binder)?;
- Ok::<PresharedKeyBinder, Error>(PresharedKeyBinder::from(new_binder))
- })
- .collect::<Result<_, _>>()?;
- Ok(())
- }
-
- fn server_hello_conf(
- server_hello: &ServerHelloPayload,
- server_hello_encoded: &Payload<'_>,
- ) -> Message<'static> {
- // The confirmation is computed over the server hello, which has had
- // its `random` field altered to zero the final 8 bytes.
- //
- // nb. we don't require that we can round-trip a `ServerHelloPayload`, to
- // allow for efficiency in its in-memory representation. That means
- // we operate here on the received encoding, as the confirmation needs
- // to be computed on that.
- let mut encoded = server_hello_encoded.clone().into_vec();
- encoded[SERVER_HELLO_ECH_CONFIRMATION_SPAN].fill(0x00);
-
- Message {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::Handshake {
- encoded: Payload::Owned(encoded),
- parsed: HandshakeMessagePayload(HandshakePayload::ServerHello(
- server_hello.clone(),
- )),
- },
- }
- }
-
- fn hello_retry_request_conf(retry_req: &HelloRetryRequest) -> Message<'_> {
- Self::ech_conf_message(HandshakeMessagePayload(
- HandshakePayload::HelloRetryRequest(retry_req.clone()),
- ))
- }
-
- fn ech_conf_message(hmp: HandshakeMessagePayload<'_>) -> Message<'_> {
- let mut hmp_encoded = Vec::new();
- hmp.payload_encode(&mut hmp_encoded, Encoding::EchConfirmation);
- Message {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::Handshake {
- encoded: Payload::new(hmp_encoded),
- parsed: hmp,
- },
- }
- }
-}
-
-/// The last eight bytes of the ServerHello's random, taken from a Handshake message containing it.
-///
-/// This has:
-/// - a HandshakeType (1 byte),
-/// - an exterior length (3 bytes),
-/// - the legacy_version (2 bytes), and
-/// - the balance of the random field (24 bytes).
-const SERVER_HELLO_ECH_CONFIRMATION_SPAN: core::ops::Range<usize> =
- (1 + 3 + 2 + 24)..(1 + 3 + 2 + 32);
-
-/// Returned from EchState::check_acceptance when the server has accepted the ECH offer.
-///
-/// Holds the state required to continue the handshake with the inner hello from the ECH offer.
-pub(crate) struct EchAccepted {
- pub(crate) transcript: HandshakeHash,
- pub(crate) random: Random,
- pub(crate) sent_extensions: Vec<ExtensionType>,
-}
-
-pub(crate) fn fatal_alert_required(
- retry_configs: Option<Vec<EchConfigPayload>>,
- common: &mut CommonState,
-) -> Error {
- common.send_fatal_alert(
- AlertDescription::EncryptedClientHelloRequired,
- PeerIncompatible::ServerRejectedEncryptedClientHello(retry_configs),
- )
-}
-
-#[cfg(test)]
-mod tests {
- use crate::enums::CipherSuite;
- use crate::msgs::handshake::{Random, ServerExtensions, SessionId};
-
- use super::*;
-
- #[test]
- fn server_hello_conf_alters_server_hello_random() {
- let server_hello = ServerHelloPayload {
- legacy_version: ProtocolVersion::TLSv1_2,
- random: Random([0xffu8; 32]),
- session_id: SessionId::empty(),
- cipher_suite: CipherSuite::TLS13_AES_256_GCM_SHA384,
- compression_method: crate::msgs::enums::Compression::Null,
- extensions: Box::new(ServerExtensions::default()),
- };
- let message = Message {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::ServerHello(server_hello.clone()),
- )),
- };
- let Message {
- payload:
- MessagePayload::Handshake {
- encoded: server_hello_encoded_before,
- ..
- },
- ..
- } = &message
- else {
- unreachable!("ServerHello is a handshake message");
- };
-
- let message = EchState::server_hello_conf(&server_hello, server_hello_encoded_before);
-
- let Message {
- payload:
- MessagePayload::Handshake {
- encoded: server_hello_encoded_after,
- ..
- },
- ..
- } = &message
- else {
- unreachable!("ServerHello is a handshake message");
- };
-
- assert_eq!(
- std::format!("{server_hello_encoded_before:x?}"),
- "020000280303ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001302000000",
- "beforehand eight bytes at end of Random should be 0xff here ^^^^^^^^^^^^^^^^ "
- );
- assert_eq!(
- std::format!("{server_hello_encoded_after:x?}"),
- "020000280303ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001302000000",
- " afterwards those bytes are zeroed ^^^^^^^^^^^^^^^^ "
- );
- }
-}
diff --git a/vendor/rustls/src/client/handy.rs b/vendor/rustls/src/client/handy.rs
deleted file mode 100644
index 3ad3073b..00000000
--- a/vendor/rustls/src/client/handy.rs
+++ /dev/null
@@ -1,390 +0,0 @@
-use pki_types::ServerName;
-
-use crate::enums::SignatureScheme;
-use crate::msgs::persist;
-use crate::sync::Arc;
-use crate::{NamedGroup, client, sign};
-
-/// An implementer of `ClientSessionStore` which does nothing.
-#[derive(Debug)]
-pub(super) struct NoClientSessionStorage;
-
-impl client::ClientSessionStore for NoClientSessionStorage {
- fn set_kx_hint(&self, _: ServerName<'static>, _: NamedGroup) {}
-
- fn kx_hint(&self, _: &ServerName<'_>) -> Option<NamedGroup> {
- None
- }
-
- fn set_tls12_session(&self, _: ServerName<'static>, _: persist::Tls12ClientSessionValue) {}
-
- fn tls12_session(&self, _: &ServerName<'_>) -> Option<persist::Tls12ClientSessionValue> {
- None
- }
-
- fn remove_tls12_session(&self, _: &ServerName<'_>) {}
-
- fn insert_tls13_ticket(&self, _: ServerName<'static>, _: persist::Tls13ClientSessionValue) {}
-
- fn take_tls13_ticket(&self, _: &ServerName<'_>) -> Option<persist::Tls13ClientSessionValue> {
- None
- }
-}
-
-#[cfg(any(feature = "std", feature = "hashbrown"))]
-mod cache {
- use alloc::collections::VecDeque;
- use core::fmt;
-
- use pki_types::ServerName;
-
- use crate::lock::Mutex;
- use crate::msgs::persist;
- use crate::{NamedGroup, limited_cache};
-
- const MAX_TLS13_TICKETS_PER_SERVER: usize = 8;
-
- struct ServerData {
- kx_hint: Option<NamedGroup>,
-
- // Zero or one TLS1.2 sessions.
- #[cfg(feature = "tls12")]
- tls12: Option<persist::Tls12ClientSessionValue>,
-
- // Up to MAX_TLS13_TICKETS_PER_SERVER TLS1.3 tickets, oldest first.
- tls13: VecDeque<persist::Tls13ClientSessionValue>,
- }
-
- impl Default for ServerData {
- fn default() -> Self {
- Self {
- kx_hint: None,
- #[cfg(feature = "tls12")]
- tls12: None,
- tls13: VecDeque::with_capacity(MAX_TLS13_TICKETS_PER_SERVER),
- }
- }
- }
-
- /// An implementer of `ClientSessionStore` that stores everything
- /// in memory.
- ///
- /// It enforces a limit on the number of entries to bound memory usage.
- pub struct ClientSessionMemoryCache {
- servers: Mutex<limited_cache::LimitedCache<ServerName<'static>, ServerData>>,
- }
-
- impl ClientSessionMemoryCache {
- /// Make a new ClientSessionMemoryCache. `size` is the
- /// maximum number of stored sessions.
- #[cfg(feature = "std")]
- pub fn new(size: usize) -> Self {
- let max_servers = size.saturating_add(MAX_TLS13_TICKETS_PER_SERVER - 1)
- / MAX_TLS13_TICKETS_PER_SERVER;
- Self {
- servers: Mutex::new(limited_cache::LimitedCache::new(max_servers)),
- }
- }
-
- /// Make a new ClientSessionMemoryCache. `size` is the
- /// maximum number of stored sessions.
- #[cfg(not(feature = "std"))]
- pub fn new<M: crate::lock::MakeMutex>(size: usize) -> Self {
- let max_servers = size.saturating_add(MAX_TLS13_TICKETS_PER_SERVER - 1)
- / MAX_TLS13_TICKETS_PER_SERVER;
- Self {
- servers: Mutex::new::<M>(limited_cache::LimitedCache::new(max_servers)),
- }
- }
- }
-
- impl super::client::ClientSessionStore for ClientSessionMemoryCache {
- fn set_kx_hint(&self, server_name: ServerName<'static>, group: NamedGroup) {
- self.servers
- .lock()
- .unwrap()
- .get_or_insert_default_and_edit(server_name, |data| data.kx_hint = Some(group));
- }
-
- fn kx_hint(&self, server_name: &ServerName<'_>) -> Option<NamedGroup> {
- self.servers
- .lock()
- .unwrap()
- .get(server_name)
- .and_then(|sd| sd.kx_hint)
- }
-
- fn set_tls12_session(
- &self,
- _server_name: ServerName<'static>,
- _value: persist::Tls12ClientSessionValue,
- ) {
- #[cfg(feature = "tls12")]
- self.servers
- .lock()
- .unwrap()
- .get_or_insert_default_and_edit(_server_name.clone(), |data| {
- data.tls12 = Some(_value)
- });
- }
-
- fn tls12_session(
- &self,
- _server_name: &ServerName<'_>,
- ) -> Option<persist::Tls12ClientSessionValue> {
- #[cfg(not(feature = "tls12"))]
- return None;
-
- #[cfg(feature = "tls12")]
- self.servers
- .lock()
- .unwrap()
- .get(_server_name)
- .and_then(|sd| sd.tls12.as_ref().cloned())
- }
-
- fn remove_tls12_session(&self, _server_name: &ServerName<'static>) {
- #[cfg(feature = "tls12")]
- self.servers
- .lock()
- .unwrap()
- .get_mut(_server_name)
- .and_then(|data| data.tls12.take());
- }
-
- fn insert_tls13_ticket(
- &self,
- server_name: ServerName<'static>,
- value: persist::Tls13ClientSessionValue,
- ) {
- self.servers
- .lock()
- .unwrap()
- .get_or_insert_default_and_edit(server_name.clone(), |data| {
- if data.tls13.len() == data.tls13.capacity() {
- data.tls13.pop_front();
- }
- data.tls13.push_back(value);
- });
- }
-
- fn take_tls13_ticket(
- &self,
- server_name: &ServerName<'static>,
- ) -> Option<persist::Tls13ClientSessionValue> {
- self.servers
- .lock()
- .unwrap()
- .get_mut(server_name)
- .and_then(|data| data.tls13.pop_back())
- }
- }
-
- impl fmt::Debug for ClientSessionMemoryCache {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- // Note: we omit self.servers as it may contain sensitive data.
- f.debug_struct("ClientSessionMemoryCache")
- .finish()
- }
- }
-}
-
-#[cfg(any(feature = "std", feature = "hashbrown"))]
-pub use cache::ClientSessionMemoryCache;
-
-#[derive(Debug)]
-pub(super) struct FailResolveClientCert {}
-
-impl client::ResolvesClientCert for FailResolveClientCert {
- fn resolve(
- &self,
- _root_hint_subjects: &[&[u8]],
- _sigschemes: &[SignatureScheme],
- ) -> Option<Arc<sign::CertifiedKey>> {
- None
- }
-
- fn has_certs(&self) -> bool {
- false
- }
-}
-
-/// An exemplar `ResolvesClientCert` implementation that always resolves to a single
-/// [RFC 7250] raw public key.
-///
-/// [RFC 7250]: https://tools.ietf.org/html/rfc7250
-#[derive(Clone, Debug)]
-pub struct AlwaysResolvesClientRawPublicKeys(Arc<sign::CertifiedKey>);
-impl AlwaysResolvesClientRawPublicKeys {
- /// Create a new `AlwaysResolvesClientRawPublicKeys` instance.
- pub fn new(certified_key: Arc<sign::CertifiedKey>) -> Self {
- Self(certified_key)
- }
-}
-
-impl client::ResolvesClientCert for AlwaysResolvesClientRawPublicKeys {
- fn resolve(
- &self,
- _root_hint_subjects: &[&[u8]],
- _sigschemes: &[SignatureScheme],
- ) -> Option<Arc<sign::CertifiedKey>> {
- Some(self.0.clone())
- }
-
- fn only_raw_public_keys(&self) -> bool {
- true
- }
-
- /// Returns true if the resolver is ready to present an identity.
- ///
- /// Even though the function is called `has_certs`, it returns true
- /// although only an RPK (Raw Public Key) is available, not an actual certificate.
- fn has_certs(&self) -> bool {
- true
- }
-}
-
-#[cfg(test)]
-#[macro_rules_attribute::apply(test_for_each_provider)]
-mod tests {
- use std::prelude::v1::*;
-
- use pki_types::{ServerName, UnixTime};
-
- use super::NoClientSessionStorage;
- use super::provider::cipher_suite;
- use crate::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
- use crate::client::{ClientSessionStore, ResolvesClientCert};
- use crate::msgs::base::PayloadU16;
- use crate::msgs::enums::NamedGroup;
- use crate::msgs::handshake::CertificateChain;
- #[cfg(feature = "tls12")]
- use crate::msgs::handshake::SessionId;
- use crate::msgs::persist::Tls13ClientSessionValue;
- use crate::pki_types::CertificateDer;
- use crate::suites::SupportedCipherSuite;
- use crate::sync::Arc;
- use crate::{DigitallySignedStruct, Error, SignatureScheme, sign};
-
- #[test]
- fn test_noclientsessionstorage_does_nothing() {
- let c = NoClientSessionStorage {};
- let name = ServerName::try_from("example.com").unwrap();
- let now = UnixTime::now();
- let server_cert_verifier: Arc<dyn ServerCertVerifier> = Arc::new(DummyServerCertVerifier);
- let resolves_client_cert: Arc<dyn ResolvesClientCert> = Arc::new(DummyResolvesClientCert);
-
- c.set_kx_hint(name.clone(), NamedGroup::X25519);
- assert_eq!(None, c.kx_hint(&name));
-
- #[cfg(feature = "tls12")]
- {
- use crate::msgs::persist::Tls12ClientSessionValue;
- let SupportedCipherSuite::Tls12(tls12_suite) =
- cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- else {
- unreachable!()
- };
-
- c.set_tls12_session(
- name.clone(),
- Tls12ClientSessionValue::new(
- tls12_suite,
- SessionId::empty(),
- Arc::new(PayloadU16::empty()),
- &[],
- CertificateChain::default(),
- &server_cert_verifier,
- &resolves_client_cert,
- now,
- 0,
- true,
- ),
- );
- assert!(c.tls12_session(&name).is_none());
- c.remove_tls12_session(&name);
- }
-
- let SupportedCipherSuite::Tls13(tls13_suite) = cipher_suite::TLS13_AES_256_GCM_SHA384
- else {
- unreachable!();
- };
- c.insert_tls13_ticket(
- name.clone(),
- Tls13ClientSessionValue::new(
- tls13_suite,
- Arc::new(PayloadU16::empty()),
- &[],
- CertificateChain::default(),
- &server_cert_verifier,
- &resolves_client_cert,
- now,
- 0,
- 0,
- 0,
- ),
- );
- assert!(c.take_tls13_ticket(&name).is_none());
- }
-
- #[derive(Debug)]
- struct DummyServerCertVerifier;
-
- impl ServerCertVerifier for DummyServerCertVerifier {
- #[cfg_attr(coverage_nightly, coverage(off))]
- fn verify_server_cert(
- &self,
- _end_entity: &CertificateDer<'_>,
- _intermediates: &[CertificateDer<'_>],
- _server_name: &ServerName<'_>,
- _ocsp_response: &[u8],
- _now: UnixTime,
- ) -> Result<ServerCertVerified, Error> {
- unreachable!()
- }
-
- #[cfg_attr(coverage_nightly, coverage(off))]
- fn verify_tls12_signature(
- &self,
- _message: &[u8],
- _cert: &CertificateDer<'_>,
- _dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error> {
- unreachable!()
- }
-
- #[cfg_attr(coverage_nightly, coverage(off))]
- fn verify_tls13_signature(
- &self,
- _message: &[u8],
- _cert: &CertificateDer<'_>,
- _dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error> {
- unreachable!()
- }
-
- #[cfg_attr(coverage_nightly, coverage(off))]
- fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
- unreachable!()
- }
- }
-
- #[derive(Debug)]
- struct DummyResolvesClientCert;
-
- impl ResolvesClientCert for DummyResolvesClientCert {
- #[cfg_attr(coverage_nightly, coverage(off))]
- fn resolve(
- &self,
- _root_hint_subjects: &[&[u8]],
- _sigschemes: &[SignatureScheme],
- ) -> Option<Arc<sign::CertifiedKey>> {
- unreachable!()
- }
-
- #[cfg_attr(coverage_nightly, coverage(off))]
- fn has_certs(&self) -> bool {
- unreachable!()
- }
- }
-}
diff --git a/vendor/rustls/src/client/hs.rs b/vendor/rustls/src/client/hs.rs
deleted file mode 100644
index 4669f33d..00000000
--- a/vendor/rustls/src/client/hs.rs
+++ /dev/null
@@ -1,1178 +0,0 @@
-use alloc::borrow::ToOwned;
-use alloc::boxed::Box;
-use alloc::vec;
-use alloc::vec::Vec;
-use core::ops::Deref;
-
-use pki_types::ServerName;
-
-#[cfg(feature = "tls12")]
-use super::tls12;
-use super::{ResolvesClientCert, Tls12Resumption};
-use crate::SupportedCipherSuite;
-#[cfg(feature = "logging")]
-use crate::bs_debug;
-use crate::check::inappropriate_handshake_message;
-use crate::client::client_conn::ClientConnectionData;
-use crate::client::common::ClientHelloDetails;
-use crate::client::ech::EchState;
-use crate::client::{ClientConfig, EchMode, EchStatus, tls13};
-use crate::common_state::{CommonState, HandshakeKind, KxState, State};
-use crate::conn::ConnectionRandoms;
-use crate::crypto::{ActiveKeyExchange, KeyExchangeAlgorithm};
-use crate::enums::{
- AlertDescription, CertificateType, CipherSuite, ContentType, HandshakeType, ProtocolVersion,
-};
-use crate::error::{Error, PeerIncompatible, PeerMisbehaved};
-use crate::hash_hs::HandshakeHashBuffer;
-use crate::log::{debug, trace};
-use crate::msgs::base::Payload;
-use crate::msgs::enums::{Compression, ExtensionType};
-use crate::msgs::handshake::{
- CertificateStatusRequest, ClientExtensions, ClientExtensionsInput, ClientHelloPayload,
- ClientSessionTicket, EncryptedClientHello, HandshakeMessagePayload, HandshakePayload,
- HelloRetryRequest, KeyShareEntry, ProtocolName, PskKeyExchangeModes, Random, ServerNamePayload,
- SessionId, SupportedEcPointFormats, SupportedProtocolVersions, TransportParameters,
-};
-use crate::msgs::message::{Message, MessagePayload};
-use crate::msgs::persist;
-use crate::sync::Arc;
-use crate::tls13::key_schedule::KeyScheduleEarly;
-use crate::verify::ServerCertVerifier;
-
-pub(super) type NextState<'a> = Box<dyn State<ClientConnectionData> + 'a>;
-pub(super) type NextStateOrError<'a> = Result<NextState<'a>, Error>;
-pub(super) type ClientContext<'a> = crate::common_state::Context<'a, ClientConnectionData>;
-
-struct ExpectServerHello {
- input: ClientHelloInput,
- transcript_buffer: HandshakeHashBuffer,
- // The key schedule for sending early data.
- //
- // If the server accepts the PSK used for early data then
- // this is used to compute the rest of the key schedule.
- // Otherwise, it is thrown away.
- //
- // If this is `None` then we do not support early data.
- early_data_key_schedule: Option<KeyScheduleEarly>,
- offered_key_share: Option<Box<dyn ActiveKeyExchange>>,
- suite: Option<SupportedCipherSuite>,
- ech_state: Option<EchState>,
-}
-
-struct ExpectServerHelloOrHelloRetryRequest {
- next: ExpectServerHello,
- extra_exts: ClientExtensionsInput<'static>,
-}
-
-pub(super) struct ClientHelloInput {
- pub(super) config: Arc<ClientConfig>,
- pub(super) resuming: Option<persist::Retrieved<ClientSessionValue>>,
- pub(super) random: Random,
- pub(super) sent_tls13_fake_ccs: bool,
- pub(super) hello: ClientHelloDetails,
- pub(super) session_id: SessionId,
- pub(super) server_name: ServerName<'static>,
- pub(super) prev_ech_ext: Option<EncryptedClientHello>,
-}
-
-impl ClientHelloInput {
- pub(super) fn new(
- server_name: ServerName<'static>,
- extra_exts: &ClientExtensionsInput<'_>,
- cx: &mut ClientContext<'_>,
- config: Arc<ClientConfig>,
- ) -> Result<Self, Error> {
- let mut resuming = ClientSessionValue::retrieve(&server_name, &config, cx);
- let session_id = match &mut resuming {
- Some(_resuming) => {
- debug!("Resuming session");
- match &mut _resuming.value {
- #[cfg(feature = "tls12")]
- ClientSessionValue::Tls12(inner) => {
- // If we have a ticket, we use the sessionid as a signal that
- // we're doing an abbreviated handshake. See section 3.4 in
- // RFC5077.
- if !inner.ticket().0.is_empty() {
- inner.session_id = SessionId::random(config.provider.secure_random)?;
- }
- Some(inner.session_id)
- }
- _ => None,
- }
- }
- _ => {
- debug!("Not resuming any session");
- None
- }
- };
-
- // https://tools.ietf.org/html/rfc8446#appendix-D.4
- // https://tools.ietf.org/html/draft-ietf-quic-tls-34#section-8.4
- let session_id = match session_id {
- Some(session_id) => session_id,
- None if cx.common.is_quic() => SessionId::empty(),
- None if !config.supports_version(ProtocolVersion::TLSv1_3) => SessionId::empty(),
- None => SessionId::random(config.provider.secure_random)?,
- };
-
- let hello = ClientHelloDetails::new(
- extra_exts
- .protocols
- .clone()
- .unwrap_or_default(),
- crate::rand::random_u16(config.provider.secure_random)?,
- );
-
- Ok(Self {
- resuming,
- random: Random::new(config.provider.secure_random)?,
- sent_tls13_fake_ccs: false,
- hello,
- session_id,
- server_name,
- prev_ech_ext: None,
- config,
- })
- }
-
- pub(super) fn start_handshake(
- self,
- extra_exts: ClientExtensionsInput<'static>,
- cx: &mut ClientContext<'_>,
- ) -> NextStateOrError<'static> {
- let mut transcript_buffer = HandshakeHashBuffer::new();
- if self
- .config
- .client_auth_cert_resolver
- .has_certs()
- {
- transcript_buffer.set_client_auth_enabled();
- }
-
- let key_share = if self.config.needs_key_share() {
- Some(tls13::initial_key_share(
- &self.config,
- &self.server_name,
- &mut cx.common.kx_state,
- )?)
- } else {
- None
- };
-
- let ech_state = match self.config.ech_mode.as_ref() {
- Some(EchMode::Enable(ech_config)) => {
- Some(ech_config.state(self.server_name.clone(), &self.config)?)
- }
- _ => None,
- };
-
- emit_client_hello_for_retry(
- transcript_buffer,
- None,
- key_share,
- extra_exts,
- None,
- self,
- cx,
- ech_state,
- )
- }
-}
-
-/// Emits the initial ClientHello or a ClientHello in response to
-/// a HelloRetryRequest.
-///
-/// `retryreq` and `suite` are `None` if this is the initial
-/// ClientHello.
-fn emit_client_hello_for_retry(
- mut transcript_buffer: HandshakeHashBuffer,
- retryreq: Option<&HelloRetryRequest>,
- key_share: Option<Box<dyn ActiveKeyExchange>>,
- extra_exts: ClientExtensionsInput<'static>,
- suite: Option<SupportedCipherSuite>,
- mut input: ClientHelloInput,
- cx: &mut ClientContext<'_>,
- mut ech_state: Option<EchState>,
-) -> NextStateOrError<'static> {
- let config = &input.config;
- // Defense in depth: the ECH state should be None if ECH is disabled based on config
- // builder semantics.
- let forbids_tls12 = cx.common.is_quic() || ech_state.is_some();
-
- let supported_versions = SupportedProtocolVersions {
- tls12: config.supports_version(ProtocolVersion::TLSv1_2) && !forbids_tls12,
- tls13: config.supports_version(ProtocolVersion::TLSv1_3),
- };
-
- // should be unreachable thanks to config builder
- assert!(supported_versions.any(|_| true));
-
- let mut exts = Box::new(ClientExtensions {
- // offer groups which are usable for any offered version
- named_groups: Some(
- config
- .provider
- .kx_groups
- .iter()
- .filter(|skxg| supported_versions.any(|v| skxg.usable_for_version(v)))
- .map(|skxg| skxg.name())
- .collect(),
- ),
- supported_versions: Some(supported_versions),
- signature_schemes: Some(
- config
- .verifier
- .supported_verify_schemes(),
- ),
- extended_master_secret_request: Some(()),
- certificate_status_request: Some(CertificateStatusRequest::build_ocsp()),
- protocols: extra_exts.protocols.clone(),
- ..Default::default()
- });
-
- match extra_exts.transport_parameters.clone() {
- Some(TransportParameters::Quic(v)) => exts.transport_parameters = Some(v),
- Some(TransportParameters::QuicDraft(v)) => exts.transport_parameters_draft = Some(v),
- None => {}
- };
-
- if supported_versions.tls13 {
- if let Some(cas_extension) = config.verifier.root_hint_subjects() {
- exts.certificate_authority_names = Some(cas_extension.to_owned());
- }
- }
-
- // Send the ECPointFormat extension only if we are proposing ECDHE
- if config
- .provider
- .kx_groups
- .iter()
- .any(|skxg| skxg.name().key_exchange_algorithm() == KeyExchangeAlgorithm::ECDHE)
- {
- exts.ec_point_formats = Some(SupportedEcPointFormats::default());
- }
-
- exts.server_name = match (ech_state.as_ref(), config.enable_sni) {
- // If we have ECH state we have a "cover name" to send in the outer hello
- // as the SNI domain name. This happens unconditionally so we ignore the
- // `enable_sni` value. That will be used later to decide what to do for
- // the protected inner hello's SNI.
- (Some(ech_state), _) => Some(ServerNamePayload::from(&ech_state.outer_name)),
-
- // If we have no ECH state, and SNI is enabled, try to use the input server_name
- // for the SNI domain name.
- (None, true) => match &input.server_name {
- ServerName::DnsName(dns_name) => Some(ServerNamePayload::from(dns_name)),
- _ => None,
- },
-
- // If we have no ECH state, and SNI is not enabled, there's nothing to do.
- (None, false) => None,
- };
-
- if let Some(key_share) = &key_share {
- debug_assert!(supported_versions.tls13);
- let mut shares = vec![KeyShareEntry::new(key_share.group(), key_share.pub_key())];
-
- if !retryreq
- .map(|rr| rr.key_share.is_some())
- .unwrap_or_default()
- {
- // Only for the initial client hello, or a HRR that does not specify a kx group,
- // see if we can send a second KeyShare for "free". We only do this if the same
- // algorithm is also supported separately by our provider for this version
- // (`find_kx_group` looks that up).
- if let Some((component_group, component_share)) =
- key_share
- .hybrid_component()
- .filter(|(group, _)| {
- config
- .find_kx_group(*group, ProtocolVersion::TLSv1_3)
- .is_some()
- })
- {
- shares.push(KeyShareEntry::new(component_group, component_share));
- }
- }
-
- exts.key_shares = Some(shares);
- }
-
- if let Some(cookie) = retryreq.and_then(|hrr| hrr.cookie.as_ref()) {
- exts.cookie = Some(cookie.clone());
- }
-
- if supported_versions.tls13 {
- // We could support PSK_KE here too. Such connections don't
- // have forward secrecy, and are similar to TLS1.2 resumption.
- exts.preshared_key_modes = Some(PskKeyExchangeModes {
- psk: false,
- psk_dhe: true,
- });
- }
-
- input.hello.offered_cert_compression =
- if supported_versions.tls13 && !config.cert_decompressors.is_empty() {
- exts.certificate_compression_algorithms = Some(
- config
- .cert_decompressors
- .iter()
- .map(|dec| dec.algorithm())
- .collect(),
- );
- true
- } else {
- false
- };
-
- if config
- .client_auth_cert_resolver
- .only_raw_public_keys()
- {
- exts.client_certificate_types = Some(vec![CertificateType::RawPublicKey]);
- }
-
- if config
- .verifier
- .requires_raw_public_keys()
- {
- exts.server_certificate_types = Some(vec![CertificateType::RawPublicKey]);
- }
-
- // If this is a second client hello we're constructing in response to an HRR, and
- // we've rejected ECH or sent GREASE ECH, then we need to carry forward the
- // exact same ECH extension we used in the first hello.
- if matches!(cx.data.ech_status, EchStatus::Rejected | EchStatus::Grease) & retryreq.is_some() {
- if let Some(prev_ech_ext) = input.prev_ech_ext.take() {
- exts.encrypted_client_hello = Some(prev_ech_ext);
- }
- }
-
- // Do we have a SessionID or ticket cached for this host?
- let tls13_session = prepare_resumption(&input.resuming, &mut exts, suite, cx, config);
-
- // Extensions MAY be randomized
- // but they also need to keep the same order as the previous ClientHello
- exts.order_seed = input.hello.extension_order_seed;
-
- let mut cipher_suites: Vec<_> = config
- .provider
- .cipher_suites
- .iter()
- .filter_map(|cs| match cs.usable_for_protocol(cx.common.protocol) {
- true => Some(cs.suite()),
- false => None,
- })
- .collect();
-
- if supported_versions.tls12 {
- // We don't do renegotiation at all, in fact.
- cipher_suites.push(CipherSuite::TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
- }
-
- let mut chp_payload = ClientHelloPayload {
- client_version: ProtocolVersion::TLSv1_2,
- random: input.random,
- session_id: input.session_id,
- cipher_suites,
- compression_methods: vec![Compression::Null],
- extensions: exts,
- };
-
- let ech_grease_ext = config
- .ech_mode
- .as_ref()
- .and_then(|mode| match mode {
- EchMode::Grease(cfg) => Some(cfg.grease_ext(
- config.provider.secure_random,
- input.server_name.clone(),
- &chp_payload,
- )),
- _ => None,
- });
-
- match (cx.data.ech_status, &mut ech_state) {
- // If we haven't offered ECH, or have offered ECH but got a non-rejecting HRR, then
- // we need to replace the client hello payload with an ECH client hello payload.
- (EchStatus::NotOffered | EchStatus::Offered, Some(ech_state)) => {
- // Replace the client hello payload with an ECH client hello payload.
- chp_payload = ech_state.ech_hello(chp_payload, retryreq, &tls13_session)?;
- cx.data.ech_status = EchStatus::Offered;
- // Store the ECH extension in case we need to carry it forward in a subsequent hello.
- input.prev_ech_ext = chp_payload
- .encrypted_client_hello
- .clone();
- }
- // If we haven't offered ECH, and have no ECH state, then consider whether to use GREASE
- // ECH.
- (EchStatus::NotOffered, None) => {
- if let Some(grease_ext) = ech_grease_ext {
- // Add the GREASE ECH extension.
- let grease_ext = grease_ext?;
- chp_payload.encrypted_client_hello = Some(grease_ext.clone());
- cx.data.ech_status = EchStatus::Grease;
- // Store the GREASE ECH extension in case we need to carry it forward in a
- // subsequent hello.
- input.prev_ech_ext = Some(grease_ext);
- }
- }
- _ => {}
- }
-
- // Note what extensions we sent.
- input.hello.sent_extensions = chp_payload.collect_used();
-
- let mut chp = HandshakeMessagePayload(HandshakePayload::ClientHello(chp_payload));
-
- let tls13_early_data_key_schedule = match (ech_state.as_mut(), tls13_session) {
- // If we're performing ECH and resuming, then the PSK binder will have been dealt with
- // separately, and we need to take the early_data_key_schedule computed for the inner hello.
- (Some(ech_state), Some(tls13_session)) => ech_state
- .early_data_key_schedule
- .take()
- .map(|schedule| (tls13_session.suite(), schedule)),
-
- // When we're not doing ECH and resuming, then the PSK binder need to be filled in as
- // normal.
- (_, Some(tls13_session)) => Some((
- tls13_session.suite(),
- tls13::fill_in_psk_binder(&tls13_session, &transcript_buffer, &mut chp),
- )),
-
- // No early key schedule in other cases.
- _ => None,
- };
-
- let ch = Message {
- version: match retryreq {
- // <https://datatracker.ietf.org/doc/html/rfc8446#section-5.1>:
- // "This value MUST be set to 0x0303 for all records generated
- // by a TLS 1.3 implementation ..."
- Some(_) => ProtocolVersion::TLSv1_2,
- // "... other than an initial ClientHello (i.e., one not
- // generated after a HelloRetryRequest), where it MAY also be
- // 0x0301 for compatibility purposes"
- //
- // (retryreq == None means we're in the "initial ClientHello" case)
- None => ProtocolVersion::TLSv1_0,
- },
- payload: MessagePayload::handshake(chp),
- };
-
- if retryreq.is_some() {
- // send dummy CCS to fool middleboxes prior
- // to second client hello
- tls13::emit_fake_ccs(&mut input.sent_tls13_fake_ccs, cx.common);
- }
-
- trace!("Sending ClientHello {ch:#?}");
-
- transcript_buffer.add_message(&ch);
- cx.common.send_msg(ch, false);
-
- // Calculate the hash of ClientHello and use it to derive EarlyTrafficSecret
- let early_data_key_schedule =
- tls13_early_data_key_schedule.map(|(resuming_suite, schedule)| {
- if !cx.data.early_data.is_enabled() {
- return schedule;
- }
-
- let (transcript_buffer, random) = match &ech_state {
- // When using ECH the early data key schedule is derived based on the inner
- // hello transcript and random.
- Some(ech_state) => (
- &ech_state.inner_hello_transcript,
- &ech_state.inner_hello_random.0,
- ),
- None => (&transcript_buffer, &input.random.0),
- };
-
- tls13::derive_early_traffic_secret(
- &*config.key_log,
- cx,
- resuming_suite.common.hash_provider,
- &schedule,
- &mut input.sent_tls13_fake_ccs,
- transcript_buffer,
- random,
- );
- schedule
- });
-
- let next = ExpectServerHello {
- input,
- transcript_buffer,
- early_data_key_schedule,
- offered_key_share: key_share,
- suite,
- ech_state,
- };
-
- Ok(if supported_versions.tls13 && retryreq.is_none() {
- Box::new(ExpectServerHelloOrHelloRetryRequest {
- next,
- extra_exts: extra_exts.into_owned(),
- })
- } else {
- Box::new(next)
- })
-}
-
-/// Prepares `exts` and `cx` with TLS 1.2 or TLS 1.3 session
-/// resumption.
-///
-/// - `suite` is `None` if this is the initial ClientHello, or
-/// `Some` if we're retrying in response to
-/// a HelloRetryRequest.
-///
-/// This function will push onto `exts` to
-///
-/// (a) request a new ticket if we don't have one,
-/// (b) send our TLS 1.2 ticket after retrieving an 1.2 session,
-/// (c) send a request for 1.3 early data if allowed and
-/// (d) send a 1.3 preshared key if we have one.
-///
-/// It returns the TLS 1.3 PSKs, if any, for further processing.
-fn prepare_resumption<'a>(
- resuming: &'a Option<persist::Retrieved<ClientSessionValue>>,
- exts: &mut ClientExtensions<'_>,
- suite: Option<SupportedCipherSuite>,
- cx: &mut ClientContext<'_>,
- config: &ClientConfig,
-) -> Option<persist::Retrieved<&'a persist::Tls13ClientSessionValue>> {
- // Check whether we're resuming with a non-empty ticket.
- let resuming = match resuming {
- Some(resuming) if !resuming.ticket().is_empty() => resuming,
- _ => {
- if config.supports_version(ProtocolVersion::TLSv1_2)
- && config.resumption.tls12_resumption == Tls12Resumption::SessionIdOrTickets
- {
- // If we don't have a ticket, request one.
- exts.session_ticket = Some(ClientSessionTicket::Request);
- }
- return None;
- }
- };
-
- let Some(tls13) = resuming.map(|csv| csv.tls13()) else {
- // TLS 1.2; send the ticket if we have support this protocol version
- if config.supports_version(ProtocolVersion::TLSv1_2)
- && config.resumption.tls12_resumption == Tls12Resumption::SessionIdOrTickets
- {
- exts.session_ticket = Some(ClientSessionTicket::Offer(Payload::new(resuming.ticket())));
- }
- return None; // TLS 1.2, so nothing to return here
- };
-
- if !config.supports_version(ProtocolVersion::TLSv1_3) {
- return None;
- }
-
- // If the server selected TLS 1.2, we can't resume.
- let suite = match suite {
- Some(SupportedCipherSuite::Tls13(suite)) => Some(suite),
- #[cfg(feature = "tls12")]
- Some(SupportedCipherSuite::Tls12(_)) => return None,
- None => None,
- };
-
- // If the selected cipher suite can't select from the session's, we can't resume.
- if let Some(suite) = suite {
- suite.can_resume_from(tls13.suite())?;
- }
-
- tls13::prepare_resumption(config, cx, &tls13, exts, suite.is_some());
- Some(tls13)
-}
-
-pub(super) fn process_alpn_protocol(
- common: &mut CommonState,
- offered_protocols: &[ProtocolName],
- selected: Option<&ProtocolName>,
-) -> Result<(), Error> {
- common.alpn_protocol = selected.map(ToOwned::to_owned);
-
- if let Some(alpn_protocol) = &common.alpn_protocol {
- if !offered_protocols.contains(alpn_protocol) {
- return Err(common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::SelectedUnofferedApplicationProtocol,
- ));
- }
- }
-
- // RFC 9001 says: "While ALPN only specifies that servers use this alert, QUIC clients MUST
- // use error 0x0178 to terminate a connection when ALPN negotiation fails." We judge that
- // the user intended to use ALPN (rather than some out-of-band protocol negotiation
- // mechanism) if and only if any ALPN protocols were configured. This defends against badly-behaved
- // servers which accept a connection that requires an application-layer protocol they do not
- // understand.
- if common.is_quic() && common.alpn_protocol.is_none() && !offered_protocols.is_empty() {
- return Err(common.send_fatal_alert(
- AlertDescription::NoApplicationProtocol,
- Error::NoApplicationProtocol,
- ));
- }
-
- debug!(
- "ALPN protocol is {:?}",
- common
- .alpn_protocol
- .as_ref()
- .map(|v| bs_debug::BsDebug(v.as_ref()))
- );
- Ok(())
-}
-
-pub(super) fn process_server_cert_type_extension(
- common: &mut CommonState,
- config: &ClientConfig,
- server_cert_extension: Option<&CertificateType>,
-) -> Result<Option<(ExtensionType, CertificateType)>, Error> {
- process_cert_type_extension(
- common,
- config
- .verifier
- .requires_raw_public_keys(),
- server_cert_extension.copied(),
- ExtensionType::ServerCertificateType,
- )
-}
-
-pub(super) fn process_client_cert_type_extension(
- common: &mut CommonState,
- config: &ClientConfig,
- client_cert_extension: Option<&CertificateType>,
-) -> Result<Option<(ExtensionType, CertificateType)>, Error> {
- process_cert_type_extension(
- common,
- config
- .client_auth_cert_resolver
- .only_raw_public_keys(),
- client_cert_extension.copied(),
- ExtensionType::ClientCertificateType,
- )
-}
-
-impl State<ClientConnectionData> for ExpectServerHello {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> NextStateOrError<'m>
- where
- Self: 'm,
- {
- let server_hello =
- require_handshake_msg!(m, HandshakeType::ServerHello, HandshakePayload::ServerHello)?;
- trace!("We got ServerHello {server_hello:#?}");
-
- use crate::ProtocolVersion::{TLSv1_2, TLSv1_3};
- let config = &self.input.config;
- let tls13_supported = config.supports_version(TLSv1_3);
-
- let server_version = if server_hello.legacy_version == TLSv1_2 {
- server_hello
- .selected_version
- .unwrap_or(server_hello.legacy_version)
- } else {
- server_hello.legacy_version
- };
-
- let version = match server_version {
- TLSv1_3 if tls13_supported => TLSv1_3,
- TLSv1_2 if config.supports_version(TLSv1_2) => {
- if cx.data.early_data.is_enabled() && cx.common.early_traffic {
- // The client must fail with a dedicated error code if the server
- // responds with TLS 1.2 when offering 0-RTT.
- return Err(PeerMisbehaved::OfferedEarlyDataWithOldProtocolVersion.into());
- }
-
- if server_hello.selected_version.is_some() {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::SelectedTls12UsingTls13VersionExtension,
- )
- });
- }
-
- TLSv1_2
- }
- _ => {
- let reason = match server_version {
- TLSv1_2 | TLSv1_3 => PeerIncompatible::ServerTlsVersionIsDisabledByOurConfig,
- _ => PeerIncompatible::ServerDoesNotSupportTls12Or13,
- };
- return Err(cx
- .common
- .send_fatal_alert(AlertDescription::ProtocolVersion, reason));
- }
- };
-
- if server_hello.compression_method != Compression::Null {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::SelectedUnofferedCompression,
- )
- });
- }
-
- let allowed_unsolicited = [ExtensionType::RenegotiationInfo];
- if self
- .input
- .hello
- .server_sent_unsolicited_extensions(server_hello, &allowed_unsolicited)
- {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::UnsupportedExtension,
- PeerMisbehaved::UnsolicitedServerHelloExtension,
- ));
- }
-
- cx.common.negotiated_version = Some(version);
-
- // Extract ALPN protocol
- if !cx.common.is_tls13() {
- process_alpn_protocol(
- cx.common,
- &self.input.hello.alpn_protocols,
- server_hello
- .selected_protocol
- .as_ref()
- .map(|s| s.as_ref()),
- )?;
- }
-
- // If ECPointFormats extension is supplied by the server, it must contain
- // Uncompressed. But it's allowed to be omitted.
- if let Some(point_fmts) = &server_hello.ec_point_formats {
- if !point_fmts.uncompressed {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::HandshakeFailure,
- PeerMisbehaved::ServerHelloMustOfferUncompressedEcPoints,
- ));
- }
- }
-
- let suite = config
- .find_cipher_suite(server_hello.cipher_suite)
- .ok_or_else(|| {
- cx.common.send_fatal_alert(
- AlertDescription::HandshakeFailure,
- PeerMisbehaved::SelectedUnofferedCipherSuite,
- )
- })?;
-
- if version != suite.version().version {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::SelectedUnusableCipherSuiteForVersion,
- )
- });
- }
-
- match self.suite {
- Some(prev_suite) if prev_suite != suite => {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::SelectedDifferentCipherSuiteAfterRetry,
- )
- });
- }
- _ => {
- debug!("Using ciphersuite {suite:?}");
- self.suite = Some(suite);
- cx.common.suite = Some(suite);
- }
- }
-
- // Start our handshake hash, and input the server-hello.
- let mut transcript = self
- .transcript_buffer
- .start_hash(suite.hash_provider());
- transcript.add_message(&m);
-
- let randoms = ConnectionRandoms::new(self.input.random, server_hello.random);
- // For TLS1.3, start message encryption using
- // handshake_traffic_secret.
- match suite {
- SupportedCipherSuite::Tls13(suite) => {
- tls13::handle_server_hello(
- cx,
- server_hello,
- randoms,
- suite,
- transcript,
- self.early_data_key_schedule,
- // We always send a key share when TLS 1.3 is enabled.
- self.offered_key_share.unwrap(),
- &m,
- self.ech_state,
- self.input,
- )
- }
- #[cfg(feature = "tls12")]
- SupportedCipherSuite::Tls12(suite) => tls12::CompleteServerHelloHandling {
- randoms,
- transcript,
- input: self.input,
- }
- .handle_server_hello(cx, suite, server_hello, tls13_supported),
- }
- }
-
- fn into_owned(self: Box<Self>) -> NextState<'static> {
- self
- }
-}
-
-impl ExpectServerHelloOrHelloRetryRequest {
- fn into_expect_server_hello(self) -> NextState<'static> {
- Box::new(self.next)
- }
-
- fn handle_hello_retry_request(
- mut self,
- cx: &mut ClientContext<'_>,
- m: Message<'_>,
- ) -> NextStateOrError<'static> {
- let hrr = require_handshake_msg!(
- m,
- HandshakeType::HelloRetryRequest,
- HandshakePayload::HelloRetryRequest
- )?;
- trace!("Got HRR {hrr:?}");
-
- cx.common.check_aligned_handshake()?;
-
- // We always send a key share when TLS 1.3 is enabled.
- let offered_key_share = self.next.offered_key_share.unwrap();
-
- // A retry request is illegal if it contains no cookie and asks for
- // retry of a group we already sent.
- let config = &self.next.input.config;
-
- if let (None, Some(req_group)) = (&hrr.cookie, hrr.key_share) {
- let offered_hybrid = offered_key_share
- .hybrid_component()
- .and_then(|(group_name, _)| {
- config.find_kx_group(group_name, ProtocolVersion::TLSv1_3)
- })
- .map(|skxg| skxg.name());
-
- if req_group == offered_key_share.group() || Some(req_group) == offered_hybrid {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::IllegalHelloRetryRequestWithOfferedGroup,
- )
- });
- }
- }
-
- // Or has an empty cookie.
- if let Some(cookie) = &hrr.cookie {
- if cookie.0.is_empty() {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::IllegalHelloRetryRequestWithEmptyCookie,
- )
- });
- }
- }
-
- // Or asks us to change nothing.
- if hrr.cookie.is_none() && hrr.key_share.is_none() {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::IllegalHelloRetryRequestWithNoChanges,
- )
- });
- }
-
- // Or does not echo the session_id from our ClientHello:
- //
- // > the HelloRetryRequest has the same format as a ServerHello message,
- // > and the legacy_version, legacy_session_id_echo, cipher_suite, and
- // > legacy_compression_method fields have the same meaning
- // <https://www.rfc-editor.org/rfc/rfc8446#section-4.1.4>
- //
- // and
- //
- // > A client which receives a legacy_session_id_echo field that does not
- // > match what it sent in the ClientHello MUST abort the handshake with an
- // > "illegal_parameter" alert.
- // <https://www.rfc-editor.org/rfc/rfc8446#section-4.1.3>
- if hrr.session_id != self.next.input.session_id {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::IllegalHelloRetryRequestWithWrongSessionId,
- )
- });
- }
-
- // Or asks us to talk a protocol we didn't offer, or doesn't support HRR at all.
- match hrr.supported_versions {
- Some(ProtocolVersion::TLSv1_3) => {
- cx.common.negotiated_version = Some(ProtocolVersion::TLSv1_3);
- }
- _ => {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::IllegalHelloRetryRequestWithUnsupportedVersion,
- )
- });
- }
- }
-
- // Or asks us to use a ciphersuite we didn't offer.
- let Some(cs) = config.find_cipher_suite(hrr.cipher_suite) else {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedCipherSuite,
- )
- });
- };
-
- // Or offers ECH related extensions when we didn't offer ECH.
- if cx.data.ech_status == EchStatus::NotOffered && hrr.encrypted_client_hello.is_some() {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::UnsupportedExtension,
- PeerMisbehaved::IllegalHelloRetryRequestWithInvalidEch,
- )
- });
- }
-
- // HRR selects the ciphersuite.
- cx.common.suite = Some(cs);
- cx.common.handshake_kind = Some(HandshakeKind::FullWithHelloRetryRequest);
-
- // If we offered ECH, we need to confirm that the server accepted it.
- match (self.next.ech_state.as_ref(), cs.tls13()) {
- (Some(ech_state), Some(tls13_cs)) => {
- if !ech_state.confirm_hrr_acceptance(hrr, tls13_cs, cx.common)? {
- // If the server did not confirm, then note the new ECH status but
- // continue the handshake. We will abort with an ECH required error
- // at the end.
- cx.data.ech_status = EchStatus::Rejected;
- }
- }
- (Some(_), None) => {
- unreachable!("ECH state should only be set when TLS 1.3 was negotiated")
- }
- _ => {}
- };
-
- // This is the draft19 change where the transcript became a tree
- let transcript = self
- .next
- .transcript_buffer
- .start_hash(cs.hash_provider());
- let mut transcript_buffer = transcript.into_hrr_buffer();
- transcript_buffer.add_message(&m);
-
- // If we offered ECH and the server accepted, we also need to update the separate
- // ECH transcript with the hello retry request message.
- if let Some(ech_state) = self.next.ech_state.as_mut() {
- ech_state.transcript_hrr_update(cs.hash_provider(), &m);
- }
-
- // Early data is not allowed after HelloRetryrequest
- if cx.data.early_data.is_enabled() {
- cx.data.early_data.rejected();
- }
-
- let key_share = match hrr.key_share {
- Some(group) if group != offered_key_share.group() => {
- let Some(skxg) = config.find_kx_group(group, ProtocolVersion::TLSv1_3) else {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::IllegalHelloRetryRequestWithUnofferedNamedGroup,
- ));
- };
-
- cx.common.kx_state = KxState::Start(skxg);
- skxg.start()?
- }
- _ => offered_key_share,
- };
-
- emit_client_hello_for_retry(
- transcript_buffer,
- Some(hrr),
- Some(key_share),
- self.extra_exts,
- Some(cs),
- self.next.input,
- cx,
- self.next.ech_state,
- )
- }
-}
-
-impl State<ClientConnectionData> for ExpectServerHelloOrHelloRetryRequest {
- fn handle<'m>(
- self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> NextStateOrError<'m>
- where
- Self: 'm,
- {
- match m.payload {
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::ServerHello(..)),
- ..
- } => self
- .into_expect_server_hello()
- .handle(cx, m),
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::HelloRetryRequest(..)),
- ..
- } => self.handle_hello_retry_request(cx, m),
- payload => Err(inappropriate_handshake_message(
- &payload,
- &[ContentType::Handshake],
- &[HandshakeType::ServerHello, HandshakeType::HelloRetryRequest],
- )),
- }
- }
-
- fn into_owned(self: Box<Self>) -> NextState<'static> {
- self
- }
-}
-
-fn process_cert_type_extension(
- common: &mut CommonState,
- client_expects: bool,
- server_negotiated: Option<CertificateType>,
- extension_type: ExtensionType,
-) -> Result<Option<(ExtensionType, CertificateType)>, Error> {
- match (client_expects, server_negotiated) {
- (true, Some(CertificateType::RawPublicKey)) => {
- Ok(Some((extension_type, CertificateType::RawPublicKey)))
- }
- (true, _) => Err(common.send_fatal_alert(
- AlertDescription::HandshakeFailure,
- Error::PeerIncompatible(PeerIncompatible::IncorrectCertificateTypeExtension),
- )),
- (_, Some(CertificateType::RawPublicKey)) => {
- unreachable!("Caught by `PeerMisbehaved::UnsolicitedEncryptedExtension`")
- }
- (_, _) => Ok(None),
- }
-}
-
-pub(super) enum ClientSessionValue {
- Tls13(persist::Tls13ClientSessionValue),
- #[cfg(feature = "tls12")]
- Tls12(persist::Tls12ClientSessionValue),
-}
-
-impl ClientSessionValue {
- fn retrieve(
- server_name: &ServerName<'static>,
- config: &ClientConfig,
- cx: &mut ClientContext<'_>,
- ) -> Option<persist::Retrieved<Self>> {
- let found = config
- .resumption
- .store
- .take_tls13_ticket(server_name)
- .map(ClientSessionValue::Tls13)
- .or_else(|| {
- #[cfg(feature = "tls12")]
- {
- config
- .resumption
- .store
- .tls12_session(server_name)
- .map(ClientSessionValue::Tls12)
- }
-
- #[cfg(not(feature = "tls12"))]
- None
- })
- .and_then(|resuming| {
- resuming.compatible_config(&config.verifier, &config.client_auth_cert_resolver)
- })
- .and_then(|resuming| {
- let now = config
- .current_time()
- .map_err(|_err| debug!("Could not get current time: {_err}"))
- .ok()?;
-
- let retrieved = persist::Retrieved::new(resuming, now);
- match retrieved.has_expired() {
- false => Some(retrieved),
- true => None,
- }
- })
- .or_else(|| {
- debug!("No cached session for {server_name:?}");
- None
- });
-
- if let Some(resuming) = &found {
- if cx.common.is_quic() {
- cx.common.quic.params = resuming
- .tls13()
- .map(|v| v.quic_params());
- }
- }
-
- found
- }
-
- fn common(&self) -> &persist::ClientSessionCommon {
- match self {
- Self::Tls13(inner) => &inner.common,
- #[cfg(feature = "tls12")]
- Self::Tls12(inner) => &inner.common,
- }
- }
-
- fn tls13(&self) -> Option<&persist::Tls13ClientSessionValue> {
- match self {
- Self::Tls13(v) => Some(v),
- #[cfg(feature = "tls12")]
- Self::Tls12(_) => None,
- }
- }
-
- fn compatible_config(
- self,
- server_cert_verifier: &Arc<dyn ServerCertVerifier>,
- client_creds: &Arc<dyn ResolvesClientCert>,
- ) -> Option<Self> {
- match &self {
- Self::Tls13(v) => v
- .compatible_config(server_cert_verifier, client_creds)
- .then_some(self),
- #[cfg(feature = "tls12")]
- Self::Tls12(v) => v
- .compatible_config(server_cert_verifier, client_creds)
- .then_some(self),
- }
- }
-}
-
-impl Deref for ClientSessionValue {
- type Target = persist::ClientSessionCommon;
-
- fn deref(&self) -> &Self::Target {
- self.common()
- }
-}
diff --git a/vendor/rustls/src/client/test.rs b/vendor/rustls/src/client/test.rs
deleted file mode 100644
index f4ea9580..00000000
--- a/vendor/rustls/src/client/test.rs
+++ /dev/null
@@ -1,712 +0,0 @@
-#![cfg(any(feature = "ring", feature = "aws_lc_rs"))]
-use core::sync::atomic::{AtomicBool, Ordering};
-use std::prelude::v1::*;
-use std::vec;
-
-use pki_types::{CertificateDer, ServerName};
-
-use crate::client::{ClientConfig, ClientConnection, Resumption, Tls12Resumption};
-use crate::crypto::CryptoProvider;
-use crate::enums::{CipherSuite, ProtocolVersion, SignatureScheme};
-use crate::msgs::base::PayloadU16;
-use crate::msgs::codec::Reader;
-use crate::msgs::enums::{Compression, NamedGroup};
-use crate::msgs::handshake::{
- ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, HelloRetryRequest, Random,
- ServerHelloPayload, SessionId,
-};
-use crate::msgs::message::{Message, MessagePayload, OutboundOpaqueMessage};
-use crate::sync::Arc;
-use crate::{Error, PeerIncompatible, PeerMisbehaved, RootCertStore};
-
-#[macro_rules_attribute::apply(test_for_each_provider)]
-mod tests {
- use std::sync::OnceLock;
-
- use super::super::*;
- use crate::client::AlwaysResolvesClientRawPublicKeys;
- use crate::crypto::cipher::MessageEncrypter;
- use crate::crypto::tls13::OkmBlock;
- use crate::enums::CertificateType;
- use crate::msgs::base::PayloadU8;
- use crate::msgs::enums::ECCurveType;
- use crate::msgs::handshake::{
- CertificateChain, EcParameters, HelloRetryRequestExtensions, KeyShareEntry,
- ServerEcdhParams, ServerExtensions, ServerKeyExchange, ServerKeyExchangeParams,
- ServerKeyExchangePayload,
- };
- use crate::msgs::message::PlainMessage;
- use crate::pki_types::pem::PemObject;
- use crate::pki_types::{PrivateKeyDer, UnixTime};
- use crate::sign::CertifiedKey;
- use crate::tls13::key_schedule::{derive_traffic_iv, derive_traffic_key};
- use crate::verify::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
- use crate::{DigitallySignedStruct, DistinguishedName, KeyLog, version};
-
- /// Tests that session_ticket(35) extension
- /// is not sent if the client does not support TLS 1.2.
- #[test]
- fn test_no_session_ticket_request_on_tls_1_3() {
- let mut config =
- ClientConfig::builder_with_provider(super::provider::default_provider().into())
- .with_protocol_versions(&[&version::TLS13])
- .unwrap()
- .with_root_certificates(roots())
- .with_no_client_auth();
- config.resumption = Resumption::in_memory_sessions(128)
- .tls12_resumption(Tls12Resumption::SessionIdOrTickets);
- let ch = client_hello_sent_for_config(config).unwrap();
- assert!(ch.extensions.session_ticket.is_none());
- }
-
- #[test]
- fn test_no_renegotiation_scsv_on_tls_1_3() {
- let ch = client_hello_sent_for_config(
- ClientConfig::builder_with_provider(super::provider::default_provider().into())
- .with_protocol_versions(&[&version::TLS13])
- .unwrap()
- .with_root_certificates(roots())
- .with_no_client_auth(),
- )
- .unwrap();
- assert!(
- !ch.cipher_suites
- .contains(&CipherSuite::TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
- );
- }
-
- #[test]
- fn test_client_does_not_offer_sha1() {
- for version in crate::ALL_VERSIONS {
- let config =
- ClientConfig::builder_with_provider(super::provider::default_provider().into())
- .with_protocol_versions(&[version])
- .unwrap()
- .with_root_certificates(roots())
- .with_no_client_auth();
- let ch = client_hello_sent_for_config(config).unwrap();
- assert!(
- !ch.extensions
- .signature_schemes
- .as_ref()
- .unwrap()
- .contains(&SignatureScheme::RSA_PKCS1_SHA1),
- "sha1 unexpectedly offered"
- );
- }
- }
-
- #[test]
- fn test_client_rejects_hrr_with_varied_session_id() {
- let config =
- ClientConfig::builder_with_provider(super::provider::default_provider().into())
- .with_safe_default_protocol_versions()
- .unwrap()
- .with_root_certificates(roots())
- .with_no_client_auth();
- let mut conn =
- ClientConnection::new(config.into(), ServerName::try_from("localhost").unwrap())
- .unwrap();
- let mut sent = Vec::new();
- conn.write_tls(&mut sent).unwrap();
-
- // server replies with HRR, but does not echo `session_id` as required.
- let hrr = Message {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::HelloRetryRequest(HelloRetryRequest {
- cipher_suite: CipherSuite::TLS13_AES_128_GCM_SHA256,
- legacy_version: ProtocolVersion::TLSv1_2,
- session_id: SessionId::empty(),
- extensions: HelloRetryRequestExtensions {
- cookie: Some(PayloadU16::new(vec![1, 2, 3, 4])),
- ..HelloRetryRequestExtensions::default()
- },
- }),
- )),
- };
-
- conn.read_tls(&mut hrr.into_wire_bytes().as_slice())
- .unwrap();
- assert_eq!(
- conn.process_new_packets().unwrap_err(),
- PeerMisbehaved::IllegalHelloRetryRequestWithWrongSessionId.into()
- );
- }
-
- #[cfg(feature = "tls12")]
- #[test]
- fn test_client_rejects_no_extended_master_secret_extension_when_require_ems_or_fips() {
- let mut config =
- ClientConfig::builder_with_provider(super::provider::default_provider().into())
- .with_safe_default_protocol_versions()
- .unwrap()
- .with_root_certificates(roots())
- .with_no_client_auth();
- if config.provider.fips() {
- assert!(config.require_ems);
- } else {
- config.require_ems = true;
- }
-
- let config = Arc::new(config);
- let mut conn =
- ClientConnection::new(config.clone(), ServerName::try_from("localhost").unwrap())
- .unwrap();
- let mut sent = Vec::new();
- conn.write_tls(&mut sent).unwrap();
-
- let sh = Message {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::ServerHello(ServerHelloPayload {
- random: Random::new(config.provider.secure_random).unwrap(),
- compression_method: Compression::Null,
- cipher_suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- legacy_version: ProtocolVersion::TLSv1_2,
- session_id: SessionId::empty(),
- extensions: Box::new(ServerExtensions::default()),
- }),
- )),
- };
- conn.read_tls(&mut sh.into_wire_bytes().as_slice())
- .unwrap();
-
- assert_eq!(
- conn.process_new_packets(),
- Err(PeerIncompatible::ExtendedMasterSecretExtensionRequired.into())
- );
- }
-
- #[test]
- fn cas_extension_in_client_hello_if_server_verifier_requests_it() {
- let cas_sending_server_verifier =
- ServerVerifierWithAuthorityNames(vec![DistinguishedName::from(b"hello".to_vec())]);
-
- for (protocol_version, cas_extension_expected) in
- [(&version::TLS12, false), (&version::TLS13, true)]
- {
- let client_hello = client_hello_sent_for_config(
- ClientConfig::builder_with_provider(super::provider::default_provider().into())
- .with_protocol_versions(&[protocol_version])
- .unwrap()
- .dangerous()
- .with_custom_certificate_verifier(Arc::new(cas_sending_server_verifier.clone()))
- .with_no_client_auth(),
- )
- .unwrap();
- assert_eq!(
- client_hello
- .extensions
- .certificate_authority_names
- .is_some(),
- cas_extension_expected
- );
- }
- }
-
- /// Regression test for <https://github.com/seanmonstar/reqwest/issues/2191>
- #[cfg(feature = "tls12")]
- #[test]
- fn test_client_with_custom_verifier_can_accept_ecdsa_sha1_signatures() {
- let verifier = Arc::new(ExpectSha1EcdsaVerifier::default());
- let config = ClientConfig::builder_with_provider(x25519_provider().into())
- .with_safe_default_protocol_versions()
- .unwrap()
- .dangerous()
- .with_custom_certificate_verifier(verifier.clone())
- .with_no_client_auth();
-
- let mut conn =
- ClientConnection::new(config.into(), ServerName::try_from("localhost").unwrap())
- .unwrap();
- let mut sent = Vec::new();
- conn.write_tls(&mut sent).unwrap();
-
- let sh = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::ServerHello(ServerHelloPayload {
- random: Random([0u8; 32]),
- compression_method: Compression::Null,
- cipher_suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- legacy_version: ProtocolVersion::TLSv1_2,
- session_id: SessionId::empty(),
- extensions: Box::new(ServerExtensions {
- extended_master_secret_ack: Some(()),
- ..ServerExtensions::default()
- }),
- }),
- )),
- };
- conn.read_tls(&mut sh.into_wire_bytes().as_slice())
- .unwrap();
- conn.process_new_packets().unwrap();
-
- let cert = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::Certificate(CertificateChain(vec![CertificateDer::from(
- &b"does not matter"[..],
- )])),
- )),
- };
- conn.read_tls(&mut cert.into_wire_bytes().as_slice())
- .unwrap();
- conn.process_new_packets().unwrap();
-
- let server_kx = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::ServerKeyExchange(ServerKeyExchangePayload::Known(
- ServerKeyExchange {
- dss: DigitallySignedStruct::new(
- SignatureScheme::ECDSA_SHA1_Legacy,
- b"also does not matter".to_vec(),
- ),
- params: ServerKeyExchangeParams::Ecdh(ServerEcdhParams {
- curve_params: EcParameters {
- curve_type: ECCurveType::NamedCurve,
- named_group: NamedGroup::X25519,
- },
- public: PayloadU8::new(vec![0xab; 32]),
- }),
- },
- )),
- )),
- };
- conn.read_tls(&mut server_kx.into_wire_bytes().as_slice())
- .unwrap();
- conn.process_new_packets().unwrap();
-
- let server_done = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::ServerHelloDone,
- )),
- };
- conn.read_tls(&mut server_done.into_wire_bytes().as_slice())
- .unwrap();
- conn.process_new_packets().unwrap();
-
- assert!(
- verifier
- .seen_sha1_signature
- .load(Ordering::SeqCst)
- );
- }
-
- #[derive(Debug, Default)]
- struct ExpectSha1EcdsaVerifier {
- seen_sha1_signature: AtomicBool,
- }
-
- impl ServerCertVerifier for ExpectSha1EcdsaVerifier {
- fn verify_server_cert(
- &self,
- _end_entity: &CertificateDer<'_>,
- _intermediates: &[CertificateDer<'_>],
- _server_name: &ServerName<'_>,
- _ocsp_response: &[u8],
- _now: UnixTime,
- ) -> Result<ServerCertVerified, Error> {
- Ok(ServerCertVerified::assertion())
- }
-
- fn verify_tls12_signature(
- &self,
- _message: &[u8],
- _cert: &CertificateDer<'_>,
- dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error> {
- assert_eq!(dss.scheme, SignatureScheme::ECDSA_SHA1_Legacy);
- self.seen_sha1_signature
- .store(true, Ordering::SeqCst);
- Ok(HandshakeSignatureValid::assertion())
- }
-
- #[cfg_attr(coverage_nightly, coverage(off))]
- fn verify_tls13_signature(
- &self,
- _message: &[u8],
- _cert: &CertificateDer<'_>,
- _dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error> {
- todo!()
- }
-
- fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
- vec![SignatureScheme::ECDSA_SHA1_Legacy]
- }
- }
-
- #[test]
- fn test_client_requiring_rpk_rejects_server_that_only_offers_x509_id_by_omission() {
- assert_eq!(
- client_requiring_rpk_receives_server_ee(ServerExtensions::default()),
- Err(PeerIncompatible::IncorrectCertificateTypeExtension.into())
- );
- }
-
- #[test]
- fn test_client_requiring_rpk_rejects_server_that_only_offers_x509_id() {
- assert_eq!(
- client_requiring_rpk_receives_server_ee(ServerExtensions {
- server_certificate_type: Some(CertificateType::X509),
- ..ServerExtensions::default()
- }),
- Err(PeerIncompatible::IncorrectCertificateTypeExtension.into())
- );
- }
-
- #[test]
- fn test_client_requiring_rpk_rejects_server_that_only_demands_x509_by_omission() {
- assert_eq!(
- client_requiring_rpk_receives_server_ee(ServerExtensions {
- server_certificate_type: Some(CertificateType::RawPublicKey),
- ..ServerExtensions::default()
- }),
- Err(PeerIncompatible::IncorrectCertificateTypeExtension.into())
- );
- }
-
- #[test]
- fn test_client_requiring_rpk_rejects_server_that_only_demands_x509() {
- assert_eq!(
- client_requiring_rpk_receives_server_ee(ServerExtensions {
- client_certificate_type: Some(CertificateType::X509),
- server_certificate_type: Some(CertificateType::RawPublicKey),
- ..ServerExtensions::default()
- }),
- Err(PeerIncompatible::IncorrectCertificateTypeExtension.into())
- );
- }
-
- #[test]
- fn test_client_requiring_rpk_accepts_rpk_server() {
- assert_eq!(
- client_requiring_rpk_receives_server_ee(ServerExtensions {
- client_certificate_type: Some(CertificateType::RawPublicKey),
- server_certificate_type: Some(CertificateType::RawPublicKey),
- ..ServerExtensions::default()
- }),
- Ok(())
- );
- }
-
- fn client_requiring_rpk_receives_server_ee(
- encrypted_extensions: ServerExtensions<'_>,
- ) -> Result<(), Error> {
- let fake_server_crypto = Arc::new(FakeServerCrypto::new());
- let mut conn = ClientConnection::new(
- client_config_for_rpk(fake_server_crypto.clone()).into(),
- ServerName::try_from("localhost").unwrap(),
- )
- .unwrap();
- let mut sent = Vec::new();
- conn.write_tls(&mut sent).unwrap();
-
- let sh = Message {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::ServerHello(ServerHelloPayload {
- random: Random([0; 32]),
- compression_method: Compression::Null,
- cipher_suite: CipherSuite::TLS13_AES_128_GCM_SHA256,
- legacy_version: ProtocolVersion::TLSv1_3,
- session_id: SessionId::empty(),
- extensions: Box::new(ServerExtensions {
- key_share: Some(KeyShareEntry {
- group: NamedGroup::X25519,
- payload: PayloadU16::new(vec![0xaa; 32]),
- }),
- ..ServerExtensions::default()
- }),
- }),
- )),
- };
- conn.read_tls(&mut sh.into_wire_bytes().as_slice())
- .unwrap();
- conn.process_new_packets().unwrap();
-
- let ee = Message {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::EncryptedExtensions(Box::new(encrypted_extensions)),
- )),
- };
-
- let mut encrypter = fake_server_crypto.server_handshake_encrypter();
- let enc_ee = encrypter
- .encrypt(PlainMessage::from(ee).borrow_outbound(), 0)
- .unwrap();
- conn.read_tls(&mut enc_ee.encode().as_slice())
- .unwrap();
- conn.process_new_packets().map(|_| ())
- }
-
- fn client_config_for_rpk(key_log: Arc<dyn KeyLog>) -> ClientConfig {
- let mut config = ClientConfig::builder_with_provider(x25519_provider().into())
- .with_protocol_versions(&[&version::TLS13])
- .unwrap()
- .dangerous()
- .with_custom_certificate_verifier(Arc::new(ServerVerifierRequiringRpk))
- .with_client_cert_resolver(Arc::new(AlwaysResolvesClientRawPublicKeys::new(Arc::new(
- client_certified_key(),
- ))));
- config.key_log = key_log;
- config
- }
-
- fn client_certified_key() -> CertifiedKey {
- let key = super::provider::default_provider()
- .key_provider
- .load_private_key(client_key())
- .unwrap();
- let public_key_as_cert = vec![CertificateDer::from(
- key.public_key()
- .unwrap()
- .as_ref()
- .to_vec(),
- )];
- CertifiedKey::new(public_key_as_cert, key)
- }
-
- fn client_key() -> PrivateKeyDer<'static> {
- PrivateKeyDer::from_pem_reader(
- &mut include_bytes!("../../../test-ca/rsa-2048/client.key").as_slice(),
- )
- .unwrap()
- }
-
- fn x25519_provider() -> CryptoProvider {
- // ensures X25519 is offered irrespective of cfg(feature = "fips"), which eases
- // creation of fake server messages.
- CryptoProvider {
- kx_groups: vec![super::provider::kx_group::X25519],
- ..super::provider::default_provider()
- }
- }
-
- #[derive(Clone, Debug)]
- struct ServerVerifierWithAuthorityNames(Vec<DistinguishedName>);
-
- impl ServerCertVerifier for ServerVerifierWithAuthorityNames {
- fn root_hint_subjects(&self) -> Option<&[DistinguishedName]> {
- Some(self.0.as_slice())
- }
-
- #[cfg_attr(coverage_nightly, coverage(off))]
- fn verify_server_cert(
- &self,
- _end_entity: &CertificateDer<'_>,
- _intermediates: &[CertificateDer<'_>],
- _server_name: &ServerName<'_>,
- _ocsp_response: &[u8],
- _now: UnixTime,
- ) -> Result<ServerCertVerified, Error> {
- unreachable!()
- }
-
- #[cfg_attr(coverage_nightly, coverage(off))]
- fn verify_tls12_signature(
- &self,
- _message: &[u8],
- _cert: &CertificateDer<'_>,
- _dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error> {
- unreachable!()
- }
-
- #[cfg_attr(coverage_nightly, coverage(off))]
- fn verify_tls13_signature(
- &self,
- _message: &[u8],
- _cert: &CertificateDer<'_>,
- _dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error> {
- unreachable!()
- }
-
- fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
- vec![SignatureScheme::RSA_PKCS1_SHA1]
- }
- }
-
- #[derive(Debug)]
- struct ServerVerifierRequiringRpk;
-
- impl ServerCertVerifier for ServerVerifierRequiringRpk {
- #[cfg_attr(coverage_nightly, coverage(off))]
- fn verify_server_cert(
- &self,
- _end_entity: &CertificateDer<'_>,
- _intermediates: &[CertificateDer<'_>],
- _server_name: &ServerName<'_>,
- _ocsp_response: &[u8],
- _now: UnixTime,
- ) -> Result<ServerCertVerified, Error> {
- todo!()
- }
-
- #[cfg_attr(coverage_nightly, coverage(off))]
- fn verify_tls12_signature(
- &self,
- _message: &[u8],
- _cert: &CertificateDer<'_>,
- _dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error> {
- todo!()
- }
-
- #[cfg_attr(coverage_nightly, coverage(off))]
- fn verify_tls13_signature(
- &self,
- _message: &[u8],
- _cert: &CertificateDer<'_>,
- _dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error> {
- todo!()
- }
-
- fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
- vec![SignatureScheme::RSA_PKCS1_SHA1]
- }
-
- fn requires_raw_public_keys(&self) -> bool {
- true
- }
- }
-
- #[derive(Debug)]
- struct FakeServerCrypto {
- server_handshake_secret: OnceLock<Vec<u8>>,
- }
-
- impl FakeServerCrypto {
- fn new() -> Self {
- Self {
- server_handshake_secret: OnceLock::new(),
- }
- }
-
- fn server_handshake_encrypter(&self) -> Box<dyn MessageEncrypter> {
- let cipher_suite = super::provider::cipher_suite::TLS13_AES_128_GCM_SHA256
- .tls13()
- .unwrap();
-
- let secret = self
- .server_handshake_secret
- .get()
- .unwrap();
-
- let expander = cipher_suite
- .hkdf_provider
- .expander_for_okm(&OkmBlock::new(secret));
-
- // Derive Encrypter
- let key = derive_traffic_key(expander.as_ref(), cipher_suite.aead_alg);
- let iv = derive_traffic_iv(expander.as_ref());
- cipher_suite.aead_alg.encrypter(key, iv)
- }
- }
-
- impl KeyLog for FakeServerCrypto {
- fn will_log(&self, _label: &str) -> bool {
- true
- }
-
- fn log(&self, label: &str, _client_random: &[u8], secret: &[u8]) {
- if label == "SERVER_HANDSHAKE_TRAFFIC_SECRET" {
- self.server_handshake_secret
- .set(secret.to_vec())
- .unwrap();
- }
- }
- }
-}
-
-// invalid with fips, as we can't offer X25519 separately
-#[cfg(all(
- feature = "aws-lc-rs",
- feature = "prefer-post-quantum",
- not(feature = "fips")
-))]
-#[test]
-fn hybrid_kx_component_share_offered_if_supported_separately() {
- let ch = client_hello_sent_for_config(
- ClientConfig::builder_with_provider(crate::crypto::aws_lc_rs::default_provider().into())
- .with_safe_default_protocol_versions()
- .unwrap()
- .with_root_certificates(roots())
- .with_no_client_auth(),
- )
- .unwrap();
-
- let key_shares = ch
- .extensions
- .key_shares
- .as_ref()
- .unwrap();
- assert_eq!(key_shares.len(), 2);
- assert_eq!(key_shares[0].group, NamedGroup::X25519MLKEM768);
- assert_eq!(key_shares[1].group, NamedGroup::X25519);
-}
-
-#[cfg(feature = "aws-lc-rs")]
-#[test]
-fn hybrid_kx_component_share_not_offered_unless_supported_separately() {
- use crate::crypto::aws_lc_rs;
- let provider = CryptoProvider {
- kx_groups: vec![aws_lc_rs::kx_group::X25519MLKEM768],
- ..aws_lc_rs::default_provider()
- };
- let ch = client_hello_sent_for_config(
- ClientConfig::builder_with_provider(provider.into())
- .with_safe_default_protocol_versions()
- .unwrap()
- .with_root_certificates(roots())
- .with_no_client_auth(),
- )
- .unwrap();
-
- let key_shares = ch
- .extensions
- .key_shares
- .as_ref()
- .unwrap();
- assert_eq!(key_shares.len(), 1);
- assert_eq!(key_shares[0].group, NamedGroup::X25519MLKEM768);
-}
-
-fn client_hello_sent_for_config(config: ClientConfig) -> Result<ClientHelloPayload, Error> {
- let mut conn =
- ClientConnection::new(config.into(), ServerName::try_from("localhost").unwrap())?;
- let mut bytes = Vec::new();
- conn.write_tls(&mut bytes).unwrap();
-
- let message = OutboundOpaqueMessage::read(&mut Reader::init(&bytes))
- .unwrap()
- .into_plain_message();
-
- match Message::try_from(message).unwrap() {
- Message {
- payload:
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::ClientHello(ch)),
- ..
- },
- ..
- } => Ok(ch),
- other => panic!("unexpected message {other:?}"),
- }
-}
-
-fn roots() -> RootCertStore {
- let mut r = RootCertStore::empty();
- r.add(CertificateDer::from_slice(include_bytes!(
- "../../../test-ca/rsa-2048/ca.der"
- )))
- .unwrap();
- r
-}
diff --git a/vendor/rustls/src/client/tls12.rs b/vendor/rustls/src/client/tls12.rs
deleted file mode 100644
index 0fc5acee..00000000
--- a/vendor/rustls/src/client/tls12.rs
+++ /dev/null
@@ -1,1372 +0,0 @@
-use alloc::borrow::ToOwned;
-use alloc::boxed::Box;
-use alloc::vec;
-use alloc::vec::Vec;
-
-use pki_types::ServerName;
-pub(super) use server_hello::CompleteServerHelloHandling;
-use subtle::ConstantTimeEq;
-
-use super::client_conn::ClientConnectionData;
-use super::hs::ClientContext;
-use crate::ConnectionTrafficSecrets;
-use crate::check::{inappropriate_handshake_message, inappropriate_message};
-use crate::client::common::{ClientAuthDetails, ServerCertDetails};
-use crate::client::{ClientConfig, hs};
-use crate::common_state::{CommonState, HandshakeKind, KxState, Side, State};
-use crate::conn::ConnectionRandoms;
-use crate::conn::kernel::{Direction, KernelContext, KernelState};
-use crate::crypto::KeyExchangeAlgorithm;
-use crate::enums::{AlertDescription, ContentType, HandshakeType, ProtocolVersion};
-use crate::error::{Error, InvalidMessage, PeerIncompatible, PeerMisbehaved};
-use crate::hash_hs::HandshakeHash;
-use crate::log::{debug, trace, warn};
-use crate::msgs::base::{Payload, PayloadU8, PayloadU16};
-use crate::msgs::ccs::ChangeCipherSpecPayload;
-use crate::msgs::handshake::{
- CertificateChain, ClientDhParams, ClientEcdhParams, ClientKeyExchangeParams,
- HandshakeMessagePayload, HandshakePayload, NewSessionTicketPayload,
- NewSessionTicketPayloadTls13, ServerKeyExchangeParams, SessionId,
-};
-use crate::msgs::message::{Message, MessagePayload};
-use crate::msgs::persist;
-use crate::sign::Signer;
-use crate::suites::{PartiallyExtractedSecrets, SupportedCipherSuite};
-use crate::sync::Arc;
-use crate::tls12::{self, ConnectionSecrets, Tls12CipherSuite};
-use crate::verify::{self, DigitallySignedStruct};
-
-mod server_hello {
- use super::*;
- use crate::client::hs::{ClientHelloInput, ClientSessionValue};
- use crate::msgs::handshake::ServerHelloPayload;
-
- pub(in crate::client) struct CompleteServerHelloHandling {
- pub(in crate::client) randoms: ConnectionRandoms,
- pub(in crate::client) transcript: HandshakeHash,
- pub(in crate::client) input: ClientHelloInput,
- }
-
- impl CompleteServerHelloHandling {
- pub(in crate::client) fn handle_server_hello(
- mut self,
- cx: &mut ClientContext<'_>,
- suite: &'static Tls12CipherSuite,
- server_hello: &ServerHelloPayload,
- tls13_supported: bool,
- ) -> hs::NextStateOrError<'static> {
- self.randoms
- .server
- .clone_from_slice(&server_hello.random.0[..]);
-
- // Look for TLS1.3 downgrade signal in server random
- // both the server random and TLS12_DOWNGRADE_SENTINEL are
- // public values and don't require constant time comparison
- let has_downgrade_marker = self.randoms.server[24..] == tls12::DOWNGRADE_SENTINEL;
- if tls13_supported && has_downgrade_marker {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::AttemptedDowngradeToTls12WhenTls13IsSupported,
- )
- });
- }
-
- // If we didn't have an input session to resume, and we sent a session ID,
- // that implies we sent a TLS 1.3 legacy_session_id for compatibility purposes.
- // In this instance since we're now continuing a TLS 1.2 handshake the server
- // should not have echoed it back: it's a randomly generated session ID it couldn't
- // have known.
- if self.input.resuming.is_none()
- && !self.input.session_id.is_empty()
- && self.input.session_id == server_hello.session_id
- {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::ServerEchoedCompatibilitySessionId,
- )
- });
- }
-
- let ClientHelloInput {
- config,
- server_name,
- ..
- } = self.input;
-
- let resuming_session = self
- .input
- .resuming
- .and_then(|resuming| match resuming.value {
- ClientSessionValue::Tls12(inner) => Some(inner),
- ClientSessionValue::Tls13(_) => None,
- });
-
- // Doing EMS?
- let using_ems = server_hello
- .extended_master_secret_ack
- .is_some();
- if config.require_ems && !using_ems {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::HandshakeFailure,
- PeerIncompatible::ExtendedMasterSecretExtensionRequired,
- )
- });
- }
-
- // Might the server send a ticket?
- let must_issue_new_ticket = if server_hello
- .session_ticket_ack
- .is_some()
- {
- debug!("Server supports tickets");
- true
- } else {
- false
- };
-
- // Might the server send a CertificateStatus between Certificate and
- // ServerKeyExchange?
- let may_send_cert_status = server_hello
- .certificate_status_request_ack
- .is_some();
- if may_send_cert_status {
- debug!("Server may staple OCSP response");
- }
-
- // See if we're successfully resuming.
- if let Some(resuming) = resuming_session {
- if resuming.session_id == server_hello.session_id {
- debug!("Server agreed to resume");
-
- // Is the server telling lies about the ciphersuite?
- if resuming.suite() != suite {
- return Err(PeerMisbehaved::ResumptionOfferedWithVariedCipherSuite.into());
- }
-
- // And about EMS support?
- if resuming.extended_ms() != using_ems {
- return Err(PeerMisbehaved::ResumptionOfferedWithVariedEms.into());
- }
-
- let secrets =
- ConnectionSecrets::new_resume(self.randoms, suite, resuming.secret());
- config.key_log.log(
- "CLIENT_RANDOM",
- &secrets.randoms.client,
- &secrets.master_secret,
- );
- cx.common
- .start_encryption_tls12(&secrets, Side::Client);
-
- // Since we're resuming, we verified the certificate and
- // proof of possession in the prior session.
- cx.common.peer_certificates = Some(
- resuming
- .server_cert_chain()
- .clone()
- .into_owned(),
- );
- cx.common.handshake_kind = Some(HandshakeKind::Resumed);
- let cert_verified = verify::ServerCertVerified::assertion();
- let sig_verified = verify::HandshakeSignatureValid::assertion();
-
- return if must_issue_new_ticket {
- Ok(Box::new(ExpectNewTicket {
- config,
- secrets,
- resuming_session: Some(resuming),
- session_id: server_hello.session_id,
- server_name,
- using_ems,
- transcript: self.transcript,
- resuming: true,
- cert_verified,
- sig_verified,
- }))
- } else {
- Ok(Box::new(ExpectCcs {
- config,
- secrets,
- resuming_session: Some(resuming),
- session_id: server_hello.session_id,
- server_name,
- using_ems,
- transcript: self.transcript,
- ticket: None,
- resuming: true,
- cert_verified,
- sig_verified,
- }))
- };
- }
- }
-
- cx.common.handshake_kind = Some(HandshakeKind::Full);
- Ok(Box::new(ExpectCertificate {
- config,
- resuming_session: None,
- session_id: server_hello.session_id,
- server_name,
- randoms: self.randoms,
- using_ems,
- transcript: self.transcript,
- suite,
- may_send_cert_status,
- must_issue_new_ticket,
- }))
- }
- }
-}
-
-struct ExpectCertificate {
- config: Arc<ClientConfig>,
- resuming_session: Option<persist::Tls12ClientSessionValue>,
- session_id: SessionId,
- server_name: ServerName<'static>,
- randoms: ConnectionRandoms,
- using_ems: bool,
- transcript: HandshakeHash,
- pub(super) suite: &'static Tls12CipherSuite,
- may_send_cert_status: bool,
- must_issue_new_ticket: bool,
-}
-
-impl State<ClientConnectionData> for ExpectCertificate {
- fn handle<'m>(
- mut self: Box<Self>,
- _cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- self.transcript.add_message(&m);
- let server_cert_chain = require_handshake_msg_move!(
- m,
- HandshakeType::Certificate,
- HandshakePayload::Certificate
- )?;
-
- if self.may_send_cert_status {
- Ok(Box::new(ExpectCertificateStatusOrServerKx {
- config: self.config,
- resuming_session: self.resuming_session,
- session_id: self.session_id,
- server_name: self.server_name,
- randoms: self.randoms,
- using_ems: self.using_ems,
- transcript: self.transcript,
- suite: self.suite,
- server_cert_chain,
- must_issue_new_ticket: self.must_issue_new_ticket,
- }))
- } else {
- let server_cert = ServerCertDetails::new(server_cert_chain, vec![]);
-
- Ok(Box::new(ExpectServerKx {
- config: self.config,
- resuming_session: self.resuming_session,
- session_id: self.session_id,
- server_name: self.server_name,
- randoms: self.randoms,
- using_ems: self.using_ems,
- transcript: self.transcript,
- suite: self.suite,
- server_cert,
- must_issue_new_ticket: self.must_issue_new_ticket,
- }))
- }
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-struct ExpectCertificateStatusOrServerKx<'m> {
- config: Arc<ClientConfig>,
- resuming_session: Option<persist::Tls12ClientSessionValue>,
- session_id: SessionId,
- server_name: ServerName<'static>,
- randoms: ConnectionRandoms,
- using_ems: bool,
- transcript: HandshakeHash,
- suite: &'static Tls12CipherSuite,
- server_cert_chain: CertificateChain<'m>,
- must_issue_new_ticket: bool,
-}
-
-impl State<ClientConnectionData> for ExpectCertificateStatusOrServerKx<'_> {
- fn handle<'m>(
- self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- match m.payload {
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::ServerKeyExchange(..)),
- ..
- } => Box::new(ExpectServerKx {
- config: self.config,
- resuming_session: self.resuming_session,
- session_id: self.session_id,
- server_name: self.server_name,
- randoms: self.randoms,
- using_ems: self.using_ems,
- transcript: self.transcript,
- suite: self.suite,
- server_cert: ServerCertDetails::new(self.server_cert_chain, vec![]),
- must_issue_new_ticket: self.must_issue_new_ticket,
- })
- .handle(cx, m),
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::CertificateStatus(..)),
- ..
- } => Box::new(ExpectCertificateStatus {
- config: self.config,
- resuming_session: self.resuming_session,
- session_id: self.session_id,
- server_name: self.server_name,
- randoms: self.randoms,
- using_ems: self.using_ems,
- transcript: self.transcript,
- suite: self.suite,
- server_cert_chain: self.server_cert_chain,
- must_issue_new_ticket: self.must_issue_new_ticket,
- })
- .handle(cx, m),
- payload => Err(inappropriate_handshake_message(
- &payload,
- &[ContentType::Handshake],
- &[
- HandshakeType::ServerKeyExchange,
- HandshakeType::CertificateStatus,
- ],
- )),
- }
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- Box::new(ExpectCertificateStatusOrServerKx {
- config: self.config,
- resuming_session: self.resuming_session,
- session_id: self.session_id,
- server_name: self.server_name,
- randoms: self.randoms,
- using_ems: self.using_ems,
- transcript: self.transcript,
- suite: self.suite,
- server_cert_chain: self.server_cert_chain.into_owned(),
- must_issue_new_ticket: self.must_issue_new_ticket,
- })
- }
-}
-
-struct ExpectCertificateStatus<'a> {
- config: Arc<ClientConfig>,
- resuming_session: Option<persist::Tls12ClientSessionValue>,
- session_id: SessionId,
- server_name: ServerName<'static>,
- randoms: ConnectionRandoms,
- using_ems: bool,
- transcript: HandshakeHash,
- suite: &'static Tls12CipherSuite,
- server_cert_chain: CertificateChain<'a>,
- must_issue_new_ticket: bool,
-}
-
-impl State<ClientConnectionData> for ExpectCertificateStatus<'_> {
- fn handle<'m>(
- mut self: Box<Self>,
- _cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- self.transcript.add_message(&m);
- let server_cert_ocsp_response = require_handshake_msg_move!(
- m,
- HandshakeType::CertificateStatus,
- HandshakePayload::CertificateStatus
- )?
- .into_inner();
-
- trace!(
- "Server stapled OCSP response is {:?}",
- &server_cert_ocsp_response
- );
-
- let server_cert = ServerCertDetails::new(self.server_cert_chain, server_cert_ocsp_response);
-
- Ok(Box::new(ExpectServerKx {
- config: self.config,
- resuming_session: self.resuming_session,
- session_id: self.session_id,
- server_name: self.server_name,
- randoms: self.randoms,
- using_ems: self.using_ems,
- transcript: self.transcript,
- suite: self.suite,
- server_cert,
- must_issue_new_ticket: self.must_issue_new_ticket,
- }))
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- Box::new(ExpectCertificateStatus {
- config: self.config,
- resuming_session: self.resuming_session,
- session_id: self.session_id,
- server_name: self.server_name,
- randoms: self.randoms,
- using_ems: self.using_ems,
- transcript: self.transcript,
- suite: self.suite,
- server_cert_chain: self.server_cert_chain.into_owned(),
- must_issue_new_ticket: self.must_issue_new_ticket,
- })
- }
-}
-
-struct ExpectServerKx<'a> {
- config: Arc<ClientConfig>,
- resuming_session: Option<persist::Tls12ClientSessionValue>,
- session_id: SessionId,
- server_name: ServerName<'static>,
- randoms: ConnectionRandoms,
- using_ems: bool,
- transcript: HandshakeHash,
- suite: &'static Tls12CipherSuite,
- server_cert: ServerCertDetails<'a>,
- must_issue_new_ticket: bool,
-}
-
-impl State<ClientConnectionData> for ExpectServerKx<'_> {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- let opaque_kx = require_handshake_msg!(
- m,
- HandshakeType::ServerKeyExchange,
- HandshakePayload::ServerKeyExchange
- )?;
- self.transcript.add_message(&m);
-
- let kx = opaque_kx
- .unwrap_given_kxa(self.suite.kx)
- .ok_or_else(|| {
- cx.common.send_fatal_alert(
- AlertDescription::DecodeError,
- InvalidMessage::MissingKeyExchange,
- )
- })?;
-
- // Save the signature and signed parameters for later verification.
- let mut kx_params = Vec::new();
- kx.params.encode(&mut kx_params);
- let server_kx = ServerKxDetails::new(kx_params, kx.dss);
-
- #[cfg_attr(not(feature = "logging"), allow(unused_variables))]
- {
- match &kx.params {
- ServerKeyExchangeParams::Ecdh(ecdhe) => {
- debug!("ECDHE curve is {:?}", ecdhe.curve_params)
- }
- ServerKeyExchangeParams::Dh(dhe) => {
- debug!("DHE params are p = {:?}, g = {:?}", dhe.dh_p, dhe.dh_g)
- }
- }
- }
-
- Ok(Box::new(ExpectServerDoneOrCertReq {
- config: self.config,
- resuming_session: self.resuming_session,
- session_id: self.session_id,
- server_name: self.server_name,
- randoms: self.randoms,
- using_ems: self.using_ems,
- transcript: self.transcript,
- suite: self.suite,
- server_cert: self.server_cert,
- server_kx,
- must_issue_new_ticket: self.must_issue_new_ticket,
- }))
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- Box::new(ExpectServerKx {
- config: self.config,
- resuming_session: self.resuming_session,
- session_id: self.session_id,
- server_name: self.server_name,
- randoms: self.randoms,
- using_ems: self.using_ems,
- transcript: self.transcript,
- suite: self.suite,
- server_cert: self.server_cert.into_owned(),
- must_issue_new_ticket: self.must_issue_new_ticket,
- })
- }
-}
-
-fn emit_certificate(
- transcript: &mut HandshakeHash,
- cert_chain: CertificateChain<'static>,
- common: &mut CommonState,
-) {
- let cert = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::handshake(HandshakeMessagePayload(HandshakePayload::Certificate(
- cert_chain,
- ))),
- };
-
- transcript.add_message(&cert);
- common.send_msg(cert, false);
-}
-
-fn emit_client_kx(
- transcript: &mut HandshakeHash,
- kxa: KeyExchangeAlgorithm,
- common: &mut CommonState,
- pub_key: &[u8],
-) {
- let mut buf = Vec::new();
- match kxa {
- KeyExchangeAlgorithm::ECDHE => ClientKeyExchangeParams::Ecdh(ClientEcdhParams {
- public: PayloadU8::new(pub_key.to_vec()),
- }),
- KeyExchangeAlgorithm::DHE => ClientKeyExchangeParams::Dh(ClientDhParams {
- public: PayloadU16::new(pub_key.to_vec()),
- }),
- }
- .encode(&mut buf);
- let pubkey = Payload::new(buf);
-
- let ckx = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::ClientKeyExchange(pubkey),
- )),
- };
-
- transcript.add_message(&ckx);
- common.send_msg(ckx, false);
-}
-
-fn emit_certverify(
- transcript: &mut HandshakeHash,
- signer: &dyn Signer,
- common: &mut CommonState,
-) -> Result<(), Error> {
- let message = transcript
- .take_handshake_buf()
- .ok_or_else(|| Error::General("Expected transcript".to_owned()))?;
-
- let scheme = signer.scheme();
- let sig = signer.sign(&message)?;
- let body = DigitallySignedStruct::new(scheme, sig);
-
- let m = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::CertificateVerify(body),
- )),
- };
-
- transcript.add_message(&m);
- common.send_msg(m, false);
- Ok(())
-}
-
-fn emit_ccs(common: &mut CommonState) {
- let ccs = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::ChangeCipherSpec(ChangeCipherSpecPayload {}),
- };
-
- common.send_msg(ccs, false);
-}
-
-fn emit_finished(
- secrets: &ConnectionSecrets,
- transcript: &mut HandshakeHash,
- common: &mut CommonState,
-) {
- let vh = transcript.current_hash();
- let verify_data = secrets.client_verify_data(&vh);
- let verify_data_payload = Payload::new(verify_data);
-
- let f = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::handshake(HandshakeMessagePayload(HandshakePayload::Finished(
- verify_data_payload,
- ))),
- };
-
- transcript.add_message(&f);
- common.send_msg(f, true);
-}
-
-struct ServerKxDetails {
- kx_params: Vec<u8>,
- kx_sig: DigitallySignedStruct,
-}
-
-impl ServerKxDetails {
- fn new(params: Vec<u8>, sig: DigitallySignedStruct) -> Self {
- Self {
- kx_params: params,
- kx_sig: sig,
- }
- }
-}
-
-// --- Either a CertificateRequest, or a ServerHelloDone. ---
-// Existence of the CertificateRequest tells us the server is asking for
-// client auth. Otherwise we go straight to ServerHelloDone.
-struct ExpectServerDoneOrCertReq<'a> {
- config: Arc<ClientConfig>,
- resuming_session: Option<persist::Tls12ClientSessionValue>,
- session_id: SessionId,
- server_name: ServerName<'static>,
- randoms: ConnectionRandoms,
- using_ems: bool,
- transcript: HandshakeHash,
- suite: &'static Tls12CipherSuite,
- server_cert: ServerCertDetails<'a>,
- server_kx: ServerKxDetails,
- must_issue_new_ticket: bool,
-}
-
-impl State<ClientConnectionData> for ExpectServerDoneOrCertReq<'_> {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- if matches!(
- m.payload,
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::CertificateRequest(_)),
- ..
- }
- ) {
- Box::new(ExpectCertificateRequest {
- config: self.config,
- resuming_session: self.resuming_session,
- session_id: self.session_id,
- server_name: self.server_name,
- randoms: self.randoms,
- using_ems: self.using_ems,
- transcript: self.transcript,
- suite: self.suite,
- server_cert: self.server_cert,
- server_kx: self.server_kx,
- must_issue_new_ticket: self.must_issue_new_ticket,
- })
- .handle(cx, m)
- } else {
- self.transcript.abandon_client_auth();
-
- Box::new(ExpectServerDone {
- config: self.config,
- resuming_session: self.resuming_session,
- session_id: self.session_id,
- server_name: self.server_name,
- randoms: self.randoms,
- using_ems: self.using_ems,
- transcript: self.transcript,
- suite: self.suite,
- server_cert: self.server_cert,
- server_kx: self.server_kx,
- client_auth: None,
- must_issue_new_ticket: self.must_issue_new_ticket,
- })
- .handle(cx, m)
- }
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- Box::new(ExpectServerDoneOrCertReq {
- config: self.config,
- resuming_session: self.resuming_session,
- session_id: self.session_id,
- server_name: self.server_name,
- randoms: self.randoms,
- using_ems: self.using_ems,
- transcript: self.transcript,
- suite: self.suite,
- server_cert: self.server_cert.into_owned(),
- server_kx: self.server_kx,
- must_issue_new_ticket: self.must_issue_new_ticket,
- })
- }
-}
-
-struct ExpectCertificateRequest<'a> {
- config: Arc<ClientConfig>,
- resuming_session: Option<persist::Tls12ClientSessionValue>,
- session_id: SessionId,
- server_name: ServerName<'static>,
- randoms: ConnectionRandoms,
- using_ems: bool,
- transcript: HandshakeHash,
- suite: &'static Tls12CipherSuite,
- server_cert: ServerCertDetails<'a>,
- server_kx: ServerKxDetails,
- must_issue_new_ticket: bool,
-}
-
-impl State<ClientConnectionData> for ExpectCertificateRequest<'_> {
- fn handle<'m>(
- mut self: Box<Self>,
- _cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- let certreq = require_handshake_msg!(
- m,
- HandshakeType::CertificateRequest,
- HandshakePayload::CertificateRequest
- )?;
- self.transcript.add_message(&m);
- debug!("Got CertificateRequest {certreq:?}");
-
- // The RFC jovially describes the design here as 'somewhat complicated'
- // and 'somewhat underspecified'. So thanks for that.
- //
- // We ignore certreq.certtypes as a result, since the information it contains
- // is entirely duplicated in certreq.sigschemes.
-
- const NO_CONTEXT: Option<Vec<u8>> = None; // TLS 1.2 doesn't use a context.
- let no_compression = None; // or compression
- let client_auth = ClientAuthDetails::resolve(
- self.config
- .client_auth_cert_resolver
- .as_ref(),
- Some(&certreq.canames),
- &certreq.sigschemes,
- NO_CONTEXT,
- no_compression,
- );
-
- Ok(Box::new(ExpectServerDone {
- config: self.config,
- resuming_session: self.resuming_session,
- session_id: self.session_id,
- server_name: self.server_name,
- randoms: self.randoms,
- using_ems: self.using_ems,
- transcript: self.transcript,
- suite: self.suite,
- server_cert: self.server_cert,
- server_kx: self.server_kx,
- client_auth: Some(client_auth),
- must_issue_new_ticket: self.must_issue_new_ticket,
- }))
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- Box::new(ExpectCertificateRequest {
- config: self.config,
- resuming_session: self.resuming_session,
- session_id: self.session_id,
- server_name: self.server_name,
- randoms: self.randoms,
- using_ems: self.using_ems,
- transcript: self.transcript,
- suite: self.suite,
- server_cert: self.server_cert.into_owned(),
- server_kx: self.server_kx,
- must_issue_new_ticket: self.must_issue_new_ticket,
- })
- }
-}
-
-struct ExpectServerDone<'a> {
- config: Arc<ClientConfig>,
- resuming_session: Option<persist::Tls12ClientSessionValue>,
- session_id: SessionId,
- server_name: ServerName<'static>,
- randoms: ConnectionRandoms,
- using_ems: bool,
- transcript: HandshakeHash,
- suite: &'static Tls12CipherSuite,
- server_cert: ServerCertDetails<'a>,
- server_kx: ServerKxDetails,
- client_auth: Option<ClientAuthDetails>,
- must_issue_new_ticket: bool,
-}
-
-impl State<ClientConnectionData> for ExpectServerDone<'_> {
- fn handle<'m>(
- self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- match m.payload {
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::ServerHelloDone),
- ..
- } => {}
- payload => {
- return Err(inappropriate_handshake_message(
- &payload,
- &[ContentType::Handshake],
- &[HandshakeType::ServerHelloDone],
- ));
- }
- }
-
- let mut st = *self;
- st.transcript.add_message(&m);
-
- cx.common.check_aligned_handshake()?;
-
- trace!("Server cert is {:?}", st.server_cert.cert_chain);
- debug!("Server DNS name is {:?}", st.server_name);
-
- let suite = st.suite;
-
- // 1. Verify the cert chain.
- // 2. Verify that the top certificate signed their kx.
- // 3. If doing client auth, send our Certificate.
- // 4. Complete the key exchange:
- // a) generate our kx pair
- // b) emit a ClientKeyExchange containing it
- // c) if doing client auth, emit a CertificateVerify
- // d) derive the shared keys
- // e) emit a CCS
- // f) use the derived keys to start encryption
- // 5. emit a Finished, our first encrypted message under the new keys.
-
- // 1.
- let (end_entity, intermediates) = st
- .server_cert
- .cert_chain
- .split_first()
- .ok_or(Error::NoCertificatesPresented)?;
-
- let now = st.config.current_time()?;
-
- let cert_verified = st
- .config
- .verifier
- .verify_server_cert(
- end_entity,
- intermediates,
- &st.server_name,
- &st.server_cert.ocsp_response,
- now,
- )
- .map_err(|err| {
- cx.common
- .send_cert_verify_error_alert(err)
- })?;
-
- // 2.
- // Build up the contents of the signed message.
- // It's ClientHello.random || ServerHello.random || ServerKeyExchange.params
- let sig_verified = {
- let mut message = Vec::new();
- message.extend_from_slice(&st.randoms.client);
- message.extend_from_slice(&st.randoms.server);
- message.extend_from_slice(&st.server_kx.kx_params);
-
- // Check the signature is compatible with the ciphersuite.
- let sig = &st.server_kx.kx_sig;
- if !SupportedCipherSuite::from(suite)
- .usable_for_signature_algorithm(sig.scheme.algorithm())
- {
- warn!(
- "peer signed kx with wrong algorithm (got {:?} expect {:?})",
- sig.scheme.algorithm(),
- suite.sign
- );
- return Err(PeerMisbehaved::SignedKxWithWrongAlgorithm.into());
- }
-
- st.config
- .verifier
- .verify_tls12_signature(&message, end_entity, sig)
- .map_err(|err| {
- cx.common
- .send_cert_verify_error_alert(err)
- })?
- };
- cx.common.peer_certificates = Some(st.server_cert.cert_chain.into_owned());
-
- // 3.
- if let Some(client_auth) = &st.client_auth {
- let certs = match client_auth {
- ClientAuthDetails::Empty { .. } => CertificateChain::default(),
- ClientAuthDetails::Verify { certkey, .. } => CertificateChain(certkey.cert.clone()),
- };
- emit_certificate(&mut st.transcript, certs, cx.common);
- }
-
- // 4a.
- let kx_params = tls12::decode_kx_params::<ServerKeyExchangeParams>(
- st.suite.kx,
- cx.common,
- &st.server_kx.kx_params,
- )?;
- let maybe_skxg = match &kx_params {
- ServerKeyExchangeParams::Ecdh(ecdh) => st
- .config
- .find_kx_group(ecdh.curve_params.named_group, ProtocolVersion::TLSv1_2),
- ServerKeyExchangeParams::Dh(dh) => {
- let ffdhe_group = dh.as_ffdhe_group();
-
- st.config
- .provider
- .kx_groups
- .iter()
- .find(|kxg| kxg.ffdhe_group() == Some(ffdhe_group))
- .copied()
- }
- };
- let Some(skxg) = maybe_skxg else {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::SelectedUnofferedKxGroup,
- ));
- };
- cx.common.kx_state = KxState::Start(skxg);
- let kx = skxg.start()?;
-
- // 4b.
- let mut transcript = st.transcript;
- emit_client_kx(&mut transcript, st.suite.kx, cx.common, kx.pub_key());
- // Note: EMS handshake hash only runs up to ClientKeyExchange.
- let ems_seed = st
- .using_ems
- .then(|| transcript.current_hash());
-
- // 4c.
- if let Some(ClientAuthDetails::Verify { signer, .. }) = &st.client_auth {
- emit_certverify(&mut transcript, signer.as_ref(), cx.common)?;
- }
-
- // 4d. Derive secrets.
- // An alert at this point will be sent in plaintext. That must happen
- // prior to the CCS, or else the peer will try to decrypt it.
- let secrets = ConnectionSecrets::from_key_exchange(
- kx,
- kx_params.pub_key(),
- ems_seed,
- st.randoms,
- suite,
- )
- .map_err(|err| {
- cx.common
- .send_fatal_alert(AlertDescription::IllegalParameter, err)
- })?;
- cx.common.kx_state.complete();
-
- // 4e. CCS. We are definitely going to switch on encryption.
- emit_ccs(cx.common);
-
- // 4f. Now commit secrets.
- st.config.key_log.log(
- "CLIENT_RANDOM",
- &secrets.randoms.client,
- &secrets.master_secret,
- );
- cx.common
- .start_encryption_tls12(&secrets, Side::Client);
- cx.common
- .record_layer
- .start_encrypting();
-
- // 5.
- emit_finished(&secrets, &mut transcript, cx.common);
-
- if st.must_issue_new_ticket {
- Ok(Box::new(ExpectNewTicket {
- config: st.config,
- secrets,
- resuming_session: st.resuming_session,
- session_id: st.session_id,
- server_name: st.server_name,
- using_ems: st.using_ems,
- transcript,
- resuming: false,
- cert_verified,
- sig_verified,
- }))
- } else {
- Ok(Box::new(ExpectCcs {
- config: st.config,
- secrets,
- resuming_session: st.resuming_session,
- session_id: st.session_id,
- server_name: st.server_name,
- using_ems: st.using_ems,
- transcript,
- ticket: None,
- resuming: false,
- cert_verified,
- sig_verified,
- }))
- }
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- Box::new(ExpectServerDone {
- config: self.config,
- resuming_session: self.resuming_session,
- session_id: self.session_id,
- server_name: self.server_name,
- randoms: self.randoms,
- using_ems: self.using_ems,
- transcript: self.transcript,
- suite: self.suite,
- server_cert: self.server_cert.into_owned(),
- server_kx: self.server_kx,
- client_auth: self.client_auth,
- must_issue_new_ticket: self.must_issue_new_ticket,
- })
- }
-}
-
-struct ExpectNewTicket {
- config: Arc<ClientConfig>,
- secrets: ConnectionSecrets,
- resuming_session: Option<persist::Tls12ClientSessionValue>,
- session_id: SessionId,
- server_name: ServerName<'static>,
- using_ems: bool,
- transcript: HandshakeHash,
- resuming: bool,
- cert_verified: verify::ServerCertVerified,
- sig_verified: verify::HandshakeSignatureValid,
-}
-
-impl State<ClientConnectionData> for ExpectNewTicket {
- fn handle<'m>(
- mut self: Box<Self>,
- _cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- self.transcript.add_message(&m);
-
- let nst = require_handshake_msg_move!(
- m,
- HandshakeType::NewSessionTicket,
- HandshakePayload::NewSessionTicket
- )?;
-
- Ok(Box::new(ExpectCcs {
- config: self.config,
- secrets: self.secrets,
- resuming_session: self.resuming_session,
- session_id: self.session_id,
- server_name: self.server_name,
- using_ems: self.using_ems,
- transcript: self.transcript,
- ticket: Some(nst),
- resuming: self.resuming,
- cert_verified: self.cert_verified,
- sig_verified: self.sig_verified,
- }))
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-// -- Waiting for their CCS --
-struct ExpectCcs {
- config: Arc<ClientConfig>,
- secrets: ConnectionSecrets,
- resuming_session: Option<persist::Tls12ClientSessionValue>,
- session_id: SessionId,
- server_name: ServerName<'static>,
- using_ems: bool,
- transcript: HandshakeHash,
- ticket: Option<NewSessionTicketPayload>,
- resuming: bool,
- cert_verified: verify::ServerCertVerified,
- sig_verified: verify::HandshakeSignatureValid,
-}
-
-impl State<ClientConnectionData> for ExpectCcs {
- fn handle<'m>(
- self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- match m.payload {
- MessagePayload::ChangeCipherSpec(..) => {}
- payload => {
- return Err(inappropriate_message(
- &payload,
- &[ContentType::ChangeCipherSpec],
- ));
- }
- }
- // CCS should not be received interleaved with fragmented handshake-level
- // message.
- cx.common.check_aligned_handshake()?;
-
- // Note: msgs layer validates trivial contents of CCS.
- cx.common
- .record_layer
- .start_decrypting();
-
- Ok(Box::new(ExpectFinished {
- config: self.config,
- secrets: self.secrets,
- resuming_session: self.resuming_session,
- session_id: self.session_id,
- server_name: self.server_name,
- using_ems: self.using_ems,
- transcript: self.transcript,
- ticket: self.ticket,
- resuming: self.resuming,
- cert_verified: self.cert_verified,
- sig_verified: self.sig_verified,
- }))
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-struct ExpectFinished {
- config: Arc<ClientConfig>,
- resuming_session: Option<persist::Tls12ClientSessionValue>,
- session_id: SessionId,
- server_name: ServerName<'static>,
- using_ems: bool,
- transcript: HandshakeHash,
- ticket: Option<NewSessionTicketPayload>,
- secrets: ConnectionSecrets,
- resuming: bool,
- cert_verified: verify::ServerCertVerified,
- sig_verified: verify::HandshakeSignatureValid,
-}
-
-impl ExpectFinished {
- // -- Waiting for their finished --
- fn save_session(&mut self, cx: &ClientContext<'_>) {
- // Save a ticket. If we got a new ticket, save that. Otherwise, save the
- // original ticket again.
- let (mut ticket, lifetime) = match self.ticket.take() {
- Some(nst) => (nst.ticket, nst.lifetime_hint),
- None => (Arc::new(PayloadU16::empty()), 0),
- };
-
- if ticket.0.is_empty() {
- if let Some(resuming_session) = &mut self.resuming_session {
- ticket = resuming_session.ticket();
- }
- }
-
- if self.session_id.is_empty() && ticket.0.is_empty() {
- debug!("Session not saved: server didn't allocate id or ticket");
- return;
- }
-
- let Ok(now) = self.config.current_time() else {
- debug!("Could not get current time");
- return;
- };
-
- let session_value = persist::Tls12ClientSessionValue::new(
- self.secrets.suite(),
- self.session_id,
- ticket,
- self.secrets.master_secret(),
- cx.common
- .peer_certificates
- .clone()
- .unwrap_or_default(),
- &self.config.verifier,
- &self.config.client_auth_cert_resolver,
- now,
- lifetime,
- self.using_ems,
- );
-
- self.config
- .resumption
- .store
- .set_tls12_session(self.server_name.clone(), session_value);
- }
-}
-
-impl State<ClientConnectionData> for ExpectFinished {
- fn handle<'m>(
- self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- let mut st = *self;
- let finished =
- require_handshake_msg!(m, HandshakeType::Finished, HandshakePayload::Finished)?;
-
- cx.common.check_aligned_handshake()?;
-
- // Work out what verify_data we expect.
- let vh = st.transcript.current_hash();
- let expect_verify_data = st.secrets.server_verify_data(&vh);
-
- // Constant-time verification of this is relatively unimportant: they only
- // get one chance. But it can't hurt.
- let _fin_verified =
- match ConstantTimeEq::ct_eq(&expect_verify_data[..], finished.bytes()).into() {
- true => verify::FinishedMessageVerified::assertion(),
- false => {
- return Err(cx
- .common
- .send_fatal_alert(AlertDescription::DecryptError, Error::DecryptError));
- }
- };
-
- // Hash this message too.
- st.transcript.add_message(&m);
-
- st.save_session(cx);
-
- if st.resuming {
- emit_ccs(cx.common);
- cx.common
- .record_layer
- .start_encrypting();
- emit_finished(&st.secrets, &mut st.transcript, cx.common);
- }
-
- cx.common
- .start_traffic(&mut cx.sendable_plaintext);
- Ok(Box::new(ExpectTraffic {
- secrets: st.secrets,
- _cert_verified: st.cert_verified,
- _sig_verified: st.sig_verified,
- _fin_verified,
- }))
- }
-
- // we could not decrypt the encrypted handshake message with session resumption
- // this might mean that the ticket was invalid for some reason, so we remove it
- // from the store to restart a session from scratch
- fn handle_decrypt_error(&self) {
- if self.resuming {
- self.config
- .resumption
- .store
- .remove_tls12_session(&self.server_name);
- }
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-// -- Traffic transit state --
-struct ExpectTraffic {
- secrets: ConnectionSecrets,
- _cert_verified: verify::ServerCertVerified,
- _sig_verified: verify::HandshakeSignatureValid,
- _fin_verified: verify::FinishedMessageVerified,
-}
-
-impl State<ClientConnectionData> for ExpectTraffic {
- fn handle<'m>(
- self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- match m.payload {
- MessagePayload::ApplicationData(payload) => cx
- .common
- .take_received_plaintext(payload),
- payload => {
- return Err(inappropriate_message(
- &payload,
- &[ContentType::ApplicationData],
- ));
- }
- }
- Ok(self)
- }
-
- fn export_keying_material(
- &self,
- output: &mut [u8],
- label: &[u8],
- context: Option<&[u8]>,
- ) -> Result<(), Error> {
- self.secrets
- .export_keying_material(output, label, context);
- Ok(())
- }
-
- fn extract_secrets(&self) -> Result<PartiallyExtractedSecrets, Error> {
- self.secrets
- .extract_secrets(Side::Client)
- }
-
- fn into_external_state(self: Box<Self>) -> Result<Box<dyn KernelState + 'static>, Error> {
- Ok(self)
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-impl KernelState for ExpectTraffic {
- fn update_secrets(&mut self, _: Direction) -> Result<ConnectionTrafficSecrets, Error> {
- Err(Error::General(
- "TLS 1.2 connections do not support traffic secret updates".into(),
- ))
- }
-
- fn handle_new_session_ticket(
- &mut self,
- _cx: &mut KernelContext<'_>,
- _message: &NewSessionTicketPayloadTls13,
- ) -> Result<(), Error> {
- Err(Error::General(
- "TLS 1.2 session tickets may not be sent once the handshake has completed".into(),
- ))
- }
-}
diff --git a/vendor/rustls/src/client/tls13.rs b/vendor/rustls/src/client/tls13.rs
deleted file mode 100644
index fe8495cc..00000000
--- a/vendor/rustls/src/client/tls13.rs
+++ /dev/null
@@ -1,1700 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec;
-use alloc::vec::Vec;
-
-use pki_types::ServerName;
-use subtle::ConstantTimeEq;
-
-use super::client_conn::ClientConnectionData;
-use super::hs::{ClientContext, ClientHelloInput, ClientSessionValue};
-use crate::check::inappropriate_handshake_message;
-use crate::client::common::{ClientAuthDetails, ClientHelloDetails, ServerCertDetails};
-use crate::client::ech::{self, EchState, EchStatus};
-use crate::client::{ClientConfig, ClientSessionStore, hs};
-use crate::common_state::{
- CommonState, HandshakeFlightTls13, HandshakeKind, KxState, Protocol, Side, State,
-};
-use crate::conn::ConnectionRandoms;
-use crate::conn::kernel::{Direction, KernelContext, KernelState};
-use crate::crypto::hash::Hash;
-use crate::crypto::{ActiveKeyExchange, SharedSecret};
-use crate::enums::{
- AlertDescription, ContentType, HandshakeType, ProtocolVersion, SignatureScheme,
-};
-use crate::error::{Error, InvalidMessage, PeerIncompatible, PeerMisbehaved};
-use crate::hash_hs::{HandshakeHash, HandshakeHashBuffer};
-use crate::log::{debug, trace, warn};
-use crate::msgs::base::{Payload, PayloadU8};
-use crate::msgs::ccs::ChangeCipherSpecPayload;
-use crate::msgs::codec::{Codec, Reader};
-use crate::msgs::enums::{ExtensionType, KeyUpdateRequest};
-use crate::msgs::handshake::{
- CERTIFICATE_MAX_SIZE_LIMIT, CertificatePayloadTls13, ClientExtensions, EchConfigPayload,
- HandshakeMessagePayload, HandshakePayload, KeyShareEntry, NewSessionTicketPayloadTls13,
- PresharedKeyBinder, PresharedKeyIdentity, PresharedKeyOffer, ServerExtensions,
- ServerHelloPayload,
-};
-use crate::msgs::message::{Message, MessagePayload};
-use crate::msgs::persist::{self, Retrieved};
-use crate::sign::{CertifiedKey, Signer};
-use crate::suites::PartiallyExtractedSecrets;
-use crate::sync::Arc;
-use crate::tls13::key_schedule::{
- KeyScheduleEarly, KeyScheduleHandshake, KeySchedulePreHandshake, KeyScheduleResumption,
- KeyScheduleTraffic,
-};
-use crate::tls13::{
- Tls13CipherSuite, construct_client_verify_message, construct_server_verify_message,
-};
-use crate::verify::{self, DigitallySignedStruct};
-use crate::{ConnectionTrafficSecrets, KeyLog, compress, crypto};
-
-// Extensions we expect in plaintext in the ServerHello.
-static ALLOWED_PLAINTEXT_EXTS: &[ExtensionType] = &[
- ExtensionType::KeyShare,
- ExtensionType::PreSharedKey,
- ExtensionType::SupportedVersions,
-];
-
-// Only the intersection of things we offer, and those disallowed
-// in TLS1.3
-static DISALLOWED_TLS13_EXTS: &[ExtensionType] = &[
- ExtensionType::ECPointFormats,
- ExtensionType::SessionTicket,
- ExtensionType::RenegotiationInfo,
- ExtensionType::ExtendedMasterSecret,
-];
-
-/// `early_data_key_schedule` is `Some` if we sent the
-/// "early_data" extension to the server.
-pub(super) fn handle_server_hello(
- cx: &mut ClientContext<'_>,
- server_hello: &ServerHelloPayload,
- mut randoms: ConnectionRandoms,
- suite: &'static Tls13CipherSuite,
- mut transcript: HandshakeHash,
- early_data_key_schedule: Option<KeyScheduleEarly>,
- our_key_share: Box<dyn ActiveKeyExchange>,
- server_hello_msg: &Message<'_>,
- ech_state: Option<EchState>,
- input: ClientHelloInput,
-) -> hs::NextStateOrError<'static> {
- validate_server_hello(cx.common, server_hello)?;
-
- let their_key_share = server_hello
- .key_share
- .as_ref()
- .ok_or_else(|| {
- cx.common.send_fatal_alert(
- AlertDescription::MissingExtension,
- PeerMisbehaved::MissingKeyShare,
- )
- })?;
-
- let ClientHelloInput {
- config,
- resuming,
- mut sent_tls13_fake_ccs,
- mut hello,
- server_name,
- ..
- } = input;
-
- let mut resuming_session = match resuming {
- Some(Retrieved {
- value: ClientSessionValue::Tls13(value),
- ..
- }) => Some(value),
- _ => None,
- };
-
- let our_key_share = KeyExchangeChoice::new(&config, cx, our_key_share, their_key_share)
- .map_err(|_| {
- cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::WrongGroupForKeyShare,
- )
- })?;
-
- let key_schedule_pre_handshake = match (server_hello.preshared_key, early_data_key_schedule) {
- (Some(selected_psk), Some(early_key_schedule)) => {
- match &resuming_session {
- Some(resuming) => {
- let Some(resuming_suite) = suite.can_resume_from(resuming.suite()) else {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::ResumptionOfferedWithIncompatibleCipherSuite,
- )
- });
- };
-
- // If the server varies the suite here, we will have encrypted early data with
- // the wrong suite.
- if cx.data.early_data.is_enabled() && resuming_suite != suite {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::EarlyDataOfferedWithVariedCipherSuite,
- )
- });
- }
-
- if selected_psk != 0 {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::SelectedInvalidPsk,
- )
- });
- }
-
- debug!("Resuming using PSK");
- // The key schedule has been initialized and set in fill_in_psk_binder()
- }
- _ => {
- return Err(PeerMisbehaved::SelectedUnofferedPsk.into());
- }
- }
- KeySchedulePreHandshake::from(early_key_schedule)
- }
- _ => {
- debug!("Not resuming");
- // Discard the early data key schedule.
- cx.data.early_data.rejected();
- cx.common.early_traffic = false;
- resuming_session.take();
- KeySchedulePreHandshake::new(suite)
- }
- };
-
- cx.common.kx_state.complete();
- let shared_secret = our_key_share
- .complete(&their_key_share.payload.0)
- .map_err(|err| {
- cx.common
- .send_fatal_alert(AlertDescription::IllegalParameter, err)
- })?;
-
- let mut key_schedule = key_schedule_pre_handshake.into_handshake(shared_secret);
-
- // If we have ECH state, check that the server accepted our offer.
- if let Some(ech_state) = ech_state {
- let Message {
- payload:
- MessagePayload::Handshake {
- encoded: server_hello_encoded,
- ..
- },
- ..
- } = &server_hello_msg
- else {
- unreachable!("ServerHello is a handshake message");
- };
- cx.data.ech_status = match ech_state.confirm_acceptance(
- &mut key_schedule,
- server_hello,
- server_hello_encoded,
- suite.common.hash_provider,
- )? {
- // The server accepted our ECH offer, so complete the inner transcript with the
- // server hello message, and switch the relevant state to the copies for the
- // inner client hello.
- Some(mut accepted) => {
- accepted
- .transcript
- .add_message(server_hello_msg);
- transcript = accepted.transcript;
- randoms.client = accepted.random.0;
- hello.sent_extensions = accepted.sent_extensions;
- EchStatus::Accepted
- }
- // The server rejected our ECH offer.
- None => EchStatus::Rejected,
- };
- }
-
- // Remember what KX group the server liked for next time.
- config
- .resumption
- .store
- .set_kx_hint(server_name.clone(), their_key_share.group);
-
- // If we change keying when a subsequent handshake message is being joined,
- // the two halves will have different record layer protections. Disallow this.
- cx.common.check_aligned_handshake()?;
-
- let hash_at_client_recvd_server_hello = transcript.current_hash();
- let key_schedule = key_schedule.derive_client_handshake_secrets(
- cx.data.early_data.is_enabled(),
- hash_at_client_recvd_server_hello,
- suite,
- &*config.key_log,
- &randoms.client,
- cx.common,
- );
-
- emit_fake_ccs(&mut sent_tls13_fake_ccs, cx.common);
-
- Ok(Box::new(ExpectEncryptedExtensions {
- config,
- resuming_session,
- server_name,
- randoms,
- suite,
- transcript,
- key_schedule,
- hello,
- }))
-}
-
-enum KeyExchangeChoice {
- Whole(Box<dyn ActiveKeyExchange>),
- Component(Box<dyn ActiveKeyExchange>),
-}
-
-impl KeyExchangeChoice {
- /// Decide between `our_key_share` or `our_key_share.hybrid_component()`
- /// based on the selection of the server expressed in `their_key_share`.
- fn new(
- config: &Arc<ClientConfig>,
- cx: &mut ClientContext<'_>,
- our_key_share: Box<dyn ActiveKeyExchange>,
- their_key_share: &KeyShareEntry,
- ) -> Result<Self, ()> {
- if our_key_share.group() == their_key_share.group {
- return Ok(Self::Whole(our_key_share));
- }
-
- let (component_group, _) = our_key_share
- .hybrid_component()
- .ok_or(())?;
-
- if component_group != their_key_share.group {
- return Err(());
- }
-
- // correct the record for the benefit of accuracy of
- // `negotiated_key_exchange_group()`
- let actual_skxg = config
- .find_kx_group(component_group, ProtocolVersion::TLSv1_3)
- .ok_or(())?;
- cx.common.kx_state = KxState::Start(actual_skxg);
-
- Ok(Self::Component(our_key_share))
- }
-
- fn complete(self, peer_pub_key: &[u8]) -> Result<SharedSecret, Error> {
- match self {
- Self::Whole(akx) => akx.complete(peer_pub_key),
- Self::Component(akx) => akx.complete_hybrid_component(peer_pub_key),
- }
- }
-}
-
-fn validate_server_hello(
- common: &mut CommonState,
- server_hello: &ServerHelloPayload,
-) -> Result<(), Error> {
- if !server_hello.only_contains(ALLOWED_PLAINTEXT_EXTS) {
- return Err(common.send_fatal_alert(
- AlertDescription::UnsupportedExtension,
- PeerMisbehaved::UnexpectedCleartextExtension,
- ));
- }
-
- Ok(())
-}
-
-pub(super) fn initial_key_share(
- config: &ClientConfig,
- server_name: &ServerName<'_>,
- kx_state: &mut KxState,
-) -> Result<Box<dyn ActiveKeyExchange>, Error> {
- let group = config
- .resumption
- .store
- .kx_hint(server_name)
- .and_then(|group_name| config.find_kx_group(group_name, ProtocolVersion::TLSv1_3))
- .unwrap_or_else(|| {
- config
- .provider
- .kx_groups
- .iter()
- .copied()
- .next()
- .expect("No kx groups configured")
- });
-
- *kx_state = KxState::Start(group);
- group.start()
-}
-
-/// This implements the horrifying TLS1.3 hack where PSK binders have a
-/// data dependency on the message they are contained within.
-pub(super) fn fill_in_psk_binder(
- resuming: &persist::Tls13ClientSessionValue,
- transcript: &HandshakeHashBuffer,
- hmp: &mut HandshakeMessagePayload<'_>,
-) -> KeyScheduleEarly {
- // We need to know the hash function of the suite we're trying to resume into.
- let suite = resuming.suite();
- let suite_hash = suite.common.hash_provider;
-
- // The binder is calculated over the clienthello, but doesn't include itself or its
- // length, or the length of its container.
- let binder_plaintext = hmp.encoding_for_binder_signing();
- let handshake_hash = transcript.hash_given(suite_hash, &binder_plaintext);
-
- // Run a fake key_schedule to simulate what the server will do if it chooses
- // to resume.
- let key_schedule = KeyScheduleEarly::new(suite, resuming.secret());
- let real_binder = key_schedule.resumption_psk_binder_key_and_sign_verify_data(&handshake_hash);
-
- if let HandshakePayload::ClientHello(ch) = &mut hmp.0 {
- if let Some(PresharedKeyOffer {
- binders,
- identities,
- }) = &mut ch.preshared_key_offer
- {
- // the caller of this function must have set up the desired identity, and a
- // matching (dummy) binder; or else the binder we compute here will be incorrect.
- // See `prepare_resumption()`.
- debug_assert_eq!(identities.len(), 1);
- debug_assert_eq!(binders.len(), 1);
- debug_assert_eq!(binders[0].as_ref().len(), real_binder.as_ref().len());
- binders[0] = PresharedKeyBinder::from(real_binder.as_ref().to_vec());
- }
- };
-
- key_schedule
-}
-
-pub(super) fn prepare_resumption(
- config: &ClientConfig,
- cx: &mut ClientContext<'_>,
- resuming_session: &Retrieved<&persist::Tls13ClientSessionValue>,
- exts: &mut ClientExtensions<'_>,
- doing_retry: bool,
-) {
- let resuming_suite = resuming_session.suite();
- cx.common.suite = Some(resuming_suite.into());
- // The EarlyData extension MUST be supplied together with the
- // PreSharedKey extension.
- let max_early_data_size = resuming_session.max_early_data_size();
- if config.enable_early_data && max_early_data_size > 0 && !doing_retry {
- cx.data
- .early_data
- .enable(max_early_data_size as usize);
- exts.early_data_request = Some(());
- }
-
- // Finally, and only for TLS1.3 with a ticket resumption, include a binder
- // for our ticket. This must go last.
- //
- // Include an empty binder. It gets filled in below because it depends on
- // the message it's contained in (!!!).
- let obfuscated_ticket_age = resuming_session.obfuscated_ticket_age();
-
- let binder_len = resuming_suite
- .common
- .hash_provider
- .output_len();
- let binder = vec![0u8; binder_len];
-
- let psk_identity =
- PresharedKeyIdentity::new(resuming_session.ticket().to_vec(), obfuscated_ticket_age);
- let psk_offer = PresharedKeyOffer::new(psk_identity, binder);
- exts.preshared_key_offer = Some(psk_offer);
-}
-
-pub(super) fn derive_early_traffic_secret(
- key_log: &dyn KeyLog,
- cx: &mut ClientContext<'_>,
- hash_alg: &'static dyn Hash,
- early_key_schedule: &KeyScheduleEarly,
- sent_tls13_fake_ccs: &mut bool,
- transcript_buffer: &HandshakeHashBuffer,
- client_random: &[u8; 32],
-) {
- // For middlebox compatibility
- emit_fake_ccs(sent_tls13_fake_ccs, cx.common);
-
- let client_hello_hash = transcript_buffer.hash_given(hash_alg, &[]);
- early_key_schedule.client_early_traffic_secret(
- &client_hello_hash,
- key_log,
- client_random,
- cx.common,
- );
-
- // Now the client can send encrypted early data
- cx.common.early_traffic = true;
- trace!("Starting early data traffic");
-}
-
-pub(super) fn emit_fake_ccs(sent_tls13_fake_ccs: &mut bool, common: &mut CommonState) {
- if common.is_quic() {
- return;
- }
-
- if core::mem::replace(sent_tls13_fake_ccs, true) {
- return;
- }
-
- let m = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::ChangeCipherSpec(ChangeCipherSpecPayload {}),
- };
- common.send_msg(m, false);
-}
-
-fn validate_encrypted_extensions(
- common: &mut CommonState,
- hello: &ClientHelloDetails,
- exts: &ServerExtensions<'_>,
-) -> Result<(), Error> {
- if hello.server_sent_unsolicited_extensions(exts, &[]) {
- return Err(common.send_fatal_alert(
- AlertDescription::UnsupportedExtension,
- PeerMisbehaved::UnsolicitedEncryptedExtension,
- ));
- }
-
- if exts.contains_any(ALLOWED_PLAINTEXT_EXTS) || exts.contains_any(DISALLOWED_TLS13_EXTS) {
- return Err(common.send_fatal_alert(
- AlertDescription::UnsupportedExtension,
- PeerMisbehaved::DisallowedEncryptedExtension,
- ));
- }
-
- Ok(())
-}
-
-struct ExpectEncryptedExtensions {
- config: Arc<ClientConfig>,
- resuming_session: Option<persist::Tls13ClientSessionValue>,
- server_name: ServerName<'static>,
- randoms: ConnectionRandoms,
- suite: &'static Tls13CipherSuite,
- transcript: HandshakeHash,
- key_schedule: KeyScheduleHandshake,
- hello: ClientHelloDetails,
-}
-
-impl State<ClientConnectionData> for ExpectEncryptedExtensions {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- let exts = require_handshake_msg!(
- m,
- HandshakeType::EncryptedExtensions,
- HandshakePayload::EncryptedExtensions
- )?;
- debug!("TLS1.3 encrypted extensions: {exts:?}");
- self.transcript.add_message(&m);
-
- validate_encrypted_extensions(cx.common, &self.hello, exts)?;
- hs::process_alpn_protocol(
- cx.common,
- &self.hello.alpn_protocols,
- exts.selected_protocol
- .as_ref()
- .map(|protocol| protocol.as_ref()),
- )?;
- hs::process_client_cert_type_extension(
- cx.common,
- &self.config,
- exts.client_certificate_type.as_ref(),
- )?;
- hs::process_server_cert_type_extension(
- cx.common,
- &self.config,
- exts.server_certificate_type.as_ref(),
- )?;
-
- let ech_retry_configs = match (cx.data.ech_status, &exts.encrypted_client_hello_ack) {
- // If we didn't offer ECH, or ECH was accepted, but the server sent an ECH encrypted
- // extension with retry configs, we must error.
- (EchStatus::NotOffered | EchStatus::Accepted, Some(_)) => {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::UnsupportedExtension,
- PeerMisbehaved::UnsolicitedEchExtension,
- ));
- }
- // If we offered ECH, and it was rejected, store the retry configs (if any) from
- // the server's ECH extension. We will return them in an error produced at the end
- // of the handshake.
- (EchStatus::Rejected, ext) => ext
- .as_ref()
- .map(|ext| ext.retry_configs.to_vec()),
- _ => None,
- };
-
- // QUIC transport parameters
- if cx.common.is_quic() {
- match exts
- .transport_parameters
- .as_ref()
- .or(exts.transport_parameters_draft.as_ref())
- {
- Some(params) => cx.common.quic.params = Some(params.clone().into_vec()),
- None => {
- return Err(cx
- .common
- .missing_extension(PeerMisbehaved::MissingQuicTransportParameters));
- }
- }
- }
-
- match self.resuming_session {
- Some(resuming_session) => {
- let was_early_traffic = cx.common.early_traffic;
- if was_early_traffic {
- match exts.early_data_ack {
- Some(()) => cx.data.early_data.accepted(),
- None => {
- cx.data.early_data.rejected();
- cx.common.early_traffic = false;
- }
- }
- }
-
- if was_early_traffic && !cx.common.early_traffic {
- // If no early traffic, set the encryption key for handshakes
- self.key_schedule
- .set_handshake_encrypter(cx.common);
- }
-
- cx.common.peer_certificates = Some(
- resuming_session
- .server_cert_chain()
- .clone(),
- );
- cx.common.handshake_kind = Some(HandshakeKind::Resumed);
-
- // We *don't* reverify the certificate chain here: resumption is a
- // continuation of the previous session in terms of security policy.
- let cert_verified = verify::ServerCertVerified::assertion();
- let sig_verified = verify::HandshakeSignatureValid::assertion();
- Ok(Box::new(ExpectFinished {
- config: self.config,
- server_name: self.server_name,
- randoms: self.randoms,
- suite: self.suite,
- transcript: self.transcript,
- key_schedule: self.key_schedule,
- client_auth: None,
- cert_verified,
- sig_verified,
- ech_retry_configs,
- }))
- }
- _ => {
- if exts.early_data_ack.is_some() {
- return Err(PeerMisbehaved::EarlyDataExtensionWithoutResumption.into());
- }
- cx.common
- .handshake_kind
- .get_or_insert(HandshakeKind::Full);
-
- Ok(if self.hello.offered_cert_compression {
- Box::new(ExpectCertificateOrCompressedCertificateOrCertReq {
- config: self.config,
- server_name: self.server_name,
- randoms: self.randoms,
- suite: self.suite,
- transcript: self.transcript,
- key_schedule: self.key_schedule,
- ech_retry_configs,
- })
- } else {
- Box::new(ExpectCertificateOrCertReq {
- config: self.config,
- server_name: self.server_name,
- randoms: self.randoms,
- suite: self.suite,
- transcript: self.transcript,
- key_schedule: self.key_schedule,
- ech_retry_configs,
- })
- })
- }
- }
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-struct ExpectCertificateOrCompressedCertificateOrCertReq {
- config: Arc<ClientConfig>,
- server_name: ServerName<'static>,
- randoms: ConnectionRandoms,
- suite: &'static Tls13CipherSuite,
- transcript: HandshakeHash,
- key_schedule: KeyScheduleHandshake,
- ech_retry_configs: Option<Vec<EchConfigPayload>>,
-}
-
-impl State<ClientConnectionData> for ExpectCertificateOrCompressedCertificateOrCertReq {
- fn handle<'m>(
- self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- match m.payload {
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::CertificateTls13(..)),
- ..
- } => Box::new(ExpectCertificate {
- config: self.config,
- server_name: self.server_name,
- randoms: self.randoms,
- suite: self.suite,
- transcript: self.transcript,
- key_schedule: self.key_schedule,
- client_auth: None,
- message_already_in_transcript: false,
- ech_retry_configs: self.ech_retry_configs,
- })
- .handle(cx, m),
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::CompressedCertificate(..)),
- ..
- } => Box::new(ExpectCompressedCertificate {
- config: self.config,
- server_name: self.server_name,
- randoms: self.randoms,
- suite: self.suite,
- transcript: self.transcript,
- key_schedule: self.key_schedule,
- client_auth: None,
- ech_retry_configs: self.ech_retry_configs,
- })
- .handle(cx, m),
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::CertificateRequestTls13(..)),
- ..
- } => Box::new(ExpectCertificateRequest {
- config: self.config,
- server_name: self.server_name,
- randoms: self.randoms,
- suite: self.suite,
- transcript: self.transcript,
- key_schedule: self.key_schedule,
- offered_cert_compression: true,
- ech_retry_configs: self.ech_retry_configs,
- })
- .handle(cx, m),
- payload => Err(inappropriate_handshake_message(
- &payload,
- &[ContentType::Handshake],
- &[
- HandshakeType::Certificate,
- HandshakeType::CertificateRequest,
- HandshakeType::CompressedCertificate,
- ],
- )),
- }
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-struct ExpectCertificateOrCompressedCertificate {
- config: Arc<ClientConfig>,
- server_name: ServerName<'static>,
- randoms: ConnectionRandoms,
- suite: &'static Tls13CipherSuite,
- transcript: HandshakeHash,
- key_schedule: KeyScheduleHandshake,
- client_auth: Option<ClientAuthDetails>,
- ech_retry_configs: Option<Vec<EchConfigPayload>>,
-}
-
-impl State<ClientConnectionData> for ExpectCertificateOrCompressedCertificate {
- fn handle<'m>(
- self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- match m.payload {
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::CertificateTls13(..)),
- ..
- } => Box::new(ExpectCertificate {
- config: self.config,
- server_name: self.server_name,
- randoms: self.randoms,
- suite: self.suite,
- transcript: self.transcript,
- key_schedule: self.key_schedule,
- client_auth: self.client_auth,
- message_already_in_transcript: false,
- ech_retry_configs: self.ech_retry_configs,
- })
- .handle(cx, m),
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::CompressedCertificate(..)),
- ..
- } => Box::new(ExpectCompressedCertificate {
- config: self.config,
- server_name: self.server_name,
- randoms: self.randoms,
- suite: self.suite,
- transcript: self.transcript,
- key_schedule: self.key_schedule,
- client_auth: self.client_auth,
- ech_retry_configs: self.ech_retry_configs,
- })
- .handle(cx, m),
- payload => Err(inappropriate_handshake_message(
- &payload,
- &[ContentType::Handshake],
- &[
- HandshakeType::Certificate,
- HandshakeType::CompressedCertificate,
- ],
- )),
- }
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-struct ExpectCertificateOrCertReq {
- config: Arc<ClientConfig>,
- server_name: ServerName<'static>,
- randoms: ConnectionRandoms,
- suite: &'static Tls13CipherSuite,
- transcript: HandshakeHash,
- key_schedule: KeyScheduleHandshake,
- ech_retry_configs: Option<Vec<EchConfigPayload>>,
-}
-
-impl State<ClientConnectionData> for ExpectCertificateOrCertReq {
- fn handle<'m>(
- self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- match m.payload {
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::CertificateTls13(..)),
- ..
- } => Box::new(ExpectCertificate {
- config: self.config,
- server_name: self.server_name,
- randoms: self.randoms,
- suite: self.suite,
- transcript: self.transcript,
- key_schedule: self.key_schedule,
- client_auth: None,
- message_already_in_transcript: false,
- ech_retry_configs: self.ech_retry_configs,
- })
- .handle(cx, m),
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::CertificateRequestTls13(..)),
- ..
- } => Box::new(ExpectCertificateRequest {
- config: self.config,
- server_name: self.server_name,
- randoms: self.randoms,
- suite: self.suite,
- transcript: self.transcript,
- key_schedule: self.key_schedule,
- offered_cert_compression: false,
- ech_retry_configs: self.ech_retry_configs,
- })
- .handle(cx, m),
- payload => Err(inappropriate_handshake_message(
- &payload,
- &[ContentType::Handshake],
- &[
- HandshakeType::Certificate,
- HandshakeType::CertificateRequest,
- ],
- )),
- }
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-// TLS1.3 version of CertificateRequest handling. We then move to expecting the server
-// Certificate. Unfortunately the CertificateRequest type changed in an annoying way
-// in TLS1.3.
-struct ExpectCertificateRequest {
- config: Arc<ClientConfig>,
- server_name: ServerName<'static>,
- randoms: ConnectionRandoms,
- suite: &'static Tls13CipherSuite,
- transcript: HandshakeHash,
- key_schedule: KeyScheduleHandshake,
- offered_cert_compression: bool,
- ech_retry_configs: Option<Vec<EchConfigPayload>>,
-}
-
-impl State<ClientConnectionData> for ExpectCertificateRequest {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- let certreq = &require_handshake_msg!(
- m,
- HandshakeType::CertificateRequest,
- HandshakePayload::CertificateRequestTls13
- )?;
- self.transcript.add_message(&m);
- debug!("Got CertificateRequest {certreq:?}");
-
- // Fortunately the problems here in TLS1.2 and prior are corrected in
- // TLS1.3.
-
- // Must be empty during handshake.
- if !certreq.context.0.is_empty() {
- warn!("Server sent non-empty certreq context");
- return Err(cx.common.send_fatal_alert(
- AlertDescription::DecodeError,
- InvalidMessage::InvalidCertRequest,
- ));
- }
-
- let compat_sigschemes = certreq
- .extensions
- .signature_algorithms
- .as_deref()
- .unwrap_or_default()
- .iter()
- .cloned()
- .filter(SignatureScheme::supported_in_tls13)
- .collect::<Vec<SignatureScheme>>();
-
- if compat_sigschemes.is_empty() {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::HandshakeFailure,
- PeerIncompatible::NoCertificateRequestSignatureSchemesInCommon,
- ));
- }
-
- let compat_compressor = certreq
- .extensions
- .certificate_compression_algorithms
- .as_deref()
- .and_then(|offered| {
- self.config
- .cert_compressors
- .iter()
- .find(|compressor| offered.contains(&compressor.algorithm()))
- })
- .cloned();
-
- let client_auth = ClientAuthDetails::resolve(
- self.config
- .client_auth_cert_resolver
- .as_ref(),
- certreq
- .extensions
- .authority_names
- .as_deref(),
- &compat_sigschemes,
- Some(certreq.context.0.clone()),
- compat_compressor,
- );
-
- Ok(if self.offered_cert_compression {
- Box::new(ExpectCertificateOrCompressedCertificate {
- config: self.config,
- server_name: self.server_name,
- randoms: self.randoms,
- suite: self.suite,
- transcript: self.transcript,
- key_schedule: self.key_schedule,
- client_auth: Some(client_auth),
- ech_retry_configs: self.ech_retry_configs,
- })
- } else {
- Box::new(ExpectCertificate {
- config: self.config,
- server_name: self.server_name,
- randoms: self.randoms,
- suite: self.suite,
- transcript: self.transcript,
- key_schedule: self.key_schedule,
- client_auth: Some(client_auth),
- message_already_in_transcript: false,
- ech_retry_configs: self.ech_retry_configs,
- })
- })
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-struct ExpectCompressedCertificate {
- config: Arc<ClientConfig>,
- server_name: ServerName<'static>,
- randoms: ConnectionRandoms,
- suite: &'static Tls13CipherSuite,
- transcript: HandshakeHash,
- key_schedule: KeyScheduleHandshake,
- client_auth: Option<ClientAuthDetails>,
- ech_retry_configs: Option<Vec<EchConfigPayload>>,
-}
-
-impl State<ClientConnectionData> for ExpectCompressedCertificate {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- self.transcript.add_message(&m);
- let compressed_cert = require_handshake_msg_move!(
- m,
- HandshakeType::CompressedCertificate,
- HandshakePayload::CompressedCertificate
- )?;
-
- let selected_decompressor = self
- .config
- .cert_decompressors
- .iter()
- .find(|item| item.algorithm() == compressed_cert.alg);
-
- let Some(decompressor) = selected_decompressor else {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::BadCertificate,
- PeerMisbehaved::SelectedUnofferedCertCompression,
- ));
- };
-
- if compressed_cert.uncompressed_len as usize > CERTIFICATE_MAX_SIZE_LIMIT {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::BadCertificate,
- InvalidMessage::MessageTooLarge,
- ));
- }
-
- let mut decompress_buffer = vec![0u8; compressed_cert.uncompressed_len as usize];
- if let Err(compress::DecompressionFailed) =
- decompressor.decompress(compressed_cert.compressed.0.bytes(), &mut decompress_buffer)
- {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::BadCertificate,
- PeerMisbehaved::InvalidCertCompression,
- ));
- }
-
- let cert_payload =
- match CertificatePayloadTls13::read(&mut Reader::init(&decompress_buffer)) {
- Ok(cm) => cm,
- Err(err) => {
- return Err(cx
- .common
- .send_fatal_alert(AlertDescription::BadCertificate, err));
- }
- };
- trace!(
- "Server certificate decompressed using {:?} ({} bytes -> {})",
- compressed_cert.alg,
- compressed_cert
- .compressed
- .0
- .bytes()
- .len(),
- compressed_cert.uncompressed_len,
- );
-
- let m = Message {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::CertificateTls13(cert_payload.into_owned()),
- )),
- };
-
- Box::new(ExpectCertificate {
- config: self.config,
- server_name: self.server_name,
- randoms: self.randoms,
- suite: self.suite,
- transcript: self.transcript,
- key_schedule: self.key_schedule,
- client_auth: self.client_auth,
- message_already_in_transcript: true,
- ech_retry_configs: self.ech_retry_configs,
- })
- .handle(cx, m)
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-struct ExpectCertificate {
- config: Arc<ClientConfig>,
- server_name: ServerName<'static>,
- randoms: ConnectionRandoms,
- suite: &'static Tls13CipherSuite,
- transcript: HandshakeHash,
- key_schedule: KeyScheduleHandshake,
- client_auth: Option<ClientAuthDetails>,
- message_already_in_transcript: bool,
- ech_retry_configs: Option<Vec<EchConfigPayload>>,
-}
-
-impl State<ClientConnectionData> for ExpectCertificate {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- if !self.message_already_in_transcript {
- self.transcript.add_message(&m);
- }
- let cert_chain = require_handshake_msg_move!(
- m,
- HandshakeType::Certificate,
- HandshakePayload::CertificateTls13
- )?;
-
- // This is only non-empty for client auth.
- if !cert_chain.context.0.is_empty() {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::DecodeError,
- InvalidMessage::InvalidCertRequest,
- ));
- }
-
- let end_entity_ocsp = cert_chain.end_entity_ocsp().to_vec();
- let server_cert = ServerCertDetails::new(
- cert_chain
- .into_certificate_chain()
- .into_owned(),
- end_entity_ocsp,
- );
-
- Ok(Box::new(ExpectCertificateVerify {
- config: self.config,
- server_name: self.server_name,
- randoms: self.randoms,
- suite: self.suite,
- transcript: self.transcript,
- key_schedule: self.key_schedule,
- server_cert,
- client_auth: self.client_auth,
- ech_retry_configs: self.ech_retry_configs,
- }))
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-// --- TLS1.3 CertificateVerify ---
-struct ExpectCertificateVerify<'a> {
- config: Arc<ClientConfig>,
- server_name: ServerName<'static>,
- randoms: ConnectionRandoms,
- suite: &'static Tls13CipherSuite,
- transcript: HandshakeHash,
- key_schedule: KeyScheduleHandshake,
- server_cert: ServerCertDetails<'a>,
- client_auth: Option<ClientAuthDetails>,
- ech_retry_configs: Option<Vec<EchConfigPayload>>,
-}
-
-impl State<ClientConnectionData> for ExpectCertificateVerify<'_> {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- let cert_verify = require_handshake_msg!(
- m,
- HandshakeType::CertificateVerify,
- HandshakePayload::CertificateVerify
- )?;
-
- trace!("Server cert is {:?}", self.server_cert.cert_chain);
-
- // 1. Verify the certificate chain.
- let (end_entity, intermediates) = self
- .server_cert
- .cert_chain
- .split_first()
- .ok_or(Error::NoCertificatesPresented)?;
-
- let now = self.config.current_time()?;
-
- let cert_verified = self
- .config
- .verifier
- .verify_server_cert(
- end_entity,
- intermediates,
- &self.server_name,
- &self.server_cert.ocsp_response,
- now,
- )
- .map_err(|err| {
- cx.common
- .send_cert_verify_error_alert(err)
- })?;
-
- // 2. Verify their signature on the handshake.
- let handshake_hash = self.transcript.current_hash();
- let sig_verified = self
- .config
- .verifier
- .verify_tls13_signature(
- construct_server_verify_message(&handshake_hash).as_ref(),
- end_entity,
- cert_verify,
- )
- .map_err(|err| {
- cx.common
- .send_cert_verify_error_alert(err)
- })?;
-
- cx.common.peer_certificates = Some(self.server_cert.cert_chain.into_owned());
- self.transcript.add_message(&m);
-
- Ok(Box::new(ExpectFinished {
- config: self.config,
- server_name: self.server_name,
- randoms: self.randoms,
- suite: self.suite,
- transcript: self.transcript,
- key_schedule: self.key_schedule,
- client_auth: self.client_auth,
- cert_verified,
- sig_verified,
- ech_retry_configs: self.ech_retry_configs,
- }))
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- Box::new(ExpectCertificateVerify {
- config: self.config,
- server_name: self.server_name,
- randoms: self.randoms,
- suite: self.suite,
- transcript: self.transcript,
- key_schedule: self.key_schedule,
- server_cert: self.server_cert.into_owned(),
- client_auth: self.client_auth,
- ech_retry_configs: self.ech_retry_configs,
- })
- }
-}
-
-fn emit_compressed_certificate_tls13(
- flight: &mut HandshakeFlightTls13<'_>,
- certkey: &CertifiedKey,
- auth_context: Option<Vec<u8>>,
- compressor: &dyn compress::CertCompressor,
- config: &ClientConfig,
-) {
- let mut cert_payload = CertificatePayloadTls13::new(certkey.cert.iter(), None);
- cert_payload.context = PayloadU8::new(auth_context.clone().unwrap_or_default());
-
- let Ok(compressed) = config
- .cert_compression_cache
- .compression_for(compressor, &cert_payload)
- else {
- return emit_certificate_tls13(flight, Some(certkey), auth_context);
- };
-
- flight.add(HandshakeMessagePayload(
- HandshakePayload::CompressedCertificate(compressed.compressed_cert_payload()),
- ));
-}
-
-fn emit_certificate_tls13(
- flight: &mut HandshakeFlightTls13<'_>,
- certkey: Option<&CertifiedKey>,
- auth_context: Option<Vec<u8>>,
-) {
- let certs = certkey
- .map(|ck| ck.cert.as_ref())
- .unwrap_or(&[][..]);
- let mut cert_payload = CertificatePayloadTls13::new(certs.iter(), None);
- cert_payload.context = PayloadU8::new(auth_context.unwrap_or_default());
-
- flight.add(HandshakeMessagePayload(HandshakePayload::CertificateTls13(
- cert_payload,
- )));
-}
-
-fn emit_certverify_tls13(
- flight: &mut HandshakeFlightTls13<'_>,
- signer: &dyn Signer,
-) -> Result<(), Error> {
- let message = construct_client_verify_message(&flight.transcript.current_hash());
-
- let scheme = signer.scheme();
- let sig = signer.sign(message.as_ref())?;
- let dss = DigitallySignedStruct::new(scheme, sig);
-
- flight.add(HandshakeMessagePayload(
- HandshakePayload::CertificateVerify(dss),
- ));
- Ok(())
-}
-
-fn emit_finished_tls13(flight: &mut HandshakeFlightTls13<'_>, verify_data: &crypto::hmac::Tag) {
- let verify_data_payload = Payload::new(verify_data.as_ref());
-
- flight.add(HandshakeMessagePayload(HandshakePayload::Finished(
- verify_data_payload,
- )));
-}
-
-fn emit_end_of_early_data_tls13(transcript: &mut HandshakeHash, common: &mut CommonState) {
- if common.is_quic() {
- return;
- }
-
- let m = Message {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::EndOfEarlyData,
- )),
- };
-
- transcript.add_message(&m);
- common.send_msg(m, true);
-}
-
-struct ExpectFinished {
- config: Arc<ClientConfig>,
- server_name: ServerName<'static>,
- randoms: ConnectionRandoms,
- suite: &'static Tls13CipherSuite,
- transcript: HandshakeHash,
- key_schedule: KeyScheduleHandshake,
- client_auth: Option<ClientAuthDetails>,
- cert_verified: verify::ServerCertVerified,
- sig_verified: verify::HandshakeSignatureValid,
- ech_retry_configs: Option<Vec<EchConfigPayload>>,
-}
-
-impl State<ClientConnectionData> for ExpectFinished {
- fn handle<'m>(
- self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- let mut st = *self;
- let finished =
- require_handshake_msg!(m, HandshakeType::Finished, HandshakePayload::Finished)?;
-
- let handshake_hash = st.transcript.current_hash();
- let expect_verify_data = st
- .key_schedule
- .sign_server_finish(&handshake_hash);
-
- let fin = match ConstantTimeEq::ct_eq(expect_verify_data.as_ref(), finished.bytes()).into()
- {
- true => verify::FinishedMessageVerified::assertion(),
- false => {
- return Err(cx
- .common
- .send_fatal_alert(AlertDescription::DecryptError, Error::DecryptError));
- }
- };
-
- st.transcript.add_message(&m);
-
- let hash_after_handshake = st.transcript.current_hash();
- /* The EndOfEarlyData message to server is still encrypted with early data keys,
- * but appears in the transcript after the server Finished. */
- if cx.common.early_traffic {
- emit_end_of_early_data_tls13(&mut st.transcript, cx.common);
- cx.common.early_traffic = false;
- cx.data.early_data.finished();
- st.key_schedule
- .set_handshake_encrypter(cx.common);
- }
-
- let mut flight = HandshakeFlightTls13::new(&mut st.transcript);
-
- /* Send our authentication/finished messages. These are still encrypted
- * with our handshake keys. */
- if let Some(client_auth) = st.client_auth {
- match client_auth {
- ClientAuthDetails::Empty {
- auth_context_tls13: auth_context,
- } => {
- emit_certificate_tls13(&mut flight, None, auth_context);
- }
- ClientAuthDetails::Verify {
- auth_context_tls13: auth_context,
- ..
- } if cx.data.ech_status == EchStatus::Rejected => {
- // If ECH was offered, and rejected, we MUST respond with
- // an empty certificate message.
- emit_certificate_tls13(&mut flight, None, auth_context);
- }
- ClientAuthDetails::Verify {
- certkey,
- signer,
- auth_context_tls13: auth_context,
- compressor,
- } => {
- if let Some(compressor) = compressor {
- emit_compressed_certificate_tls13(
- &mut flight,
- &certkey,
- auth_context,
- compressor,
- &st.config,
- );
- } else {
- emit_certificate_tls13(&mut flight, Some(&certkey), auth_context);
- }
- emit_certverify_tls13(&mut flight, signer.as_ref())?;
- }
- }
- }
-
- let (key_schedule_pre_finished, verify_data) = st
- .key_schedule
- .into_pre_finished_client_traffic(
- hash_after_handshake,
- flight.transcript.current_hash(),
- &*st.config.key_log,
- &st.randoms.client,
- );
-
- emit_finished_tls13(&mut flight, &verify_data);
- flight.finish(cx.common);
-
- /* We're now sure this server supports TLS1.3. But if we run out of TLS1.3 tickets
- * when connecting to it again, we definitely don't want to attempt a TLS1.2 resumption. */
- st.config
- .resumption
- .store
- .remove_tls12_session(&st.server_name);
-
- /* Now move to our application traffic keys. */
- cx.common.check_aligned_handshake()?;
- let (key_schedule, resumption) =
- key_schedule_pre_finished.into_traffic(cx.common, st.transcript.current_hash());
- cx.common
- .start_traffic(&mut cx.sendable_plaintext);
-
- // Now that we've reached the end of the normal handshake we must enforce ECH acceptance by
- // sending an alert and returning an error (potentially with retry configs) if the server
- // did not accept our ECH offer.
- if cx.data.ech_status == EchStatus::Rejected {
- return Err(ech::fatal_alert_required(st.ech_retry_configs, cx.common));
- }
-
- let st = ExpectTraffic {
- config: st.config.clone(),
- session_storage: st.config.resumption.store.clone(),
- server_name: st.server_name,
- suite: st.suite,
- key_schedule,
- resumption,
- _cert_verified: st.cert_verified,
- _sig_verified: st.sig_verified,
- _fin_verified: fin,
- };
-
- Ok(match cx.common.is_quic() {
- true => Box::new(ExpectQuicTraffic(st)),
- false => Box::new(st),
- })
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-// -- Traffic transit state (TLS1.3) --
-// In this state we can be sent tickets, key updates,
-// and application data.
-struct ExpectTraffic {
- config: Arc<ClientConfig>,
- session_storage: Arc<dyn ClientSessionStore>,
- server_name: ServerName<'static>,
- suite: &'static Tls13CipherSuite,
- key_schedule: KeyScheduleTraffic,
- resumption: KeyScheduleResumption,
- _cert_verified: verify::ServerCertVerified,
- _sig_verified: verify::HandshakeSignatureValid,
- _fin_verified: verify::FinishedMessageVerified,
-}
-
-impl ExpectTraffic {
- fn handle_new_ticket_impl(
- &mut self,
- cx: &mut KernelContext<'_>,
- nst: &NewSessionTicketPayloadTls13,
- ) -> Result<(), Error> {
- let secret = self
- .resumption
- .derive_ticket_psk(&nst.nonce.0);
-
- let now = self.config.current_time()?;
-
- #[allow(unused_mut)]
- let mut value = persist::Tls13ClientSessionValue::new(
- self.suite,
- nst.ticket.clone(),
- secret.as_ref(),
- cx.peer_certificates
- .cloned()
- .unwrap_or_default(),
- &self.config.verifier,
- &self.config.client_auth_cert_resolver,
- now,
- nst.lifetime,
- nst.age_add,
- nst.extensions
- .max_early_data_size
- .unwrap_or_default(),
- );
-
- if cx.is_quic() {
- if let Some(sz) = nst.extensions.max_early_data_size {
- if sz != 0 && sz != 0xffff_ffff {
- return Err(PeerMisbehaved::InvalidMaxEarlyDataSize.into());
- }
- }
-
- if let Some(quic_params) = &cx.quic.params {
- value.set_quic_params(quic_params);
- }
- }
-
- self.session_storage
- .insert_tls13_ticket(self.server_name.clone(), value);
- Ok(())
- }
-
- fn handle_new_ticket_tls13(
- &mut self,
- cx: &mut ClientContext<'_>,
- nst: &NewSessionTicketPayloadTls13,
- ) -> Result<(), Error> {
- let mut kcx = KernelContext {
- peer_certificates: cx.common.peer_certificates.as_ref(),
- protocol: cx.common.protocol,
- quic: &cx.common.quic,
- };
- cx.common.tls13_tickets_received = cx
- .common
- .tls13_tickets_received
- .saturating_add(1);
- self.handle_new_ticket_impl(&mut kcx, nst)
- }
-
- fn handle_key_update(
- &mut self,
- common: &mut CommonState,
- key_update_request: &KeyUpdateRequest,
- ) -> Result<(), Error> {
- if let Protocol::Quic = common.protocol {
- return Err(common.send_fatal_alert(
- AlertDescription::UnexpectedMessage,
- PeerMisbehaved::KeyUpdateReceivedInQuicConnection,
- ));
- }
-
- // Mustn't be interleaved with other handshake messages.
- common.check_aligned_handshake()?;
-
- if common.should_update_key(key_update_request)? {
- self.key_schedule
- .update_encrypter_and_notify(common);
- }
-
- // Update our read-side keys.
- self.key_schedule
- .update_decrypter(common);
- Ok(())
- }
-}
-
-impl State<ClientConnectionData> for ExpectTraffic {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- match m.payload {
- MessagePayload::ApplicationData(payload) => cx
- .common
- .take_received_plaintext(payload),
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::NewSessionTicketTls13(new_ticket)),
- ..
- } => self.handle_new_ticket_tls13(cx, &new_ticket)?,
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::KeyUpdate(key_update)),
- ..
- } => self.handle_key_update(cx.common, &key_update)?,
- payload => {
- return Err(inappropriate_handshake_message(
- &payload,
- &[ContentType::ApplicationData, ContentType::Handshake],
- &[HandshakeType::NewSessionTicket, HandshakeType::KeyUpdate],
- ));
- }
- }
-
- Ok(self)
- }
-
- fn send_key_update_request(&mut self, common: &mut CommonState) -> Result<(), Error> {
- self.key_schedule
- .request_key_update_and_update_encrypter(common)
- }
-
- fn export_keying_material(
- &self,
- output: &mut [u8],
- label: &[u8],
- context: Option<&[u8]>,
- ) -> Result<(), Error> {
- self.key_schedule
- .export_keying_material(output, label, context)
- }
-
- fn extract_secrets(&self) -> Result<PartiallyExtractedSecrets, Error> {
- self.key_schedule
- .extract_secrets(Side::Client)
- }
-
- fn into_external_state(self: Box<Self>) -> Result<Box<dyn KernelState + 'static>, Error> {
- Ok(self)
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-impl KernelState for ExpectTraffic {
- fn update_secrets(&mut self, dir: Direction) -> Result<ConnectionTrafficSecrets, Error> {
- self.key_schedule
- .refresh_traffic_secret(match dir {
- Direction::Transmit => Side::Client,
- Direction::Receive => Side::Server,
- })
- }
-
- fn handle_new_session_ticket(
- &mut self,
- cx: &mut KernelContext<'_>,
- message: &NewSessionTicketPayloadTls13,
- ) -> Result<(), Error> {
- self.handle_new_ticket_impl(cx, message)
- }
-}
-
-struct ExpectQuicTraffic(ExpectTraffic);
-
-impl State<ClientConnectionData> for ExpectQuicTraffic {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ClientContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- let nst = require_handshake_msg!(
- m,
- HandshakeType::NewSessionTicket,
- HandshakePayload::NewSessionTicketTls13
- )?;
- self.0
- .handle_new_ticket_tls13(cx, nst)?;
- Ok(self)
- }
-
- fn export_keying_material(
- &self,
- output: &mut [u8],
- label: &[u8],
- context: Option<&[u8]>,
- ) -> Result<(), Error> {
- self.0
- .export_keying_material(output, label, context)
- }
-
- fn into_external_state(self: Box<Self>) -> Result<Box<dyn KernelState + 'static>, Error> {
- Ok(self)
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-impl KernelState for ExpectQuicTraffic {
- fn update_secrets(&mut self, _: Direction) -> Result<ConnectionTrafficSecrets, Error> {
- Err(Error::General(
- "KeyUpdate is not supported for QUIC connections".into(),
- ))
- }
-
- fn handle_new_session_ticket(
- &mut self,
- cx: &mut KernelContext<'_>,
- nst: &NewSessionTicketPayloadTls13,
- ) -> Result<(), Error> {
- self.0.handle_new_ticket_impl(cx, nst)
- }
-}
diff --git a/vendor/rustls/src/common_state.rs b/vendor/rustls/src/common_state.rs
deleted file mode 100644
index 4d47cf15..00000000
--- a/vendor/rustls/src/common_state.rs
+++ /dev/null
@@ -1,1049 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec::Vec;
-
-use pki_types::CertificateDer;
-
-use crate::conn::kernel::KernelState;
-use crate::crypto::SupportedKxGroup;
-use crate::enums::{AlertDescription, ContentType, HandshakeType, ProtocolVersion};
-use crate::error::{Error, InvalidMessage, PeerMisbehaved};
-use crate::hash_hs::HandshakeHash;
-use crate::log::{debug, error, warn};
-use crate::msgs::alert::AlertMessagePayload;
-use crate::msgs::base::Payload;
-use crate::msgs::codec::Codec;
-use crate::msgs::enums::{AlertLevel, KeyUpdateRequest};
-use crate::msgs::fragmenter::MessageFragmenter;
-use crate::msgs::handshake::{CertificateChain, HandshakeMessagePayload, ProtocolName};
-use crate::msgs::message::{
- Message, MessagePayload, OutboundChunks, OutboundOpaqueMessage, OutboundPlainMessage,
- PlainMessage,
-};
-use crate::record_layer::PreEncryptAction;
-use crate::suites::{PartiallyExtractedSecrets, SupportedCipherSuite};
-#[cfg(feature = "tls12")]
-use crate::tls12::ConnectionSecrets;
-use crate::unbuffered::{EncryptError, InsufficientSizeError};
-use crate::vecbuf::ChunkVecBuffer;
-use crate::{quic, record_layer};
-
-/// Connection state common to both client and server connections.
-pub struct CommonState {
- pub(crate) negotiated_version: Option<ProtocolVersion>,
- pub(crate) handshake_kind: Option<HandshakeKind>,
- pub(crate) side: Side,
- pub(crate) record_layer: record_layer::RecordLayer,
- pub(crate) suite: Option<SupportedCipherSuite>,
- pub(crate) kx_state: KxState,
- pub(crate) alpn_protocol: Option<ProtocolName>,
- pub(crate) aligned_handshake: bool,
- pub(crate) may_send_application_data: bool,
- pub(crate) may_receive_application_data: bool,
- pub(crate) early_traffic: bool,
- sent_fatal_alert: bool,
- /// If we signaled end of stream.
- pub(crate) has_sent_close_notify: bool,
- /// If the peer has signaled end of stream.
- pub(crate) has_received_close_notify: bool,
- #[cfg(feature = "std")]
- pub(crate) has_seen_eof: bool,
- pub(crate) peer_certificates: Option<CertificateChain<'static>>,
- message_fragmenter: MessageFragmenter,
- pub(crate) received_plaintext: ChunkVecBuffer,
- pub(crate) sendable_tls: ChunkVecBuffer,
- queued_key_update_message: Option<Vec<u8>>,
-
- /// Protocol whose key schedule should be used. Unused for TLS < 1.3.
- pub(crate) protocol: Protocol,
- pub(crate) quic: quic::Quic,
- pub(crate) enable_secret_extraction: bool,
- temper_counters: TemperCounters,
- pub(crate) refresh_traffic_keys_pending: bool,
- pub(crate) fips: bool,
- pub(crate) tls13_tickets_received: u32,
-}
-
-impl CommonState {
- pub(crate) fn new(side: Side) -> Self {
- Self {
- negotiated_version: None,
- handshake_kind: None,
- side,
- record_layer: record_layer::RecordLayer::new(),
- suite: None,
- kx_state: KxState::default(),
- alpn_protocol: None,
- aligned_handshake: true,
- may_send_application_data: false,
- may_receive_application_data: false,
- early_traffic: false,
- sent_fatal_alert: false,
- has_sent_close_notify: false,
- has_received_close_notify: false,
- #[cfg(feature = "std")]
- has_seen_eof: false,
- peer_certificates: None,
- message_fragmenter: MessageFragmenter::default(),
- received_plaintext: ChunkVecBuffer::new(Some(DEFAULT_RECEIVED_PLAINTEXT_LIMIT)),
- sendable_tls: ChunkVecBuffer::new(Some(DEFAULT_BUFFER_LIMIT)),
- queued_key_update_message: None,
- protocol: Protocol::Tcp,
- quic: quic::Quic::default(),
- enable_secret_extraction: false,
- temper_counters: TemperCounters::default(),
- refresh_traffic_keys_pending: false,
- fips: false,
- tls13_tickets_received: 0,
- }
- }
-
- /// Returns true if the caller should call [`Connection::write_tls`] as soon as possible.
- ///
- /// [`Connection::write_tls`]: crate::Connection::write_tls
- pub fn wants_write(&self) -> bool {
- !self.sendable_tls.is_empty()
- }
-
- /// Returns true if the connection is currently performing the TLS handshake.
- ///
- /// During this time plaintext written to the connection is buffered in memory. After
- /// [`Connection::process_new_packets()`] has been called, this might start to return `false`
- /// while the final handshake packets still need to be extracted from the connection's buffers.
- ///
- /// [`Connection::process_new_packets()`]: crate::Connection::process_new_packets
- pub fn is_handshaking(&self) -> bool {
- !(self.may_send_application_data && self.may_receive_application_data)
- }
-
- /// Retrieves the certificate chain or the raw public key used by the peer to authenticate.
- ///
- /// The order of the certificate chain is as it appears in the TLS
- /// protocol: the first certificate relates to the peer, the
- /// second certifies the first, the third certifies the second, and
- /// so on.
- ///
- /// When using raw public keys, the first and only element is the raw public key.
- ///
- /// This is made available for both full and resumed handshakes.
- ///
- /// For clients, this is the certificate chain or the raw public key of the server.
- ///
- /// For servers, this is the certificate chain or the raw public key of the client,
- /// if client authentication was completed.
- ///
- /// The return value is None until this value is available.
- ///
- /// Note: the return type of the 'certificate', when using raw public keys is `CertificateDer<'static>`
- /// even though this should technically be a `SubjectPublicKeyInfoDer<'static>`.
- /// This choice simplifies the API and ensures backwards compatibility.
- pub fn peer_certificates(&self) -> Option<&[CertificateDer<'static>]> {
- self.peer_certificates.as_deref()
- }
-
- /// Retrieves the protocol agreed with the peer via ALPN.
- ///
- /// A return value of `None` after handshake completion
- /// means no protocol was agreed (because no protocols
- /// were offered or accepted by the peer).
- pub fn alpn_protocol(&self) -> Option<&[u8]> {
- self.get_alpn_protocol()
- }
-
- /// Retrieves the ciphersuite agreed with the peer.
- ///
- /// This returns None until the ciphersuite is agreed.
- pub fn negotiated_cipher_suite(&self) -> Option<SupportedCipherSuite> {
- self.suite
- }
-
- /// Retrieves the key exchange group agreed with the peer.
- ///
- /// This function may return `None` depending on the state of the connection,
- /// the type of handshake, and the protocol version.
- ///
- /// If [`CommonState::is_handshaking()`] is true this function will return `None`.
- /// Similarly, if the [`CommonState::handshake_kind()`] is [`HandshakeKind::Resumed`]
- /// and the [`CommonState::protocol_version()`] is TLS 1.2, then no key exchange will have
- /// occurred and this function will return `None`.
- pub fn negotiated_key_exchange_group(&self) -> Option<&'static dyn SupportedKxGroup> {
- match self.kx_state {
- KxState::Complete(group) => Some(group),
- _ => None,
- }
- }
-
- /// Retrieves the protocol version agreed with the peer.
- ///
- /// This returns `None` until the version is agreed.
- pub fn protocol_version(&self) -> Option<ProtocolVersion> {
- self.negotiated_version
- }
-
- /// Which kind of handshake was performed.
- ///
- /// This tells you whether the handshake was a resumption or not.
- ///
- /// This will return `None` before it is known which sort of
- /// handshake occurred.
- pub fn handshake_kind(&self) -> Option<HandshakeKind> {
- self.handshake_kind
- }
-
- pub(crate) fn is_tls13(&self) -> bool {
- matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
- }
-
- pub(crate) fn process_main_protocol<Data>(
- &mut self,
- msg: Message<'_>,
- mut state: Box<dyn State<Data>>,
- data: &mut Data,
- sendable_plaintext: Option<&mut ChunkVecBuffer>,
- ) -> Result<Box<dyn State<Data>>, Error> {
- // For TLS1.2, outside of the handshake, send rejection alerts for
- // renegotiation requests. These can occur any time.
- if self.may_receive_application_data && !self.is_tls13() {
- let reject_ty = match self.side {
- Side::Client => HandshakeType::HelloRequest,
- Side::Server => HandshakeType::ClientHello,
- };
- if msg.is_handshake_type(reject_ty) {
- self.temper_counters
- .received_renegotiation_request()?;
- self.send_warning_alert(AlertDescription::NoRenegotiation);
- return Ok(state);
- }
- }
-
- let mut cx = Context {
- common: self,
- data,
- sendable_plaintext,
- };
- match state.handle(&mut cx, msg) {
- Ok(next) => {
- state = next.into_owned();
- Ok(state)
- }
- Err(e @ Error::InappropriateMessage { .. })
- | Err(e @ Error::InappropriateHandshakeMessage { .. }) => {
- Err(self.send_fatal_alert(AlertDescription::UnexpectedMessage, e))
- }
- Err(e) => Err(e),
- }
- }
-
- pub(crate) fn write_plaintext(
- &mut self,
- payload: OutboundChunks<'_>,
- outgoing_tls: &mut [u8],
- ) -> Result<usize, EncryptError> {
- if payload.is_empty() {
- return Ok(0);
- }
-
- let fragments = self
- .message_fragmenter
- .fragment_payload(
- ContentType::ApplicationData,
- ProtocolVersion::TLSv1_2,
- payload.clone(),
- );
-
- for f in 0..fragments.len() {
- match self
- .record_layer
- .pre_encrypt_action(f as u64)
- {
- PreEncryptAction::Nothing => {}
- PreEncryptAction::RefreshOrClose => match self.negotiated_version {
- Some(ProtocolVersion::TLSv1_3) => {
- // driven by caller, as we don't have the `State` here
- self.refresh_traffic_keys_pending = true;
- }
- _ => {
- error!(
- "traffic keys exhausted, closing connection to prevent security failure"
- );
- self.send_close_notify();
- return Err(EncryptError::EncryptExhausted);
- }
- },
- PreEncryptAction::Refuse => {
- return Err(EncryptError::EncryptExhausted);
- }
- }
- }
-
- self.perhaps_write_key_update();
-
- self.check_required_size(outgoing_tls, fragments)?;
-
- let fragments = self
- .message_fragmenter
- .fragment_payload(
- ContentType::ApplicationData,
- ProtocolVersion::TLSv1_2,
- payload,
- );
-
- Ok(self.write_fragments(outgoing_tls, fragments))
- }
-
- // Changing the keys must not span any fragmented handshake
- // messages. Otherwise the defragmented messages will have
- // been protected with two different record layer protections,
- // which is illegal. Not mentioned in RFC.
- pub(crate) fn check_aligned_handshake(&mut self) -> Result<(), Error> {
- if !self.aligned_handshake {
- Err(self.send_fatal_alert(
- AlertDescription::UnexpectedMessage,
- PeerMisbehaved::KeyEpochWithPendingFragment,
- ))
- } else {
- Ok(())
- }
- }
-
- /// Fragment `m`, encrypt the fragments, and then queue
- /// the encrypted fragments for sending.
- pub(crate) fn send_msg_encrypt(&mut self, m: PlainMessage) {
- let iter = self
- .message_fragmenter
- .fragment_message(&m);
- for m in iter {
- self.send_single_fragment(m);
- }
- }
-
- /// Like send_msg_encrypt, but operate on an appdata directly.
- fn send_appdata_encrypt(&mut self, payload: OutboundChunks<'_>, limit: Limit) -> usize {
- // Here, the limit on sendable_tls applies to encrypted data,
- // but we're respecting it for plaintext data -- so we'll
- // be out by whatever the cipher+record overhead is. That's a
- // constant and predictable amount, so it's not a terrible issue.
- let len = match limit {
- #[cfg(feature = "std")]
- Limit::Yes => self
- .sendable_tls
- .apply_limit(payload.len()),
- Limit::No => payload.len(),
- };
-
- let iter = self
- .message_fragmenter
- .fragment_payload(
- ContentType::ApplicationData,
- ProtocolVersion::TLSv1_2,
- payload.split_at(len).0,
- );
- for m in iter {
- self.send_single_fragment(m);
- }
-
- len
- }
-
- fn send_single_fragment(&mut self, m: OutboundPlainMessage<'_>) {
- if m.typ == ContentType::Alert {
- // Alerts are always sendable -- never quashed by a PreEncryptAction.
- let em = self.record_layer.encrypt_outgoing(m);
- self.queue_tls_message(em);
- return;
- }
-
- match self
- .record_layer
- .next_pre_encrypt_action()
- {
- PreEncryptAction::Nothing => {}
-
- // Close connection once we start to run out of
- // sequence space.
- PreEncryptAction::RefreshOrClose => {
- match self.negotiated_version {
- Some(ProtocolVersion::TLSv1_3) => {
- // driven by caller, as we don't have the `State` here
- self.refresh_traffic_keys_pending = true;
- }
- _ => {
- error!(
- "traffic keys exhausted, closing connection to prevent security failure"
- );
- self.send_close_notify();
- return;
- }
- }
- }
-
- // Refuse to wrap counter at all costs. This
- // is basically untestable unfortunately.
- PreEncryptAction::Refuse => {
- return;
- }
- };
-
- let em = self.record_layer.encrypt_outgoing(m);
- self.queue_tls_message(em);
- }
-
- fn send_plain_non_buffering(&mut self, payload: OutboundChunks<'_>, limit: Limit) -> usize {
- debug_assert!(self.may_send_application_data);
- debug_assert!(self.record_layer.is_encrypting());
-
- if payload.is_empty() {
- // Don't send empty fragments.
- return 0;
- }
-
- self.send_appdata_encrypt(payload, limit)
- }
-
- /// Mark the connection as ready to send application data.
- ///
- /// Also flush `sendable_plaintext` if it is `Some`.
- pub(crate) fn start_outgoing_traffic(
- &mut self,
- sendable_plaintext: &mut Option<&mut ChunkVecBuffer>,
- ) {
- self.may_send_application_data = true;
- if let Some(sendable_plaintext) = sendable_plaintext {
- self.flush_plaintext(sendable_plaintext);
- }
- }
-
- /// Mark the connection as ready to send and receive application data.
- ///
- /// Also flush `sendable_plaintext` if it is `Some`.
- pub(crate) fn start_traffic(&mut self, sendable_plaintext: &mut Option<&mut ChunkVecBuffer>) {
- self.may_receive_application_data = true;
- self.start_outgoing_traffic(sendable_plaintext);
- }
-
- /// Send any buffered plaintext. Plaintext is buffered if
- /// written during handshake.
- fn flush_plaintext(&mut self, sendable_plaintext: &mut ChunkVecBuffer) {
- if !self.may_send_application_data {
- return;
- }
-
- while let Some(buf) = sendable_plaintext.pop() {
- self.send_plain_non_buffering(buf.as_slice().into(), Limit::No);
- }
- }
-
- // Put m into sendable_tls for writing.
- fn queue_tls_message(&mut self, m: OutboundOpaqueMessage) {
- self.perhaps_write_key_update();
- self.sendable_tls.append(m.encode());
- }
-
- pub(crate) fn perhaps_write_key_update(&mut self) {
- if let Some(message) = self.queued_key_update_message.take() {
- self.sendable_tls.append(message);
- }
- }
-
- /// Send a raw TLS message, fragmenting it if needed.
- pub(crate) fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool) {
- {
- if let Protocol::Quic = self.protocol {
- if let MessagePayload::Alert(alert) = m.payload {
- self.quic.alert = Some(alert.description);
- } else {
- debug_assert!(
- matches!(
- m.payload,
- MessagePayload::Handshake { .. } | MessagePayload::HandshakeFlight(_)
- ),
- "QUIC uses TLS for the cryptographic handshake only"
- );
- let mut bytes = Vec::new();
- m.payload.encode(&mut bytes);
- self.quic
- .hs_queue
- .push_back((must_encrypt, bytes));
- }
- return;
- }
- }
- if !must_encrypt {
- let msg = &m.into();
- let iter = self
- .message_fragmenter
- .fragment_message(msg);
- for m in iter {
- self.queue_tls_message(m.to_unencrypted_opaque());
- }
- } else {
- self.send_msg_encrypt(m.into());
- }
- }
-
- pub(crate) fn take_received_plaintext(&mut self, bytes: Payload<'_>) {
- self.received_plaintext
- .append(bytes.into_vec());
- }
-
- #[cfg(feature = "tls12")]
- pub(crate) fn start_encryption_tls12(&mut self, secrets: &ConnectionSecrets, side: Side) {
- let (dec, enc) = secrets.make_cipher_pair(side);
- self.record_layer
- .prepare_message_encrypter(
- enc,
- secrets
- .suite()
- .common
- .confidentiality_limit,
- );
- self.record_layer
- .prepare_message_decrypter(dec);
- }
-
- pub(crate) fn missing_extension(&mut self, why: PeerMisbehaved) -> Error {
- self.send_fatal_alert(AlertDescription::MissingExtension, why)
- }
-
- fn send_warning_alert(&mut self, desc: AlertDescription) {
- warn!("Sending warning alert {desc:?}");
- self.send_warning_alert_no_log(desc);
- }
-
- pub(crate) fn process_alert(&mut self, alert: &AlertMessagePayload) -> Result<(), Error> {
- // Reject unknown AlertLevels.
- if let AlertLevel::Unknown(_) = alert.level {
- return Err(self.send_fatal_alert(
- AlertDescription::IllegalParameter,
- Error::AlertReceived(alert.description),
- ));
- }
-
- // If we get a CloseNotify, make a note to declare EOF to our
- // caller. But do not treat unauthenticated alerts like this.
- if self.may_receive_application_data && alert.description == AlertDescription::CloseNotify {
- self.has_received_close_notify = true;
- return Ok(());
- }
-
- // Warnings are nonfatal for TLS1.2, but outlawed in TLS1.3
- // (except, for no good reason, user_cancelled).
- let err = Error::AlertReceived(alert.description);
- if alert.level == AlertLevel::Warning {
- self.temper_counters
- .received_warning_alert()?;
- if self.is_tls13() && alert.description != AlertDescription::UserCanceled {
- return Err(self.send_fatal_alert(AlertDescription::DecodeError, err));
- }
-
- // Some implementations send pointless `user_canceled` alerts, don't log them
- // in release mode (https://bugs.openjdk.org/browse/JDK-8323517).
- if alert.description != AlertDescription::UserCanceled || cfg!(debug_assertions) {
- warn!("TLS alert warning received: {alert:?}");
- }
-
- return Ok(());
- }
-
- Err(err)
- }
-
- pub(crate) fn send_cert_verify_error_alert(&mut self, err: Error) -> Error {
- self.send_fatal_alert(
- match &err {
- Error::InvalidCertificate(e) => e.clone().into(),
- Error::PeerMisbehaved(_) => AlertDescription::IllegalParameter,
- _ => AlertDescription::HandshakeFailure,
- },
- err,
- )
- }
-
- pub(crate) fn send_fatal_alert(
- &mut self,
- desc: AlertDescription,
- err: impl Into<Error>,
- ) -> Error {
- debug_assert!(!self.sent_fatal_alert);
- let m = Message::build_alert(AlertLevel::Fatal, desc);
- self.send_msg(m, self.record_layer.is_encrypting());
- self.sent_fatal_alert = true;
- err.into()
- }
-
- /// Queues a `close_notify` warning alert to be sent in the next
- /// [`Connection::write_tls`] call. This informs the peer that the
- /// connection is being closed.
- ///
- /// Does nothing if any `close_notify` or fatal alert was already sent.
- ///
- /// [`Connection::write_tls`]: crate::Connection::write_tls
- pub fn send_close_notify(&mut self) {
- if self.sent_fatal_alert {
- return;
- }
- debug!("Sending warning alert {:?}", AlertDescription::CloseNotify);
- self.sent_fatal_alert = true;
- self.has_sent_close_notify = true;
- self.send_warning_alert_no_log(AlertDescription::CloseNotify);
- }
-
- pub(crate) fn eager_send_close_notify(
- &mut self,
- outgoing_tls: &mut [u8],
- ) -> Result<usize, EncryptError> {
- self.send_close_notify();
- self.check_required_size(outgoing_tls, [].into_iter())?;
- Ok(self.write_fragments(outgoing_tls, [].into_iter()))
- }
-
- fn send_warning_alert_no_log(&mut self, desc: AlertDescription) {
- let m = Message::build_alert(AlertLevel::Warning, desc);
- self.send_msg(m, self.record_layer.is_encrypting());
- }
-
- fn check_required_size<'a>(
- &self,
- outgoing_tls: &mut [u8],
- fragments: impl Iterator<Item = OutboundPlainMessage<'a>>,
- ) -> Result<(), EncryptError> {
- let mut required_size = self.sendable_tls.len();
-
- for m in fragments {
- required_size += m.encoded_len(&self.record_layer);
- }
-
- if required_size > outgoing_tls.len() {
- return Err(EncryptError::InsufficientSize(InsufficientSizeError {
- required_size,
- }));
- }
-
- Ok(())
- }
-
- fn write_fragments<'a>(
- &mut self,
- outgoing_tls: &mut [u8],
- fragments: impl Iterator<Item = OutboundPlainMessage<'a>>,
- ) -> usize {
- let mut written = 0;
-
- // Any pre-existing encrypted messages in `sendable_tls` must
- // be output before encrypting any of the `fragments`.
- while let Some(message) = self.sendable_tls.pop() {
- let len = message.len();
- outgoing_tls[written..written + len].copy_from_slice(&message);
- written += len;
- }
-
- for m in fragments {
- let em = self
- .record_layer
- .encrypt_outgoing(m)
- .encode();
-
- let len = em.len();
- outgoing_tls[written..written + len].copy_from_slice(&em);
- written += len;
- }
-
- written
- }
-
- pub(crate) fn set_max_fragment_size(&mut self, new: Option<usize>) -> Result<(), Error> {
- self.message_fragmenter
- .set_max_fragment_size(new)
- }
-
- pub(crate) fn get_alpn_protocol(&self) -> Option<&[u8]> {
- self.alpn_protocol
- .as_ref()
- .map(AsRef::as_ref)
- }
-
- /// Returns true if the caller should call [`Connection::read_tls`] as soon
- /// as possible.
- ///
- /// If there is pending plaintext data to read with [`Connection::reader`],
- /// this returns false. If your application respects this mechanism,
- /// only one full TLS message will be buffered by rustls.
- ///
- /// [`Connection::reader`]: crate::Connection::reader
- /// [`Connection::read_tls`]: crate::Connection::read_tls
- pub fn wants_read(&self) -> bool {
- // We want to read more data all the time, except when we have unprocessed plaintext.
- // This provides back-pressure to the TCP buffers. We also don't want to read more after
- // the peer has sent us a close notification.
- //
- // In the handshake case we don't have readable plaintext before the handshake has
- // completed, but also don't want to read if we still have sendable tls.
- self.received_plaintext.is_empty()
- && !self.has_received_close_notify
- && (self.may_send_application_data || self.sendable_tls.is_empty())
- }
-
- pub(crate) fn current_io_state(&self) -> IoState {
- IoState {
- tls_bytes_to_write: self.sendable_tls.len(),
- plaintext_bytes_to_read: self.received_plaintext.len(),
- peer_has_closed: self.has_received_close_notify,
- }
- }
-
- pub(crate) fn is_quic(&self) -> bool {
- self.protocol == Protocol::Quic
- }
-
- pub(crate) fn should_update_key(
- &mut self,
- key_update_request: &KeyUpdateRequest,
- ) -> Result<bool, Error> {
- self.temper_counters
- .received_key_update_request()?;
-
- match key_update_request {
- KeyUpdateRequest::UpdateNotRequested => Ok(false),
- KeyUpdateRequest::UpdateRequested => Ok(self.queued_key_update_message.is_none()),
- _ => Err(self.send_fatal_alert(
- AlertDescription::IllegalParameter,
- InvalidMessage::InvalidKeyUpdate,
- )),
- }
- }
-
- pub(crate) fn enqueue_key_update_notification(&mut self) {
- let message = PlainMessage::from(Message::build_key_update_notify());
- self.queued_key_update_message = Some(
- self.record_layer
- .encrypt_outgoing(message.borrow_outbound())
- .encode(),
- );
- }
-
- pub(crate) fn received_tls13_change_cipher_spec(&mut self) -> Result<(), Error> {
- self.temper_counters
- .received_tls13_change_cipher_spec()
- }
-}
-
-#[cfg(feature = "std")]
-impl CommonState {
- /// Send plaintext application data, fragmenting and
- /// encrypting it as it goes out.
- ///
- /// If internal buffers are too small, this function will not accept
- /// all the data.
- pub(crate) fn buffer_plaintext(
- &mut self,
- payload: OutboundChunks<'_>,
- sendable_plaintext: &mut ChunkVecBuffer,
- ) -> usize {
- self.perhaps_write_key_update();
- self.send_plain(payload, Limit::Yes, sendable_plaintext)
- }
-
- pub(crate) fn send_early_plaintext(&mut self, data: &[u8]) -> usize {
- debug_assert!(self.early_traffic);
- debug_assert!(self.record_layer.is_encrypting());
-
- if data.is_empty() {
- // Don't send empty fragments.
- return 0;
- }
-
- self.send_appdata_encrypt(data.into(), Limit::Yes)
- }
-
- /// Encrypt and send some plaintext `data`. `limit` controls
- /// whether the per-connection buffer limits apply.
- ///
- /// Returns the number of bytes written from `data`: this might
- /// be less than `data.len()` if buffer limits were exceeded.
- fn send_plain(
- &mut self,
- payload: OutboundChunks<'_>,
- limit: Limit,
- sendable_plaintext: &mut ChunkVecBuffer,
- ) -> usize {
- if !self.may_send_application_data {
- // If we haven't completed handshaking, buffer
- // plaintext to send once we do.
- let len = match limit {
- Limit::Yes => sendable_plaintext.append_limited_copy(payload),
- Limit::No => sendable_plaintext.append(payload.to_vec()),
- };
- return len;
- }
-
- self.send_plain_non_buffering(payload, limit)
- }
-}
-
-/// Describes which sort of handshake happened.
-#[derive(Debug, PartialEq, Clone, Copy)]
-pub enum HandshakeKind {
- /// A full handshake.
- ///
- /// This is the typical TLS connection initiation process when resumption is
- /// not yet unavailable, and the initial `ClientHello` was accepted by the server.
- Full,
-
- /// A full TLS1.3 handshake, with an extra round-trip for a `HelloRetryRequest`.
- ///
- /// The server can respond with a `HelloRetryRequest` if the initial `ClientHello`
- /// is unacceptable for several reasons, the most likely if no supported key
- /// shares were offered by the client.
- FullWithHelloRetryRequest,
-
- /// A resumed handshake.
- ///
- /// Resumed handshakes involve fewer round trips and less cryptography than
- /// full ones, but can only happen when the peers have previously done a full
- /// handshake together, and then remember data about it.
- Resumed,
-}
-
-/// Values of this structure are returned from [`Connection::process_new_packets`]
-/// and tell the caller the current I/O state of the TLS connection.
-///
-/// [`Connection::process_new_packets`]: crate::Connection::process_new_packets
-#[derive(Debug, Eq, PartialEq)]
-pub struct IoState {
- tls_bytes_to_write: usize,
- plaintext_bytes_to_read: usize,
- peer_has_closed: bool,
-}
-
-impl IoState {
- /// How many bytes could be written by [`Connection::write_tls`] if called
- /// right now. A non-zero value implies [`CommonState::wants_write`].
- ///
- /// [`Connection::write_tls`]: crate::Connection::write_tls
- pub fn tls_bytes_to_write(&self) -> usize {
- self.tls_bytes_to_write
- }
-
- /// How many plaintext bytes could be obtained via [`std::io::Read`]
- /// without further I/O.
- pub fn plaintext_bytes_to_read(&self) -> usize {
- self.plaintext_bytes_to_read
- }
-
- /// True if the peer has sent us a close_notify alert. This is
- /// the TLS mechanism to securely half-close a TLS connection,
- /// and signifies that the peer will not send any further data
- /// on this connection.
- ///
- /// This is also signalled via returning `Ok(0)` from
- /// [`std::io::Read`], after all the received bytes have been
- /// retrieved.
- pub fn peer_has_closed(&self) -> bool {
- self.peer_has_closed
- }
-}
-
-pub(crate) trait State<Data>: Send + Sync {
- fn handle<'m>(
- self: Box<Self>,
- cx: &mut Context<'_, Data>,
- message: Message<'m>,
- ) -> Result<Box<dyn State<Data> + 'm>, Error>
- where
- Self: 'm;
-
- fn export_keying_material(
- &self,
- _output: &mut [u8],
- _label: &[u8],
- _context: Option<&[u8]>,
- ) -> Result<(), Error> {
- Err(Error::HandshakeNotComplete)
- }
-
- fn extract_secrets(&self) -> Result<PartiallyExtractedSecrets, Error> {
- Err(Error::HandshakeNotComplete)
- }
-
- fn send_key_update_request(&mut self, _common: &mut CommonState) -> Result<(), Error> {
- Err(Error::HandshakeNotComplete)
- }
-
- fn handle_decrypt_error(&self) {}
-
- fn into_external_state(self: Box<Self>) -> Result<Box<dyn KernelState + 'static>, Error> {
- Err(Error::HandshakeNotComplete)
- }
-
- fn into_owned(self: Box<Self>) -> Box<dyn State<Data> + 'static>;
-}
-
-pub(crate) struct Context<'a, Data> {
- pub(crate) common: &'a mut CommonState,
- pub(crate) data: &'a mut Data,
- /// Buffered plaintext. This is `Some` if any plaintext was written during handshake and `None`
- /// otherwise.
- pub(crate) sendable_plaintext: Option<&'a mut ChunkVecBuffer>,
-}
-
-/// Side of the connection.
-#[derive(Clone, Copy, Debug, PartialEq)]
-pub enum Side {
- /// A client initiates the connection.
- Client,
- /// A server waits for a client to connect.
- Server,
-}
-
-impl Side {
- pub(crate) fn peer(&self) -> Self {
- match self {
- Self::Client => Self::Server,
- Self::Server => Self::Client,
- }
- }
-}
-
-#[derive(Copy, Clone, Eq, PartialEq, Debug)]
-pub(crate) enum Protocol {
- Tcp,
- Quic,
-}
-
-enum Limit {
- #[cfg(feature = "std")]
- Yes,
- No,
-}
-
-/// Tracking technically-allowed protocol actions
-/// that we limit to avoid denial-of-service vectors.
-struct TemperCounters {
- allowed_warning_alerts: u8,
- allowed_renegotiation_requests: u8,
- allowed_key_update_requests: u8,
- allowed_middlebox_ccs: u8,
-}
-
-impl TemperCounters {
- fn received_warning_alert(&mut self) -> Result<(), Error> {
- match self.allowed_warning_alerts {
- 0 => Err(PeerMisbehaved::TooManyWarningAlertsReceived.into()),
- _ => {
- self.allowed_warning_alerts -= 1;
- Ok(())
- }
- }
- }
-
- fn received_renegotiation_request(&mut self) -> Result<(), Error> {
- match self.allowed_renegotiation_requests {
- 0 => Err(PeerMisbehaved::TooManyRenegotiationRequests.into()),
- _ => {
- self.allowed_renegotiation_requests -= 1;
- Ok(())
- }
- }
- }
-
- fn received_key_update_request(&mut self) -> Result<(), Error> {
- match self.allowed_key_update_requests {
- 0 => Err(PeerMisbehaved::TooManyKeyUpdateRequests.into()),
- _ => {
- self.allowed_key_update_requests -= 1;
- Ok(())
- }
- }
- }
-
- fn received_tls13_change_cipher_spec(&mut self) -> Result<(), Error> {
- match self.allowed_middlebox_ccs {
- 0 => Err(PeerMisbehaved::IllegalMiddleboxChangeCipherSpec.into()),
- _ => {
- self.allowed_middlebox_ccs -= 1;
- Ok(())
- }
- }
- }
-}
-
-impl Default for TemperCounters {
- fn default() -> Self {
- Self {
- // cf. BoringSSL `kMaxWarningAlerts`
- // <https://github.com/google/boringssl/blob/dec5989b793c56ad4dd32173bd2d8595ca78b398/ssl/tls_record.cc#L137-L139>
- allowed_warning_alerts: 4,
-
- // we rebuff renegotiation requests with a `NoRenegotiation` warning alerts.
- // a second request after this is fatal.
- allowed_renegotiation_requests: 1,
-
- // cf. BoringSSL `kMaxKeyUpdates`
- // <https://github.com/google/boringssl/blob/dec5989b793c56ad4dd32173bd2d8595ca78b398/ssl/tls13_both.cc#L35-L38>
- allowed_key_update_requests: 32,
-
- // At most two CCS are allowed: one after each ClientHello (recall a second
- // ClientHello happens after a HelloRetryRequest).
- //
- // note BoringSSL allows up to 32.
- allowed_middlebox_ccs: 2,
- }
- }
-}
-
-#[derive(Debug, Default)]
-pub(crate) enum KxState {
- #[default]
- None,
- Start(&'static dyn SupportedKxGroup),
- Complete(&'static dyn SupportedKxGroup),
-}
-
-impl KxState {
- pub(crate) fn complete(&mut self) {
- debug_assert!(matches!(self, Self::Start(_)));
- if let Self::Start(group) = self {
- *self = Self::Complete(*group);
- }
- }
-}
-
-pub(crate) struct HandshakeFlight<'a, const TLS13: bool> {
- pub(crate) transcript: &'a mut HandshakeHash,
- body: Vec<u8>,
-}
-
-impl<'a, const TLS13: bool> HandshakeFlight<'a, TLS13> {
- pub(crate) fn new(transcript: &'a mut HandshakeHash) -> Self {
- Self {
- transcript,
- body: Vec::new(),
- }
- }
-
- pub(crate) fn add(&mut self, hs: HandshakeMessagePayload<'_>) {
- let start_len = self.body.len();
- hs.encode(&mut self.body);
- self.transcript
- .add(&self.body[start_len..]);
- }
-
- pub(crate) fn finish(self, common: &mut CommonState) {
- common.send_msg(
- Message {
- version: match TLS13 {
- true => ProtocolVersion::TLSv1_3,
- false => ProtocolVersion::TLSv1_2,
- },
- payload: MessagePayload::HandshakeFlight(Payload::new(self.body)),
- },
- TLS13,
- );
- }
-}
-
-#[cfg(feature = "tls12")]
-pub(crate) type HandshakeFlightTls12<'a> = HandshakeFlight<'a, false>;
-pub(crate) type HandshakeFlightTls13<'a> = HandshakeFlight<'a, true>;
-
-const DEFAULT_RECEIVED_PLAINTEXT_LIMIT: usize = 16 * 1024;
-pub(crate) const DEFAULT_BUFFER_LIMIT: usize = 64 * 1024;
diff --git a/vendor/rustls/src/compress.rs b/vendor/rustls/src/compress.rs
deleted file mode 100644
index d34cbaff..00000000
--- a/vendor/rustls/src/compress.rs
+++ /dev/null
@@ -1,677 +0,0 @@
-//! Certificate compression and decompression support
-//!
-//! This crate supports compression and decompression everywhere
-//! certificates are used, in accordance with [RFC8879][rfc8879].
-//!
-//! Note that this is only supported for TLS1.3 connections.
-//!
-//! # Getting started
-//!
-//! Build this crate with the `brotli` and/or `zlib` crate features. This
-//! adds dependencies on these crates. They are used by default if enabled.
-//!
-//! We especially recommend `brotli` as it has the widest deployment so far.
-//!
-//! # Custom compression/decompression implementations
-//!
-//! 1. Implement the [`CertCompressor`] and/or [`CertDecompressor`] traits
-//! 2. Provide those to:
-//! - [`ClientConfig::cert_compressors`][cc_cc] or [`ServerConfig::cert_compressors`][sc_cc].
-//! - [`ClientConfig::cert_decompressors`][cc_cd] or [`ServerConfig::cert_decompressors`][sc_cd].
-//!
-//! These are used in these circumstances:
-//!
-//! | Peer | Client authentication | Server authentication |
-//! | ---- | --------------------- | --------------------- |
-//! | *Client* | [`ClientConfig::cert_compressors`][cc_cc] | [`ClientConfig::cert_decompressors`][cc_cd] |
-//! | *Server* | [`ServerConfig::cert_decompressors`][sc_cd] | [`ServerConfig::cert_compressors`][sc_cc] |
-//!
-//! [rfc8879]: https://datatracker.ietf.org/doc/html/rfc8879
-//! [cc_cc]: crate::ClientConfig::cert_compressors
-//! [sc_cc]: crate::ServerConfig::cert_compressors
-//! [cc_cd]: crate::ClientConfig::cert_decompressors
-//! [sc_cd]: crate::ServerConfig::cert_decompressors
-
-#[cfg(feature = "std")]
-use alloc::collections::VecDeque;
-use alloc::vec::Vec;
-use core::fmt::Debug;
-#[cfg(feature = "std")]
-use std::sync::Mutex;
-
-use crate::enums::CertificateCompressionAlgorithm;
-use crate::msgs::base::{Payload, PayloadU24};
-use crate::msgs::codec::Codec;
-use crate::msgs::handshake::{CertificatePayloadTls13, CompressedCertificatePayload};
-use crate::sync::Arc;
-
-/// Returns the supported `CertDecompressor` implementations enabled
-/// by crate features.
-pub fn default_cert_decompressors() -> &'static [&'static dyn CertDecompressor] {
- &[
- #[cfg(feature = "brotli")]
- BROTLI_DECOMPRESSOR,
- #[cfg(feature = "zlib")]
- ZLIB_DECOMPRESSOR,
- ]
-}
-
-/// An available certificate decompression algorithm.
-pub trait CertDecompressor: Debug + Send + Sync {
- /// Decompress `input`, writing the result to `output`.
- ///
- /// `output` is sized to match the declared length of the decompressed data.
- ///
- /// `Err(DecompressionFailed)` should be returned if decompression produces more, or fewer
- /// bytes than fit in `output`, or if the `input` is in any way malformed.
- fn decompress(&self, input: &[u8], output: &mut [u8]) -> Result<(), DecompressionFailed>;
-
- /// Which algorithm this decompressor handles.
- fn algorithm(&self) -> CertificateCompressionAlgorithm;
-}
-
-/// Returns the supported `CertCompressor` implementations enabled
-/// by crate features.
-pub fn default_cert_compressors() -> &'static [&'static dyn CertCompressor] {
- &[
- #[cfg(feature = "brotli")]
- BROTLI_COMPRESSOR,
- #[cfg(feature = "zlib")]
- ZLIB_COMPRESSOR,
- ]
-}
-
-/// An available certificate compression algorithm.
-pub trait CertCompressor: Debug + Send + Sync {
- /// Compress `input`, returning the result.
- ///
- /// `input` is consumed by this function so (if the underlying implementation
- /// supports it) the compression can be performed in-place.
- ///
- /// `level` is a hint as to how much effort to expend on the compression.
- ///
- /// `Err(CompressionFailed)` may be returned for any reason.
- fn compress(
- &self,
- input: Vec<u8>,
- level: CompressionLevel,
- ) -> Result<Vec<u8>, CompressionFailed>;
-
- /// Which algorithm this compressor handles.
- fn algorithm(&self) -> CertificateCompressionAlgorithm;
-}
-
-/// A hint for how many resources to dedicate to a compression.
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-pub enum CompressionLevel {
- /// This compression is happening interactively during a handshake.
- ///
- /// Implementations may wish to choose a conservative compression level.
- Interactive,
-
- /// The compression may be amortized over many connections.
- ///
- /// Implementations may wish to choose an aggressive compression level.
- Amortized,
-}
-
-/// A content-less error for when `CertDecompressor::decompress` fails.
-#[derive(Debug)]
-pub struct DecompressionFailed;
-
-/// A content-less error for when `CertCompressor::compress` fails.
-#[derive(Debug)]
-pub struct CompressionFailed;
-
-#[cfg(feature = "zlib")]
-mod feat_zlib_rs {
- use zlib_rs::c_api::Z_BEST_COMPRESSION;
- use zlib_rs::{ReturnCode, deflate, inflate};
-
- use super::*;
-
- /// A certificate decompressor for the Zlib algorithm using the `zlib-rs` crate.
- pub const ZLIB_DECOMPRESSOR: &dyn CertDecompressor = &ZlibRsDecompressor;
-
- #[derive(Debug)]
- struct ZlibRsDecompressor;
-
- impl CertDecompressor for ZlibRsDecompressor {
- fn decompress(&self, input: &[u8], output: &mut [u8]) -> Result<(), DecompressionFailed> {
- let output_len = output.len();
- match inflate::uncompress_slice(output, input, inflate::InflateConfig::default()) {
- (output_filled, ReturnCode::Ok) if output_filled.len() == output_len => Ok(()),
- (_, _) => Err(DecompressionFailed),
- }
- }
-
- fn algorithm(&self) -> CertificateCompressionAlgorithm {
- CertificateCompressionAlgorithm::Zlib
- }
- }
-
- /// A certificate compressor for the Zlib algorithm using the `zlib-rs` crate.
- pub const ZLIB_COMPRESSOR: &dyn CertCompressor = &ZlibRsCompressor;
-
- #[derive(Debug)]
- struct ZlibRsCompressor;
-
- impl CertCompressor for ZlibRsCompressor {
- fn compress(
- &self,
- input: Vec<u8>,
- level: CompressionLevel,
- ) -> Result<Vec<u8>, CompressionFailed> {
- let mut output = alloc::vec![0u8; deflate::compress_bound(input.len())];
- let config = match level {
- CompressionLevel::Interactive => deflate::DeflateConfig::default(),
- CompressionLevel::Amortized => deflate::DeflateConfig::new(Z_BEST_COMPRESSION),
- };
- let (output_filled, rc) = deflate::compress_slice(&mut output, &input, config);
- if rc != ReturnCode::Ok {
- return Err(CompressionFailed);
- }
-
- let used = output_filled.len();
- output.truncate(used);
- Ok(output)
- }
-
- fn algorithm(&self) -> CertificateCompressionAlgorithm {
- CertificateCompressionAlgorithm::Zlib
- }
- }
-}
-
-#[cfg(feature = "zlib")]
-pub use feat_zlib_rs::{ZLIB_COMPRESSOR, ZLIB_DECOMPRESSOR};
-
-#[cfg(feature = "brotli")]
-mod feat_brotli {
- use std::io::{Cursor, Write};
-
- use super::*;
-
- /// A certificate decompressor for the brotli algorithm using the `brotli` crate.
- pub const BROTLI_DECOMPRESSOR: &dyn CertDecompressor = &BrotliDecompressor;
-
- #[derive(Debug)]
- struct BrotliDecompressor;
-
- impl CertDecompressor for BrotliDecompressor {
- fn decompress(&self, input: &[u8], output: &mut [u8]) -> Result<(), DecompressionFailed> {
- let mut in_cursor = Cursor::new(input);
- let mut out_cursor = Cursor::new(output);
-
- brotli::BrotliDecompress(&mut in_cursor, &mut out_cursor)
- .map_err(|_| DecompressionFailed)?;
-
- if out_cursor.position() as usize != out_cursor.into_inner().len() {
- return Err(DecompressionFailed);
- }
-
- Ok(())
- }
-
- fn algorithm(&self) -> CertificateCompressionAlgorithm {
- CertificateCompressionAlgorithm::Brotli
- }
- }
-
- /// A certificate compressor for the brotli algorithm using the `brotli` crate.
- pub const BROTLI_COMPRESSOR: &dyn CertCompressor = &BrotliCompressor;
-
- #[derive(Debug)]
- struct BrotliCompressor;
-
- impl CertCompressor for BrotliCompressor {
- fn compress(
- &self,
- input: Vec<u8>,
- level: CompressionLevel,
- ) -> Result<Vec<u8>, CompressionFailed> {
- let quality = match level {
- CompressionLevel::Interactive => QUALITY_FAST,
- CompressionLevel::Amortized => QUALITY_SLOW,
- };
- let output = Cursor::new(Vec::with_capacity(input.len() / 2));
- let mut compressor = brotli::CompressorWriter::new(output, BUFFER_SIZE, quality, LGWIN);
- compressor
- .write_all(&input)
- .map_err(|_| CompressionFailed)?;
- Ok(compressor.into_inner().into_inner())
- }
-
- fn algorithm(&self) -> CertificateCompressionAlgorithm {
- CertificateCompressionAlgorithm::Brotli
- }
- }
-
- /// Brotli buffer size.
- ///
- /// Chosen based on brotli `examples/compress.rs`.
- const BUFFER_SIZE: usize = 4096;
-
- /// This is the default lgwin parameter, see `BrotliEncoderInitParams()`
- const LGWIN: u32 = 22;
-
- /// Compression quality we use for interactive compressions.
- /// See <https://blog.cloudflare.com/results-experimenting-brotli> for data.
- const QUALITY_FAST: u32 = 4;
-
- /// Compression quality we use for offline compressions (the maximum).
- const QUALITY_SLOW: u32 = 11;
-}
-
-#[cfg(feature = "brotli")]
-pub use feat_brotli::{BROTLI_COMPRESSOR, BROTLI_DECOMPRESSOR};
-
-/// An LRU cache for compressions.
-///
-/// The prospect of being able to reuse a given compression for many connections
-/// means we can afford to spend more time on that compression (by passing
-/// `CompressionLevel::Amortized` to the compressor).
-#[derive(Debug)]
-pub enum CompressionCache {
- /// No caching happens, and compression happens each time using
- /// `CompressionLevel::Interactive`.
- Disabled,
-
- /// Compressions are stored in an LRU cache.
- #[cfg(feature = "std")]
- Enabled(CompressionCacheInner),
-}
-
-/// Innards of an enabled CompressionCache.
-///
-/// You cannot make one of these directly. Use [`CompressionCache::new`].
-#[cfg(feature = "std")]
-#[derive(Debug)]
-pub struct CompressionCacheInner {
- /// Maximum size of underlying storage.
- size: usize,
-
- /// LRU-order entries.
- ///
- /// First is least-used, last is most-used.
- entries: Mutex<VecDeque<Arc<CompressionCacheEntry>>>,
-}
-
-impl CompressionCache {
- /// Make a `CompressionCache` that stores up to `size` compressed
- /// certificate messages.
- #[cfg(feature = "std")]
- pub fn new(size: usize) -> Self {
- if size == 0 {
- return Self::Disabled;
- }
-
- Self::Enabled(CompressionCacheInner {
- size,
- entries: Mutex::new(VecDeque::with_capacity(size)),
- })
- }
-
- /// Return a `CompressionCacheEntry`, which is an owning
- /// wrapper for a `CompressedCertificatePayload`.
- ///
- /// `compressor` is the compression function we have negotiated.
- /// `original` is the uncompressed certificate message.
- pub(crate) fn compression_for(
- &self,
- compressor: &dyn CertCompressor,
- original: &CertificatePayloadTls13<'_>,
- ) -> Result<Arc<CompressionCacheEntry>, CompressionFailed> {
- match self {
- Self::Disabled => Self::uncached_compression(compressor, original),
-
- #[cfg(feature = "std")]
- Self::Enabled(_) => self.compression_for_impl(compressor, original),
- }
- }
-
- #[cfg(feature = "std")]
- fn compression_for_impl(
- &self,
- compressor: &dyn CertCompressor,
- original: &CertificatePayloadTls13<'_>,
- ) -> Result<Arc<CompressionCacheEntry>, CompressionFailed> {
- let (max_size, entries) = match self {
- Self::Enabled(CompressionCacheInner { size, entries }) => (*size, entries),
- _ => unreachable!(),
- };
-
- // context is a per-connection quantity, and included in the compressed data.
- // it is not suitable for inclusion in the cache.
- if !original.context.0.is_empty() {
- return Self::uncached_compression(compressor, original);
- }
-
- // cache probe:
- let encoding = original.get_encoding();
- let algorithm = compressor.algorithm();
-
- let mut cache = entries
- .lock()
- .map_err(|_| CompressionFailed)?;
- for (i, item) in cache.iter().enumerate() {
- if item.algorithm == algorithm && item.original == encoding {
- // this item is now MRU
- let item = cache.remove(i).unwrap();
- cache.push_back(item.clone());
- return Ok(item);
- }
- }
- drop(cache);
-
- // do compression:
- let uncompressed_len = encoding.len() as u32;
- let compressed = compressor.compress(encoding.clone(), CompressionLevel::Amortized)?;
- let new_entry = Arc::new(CompressionCacheEntry {
- algorithm,
- original: encoding,
- compressed: CompressedCertificatePayload {
- alg: algorithm,
- uncompressed_len,
- compressed: PayloadU24(Payload::new(compressed)),
- },
- });
-
- // insert into cache
- let mut cache = entries
- .lock()
- .map_err(|_| CompressionFailed)?;
- if cache.len() == max_size {
- cache.pop_front();
- }
- cache.push_back(new_entry.clone());
- Ok(new_entry)
- }
-
- /// Compress `original` using `compressor` at `Interactive` level.
- fn uncached_compression(
- compressor: &dyn CertCompressor,
- original: &CertificatePayloadTls13<'_>,
- ) -> Result<Arc<CompressionCacheEntry>, CompressionFailed> {
- let algorithm = compressor.algorithm();
- let encoding = original.get_encoding();
- let uncompressed_len = encoding.len() as u32;
- let compressed = compressor.compress(encoding, CompressionLevel::Interactive)?;
-
- // this `CompressionCacheEntry` in fact never makes it into the cache, so
- // `original` is left empty
- Ok(Arc::new(CompressionCacheEntry {
- algorithm,
- original: Vec::new(),
- compressed: CompressedCertificatePayload {
- alg: algorithm,
- uncompressed_len,
- compressed: PayloadU24(Payload::new(compressed)),
- },
- }))
- }
-}
-
-impl Default for CompressionCache {
- fn default() -> Self {
- #[cfg(feature = "std")]
- {
- // 4 entries allows 2 certificate chains times 2 compression algorithms
- Self::new(4)
- }
-
- #[cfg(not(feature = "std"))]
- {
- Self::Disabled
- }
- }
-}
-
-#[cfg_attr(not(feature = "std"), allow(dead_code))]
-#[derive(Debug)]
-pub(crate) struct CompressionCacheEntry {
- // cache key is algorithm + original:
- algorithm: CertificateCompressionAlgorithm,
- original: Vec<u8>,
-
- // cache value is compression result:
- compressed: CompressedCertificatePayload<'static>,
-}
-
-impl CompressionCacheEntry {
- pub(crate) fn compressed_cert_payload(&self) -> CompressedCertificatePayload<'_> {
- self.compressed.as_borrowed()
- }
-}
-
-#[cfg(all(test, any(feature = "brotli", feature = "zlib")))]
-mod tests {
- use std::{println, vec};
-
- use super::*;
-
- #[test]
- #[cfg(feature = "zlib")]
- fn test_zlib() {
- test_compressor(ZLIB_COMPRESSOR, ZLIB_DECOMPRESSOR);
- }
-
- #[test]
- #[cfg(feature = "brotli")]
- fn test_brotli() {
- test_compressor(BROTLI_COMPRESSOR, BROTLI_DECOMPRESSOR);
- }
-
- fn test_compressor(comp: &dyn CertCompressor, decomp: &dyn CertDecompressor) {
- assert_eq!(comp.algorithm(), decomp.algorithm());
- for sz in [16, 64, 512, 2048, 8192, 16384] {
- test_trivial_pairwise(comp, decomp, sz);
- }
- test_decompress_wrong_len(comp, decomp);
- test_decompress_garbage(decomp);
- }
-
- fn test_trivial_pairwise(
- comp: &dyn CertCompressor,
- decomp: &dyn CertDecompressor,
- plain_len: usize,
- ) {
- let original = vec![0u8; plain_len];
-
- for level in [CompressionLevel::Interactive, CompressionLevel::Amortized] {
- let compressed = comp
- .compress(original.clone(), level)
- .unwrap();
- println!(
- "{:?} compressed trivial {} -> {} using {:?} level",
- comp.algorithm(),
- original.len(),
- compressed.len(),
- level
- );
- let mut recovered = vec![0xffu8; plain_len];
- decomp
- .decompress(&compressed, &mut recovered)
- .unwrap();
- assert_eq!(original, recovered);
- }
- }
-
- fn test_decompress_wrong_len(comp: &dyn CertCompressor, decomp: &dyn CertDecompressor) {
- let original = vec![0u8; 2048];
- let compressed = comp
- .compress(original.clone(), CompressionLevel::Interactive)
- .unwrap();
- println!("{compressed:?}");
-
- // too big
- let mut recovered = vec![0xffu8; original.len() + 1];
- decomp
- .decompress(&compressed, &mut recovered)
- .unwrap_err();
-
- // too small
- let mut recovered = vec![0xffu8; original.len() - 1];
- decomp
- .decompress(&compressed, &mut recovered)
- .unwrap_err();
- }
-
- fn test_decompress_garbage(decomp: &dyn CertDecompressor) {
- let junk = [0u8; 1024];
- let mut recovered = vec![0u8; 512];
- decomp
- .decompress(&junk, &mut recovered)
- .unwrap_err();
- }
-
- #[test]
- #[cfg(all(feature = "brotli", feature = "zlib"))]
- fn test_cache_evicts_lru() {
- use core::sync::atomic::{AtomicBool, Ordering};
-
- use pki_types::CertificateDer;
-
- let cache = CompressionCache::default();
-
- let cert = CertificateDer::from(vec![1]);
-
- let cert1 = CertificatePayloadTls13::new([&cert].into_iter(), Some(b"1"));
- let cert2 = CertificatePayloadTls13::new([&cert].into_iter(), Some(b"2"));
- let cert3 = CertificatePayloadTls13::new([&cert].into_iter(), Some(b"3"));
- let cert4 = CertificatePayloadTls13::new([&cert].into_iter(), Some(b"4"));
-
- // insert zlib (1), (2), (3), (4)
-
- cache
- .compression_for(
- &RequireCompress(ZLIB_COMPRESSOR, AtomicBool::default(), true),
- &cert1,
- )
- .unwrap();
- cache
- .compression_for(
- &RequireCompress(ZLIB_COMPRESSOR, AtomicBool::default(), true),
- &cert2,
- )
- .unwrap();
- cache
- .compression_for(
- &RequireCompress(ZLIB_COMPRESSOR, AtomicBool::default(), true),
- &cert3,
- )
- .unwrap();
- cache
- .compression_for(
- &RequireCompress(ZLIB_COMPRESSOR, AtomicBool::default(), true),
- &cert4,
- )
- .unwrap();
-
- // -- now full
-
- // insert brotli (1) evicts zlib (1)
- cache
- .compression_for(
- &RequireCompress(BROTLI_COMPRESSOR, AtomicBool::default(), true),
- &cert4,
- )
- .unwrap();
-
- // now zlib (2), (3), (4) and brotli (4) exist
- cache
- .compression_for(
- &RequireCompress(ZLIB_COMPRESSOR, AtomicBool::default(), false),
- &cert2,
- )
- .unwrap();
- cache
- .compression_for(
- &RequireCompress(ZLIB_COMPRESSOR, AtomicBool::default(), false),
- &cert3,
- )
- .unwrap();
- cache
- .compression_for(
- &RequireCompress(ZLIB_COMPRESSOR, AtomicBool::default(), false),
- &cert4,
- )
- .unwrap();
- cache
- .compression_for(
- &RequireCompress(BROTLI_COMPRESSOR, AtomicBool::default(), false),
- &cert4,
- )
- .unwrap();
-
- // insert zlib (1) requires re-compression & evicts zlib (2)
- cache
- .compression_for(
- &RequireCompress(ZLIB_COMPRESSOR, AtomicBool::default(), true),
- &cert1,
- )
- .unwrap();
-
- // now zlib (1), (3), (4) and brotli (4) exist
- // query zlib (4), (3), (1) to demonstrate LRU tracks usage rather than insertion
- cache
- .compression_for(
- &RequireCompress(ZLIB_COMPRESSOR, AtomicBool::default(), false),
- &cert4,
- )
- .unwrap();
- cache
- .compression_for(
- &RequireCompress(ZLIB_COMPRESSOR, AtomicBool::default(), false),
- &cert3,
- )
- .unwrap();
- cache
- .compression_for(
- &RequireCompress(ZLIB_COMPRESSOR, AtomicBool::default(), false),
- &cert1,
- )
- .unwrap();
-
- // now brotli (4), zlib (4), (3), (1)
- // insert brotli (1) evicting brotli (4)
- cache
- .compression_for(
- &RequireCompress(BROTLI_COMPRESSOR, AtomicBool::default(), true),
- &cert1,
- )
- .unwrap();
-
- // verify brotli (4) disappeared
- cache
- .compression_for(
- &RequireCompress(BROTLI_COMPRESSOR, AtomicBool::default(), true),
- &cert4,
- )
- .unwrap();
-
- #[derive(Debug)]
- struct RequireCompress(&'static dyn CertCompressor, AtomicBool, bool);
-
- impl CertCompressor for RequireCompress {
- fn compress(
- &self,
- input: Vec<u8>,
- level: CompressionLevel,
- ) -> Result<Vec<u8>, CompressionFailed> {
- self.1.store(true, Ordering::SeqCst);
- self.0.compress(input, level)
- }
-
- fn algorithm(&self) -> CertificateCompressionAlgorithm {
- self.0.algorithm()
- }
- }
-
- impl Drop for RequireCompress {
- fn drop(&mut self) {
- assert_eq!(self.1.load(Ordering::SeqCst), self.2);
- }
- }
- }
-}
diff --git a/vendor/rustls/src/conn.rs b/vendor/rustls/src/conn.rs
deleted file mode 100644
index 1a95079f..00000000
--- a/vendor/rustls/src/conn.rs
+++ /dev/null
@@ -1,1280 +0,0 @@
-use alloc::boxed::Box;
-use core::fmt::Debug;
-use core::mem;
-use core::ops::{Deref, DerefMut, Range};
-#[cfg(feature = "std")]
-use std::io;
-
-use kernel::KernelConnection;
-
-use crate::common_state::{CommonState, Context, DEFAULT_BUFFER_LIMIT, IoState, State};
-use crate::enums::{AlertDescription, ContentType, ProtocolVersion};
-use crate::error::{Error, PeerMisbehaved};
-use crate::log::trace;
-use crate::msgs::deframer::DeframerIter;
-use crate::msgs::deframer::buffers::{BufferProgress, DeframerVecBuffer, Delocator, Locator};
-use crate::msgs::deframer::handshake::HandshakeDeframer;
-use crate::msgs::handshake::Random;
-use crate::msgs::message::{InboundPlainMessage, Message, MessagePayload};
-use crate::record_layer::Decrypted;
-use crate::suites::ExtractedSecrets;
-use crate::vecbuf::ChunkVecBuffer;
-
-// pub so that it can be re-exported from the crate root
-pub mod kernel;
-pub(crate) mod unbuffered;
-
-#[cfg(feature = "std")]
-mod connection {
- use alloc::vec::Vec;
- use core::fmt::Debug;
- use core::ops::{Deref, DerefMut};
- use std::io::{self, BufRead, Read};
-
- use crate::ConnectionCommon;
- use crate::common_state::{CommonState, IoState};
- use crate::error::Error;
- use crate::msgs::message::OutboundChunks;
- use crate::suites::ExtractedSecrets;
- use crate::vecbuf::ChunkVecBuffer;
-
- /// A client or server connection.
- #[derive(Debug)]
- pub enum Connection {
- /// A client connection
- Client(crate::client::ClientConnection),
- /// A server connection
- Server(crate::server::ServerConnection),
- }
-
- impl Connection {
- /// Read TLS content from `rd`.
- ///
- /// See [`ConnectionCommon::read_tls()`] for more information.
- pub fn read_tls(&mut self, rd: &mut dyn Read) -> Result<usize, io::Error> {
- match self {
- Self::Client(conn) => conn.read_tls(rd),
- Self::Server(conn) => conn.read_tls(rd),
- }
- }
-
- /// Writes TLS messages to `wr`.
- ///
- /// See [`ConnectionCommon::write_tls()`] for more information.
- pub fn write_tls(&mut self, wr: &mut dyn io::Write) -> Result<usize, io::Error> {
- self.sendable_tls.write_to(wr)
- }
-
- /// Returns an object that allows reading plaintext.
- pub fn reader(&mut self) -> Reader<'_> {
- match self {
- Self::Client(conn) => conn.reader(),
- Self::Server(conn) => conn.reader(),
- }
- }
-
- /// Returns an object that allows writing plaintext.
- pub fn writer(&mut self) -> Writer<'_> {
- match self {
- Self::Client(conn) => Writer::new(&mut **conn),
- Self::Server(conn) => Writer::new(&mut **conn),
- }
- }
-
- /// Processes any new packets read by a previous call to [`Connection::read_tls`].
- ///
- /// See [`ConnectionCommon::process_new_packets()`] for more information.
- pub fn process_new_packets(&mut self) -> Result<IoState, Error> {
- match self {
- Self::Client(conn) => conn.process_new_packets(),
- Self::Server(conn) => conn.process_new_packets(),
- }
- }
-
- /// Derives key material from the agreed connection secrets.
- ///
- /// See [`ConnectionCommon::export_keying_material()`] for more information.
- pub fn export_keying_material<T: AsMut<[u8]>>(
- &self,
- output: T,
- label: &[u8],
- context: Option<&[u8]>,
- ) -> Result<T, Error> {
- match self {
- Self::Client(conn) => conn.export_keying_material(output, label, context),
- Self::Server(conn) => conn.export_keying_material(output, label, context),
- }
- }
-
- /// This function uses `io` to complete any outstanding IO for this connection.
- ///
- /// See [`ConnectionCommon::complete_io()`] for more information.
- pub fn complete_io<T>(&mut self, io: &mut T) -> Result<(usize, usize), io::Error>
- where
- Self: Sized,
- T: Read + io::Write,
- {
- match self {
- Self::Client(conn) => conn.complete_io(io),
- Self::Server(conn) => conn.complete_io(io),
- }
- }
-
- /// Extract secrets, so they can be used when configuring kTLS, for example.
- /// Should be used with care as it exposes secret key material.
- pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
- match self {
- Self::Client(client) => client.dangerous_extract_secrets(),
- Self::Server(server) => server.dangerous_extract_secrets(),
- }
- }
-
- /// Sets a limit on the internal buffers
- ///
- /// See [`ConnectionCommon::set_buffer_limit()`] for more information.
- pub fn set_buffer_limit(&mut self, limit: Option<usize>) {
- match self {
- Self::Client(client) => client.set_buffer_limit(limit),
- Self::Server(server) => server.set_buffer_limit(limit),
- }
- }
-
- /// Sends a TLS1.3 `key_update` message to refresh a connection's keys
- ///
- /// See [`ConnectionCommon::refresh_traffic_keys()`] for more information.
- pub fn refresh_traffic_keys(&mut self) -> Result<(), Error> {
- match self {
- Self::Client(client) => client.refresh_traffic_keys(),
- Self::Server(server) => server.refresh_traffic_keys(),
- }
- }
- }
-
- impl Deref for Connection {
- type Target = CommonState;
-
- fn deref(&self) -> &Self::Target {
- match self {
- Self::Client(conn) => &conn.core.common_state,
- Self::Server(conn) => &conn.core.common_state,
- }
- }
- }
-
- impl DerefMut for Connection {
- fn deref_mut(&mut self) -> &mut Self::Target {
- match self {
- Self::Client(conn) => &mut conn.core.common_state,
- Self::Server(conn) => &mut conn.core.common_state,
- }
- }
- }
-
- /// A structure that implements [`std::io::Read`] for reading plaintext.
- pub struct Reader<'a> {
- pub(super) received_plaintext: &'a mut ChunkVecBuffer,
- pub(super) has_received_close_notify: bool,
- pub(super) has_seen_eof: bool,
- }
-
- impl<'a> Reader<'a> {
- /// Check the connection's state if no bytes are available for reading.
- fn check_no_bytes_state(&self) -> io::Result<()> {
- match (self.has_received_close_notify, self.has_seen_eof) {
- // cleanly closed; don't care about TCP EOF: express this as Ok(0)
- (true, _) => Ok(()),
- // unclean closure
- (false, true) => Err(io::Error::new(
- io::ErrorKind::UnexpectedEof,
- UNEXPECTED_EOF_MESSAGE,
- )),
- // connection still going, but needs more data: signal `WouldBlock` so that
- // the caller knows this
- (false, false) => Err(io::ErrorKind::WouldBlock.into()),
- }
- }
-
- /// Obtain a chunk of plaintext data received from the peer over this TLS connection.
- ///
- /// This method consumes `self` so that it can return a slice whose lifetime is bounded by
- /// the [`ConnectionCommon`] that created this `Reader`.
- pub fn into_first_chunk(self) -> io::Result<&'a [u8]> {
- match self.received_plaintext.chunk() {
- Some(chunk) => Ok(chunk),
- None => {
- self.check_no_bytes_state()?;
- Ok(&[])
- }
- }
- }
- }
-
- impl Read for Reader<'_> {
- /// Obtain plaintext data received from the peer over this TLS connection.
- ///
- /// If the peer closes the TLS session cleanly, this returns `Ok(0)` once all
- /// the pending data has been read. No further data can be received on that
- /// connection, so the underlying TCP connection should be half-closed too.
- ///
- /// If the peer closes the TLS session uncleanly (a TCP EOF without sending a
- /// `close_notify` alert) this function returns a `std::io::Error` of type
- /// `ErrorKind::UnexpectedEof` once any pending data has been read.
- ///
- /// Note that support for `close_notify` varies in peer TLS libraries: many do not
- /// support it and uncleanly close the TCP connection (this might be
- /// vulnerable to truncation attacks depending on the application protocol).
- /// This means applications using rustls must both handle EOF
- /// from this function, *and* unexpected EOF of the underlying TCP connection.
- ///
- /// If there are no bytes to read, this returns `Err(ErrorKind::WouldBlock.into())`.
- ///
- /// You may learn the number of bytes available at any time by inspecting
- /// the return of [`Connection::process_new_packets`].
- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- let len = self.received_plaintext.read(buf)?;
- if len > 0 || buf.is_empty() {
- return Ok(len);
- }
-
- self.check_no_bytes_state()
- .map(|()| len)
- }
-
- /// Obtain plaintext data received from the peer over this TLS connection.
- ///
- /// If the peer closes the TLS session, this returns `Ok(())` without filling
- /// any more of the buffer once all the pending data has been read. No further
- /// data can be received on that connection, so the underlying TCP connection
- /// should be half-closed too.
- ///
- /// If the peer closes the TLS session uncleanly (a TCP EOF without sending a
- /// `close_notify` alert) this function returns a `std::io::Error` of type
- /// `ErrorKind::UnexpectedEof` once any pending data has been read.
- ///
- /// Note that support for `close_notify` varies in peer TLS libraries: many do not
- /// support it and uncleanly close the TCP connection (this might be
- /// vulnerable to truncation attacks depending on the application protocol).
- /// This means applications using rustls must both handle EOF
- /// from this function, *and* unexpected EOF of the underlying TCP connection.
- ///
- /// If there are no bytes to read, this returns `Err(ErrorKind::WouldBlock.into())`.
- ///
- /// You may learn the number of bytes available at any time by inspecting
- /// the return of [`Connection::process_new_packets`].
- #[cfg(read_buf)]
- fn read_buf(&mut self, mut cursor: core::io::BorrowedCursor<'_>) -> io::Result<()> {
- let before = cursor.written();
- self.received_plaintext
- .read_buf(cursor.reborrow())?;
- let len = cursor.written() - before;
- if len > 0 || cursor.capacity() == 0 {
- return Ok(());
- }
-
- self.check_no_bytes_state()
- }
- }
-
- impl BufRead for Reader<'_> {
- /// Obtain a chunk of plaintext data received from the peer over this TLS connection.
- /// This reads the same data as [`Reader::read()`], but returns a reference instead of
- /// copying the data.
- ///
- /// The caller should call [`Reader::consume()`] afterward to advance the buffer.
- ///
- /// See [`Reader::into_first_chunk()`] for a version of this function that returns a
- /// buffer with a longer lifetime.
- fn fill_buf(&mut self) -> io::Result<&[u8]> {
- Reader {
- // reborrow
- received_plaintext: self.received_plaintext,
- ..*self
- }
- .into_first_chunk()
- }
-
- fn consume(&mut self, amt: usize) {
- self.received_plaintext
- .consume_first_chunk(amt)
- }
- }
-
- const UNEXPECTED_EOF_MESSAGE: &str = "peer closed connection without sending TLS close_notify: \
-https://docs.rs/rustls/latest/rustls/manual/_03_howto/index.html#unexpected-eof";
-
- /// A structure that implements [`std::io::Write`] for writing plaintext.
- pub struct Writer<'a> {
- sink: &'a mut dyn PlaintextSink,
- }
-
- impl<'a> Writer<'a> {
- /// Create a new Writer.
- ///
- /// This is not an external interface. Get one of these objects
- /// from [`Connection::writer`].
- pub(crate) fn new(sink: &'a mut dyn PlaintextSink) -> Self {
- Writer { sink }
- }
- }
-
- impl io::Write for Writer<'_> {
- /// Send the plaintext `buf` to the peer, encrypting
- /// and authenticating it. Once this function succeeds
- /// you should call [`Connection::write_tls`] which will output the
- /// corresponding TLS records.
- ///
- /// This function buffers plaintext sent before the
- /// TLS handshake completes, and sends it as soon
- /// as it can. See [`ConnectionCommon::set_buffer_limit`] to control
- /// the size of this buffer.
- fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- self.sink.write(buf)
- }
-
- fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
- self.sink.write_vectored(bufs)
- }
-
- fn flush(&mut self) -> io::Result<()> {
- self.sink.flush()
- }
- }
-
- /// Internal trait implemented by the [`ServerConnection`]/[`ClientConnection`]
- /// allowing them to be the subject of a [`Writer`].
- ///
- /// [`ServerConnection`]: crate::ServerConnection
- /// [`ClientConnection`]: crate::ClientConnection
- pub(crate) trait PlaintextSink {
- fn write(&mut self, buf: &[u8]) -> io::Result<usize>;
- fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize>;
- fn flush(&mut self) -> io::Result<()>;
- }
-
- impl<T> PlaintextSink for ConnectionCommon<T> {
- fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- let len = self
- .core
- .common_state
- .buffer_plaintext(buf.into(), &mut self.sendable_plaintext);
- self.core.maybe_refresh_traffic_keys();
- Ok(len)
- }
-
- fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
- let payload_owner: Vec<&[u8]>;
- let payload = match bufs.len() {
- 0 => return Ok(0),
- 1 => OutboundChunks::Single(bufs[0].deref()),
- _ => {
- payload_owner = bufs
- .iter()
- .map(|io_slice| io_slice.deref())
- .collect();
-
- OutboundChunks::new(&payload_owner)
- }
- };
- let len = self
- .core
- .common_state
- .buffer_plaintext(payload, &mut self.sendable_plaintext);
- self.core.maybe_refresh_traffic_keys();
- Ok(len)
- }
-
- fn flush(&mut self) -> io::Result<()> {
- Ok(())
- }
- }
-}
-
-#[cfg(feature = "std")]
-pub use connection::{Connection, Reader, Writer};
-
-#[derive(Debug)]
-pub(crate) struct ConnectionRandoms {
- pub(crate) client: [u8; 32],
- pub(crate) server: [u8; 32],
-}
-
-impl ConnectionRandoms {
- pub(crate) fn new(client: Random, server: Random) -> Self {
- Self {
- client: client.0,
- server: server.0,
- }
- }
-}
-
-/// Interface shared by client and server connections.
-pub struct ConnectionCommon<Data> {
- pub(crate) core: ConnectionCore<Data>,
- deframer_buffer: DeframerVecBuffer,
- sendable_plaintext: ChunkVecBuffer,
-}
-
-impl<Data> ConnectionCommon<Data> {
- /// Processes any new packets read by a previous call to
- /// [`Connection::read_tls`].
- ///
- /// Errors from this function relate to TLS protocol errors, and
- /// are fatal to the connection. Future calls after an error will do
- /// no new work and will return the same error. After an error is
- /// received from [`process_new_packets`], you should not call [`read_tls`]
- /// any more (it will fill up buffers to no purpose). However, you
- /// may call the other methods on the connection, including `write`,
- /// `send_close_notify`, and `write_tls`. Most likely you will want to
- /// call `write_tls` to send any alerts queued by the error and then
- /// close the underlying connection.
- ///
- /// Success from this function comes with some sundry state data
- /// about the connection.
- ///
- /// [`read_tls`]: Connection::read_tls
- /// [`process_new_packets`]: Connection::process_new_packets
- #[inline]
- pub fn process_new_packets(&mut self) -> Result<IoState, Error> {
- self.core
- .process_new_packets(&mut self.deframer_buffer, &mut self.sendable_plaintext)
- }
-
- /// Derives key material from the agreed connection secrets.
- ///
- /// This function fills in `output` with `output.len()` bytes of key
- /// material derived from the master session secret using `label`
- /// and `context` for diversification. Ownership of the buffer is taken
- /// by the function and returned via the Ok result to ensure no key
- /// material leaks if the function fails.
- ///
- /// See RFC5705 for more details on what this does and is for.
- ///
- /// For TLS1.3 connections, this function does not use the
- /// "early" exporter at any point.
- ///
- /// This function fails if called prior to the handshake completing;
- /// check with [`CommonState::is_handshaking`] first.
- ///
- /// This function fails if `output.len()` is zero.
- #[inline]
- pub fn export_keying_material<T: AsMut<[u8]>>(
- &self,
- output: T,
- label: &[u8],
- context: Option<&[u8]>,
- ) -> Result<T, Error> {
- self.core
- .export_keying_material(output, label, context)
- }
-
- /// Extract secrets, so they can be used when configuring kTLS, for example.
- /// Should be used with care as it exposes secret key material.
- pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
- self.core.dangerous_extract_secrets()
- }
-
- /// Sets a limit on the internal buffers used to buffer
- /// unsent plaintext (prior to completing the TLS handshake)
- /// and unsent TLS records. This limit acts only on application
- /// data written through [`Connection::writer`].
- ///
- /// By default the limit is 64KB. The limit can be set
- /// at any time, even if the current buffer use is higher.
- ///
- /// [`None`] means no limit applies, and will mean that written
- /// data is buffered without bound -- it is up to the application
- /// to appropriately schedule its plaintext and TLS writes to bound
- /// memory usage.
- ///
- /// For illustration: `Some(1)` means a limit of one byte applies:
- /// [`Connection::writer`] will accept only one byte, encrypt it and
- /// add a TLS header. Once this is sent via [`Connection::write_tls`],
- /// another byte may be sent.
- ///
- /// # Internal write-direction buffering
- /// rustls has two buffers whose size are bounded by this setting:
- ///
- /// ## Buffering of unsent plaintext data prior to handshake completion
- ///
- /// Calls to [`Connection::writer`] before or during the handshake
- /// are buffered (up to the limit specified here). Once the
- /// handshake completes this data is encrypted and the resulting
- /// TLS records are added to the outgoing buffer.
- ///
- /// ## Buffering of outgoing TLS records
- ///
- /// This buffer is used to store TLS records that rustls needs to
- /// send to the peer. It is used in these two circumstances:
- ///
- /// - by [`Connection::process_new_packets`] when a handshake or alert
- /// TLS record needs to be sent.
- /// - by [`Connection::writer`] post-handshake: the plaintext is
- /// encrypted and the resulting TLS record is buffered.
- ///
- /// This buffer is emptied by [`Connection::write_tls`].
- ///
- /// [`Connection::writer`]: crate::Connection::writer
- /// [`Connection::write_tls`]: crate::Connection::write_tls
- /// [`Connection::process_new_packets`]: crate::Connection::process_new_packets
- pub fn set_buffer_limit(&mut self, limit: Option<usize>) {
- self.sendable_plaintext.set_limit(limit);
- self.sendable_tls.set_limit(limit);
- }
-
- /// Sends a TLS1.3 `key_update` message to refresh a connection's keys.
- ///
- /// This call refreshes our encryption keys. Once the peer receives the message,
- /// it refreshes _its_ encryption and decryption keys and sends a response.
- /// Once we receive that response, we refresh our decryption keys to match.
- /// At the end of this process, keys in both directions have been refreshed.
- ///
- /// Note that this process does not happen synchronously: this call just
- /// arranges that the `key_update` message will be included in the next
- /// `write_tls` output.
- ///
- /// This fails with `Error::HandshakeNotComplete` if called before the initial
- /// handshake is complete, or if a version prior to TLS1.3 is negotiated.
- ///
- /// # Usage advice
- /// Note that other implementations (including rustls) may enforce limits on
- /// the number of `key_update` messages allowed on a given connection to prevent
- /// denial of service. Therefore, this should be called sparingly.
- ///
- /// rustls implicitly and automatically refreshes traffic keys when needed
- /// according to the selected cipher suite's cryptographic constraints. There
- /// is therefore no need to call this manually to avoid cryptographic keys
- /// "wearing out".
- ///
- /// The main reason to call this manually is to roll keys when it is known
- /// a connection will be idle for a long period.
- pub fn refresh_traffic_keys(&mut self) -> Result<(), Error> {
- self.core.refresh_traffic_keys()
- }
-}
-
-#[cfg(feature = "std")]
-impl<Data> ConnectionCommon<Data> {
- /// Returns an object that allows reading plaintext.
- pub fn reader(&mut self) -> Reader<'_> {
- let common = &mut self.core.common_state;
- Reader {
- received_plaintext: &mut common.received_plaintext,
- // Are we done? i.e., have we processed all received messages, and received a
- // close_notify to indicate that no new messages will arrive?
- has_received_close_notify: common.has_received_close_notify,
- has_seen_eof: common.has_seen_eof,
- }
- }
-
- /// Returns an object that allows writing plaintext.
- pub fn writer(&mut self) -> Writer<'_> {
- Writer::new(self)
- }
-
- /// This function uses `io` to complete any outstanding IO for
- /// this connection.
- ///
- /// This is a convenience function which solely uses other parts
- /// of the public API.
- ///
- /// What this means depends on the connection state:
- ///
- /// - If the connection [`is_handshaking`], then IO is performed until
- /// the handshake is complete.
- /// - Otherwise, if [`wants_write`] is true, [`write_tls`] is invoked
- /// until it is all written.
- /// - Otherwise, if [`wants_read`] is true, [`read_tls`] is invoked
- /// once.
- ///
- /// The return value is the number of bytes read from and written
- /// to `io`, respectively.
- ///
- /// This function will block if `io` blocks.
- ///
- /// Errors from TLS record handling (i.e., from [`process_new_packets`])
- /// are wrapped in an `io::ErrorKind::InvalidData`-kind error.
- ///
- /// [`is_handshaking`]: CommonState::is_handshaking
- /// [`wants_read`]: CommonState::wants_read
- /// [`wants_write`]: CommonState::wants_write
- /// [`write_tls`]: ConnectionCommon::write_tls
- /// [`read_tls`]: ConnectionCommon::read_tls
- /// [`process_new_packets`]: ConnectionCommon::process_new_packets
- pub fn complete_io<T>(&mut self, io: &mut T) -> Result<(usize, usize), io::Error>
- where
- Self: Sized,
- T: io::Read + io::Write,
- {
- let mut eof = false;
- let mut wrlen = 0;
- let mut rdlen = 0;
-
- loop {
- let until_handshaked = self.is_handshaking();
-
- if !self.wants_write() && !self.wants_read() {
- // We will make no further progress.
- return Ok((rdlen, wrlen));
- }
-
- while self.wants_write() {
- match self.write_tls(io)? {
- 0 => {
- io.flush()?;
- return Ok((rdlen, wrlen)); // EOF.
- }
- n => wrlen += n,
- }
- }
- io.flush()?;
-
- if !until_handshaked && wrlen > 0 {
- return Ok((rdlen, wrlen));
- }
-
- while !eof && self.wants_read() {
- let read_size = match self.read_tls(io) {
- Ok(0) => {
- eof = true;
- Some(0)
- }
- Ok(n) => {
- rdlen += n;
- Some(n)
- }
- Err(err) if err.kind() == io::ErrorKind::Interrupted => None, // nothing to do
- Err(err) => return Err(err),
- };
- if read_size.is_some() {
- break;
- }
- }
-
- match self.process_new_packets() {
- Ok(_) => {}
- Err(e) => {
- // In case we have an alert to send describing this error,
- // try a last-gasp write -- but don't predate the primary
- // error.
- let _ignored = self.write_tls(io);
- let _ignored = io.flush();
-
- return Err(io::Error::new(io::ErrorKind::InvalidData, e));
- }
- };
-
- // if we're doing IO until handshaked, and we believe we've finished handshaking,
- // but process_new_packets() has queued TLS data to send, loop around again to write
- // the queued messages.
- if until_handshaked && !self.is_handshaking() && self.wants_write() {
- continue;
- }
-
- match (eof, until_handshaked, self.is_handshaking()) {
- (_, true, false) => return Ok((rdlen, wrlen)),
- (_, false, _) => return Ok((rdlen, wrlen)),
- (true, true, true) => return Err(io::Error::from(io::ErrorKind::UnexpectedEof)),
- (..) => {}
- }
- }
- }
-
- /// Extract the first handshake message.
- ///
- /// This is a shortcut to the `process_new_packets()` -> `process_msg()` ->
- /// `process_handshake_messages()` path, specialized for the first handshake message.
- pub(crate) fn first_handshake_message(&mut self) -> Result<Option<Message<'static>>, Error> {
- let mut buffer_progress = self.core.hs_deframer.progress();
-
- let res = self
- .core
- .deframe(
- None,
- self.deframer_buffer.filled_mut(),
- &mut buffer_progress,
- )
- .map(|opt| opt.map(|pm| Message::try_from(pm).map(|m| m.into_owned())));
-
- match res? {
- Some(Ok(msg)) => {
- self.deframer_buffer
- .discard(buffer_progress.take_discard());
- Ok(Some(msg))
- }
- Some(Err(err)) => Err(self.send_fatal_alert(AlertDescription::DecodeError, err)),
- None => Ok(None),
- }
- }
-
- pub(crate) fn replace_state(&mut self, new: Box<dyn State<Data>>) {
- self.core.state = Ok(new);
- }
-
- /// Read TLS content from `rd` into the internal buffer.
- ///
- /// Due to the internal buffering, `rd` can supply TLS messages in arbitrary-sized chunks (like
- /// a socket or pipe might).
- ///
- /// You should call [`process_new_packets()`] each time a call to this function succeeds in order
- /// to empty the incoming TLS data buffer.
- ///
- /// This function returns `Ok(0)` when the underlying `rd` does so. This typically happens when
- /// a socket is cleanly closed, or a file is at EOF. Errors may result from the IO done through
- /// `rd`; additionally, errors of `ErrorKind::Other` are emitted to signal backpressure:
- ///
- /// * In order to empty the incoming TLS data buffer, you should call [`process_new_packets()`]
- /// each time a call to this function succeeds.
- /// * In order to empty the incoming plaintext data buffer, you should empty it through
- /// the [`reader()`] after the call to [`process_new_packets()`].
- ///
- /// This function also returns `Ok(0)` once a `close_notify` alert has been successfully
- /// received. No additional data is ever read in this state.
- ///
- /// [`process_new_packets()`]: ConnectionCommon::process_new_packets
- /// [`reader()`]: ConnectionCommon::reader
- pub fn read_tls(&mut self, rd: &mut dyn io::Read) -> Result<usize, io::Error> {
- if self.received_plaintext.is_full() {
- return Err(io::Error::new(
- io::ErrorKind::Other,
- "received plaintext buffer full",
- ));
- }
-
- if self.has_received_close_notify {
- return Ok(0);
- }
-
- let res = self
- .deframer_buffer
- .read(rd, self.core.hs_deframer.is_active());
- if let Ok(0) = res {
- self.has_seen_eof = true;
- }
- res
- }
-
- /// Writes TLS messages to `wr`.
- ///
- /// On success, this function returns `Ok(n)` where `n` is a number of bytes written to `wr`
- /// (after encoding and encryption).
- ///
- /// After this function returns, the connection buffer may not yet be fully flushed. The
- /// [`CommonState::wants_write`] function can be used to check if the output buffer is empty.
- pub fn write_tls(&mut self, wr: &mut dyn io::Write) -> Result<usize, io::Error> {
- self.sendable_tls.write_to(wr)
- }
-}
-
-impl<'a, Data> From<&'a mut ConnectionCommon<Data>> for Context<'a, Data> {
- fn from(conn: &'a mut ConnectionCommon<Data>) -> Self {
- Self {
- common: &mut conn.core.common_state,
- data: &mut conn.core.data,
- sendable_plaintext: Some(&mut conn.sendable_plaintext),
- }
- }
-}
-
-impl<T> Deref for ConnectionCommon<T> {
- type Target = CommonState;
-
- fn deref(&self) -> &Self::Target {
- &self.core.common_state
- }
-}
-
-impl<T> DerefMut for ConnectionCommon<T> {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.core.common_state
- }
-}
-
-impl<Data> From<ConnectionCore<Data>> for ConnectionCommon<Data> {
- fn from(core: ConnectionCore<Data>) -> Self {
- Self {
- core,
- deframer_buffer: DeframerVecBuffer::default(),
- sendable_plaintext: ChunkVecBuffer::new(Some(DEFAULT_BUFFER_LIMIT)),
- }
- }
-}
-
-/// Interface shared by unbuffered client and server connections.
-pub struct UnbufferedConnectionCommon<Data> {
- pub(crate) core: ConnectionCore<Data>,
- wants_write: bool,
- emitted_peer_closed_state: bool,
-}
-
-impl<Data> From<ConnectionCore<Data>> for UnbufferedConnectionCommon<Data> {
- fn from(core: ConnectionCore<Data>) -> Self {
- Self {
- core,
- wants_write: false,
- emitted_peer_closed_state: false,
- }
- }
-}
-
-impl<Data> UnbufferedConnectionCommon<Data> {
- /// Extract secrets, so they can be used when configuring kTLS, for example.
- /// Should be used with care as it exposes secret key material.
- pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
- self.core.dangerous_extract_secrets()
- }
-}
-
-impl<T> Deref for UnbufferedConnectionCommon<T> {
- type Target = CommonState;
-
- fn deref(&self) -> &Self::Target {
- &self.core.common_state
- }
-}
-
-pub(crate) struct ConnectionCore<Data> {
- pub(crate) state: Result<Box<dyn State<Data>>, Error>,
- pub(crate) data: Data,
- pub(crate) common_state: CommonState,
- pub(crate) hs_deframer: HandshakeDeframer,
-
- /// We limit consecutive empty fragments to avoid a route for the peer to send
- /// us significant but fruitless traffic.
- seen_consecutive_empty_fragments: u8,
-}
-
-impl<Data> ConnectionCore<Data> {
- pub(crate) fn new(state: Box<dyn State<Data>>, data: Data, common_state: CommonState) -> Self {
- Self {
- state: Ok(state),
- data,
- common_state,
- hs_deframer: HandshakeDeframer::default(),
- seen_consecutive_empty_fragments: 0,
- }
- }
-
- pub(crate) fn process_new_packets(
- &mut self,
- deframer_buffer: &mut DeframerVecBuffer,
- sendable_plaintext: &mut ChunkVecBuffer,
- ) -> Result<IoState, Error> {
- let mut state = match mem::replace(&mut self.state, Err(Error::HandshakeNotComplete)) {
- Ok(state) => state,
- Err(e) => {
- self.state = Err(e.clone());
- return Err(e);
- }
- };
-
- let mut buffer_progress = self.hs_deframer.progress();
-
- loop {
- let res = self.deframe(
- Some(&*state),
- deframer_buffer.filled_mut(),
- &mut buffer_progress,
- );
-
- let opt_msg = match res {
- Ok(opt_msg) => opt_msg,
- Err(e) => {
- self.state = Err(e.clone());
- deframer_buffer.discard(buffer_progress.take_discard());
- return Err(e);
- }
- };
-
- let Some(msg) = opt_msg else {
- break;
- };
-
- match self.process_msg(msg, state, Some(sendable_plaintext)) {
- Ok(new) => state = new,
- Err(e) => {
- self.state = Err(e.clone());
- deframer_buffer.discard(buffer_progress.take_discard());
- return Err(e);
- }
- }
-
- if self
- .common_state
- .has_received_close_notify
- {
- // "Any data received after a closure alert has been received MUST be ignored."
- // -- <https://datatracker.ietf.org/doc/html/rfc8446#section-6.1>
- // This is data that has already been accepted in `read_tls`.
- buffer_progress.add_discard(deframer_buffer.filled().len());
- break;
- }
-
- deframer_buffer.discard(buffer_progress.take_discard());
- }
-
- deframer_buffer.discard(buffer_progress.take_discard());
- self.state = Ok(state);
- Ok(self.common_state.current_io_state())
- }
-
- /// Pull a message out of the deframer and send any messages that need to be sent as a result.
- fn deframe<'b>(
- &mut self,
- state: Option<&dyn State<Data>>,
- buffer: &'b mut [u8],
- buffer_progress: &mut BufferProgress,
- ) -> Result<Option<InboundPlainMessage<'b>>, Error> {
- // before processing any more of `buffer`, return any extant messages from `hs_deframer`
- if self.hs_deframer.has_message_ready() {
- Ok(self.take_handshake_message(buffer, buffer_progress))
- } else {
- self.process_more_input(state, buffer, buffer_progress)
- }
- }
-
- fn take_handshake_message<'b>(
- &mut self,
- buffer: &'b mut [u8],
- buffer_progress: &mut BufferProgress,
- ) -> Option<InboundPlainMessage<'b>> {
- self.hs_deframer
- .iter(buffer)
- .next()
- .map(|(message, discard)| {
- buffer_progress.add_discard(discard);
- message
- })
- }
-
- fn process_more_input<'b>(
- &mut self,
- state: Option<&dyn State<Data>>,
- buffer: &'b mut [u8],
- buffer_progress: &mut BufferProgress,
- ) -> Result<Option<InboundPlainMessage<'b>>, Error> {
- let version_is_tls13 = matches!(
- self.common_state.negotiated_version,
- Some(ProtocolVersion::TLSv1_3)
- );
-
- let locator = Locator::new(buffer);
-
- loop {
- let mut iter = DeframerIter::new(&mut buffer[buffer_progress.processed()..]);
-
- let (message, processed) = loop {
- let message = match iter.next().transpose() {
- Ok(Some(message)) => message,
- Ok(None) => return Ok(None),
- Err(err) => return Err(self.handle_deframe_error(err, state)),
- };
-
- let allowed_plaintext = match message.typ {
- // CCS messages are always plaintext.
- ContentType::ChangeCipherSpec => true,
- // Alerts are allowed to be plaintext if-and-only-if:
- // * The negotiated protocol version is TLS 1.3. - In TLS 1.2 it is unambiguous when
- // keying changes based on the CCS message. Only TLS 1.3 requires these heuristics.
- // * We have not yet decrypted any messages from the peer - if we have we don't
- // expect any plaintext.
- // * The payload size is indicative of a plaintext alert message.
- ContentType::Alert
- if version_is_tls13
- && !self
- .common_state
- .record_layer
- .has_decrypted()
- && message.payload.len() <= 2 =>
- {
- true
- }
- // In other circumstances, we expect all messages to be encrypted.
- _ => false,
- };
-
- if allowed_plaintext && !self.hs_deframer.is_active() {
- break (message.into_plain_message(), iter.bytes_consumed());
- }
-
- let message = match self
- .common_state
- .record_layer
- .decrypt_incoming(message)
- {
- // failed decryption during trial decryption is not allowed to be
- // interleaved with partial handshake data.
- Ok(None) if !self.hs_deframer.is_aligned() => {
- return Err(
- PeerMisbehaved::RejectedEarlyDataInterleavedWithHandshakeMessage.into(),
- );
- }
-
- // failed decryption during trial decryption.
- Ok(None) => continue,
-
- Ok(Some(message)) => message,
-
- Err(err) => return Err(self.handle_deframe_error(err, state)),
- };
-
- let Decrypted {
- want_close_before_decrypt,
- plaintext,
- } = message;
-
- if want_close_before_decrypt {
- self.common_state.send_close_notify();
- }
-
- break (plaintext, iter.bytes_consumed());
- };
-
- if !self.hs_deframer.is_aligned() && message.typ != ContentType::Handshake {
- // "Handshake messages MUST NOT be interleaved with other record
- // types. That is, if a handshake message is split over two or more
- // records, there MUST NOT be any other records between them."
- // https://www.rfc-editor.org/rfc/rfc8446#section-5.1
- return Err(PeerMisbehaved::MessageInterleavedWithHandshakeMessage.into());
- }
-
- match message.payload.len() {
- 0 => {
- if self.seen_consecutive_empty_fragments
- == ALLOWED_CONSECUTIVE_EMPTY_FRAGMENTS_MAX
- {
- return Err(PeerMisbehaved::TooManyEmptyFragments.into());
- }
- self.seen_consecutive_empty_fragments += 1;
- }
- _ => {
- self.seen_consecutive_empty_fragments = 0;
- }
- };
-
- buffer_progress.add_processed(processed);
-
- // do an end-run around the borrow checker, converting `message` (containing
- // a borrowed slice) to an unborrowed one (containing a `Range` into the
- // same buffer). the reborrow happens inside the branch that returns the
- // message.
- //
- // is fixed by -Zpolonius
- // https://github.com/rust-lang/rfcs/blob/master/text/2094-nll.md#problem-case-3-conditional-control-flow-across-functions
- let unborrowed = InboundUnborrowedMessage::unborrow(&locator, message);
-
- if unborrowed.typ != ContentType::Handshake {
- let message = unborrowed.reborrow(&Delocator::new(buffer));
- buffer_progress.add_discard(processed);
- return Ok(Some(message));
- }
-
- let message = unborrowed.reborrow(&Delocator::new(buffer));
- self.hs_deframer
- .input_message(message, &locator, buffer_progress.processed());
- self.hs_deframer.coalesce(buffer)?;
-
- self.common_state.aligned_handshake = self.hs_deframer.is_aligned();
-
- if self.hs_deframer.has_message_ready() {
- // trial decryption finishes with the first handshake message after it started.
- self.common_state
- .record_layer
- .finish_trial_decryption();
-
- return Ok(self.take_handshake_message(buffer, buffer_progress));
- }
- }
- }
-
- fn handle_deframe_error(&mut self, error: Error, state: Option<&dyn State<Data>>) -> Error {
- match error {
- error @ Error::InvalidMessage(_) => {
- if self.common_state.is_quic() {
- self.common_state.quic.alert = Some(AlertDescription::DecodeError);
- error
- } else {
- self.common_state
- .send_fatal_alert(AlertDescription::DecodeError, error)
- }
- }
- Error::PeerSentOversizedRecord => self
- .common_state
- .send_fatal_alert(AlertDescription::RecordOverflow, error),
- Error::DecryptError => {
- if let Some(state) = state {
- state.handle_decrypt_error();
- }
- self.common_state
- .send_fatal_alert(AlertDescription::BadRecordMac, error)
- }
-
- error => error,
- }
- }
-
- fn process_msg(
- &mut self,
- msg: InboundPlainMessage<'_>,
- state: Box<dyn State<Data>>,
- sendable_plaintext: Option<&mut ChunkVecBuffer>,
- ) -> Result<Box<dyn State<Data>>, Error> {
- // Drop CCS messages during handshake in TLS1.3
- if msg.typ == ContentType::ChangeCipherSpec
- && !self
- .common_state
- .may_receive_application_data
- && self.common_state.is_tls13()
- {
- if !msg.is_valid_ccs() {
- // "An implementation which receives any other change_cipher_spec value or
- // which receives a protected change_cipher_spec record MUST abort the
- // handshake with an "unexpected_message" alert."
- return Err(self.common_state.send_fatal_alert(
- AlertDescription::UnexpectedMessage,
- PeerMisbehaved::IllegalMiddleboxChangeCipherSpec,
- ));
- }
-
- self.common_state
- .received_tls13_change_cipher_spec()?;
- trace!("Dropping CCS");
- return Ok(state);
- }
-
- // Now we can fully parse the message payload.
- let msg = match Message::try_from(msg) {
- Ok(msg) => msg,
- Err(err) => {
- return Err(self
- .common_state
- .send_fatal_alert(AlertDescription::from(err), err));
- }
- };
-
- // For alerts, we have separate logic.
- if let MessagePayload::Alert(alert) = &msg.payload {
- self.common_state.process_alert(alert)?;
- return Ok(state);
- }
-
- self.common_state
- .process_main_protocol(msg, state, &mut self.data, sendable_plaintext)
- }
-
- pub(crate) fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
- Ok(self
- .dangerous_into_kernel_connection()?
- .0)
- }
-
- pub(crate) fn dangerous_into_kernel_connection(
- self,
- ) -> Result<(ExtractedSecrets, KernelConnection<Data>), Error> {
- if !self
- .common_state
- .enable_secret_extraction
- {
- return Err(Error::General("Secret extraction is disabled".into()));
- }
-
- if self.common_state.is_handshaking() {
- return Err(Error::HandshakeNotComplete);
- }
-
- if !self
- .common_state
- .sendable_tls
- .is_empty()
- {
- return Err(Error::General(
- "cannot convert into an KernelConnection while there are still buffered TLS records to send"
- .into()
- ));
- }
-
- let state = self.state?;
-
- let record_layer = &self.common_state.record_layer;
- let secrets = state.extract_secrets()?;
- let secrets = ExtractedSecrets {
- tx: (record_layer.write_seq(), secrets.tx),
- rx: (record_layer.read_seq(), secrets.rx),
- };
-
- let state = state.into_external_state()?;
- let external = KernelConnection::new(state, self.common_state)?;
-
- Ok((secrets, external))
- }
-
- pub(crate) fn export_keying_material<T: AsMut<[u8]>>(
- &self,
- mut output: T,
- label: &[u8],
- context: Option<&[u8]>,
- ) -> Result<T, Error> {
- if output.as_mut().is_empty() {
- return Err(Error::General(
- "export_keying_material with zero-length output".into(),
- ));
- }
-
- match self.state.as_ref() {
- Ok(st) => st
- .export_keying_material(output.as_mut(), label, context)
- .map(|_| output),
- Err(e) => Err(e.clone()),
- }
- }
-
- /// Trigger a `refresh_traffic_keys` if required by `CommonState`.
- fn maybe_refresh_traffic_keys(&mut self) {
- if mem::take(
- &mut self
- .common_state
- .refresh_traffic_keys_pending,
- ) {
- let _ = self.refresh_traffic_keys();
- }
- }
-
- fn refresh_traffic_keys(&mut self) -> Result<(), Error> {
- match &mut self.state {
- Ok(st) => st.send_key_update_request(&mut self.common_state),
- Err(e) => Err(e.clone()),
- }
- }
-}
-
-/// Data specific to the peer's side (client or server).
-pub trait SideData: Debug {}
-
-/// An InboundPlainMessage which does not borrow its payload, but
-/// references a range that can later be borrowed.
-struct InboundUnborrowedMessage {
- typ: ContentType,
- version: ProtocolVersion,
- bounds: Range<usize>,
-}
-
-impl InboundUnborrowedMessage {
- fn unborrow(locator: &Locator, msg: InboundPlainMessage<'_>) -> Self {
- Self {
- typ: msg.typ,
- version: msg.version,
- bounds: locator.locate(msg.payload),
- }
- }
-
- fn reborrow<'b>(self, delocator: &Delocator<'b>) -> InboundPlainMessage<'b> {
- InboundPlainMessage {
- typ: self.typ,
- version: self.version,
- payload: delocator.slice_from_range(&self.bounds),
- }
- }
-}
-
-/// cf. BoringSSL's `kMaxEmptyRecords`
-/// <https://github.com/google/boringssl/blob/dec5989b793c56ad4dd32173bd2d8595ca78b398/ssl/tls_record.cc#L124-L128>
-const ALLOWED_CONSECUTIVE_EMPTY_FRAGMENTS_MAX: u8 = 32;
diff --git a/vendor/rustls/src/conn/kernel.rs b/vendor/rustls/src/conn/kernel.rs
deleted file mode 100644
index b90fad39..00000000
--- a/vendor/rustls/src/conn/kernel.rs
+++ /dev/null
@@ -1,268 +0,0 @@
-//! Kernel connection API.
-//!
-//! This module gives you the bare minimum you need to implement a TLS connection
-//! that does its own encryption and decryption while still using rustls to manage
-//! connection secrets and session tickets. It is intended for use cases like kTLS
-//! where you want to use rustls to establish the connection but want to use
-//! something else to do the encryption/decryption after that.
-//!
-//! There are only two things that [`KernelConnection`] is able to do:
-//! 1. Compute new traffic secrets when a key update occurs.
-//! 2. Save received session tickets sent by a server peer.
-//!
-//! That's it. Everything else you will need to implement yourself.
-//!
-//! # Entry Point
-//! The entry points into this API are
-//! [`UnbufferedClientConnection::dangerous_into_kernel_connection`][client-into]
-//! and
-//! [`UnbufferedServerConnection::dangerous_into_kernel_connection`][server-into].
-//!
-//! In order to actually create an [`KernelConnection`] all of the following
-//! must be true:
-//! - the connection must have completed its handshake,
-//! - the connection must have no buffered TLS data waiting to be sent, and,
-//! - the config used to create the connection must have `enable_extract_secrets`
-//! set to true.
-//!
-//! This sounds fairly complicated to achieve at first glance. However, if you
-//! drive an unbuffered connection through the handshake until it returns
-//! [`WriteTraffic`] then it will end up in an appropriate state to convert
-//! into an external connection.
-//!
-//! [client-into]: crate::client::UnbufferedClientConnection::dangerous_into_kernel_connection
-//! [server-into]: crate::server::UnbufferedServerConnection::dangerous_into_kernel_connection
-//! [`WriteTraffic`]: crate::unbuffered::ConnectionState::WriteTraffic
-//!
-//! # Cipher Suite Confidentiality Limits
-//! Some cipher suites (notably AES-GCM) have vulnerabilities where they are no
-//! longer secure once a certain number of messages have been sent. Normally,
-//! rustls tracks how many messages have been written or read and will
-//! automatically either refresh keys or emit an error when approaching the
-//! confidentiality limit of the cipher suite.
-//!
-//! [`KernelConnection`] has no way to track this. It is the responsibility
-//! of the user of the API to track approximately how many messages have been
-//! sent and either refresh the traffic keys or abort the connection before the
-//! confidentiality limit is reached.
-//!
-//! You can find the current confidentiality limit by looking at
-//! [`CipherSuiteCommon::confidentiality_limit`] for the cipher suite selected
-//! by the connection.
-//!
-//! [`CipherSuiteCommon::confidentiality_limit`]: crate::CipherSuiteCommon::confidentiality_limit
-//! [`KernelConnection`]: crate::kernel::KernelConnection
-
-use alloc::boxed::Box;
-use core::marker::PhantomData;
-
-use crate::client::ClientConnectionData;
-use crate::common_state::Protocol;
-use crate::msgs::codec::Codec;
-use crate::msgs::handshake::{CertificateChain, NewSessionTicketPayloadTls13};
-use crate::quic::Quic;
-use crate::{CommonState, ConnectionTrafficSecrets, Error, ProtocolVersion, SupportedCipherSuite};
-
-/// A kernel connection.
-///
-/// This does not directly wrap a kernel connection, rather it gives you the
-/// minimal interfaces you need to implement a well-behaved TLS connection on
-/// top of kTLS.
-///
-/// See the [`crate::kernel`] module docs for more details.
-pub struct KernelConnection<Data> {
- state: Box<dyn KernelState>,
-
- peer_certificates: Option<CertificateChain<'static>>,
- quic: Quic,
-
- negotiated_version: ProtocolVersion,
- protocol: Protocol,
- suite: SupportedCipherSuite,
-
- _data: PhantomData<Data>,
-}
-
-impl<Data> KernelConnection<Data> {
- pub(crate) fn new(state: Box<dyn KernelState>, common: CommonState) -> Result<Self, Error> {
- Ok(Self {
- state,
-
- peer_certificates: common.peer_certificates,
- quic: common.quic,
- negotiated_version: common
- .negotiated_version
- .ok_or(Error::HandshakeNotComplete)?,
- protocol: common.protocol,
- suite: common
- .suite
- .ok_or(Error::HandshakeNotComplete)?,
-
- _data: PhantomData,
- })
- }
-
- /// Retrieves the ciphersuite agreed with the peer.
- pub fn negotiated_cipher_suite(&self) -> SupportedCipherSuite {
- self.suite
- }
-
- /// Retrieves the protocol version agreed with the peer.
- pub fn protocol_version(&self) -> ProtocolVersion {
- self.negotiated_version
- }
-
- /// Update the traffic secret used for encrypting messages sent to the peer.
- ///
- /// Returns the new traffic secret and initial sequence number to use.
- ///
- /// In order to use the new secret you should send a TLS 1.3 key update to
- /// the peer and then use the new traffic secrets to encrypt any future
- /// messages.
- ///
- /// Note that it is only possible to update the traffic secrets on a TLS 1.3
- /// connection. Attempting to do so on a non-TLS 1.3 connection will result
- /// in an error.
- pub fn update_tx_secret(&mut self) -> Result<(u64, ConnectionTrafficSecrets), Error> {
- // The sequence number always starts at 0 after a key update.
- self.state
- .update_secrets(Direction::Transmit)
- .map(|secret| (0, secret))
- }
-
- /// Update the traffic secret used for decrypting messages received from the
- /// peer.
- ///
- /// Returns the new traffic secret and initial sequence number to use.
- ///
- /// You should call this method once you receive a TLS 1.3 key update message
- /// from the peer.
- ///
- /// Note that it is only possible to update the traffic secrets on a TLS 1.3
- /// connection. Attempting to do so on a non-TLS 1.3 connection will result
- /// in an error.
- pub fn update_rx_secret(&mut self) -> Result<(u64, ConnectionTrafficSecrets), Error> {
- // The sequence number always starts at 0 after a key update.
- self.state
- .update_secrets(Direction::Receive)
- .map(|secret| (0, secret))
- }
-}
-
-impl KernelConnection<ClientConnectionData> {
- /// Handle a `new_session_ticket` message from the peer.
- ///
- /// This will register the session ticket within with rustls so that it can
- /// be used to establish future TLS connections.
- ///
- /// # Getting the right payload
- ///
- /// This method expects to be passed the inner payload of the handshake
- /// message. This means that you will need to parse the header of the
- /// handshake message in order to determine the correct payload to pass in.
- /// The message format is described in [RFC 8446 section 4][0]. `payload`
- /// should not include the `msg_type` or `length` fields.
- ///
- /// Code to parse out the payload should look something like this
- /// ```no_run
- /// use rustls::{ContentType, HandshakeType};
- /// use rustls::kernel::KernelConnection;
- /// use rustls::client::ClientConnectionData;
- ///
- /// # fn doctest(conn: &mut KernelConnection<ClientConnectionData>, typ: ContentType, message: &[u8]) -> Result<(), rustls::Error> {
- /// let conn: &mut KernelConnection<ClientConnectionData> = // ...
- /// # conn;
- /// let typ: ContentType = // ...
- /// # typ;
- /// let mut message: &[u8] = // ...
- /// # message;
- ///
- /// // Processing for other messages not included in this example
- /// assert_eq!(typ, ContentType::Handshake);
- ///
- /// // There may be multiple handshake payloads within a single handshake message.
- /// while !message.is_empty() {
- /// let (typ, len, rest) = match message {
- /// &[typ, a, b, c, ref rest @ ..] => (
- /// HandshakeType::from(typ),
- /// u32::from_be_bytes([0, a, b, c]) as usize,
- /// rest
- /// ),
- /// _ => panic!("error handling not included in this example")
- /// };
- ///
- /// // Processing for other messages not included in this example.
- /// assert_eq!(typ, HandshakeType::NewSessionTicket);
- /// assert!(rest.len() >= len, "invalid handshake message");
- ///
- /// let (payload, rest) = rest.split_at(len);
- /// message = rest;
- ///
- /// conn.handle_new_session_ticket(payload)?;
- /// }
- /// # Ok(())
- /// # }
- /// ```
- ///
- /// # Errors
- /// This method will return an error if:
- /// - This connection is not a TLS 1.3 connection (in TLS 1.2 session tickets
- /// are sent as part of the handshake).
- /// - The provided payload is not a valid `new_session_ticket` payload or has
- /// extra unparsed trailing data.
- /// - An error occurs while the connection updates the session ticket store.
- ///
- /// [0]: https://datatracker.ietf.org/doc/html/rfc8446#section-4
- pub fn handle_new_session_ticket(&mut self, payload: &[u8]) -> Result<(), Error> {
- // We want to return a more specific error here first if this is called
- // on a non-TLS 1.3 connection since a parsing error isn't the real issue
- // here.
- if self.protocol_version() != ProtocolVersion::TLSv1_3 {
- return Err(Error::General(
- "TLS 1.2 session tickets may not be sent once the handshake has completed".into(),
- ));
- }
-
- let nst = NewSessionTicketPayloadTls13::read_bytes(payload)?;
- let mut cx = KernelContext {
- peer_certificates: self.peer_certificates.as_ref(),
- protocol: self.protocol,
- quic: &self.quic,
- };
- self.state
- .handle_new_session_ticket(&mut cx, &nst)
- }
-}
-
-pub(crate) trait KernelState: Send + Sync {
- /// Update the traffic secret for the specified direction on the connection.
- fn update_secrets(&mut self, dir: Direction) -> Result<ConnectionTrafficSecrets, Error>;
-
- /// Handle a new session ticket.
- ///
- /// This will only ever be called for client connections, as [`KernelConnection`]
- /// only exposes the relevant API for client connections.
- fn handle_new_session_ticket(
- &mut self,
- cx: &mut KernelContext<'_>,
- message: &NewSessionTicketPayloadTls13,
- ) -> Result<(), Error>;
-}
-
-pub(crate) struct KernelContext<'a> {
- pub(crate) peer_certificates: Option<&'a CertificateChain<'static>>,
- pub(crate) protocol: Protocol,
- pub(crate) quic: &'a Quic,
-}
-
-impl KernelContext<'_> {
- pub(crate) fn is_quic(&self) -> bool {
- self.protocol == Protocol::Quic
- }
-}
-
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-pub(crate) enum Direction {
- Transmit,
- Receive,
-}
diff --git a/vendor/rustls/src/conn/unbuffered.rs b/vendor/rustls/src/conn/unbuffered.rs
deleted file mode 100644
index 84fe3f09..00000000
--- a/vendor/rustls/src/conn/unbuffered.rs
+++ /dev/null
@@ -1,613 +0,0 @@
-//! Unbuffered connection API
-
-use alloc::vec::Vec;
-use core::num::NonZeroUsize;
-use core::{fmt, mem};
-#[cfg(feature = "std")]
-use std::error::Error as StdError;
-
-use super::UnbufferedConnectionCommon;
-use crate::Error;
-use crate::client::ClientConnectionData;
-use crate::msgs::deframer::buffers::DeframerSliceBuffer;
-use crate::server::ServerConnectionData;
-
-impl UnbufferedConnectionCommon<ClientConnectionData> {
- /// Processes the TLS records in `incoming_tls` buffer until a new [`UnbufferedStatus`] is
- /// reached.
- pub fn process_tls_records<'c, 'i>(
- &'c mut self,
- incoming_tls: &'i mut [u8],
- ) -> UnbufferedStatus<'c, 'i, ClientConnectionData> {
- self.process_tls_records_common(incoming_tls, |_| false, |_, _| unreachable!())
- }
-}
-
-impl UnbufferedConnectionCommon<ServerConnectionData> {
- /// Processes the TLS records in `incoming_tls` buffer until a new [`UnbufferedStatus`] is
- /// reached.
- pub fn process_tls_records<'c, 'i>(
- &'c mut self,
- incoming_tls: &'i mut [u8],
- ) -> UnbufferedStatus<'c, 'i, ServerConnectionData> {
- self.process_tls_records_common(
- incoming_tls,
- |conn| conn.peek_early_data().is_some(),
- |conn, incoming_tls| ReadEarlyData::new(conn, incoming_tls).into(),
- )
- }
-}
-
-impl<Data> UnbufferedConnectionCommon<Data> {
- fn process_tls_records_common<'c, 'i>(
- &'c mut self,
- incoming_tls: &'i mut [u8],
- mut early_data_available: impl FnMut(&mut Self) -> bool,
- early_data_state: impl FnOnce(&'c mut Self, &'i mut [u8]) -> ConnectionState<'c, 'i, Data>,
- ) -> UnbufferedStatus<'c, 'i, Data> {
- let mut buffer = DeframerSliceBuffer::new(incoming_tls);
- let mut buffer_progress = self.core.hs_deframer.progress();
-
- let (discard, state) = loop {
- if early_data_available(self) {
- break (
- buffer.pending_discard(),
- early_data_state(self, incoming_tls),
- );
- }
-
- if !self
- .core
- .common_state
- .received_plaintext
- .is_empty()
- {
- break (
- buffer.pending_discard(),
- ReadTraffic::new(self, incoming_tls).into(),
- );
- }
-
- if let Some(chunk) = self
- .core
- .common_state
- .sendable_tls
- .pop()
- {
- break (
- buffer.pending_discard(),
- EncodeTlsData::new(self, chunk).into(),
- );
- }
-
- let deframer_output =
- match self
- .core
- .deframe(None, buffer.filled_mut(), &mut buffer_progress)
- {
- Err(err) => {
- buffer.queue_discard(buffer_progress.take_discard());
- return UnbufferedStatus {
- discard: buffer.pending_discard(),
- state: Err(err),
- };
- }
- Ok(r) => r,
- };
-
- if let Some(msg) = deframer_output {
- let mut state =
- match mem::replace(&mut self.core.state, Err(Error::HandshakeNotComplete)) {
- Ok(state) => state,
- Err(e) => {
- buffer.queue_discard(buffer_progress.take_discard());
- self.core.state = Err(e.clone());
- return UnbufferedStatus {
- discard: buffer.pending_discard(),
- state: Err(e),
- };
- }
- };
-
- match self.core.process_msg(msg, state, None) {
- Ok(new) => state = new,
-
- Err(e) => {
- buffer.queue_discard(buffer_progress.take_discard());
- self.core.state = Err(e.clone());
- return UnbufferedStatus {
- discard: buffer.pending_discard(),
- state: Err(e),
- };
- }
- }
-
- buffer.queue_discard(buffer_progress.take_discard());
-
- self.core.state = Ok(state);
- } else if self.wants_write {
- break (
- buffer.pending_discard(),
- TransmitTlsData { conn: self }.into(),
- );
- } else if self
- .core
- .common_state
- .has_received_close_notify
- && !self.emitted_peer_closed_state
- {
- self.emitted_peer_closed_state = true;
- break (buffer.pending_discard(), ConnectionState::PeerClosed);
- } else if self
- .core
- .common_state
- .has_received_close_notify
- && self
- .core
- .common_state
- .has_sent_close_notify
- {
- break (buffer.pending_discard(), ConnectionState::Closed);
- } else if self
- .core
- .common_state
- .may_send_application_data
- {
- break (
- buffer.pending_discard(),
- ConnectionState::WriteTraffic(WriteTraffic { conn: self }),
- );
- } else {
- break (buffer.pending_discard(), ConnectionState::BlockedHandshake);
- }
- };
-
- UnbufferedStatus {
- discard,
- state: Ok(state),
- }
- }
-}
-
-/// The current status of the `UnbufferedConnection*`
-#[must_use]
-#[derive(Debug)]
-pub struct UnbufferedStatus<'c, 'i, Data> {
- /// Number of bytes to discard
- ///
- /// After the `state` field of this object has been handled, `discard` bytes must be
- /// removed from the *front* of the `incoming_tls` buffer that was passed to
- /// the [`UnbufferedConnectionCommon::process_tls_records`] call that returned this object.
- ///
- /// This discard operation MUST happen *before*
- /// [`UnbufferedConnectionCommon::process_tls_records`] is called again.
- pub discard: usize,
-
- /// The current state of the handshake process
- ///
- /// This value MUST be handled prior to calling
- /// [`UnbufferedConnectionCommon::process_tls_records`] again. See the documentation on the
- /// variants of [`ConnectionState`] for more details.
- pub state: Result<ConnectionState<'c, 'i, Data>, Error>,
-}
-
-/// The state of the [`UnbufferedConnectionCommon`] object
-#[non_exhaustive] // for forwards compatibility; to support caller-side certificate verification
-pub enum ConnectionState<'c, 'i, Data> {
- /// One, or more, application data records are available
- ///
- /// See [`ReadTraffic`] for more details on how to use the enclosed object to access
- /// the received data.
- ReadTraffic(ReadTraffic<'c, 'i, Data>),
-
- /// Connection has been cleanly closed by the peer.
- ///
- /// This state is encountered at most once by each connection -- it is
- /// "edge" triggered, rather than "level" triggered.
- ///
- /// It delimits the data received from the peer, meaning you can be sure you
- /// have received all the data the peer sent.
- ///
- /// No further application data will be received from the peer, so no further
- /// `ReadTraffic` states will be produced.
- ///
- /// However, it is possible to _send_ further application data via `WriteTraffic`
- /// states, or close the connection cleanly by calling
- /// [`WriteTraffic::queue_close_notify()`].
- PeerClosed,
-
- /// Connection has been cleanly closed by both us and the peer.
- ///
- /// This is a terminal state. No other states will be produced for this
- /// connection.
- Closed,
-
- /// One, or more, early (RTT-0) data records are available
- ReadEarlyData(ReadEarlyData<'c, 'i, Data>),
-
- /// A Handshake record is ready for encoding
- ///
- /// Call [`EncodeTlsData::encode`] on the enclosed object, providing an `outgoing_tls`
- /// buffer to store the encoding
- EncodeTlsData(EncodeTlsData<'c, Data>),
-
- /// Previously encoded handshake records need to be transmitted
- ///
- /// Transmit the contents of the `outgoing_tls` buffer that was passed to previous
- /// [`EncodeTlsData::encode`] calls to the peer.
- ///
- /// After transmitting the contents, call [`TransmitTlsData::done`] on the enclosed object.
- /// The transmitted contents MUST not be sent to the peer more than once so they SHOULD be
- /// discarded at this point.
- ///
- /// At some stages of the handshake process, it's possible to send application-data alongside
- /// handshake records. Call [`TransmitTlsData::may_encrypt_app_data`] on the enclosed
- /// object to probe if that's allowed.
- TransmitTlsData(TransmitTlsData<'c, Data>),
-
- /// More TLS data is needed to continue with the handshake
- ///
- /// Request more data from the peer and append the contents to the `incoming_tls` buffer that
- /// was passed to [`UnbufferedConnectionCommon::process_tls_records`].
- BlockedHandshake,
-
- /// The handshake process has been completed.
- ///
- /// [`WriteTraffic::encrypt`] can be called on the enclosed object to encrypt application
- /// data into an `outgoing_tls` buffer. Similarly, [`WriteTraffic::queue_close_notify`] can
- /// be used to encrypt a close_notify alert message into a buffer to signal the peer that the
- /// connection is being closed. Data written into `outgoing_buffer` by either method MAY be
- /// transmitted to the peer during this state.
- ///
- /// Once this state has been reached, data MAY be requested from the peer and appended to an
- /// `incoming_tls` buffer that will be passed to a future
- /// [`UnbufferedConnectionCommon::process_tls_records`] invocation. When enough data has been
- /// appended to `incoming_tls`, [`UnbufferedConnectionCommon::process_tls_records`] will yield
- /// the [`ConnectionState::ReadTraffic`] state.
- WriteTraffic(WriteTraffic<'c, Data>),
-}
-
-impl<'c, 'i, Data> From<ReadTraffic<'c, 'i, Data>> for ConnectionState<'c, 'i, Data> {
- fn from(v: ReadTraffic<'c, 'i, Data>) -> Self {
- Self::ReadTraffic(v)
- }
-}
-
-impl<'c, 'i, Data> From<ReadEarlyData<'c, 'i, Data>> for ConnectionState<'c, 'i, Data> {
- fn from(v: ReadEarlyData<'c, 'i, Data>) -> Self {
- Self::ReadEarlyData(v)
- }
-}
-
-impl<'c, Data> From<EncodeTlsData<'c, Data>> for ConnectionState<'c, '_, Data> {
- fn from(v: EncodeTlsData<'c, Data>) -> Self {
- Self::EncodeTlsData(v)
- }
-}
-
-impl<'c, Data> From<TransmitTlsData<'c, Data>> for ConnectionState<'c, '_, Data> {
- fn from(v: TransmitTlsData<'c, Data>) -> Self {
- Self::TransmitTlsData(v)
- }
-}
-
-impl<Data> fmt::Debug for ConnectionState<'_, '_, Data> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::ReadTraffic(..) => f.debug_tuple("ReadTraffic").finish(),
-
- Self::PeerClosed => write!(f, "PeerClosed"),
-
- Self::Closed => write!(f, "Closed"),
-
- Self::ReadEarlyData(..) => f.debug_tuple("ReadEarlyData").finish(),
-
- Self::EncodeTlsData(..) => f.debug_tuple("EncodeTlsData").finish(),
-
- Self::TransmitTlsData(..) => f
- .debug_tuple("TransmitTlsData")
- .finish(),
-
- Self::BlockedHandshake => f
- .debug_tuple("BlockedHandshake")
- .finish(),
-
- Self::WriteTraffic(..) => f.debug_tuple("WriteTraffic").finish(),
- }
- }
-}
-
-/// Application data is available
-pub struct ReadTraffic<'c, 'i, Data> {
- conn: &'c mut UnbufferedConnectionCommon<Data>,
- // for forwards compatibility; to support in-place decryption in the future
- _incoming_tls: &'i mut [u8],
-
- // owner of the latest chunk obtained in `next_record`, as borrowed by
- // `AppDataRecord`
- chunk: Option<Vec<u8>>,
-}
-
-impl<'c, 'i, Data> ReadTraffic<'c, 'i, Data> {
- fn new(conn: &'c mut UnbufferedConnectionCommon<Data>, _incoming_tls: &'i mut [u8]) -> Self {
- Self {
- conn,
- _incoming_tls,
- chunk: None,
- }
- }
-
- /// Decrypts and returns the next available app-data record
- // TODO deprecate in favor of `Iterator` implementation, which requires in-place decryption
- pub fn next_record(&mut self) -> Option<Result<AppDataRecord<'_>, Error>> {
- self.chunk = self
- .conn
- .core
- .common_state
- .received_plaintext
- .pop();
- self.chunk.as_ref().map(|chunk| {
- Ok(AppDataRecord {
- discard: 0,
- payload: chunk,
- })
- })
- }
-
- /// Returns the payload size of the next app-data record *without* decrypting it
- ///
- /// Returns `None` if there are no more app-data records
- pub fn peek_len(&self) -> Option<NonZeroUsize> {
- self.conn
- .core
- .common_state
- .received_plaintext
- .peek()
- .and_then(|ch| NonZeroUsize::new(ch.len()))
- }
-}
-
-/// Early application-data is available.
-pub struct ReadEarlyData<'c, 'i, Data> {
- conn: &'c mut UnbufferedConnectionCommon<Data>,
-
- // for forwards compatibility; to support in-place decryption in the future
- _incoming_tls: &'i mut [u8],
-
- // owner of the latest chunk obtained in `next_record`, as borrowed by
- // `AppDataRecord`
- chunk: Option<Vec<u8>>,
-}
-
-impl<'c, 'i> ReadEarlyData<'c, 'i, ServerConnectionData> {
- fn new(
- conn: &'c mut UnbufferedConnectionCommon<ServerConnectionData>,
- _incoming_tls: &'i mut [u8],
- ) -> Self {
- Self {
- conn,
- _incoming_tls,
- chunk: None,
- }
- }
-
- /// decrypts and returns the next available app-data record
- // TODO deprecate in favor of `Iterator` implementation, which requires in-place decryption
- pub fn next_record(&mut self) -> Option<Result<AppDataRecord<'_>, Error>> {
- self.chunk = self.conn.pop_early_data();
- self.chunk.as_ref().map(|chunk| {
- Ok(AppDataRecord {
- discard: 0,
- payload: chunk,
- })
- })
- }
-
- /// returns the payload size of the next app-data record *without* decrypting it
- ///
- /// returns `None` if there are no more app-data records
- pub fn peek_len(&self) -> Option<NonZeroUsize> {
- self.conn
- .peek_early_data()
- .and_then(|ch| NonZeroUsize::new(ch.len()))
- }
-}
-
-/// A decrypted application-data record
-pub struct AppDataRecord<'i> {
- /// Number of additional bytes to discard
- ///
- /// This number MUST be added to the value of [`UnbufferedStatus.discard`] *prior* to the
- /// discard operation. See [`UnbufferedStatus.discard`] for more details
- pub discard: usize,
-
- /// The payload of the app-data record
- pub payload: &'i [u8],
-}
-
-/// Allows encrypting app-data
-pub struct WriteTraffic<'c, Data> {
- conn: &'c mut UnbufferedConnectionCommon<Data>,
-}
-
-impl<Data> WriteTraffic<'_, Data> {
- /// Encrypts `application_data` into the `outgoing_tls` buffer
- ///
- /// Returns the number of bytes that were written into `outgoing_tls`, or an error if
- /// the provided buffer is too small. In the error case, `outgoing_tls` is not modified
- pub fn encrypt(
- &mut self,
- application_data: &[u8],
- outgoing_tls: &mut [u8],
- ) -> Result<usize, EncryptError> {
- self.conn
- .core
- .maybe_refresh_traffic_keys();
- self.conn
- .core
- .common_state
- .write_plaintext(application_data.into(), outgoing_tls)
- }
-
- /// Encrypts a close_notify warning alert in `outgoing_tls`
- ///
- /// Returns the number of bytes that were written into `outgoing_tls`, or an error if
- /// the provided buffer is too small. In the error case, `outgoing_tls` is not modified
- pub fn queue_close_notify(&mut self, outgoing_tls: &mut [u8]) -> Result<usize, EncryptError> {
- self.conn
- .core
- .common_state
- .eager_send_close_notify(outgoing_tls)
- }
-
- /// Arranges for a TLS1.3 `key_update` to be sent.
- ///
- /// This consumes the `WriteTraffic` state: to actually send the message,
- /// call [`UnbufferedConnectionCommon::process_tls_records`] again which will
- /// return a `ConnectionState::EncodeTlsData` that emits the `key_update`
- /// message.
- ///
- /// See [`ConnectionCommon::refresh_traffic_keys()`] for full documentation,
- /// including why you might call this and in what circumstances it will fail.
- ///
- /// [`ConnectionCommon::refresh_traffic_keys()`]: crate::ConnectionCommon::refresh_traffic_keys
- pub fn refresh_traffic_keys(self) -> Result<(), Error> {
- self.conn.core.refresh_traffic_keys()
- }
-}
-
-/// A handshake record must be encoded
-pub struct EncodeTlsData<'c, Data> {
- conn: &'c mut UnbufferedConnectionCommon<Data>,
- chunk: Option<Vec<u8>>,
-}
-
-impl<'c, Data> EncodeTlsData<'c, Data> {
- fn new(conn: &'c mut UnbufferedConnectionCommon<Data>, chunk: Vec<u8>) -> Self {
- Self {
- conn,
- chunk: Some(chunk),
- }
- }
-
- /// Encodes a handshake record into the `outgoing_tls` buffer
- ///
- /// Returns the number of bytes that were written into `outgoing_tls`, or an error if
- /// the provided buffer is too small. In the error case, `outgoing_tls` is not modified
- pub fn encode(&mut self, outgoing_tls: &mut [u8]) -> Result<usize, EncodeError> {
- let Some(chunk) = self.chunk.take() else {
- return Err(EncodeError::AlreadyEncoded);
- };
-
- let required_size = chunk.len();
-
- if required_size > outgoing_tls.len() {
- self.chunk = Some(chunk);
- Err(InsufficientSizeError { required_size }.into())
- } else {
- let written = chunk.len();
- outgoing_tls[..written].copy_from_slice(&chunk);
-
- self.conn.wants_write = true;
-
- Ok(written)
- }
- }
-}
-
-/// Previously encoded TLS data must be transmitted
-pub struct TransmitTlsData<'c, Data> {
- pub(crate) conn: &'c mut UnbufferedConnectionCommon<Data>,
-}
-
-impl<Data> TransmitTlsData<'_, Data> {
- /// Signals that the previously encoded TLS data has been transmitted
- pub fn done(self) {
- self.conn.wants_write = false;
- }
-
- /// Returns an adapter that allows encrypting application data
- ///
- /// If allowed at this stage of the handshake process
- pub fn may_encrypt_app_data(&mut self) -> Option<WriteTraffic<'_, Data>> {
- if self
- .conn
- .core
- .common_state
- .may_send_application_data
- {
- Some(WriteTraffic { conn: self.conn })
- } else {
- None
- }
- }
-}
-
-/// Errors that may arise when encoding a handshake record
-#[derive(Debug)]
-pub enum EncodeError {
- /// Provided buffer was too small
- InsufficientSize(InsufficientSizeError),
-
- /// The handshake record has already been encoded; do not call `encode` again
- AlreadyEncoded,
-}
-
-impl From<InsufficientSizeError> for EncodeError {
- fn from(v: InsufficientSizeError) -> Self {
- Self::InsufficientSize(v)
- }
-}
-
-impl fmt::Display for EncodeError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::InsufficientSize(InsufficientSizeError { required_size }) => write!(
- f,
- "cannot encode due to insufficient size, {required_size} bytes are required"
- ),
- Self::AlreadyEncoded => "cannot encode, data has already been encoded".fmt(f),
- }
- }
-}
-
-#[cfg(feature = "std")]
-impl StdError for EncodeError {}
-
-/// Errors that may arise when encrypting application data
-#[derive(Debug)]
-pub enum EncryptError {
- /// Provided buffer was too small
- InsufficientSize(InsufficientSizeError),
-
- /// Encrypter has been exhausted
- EncryptExhausted,
-}
-
-impl From<InsufficientSizeError> for EncryptError {
- fn from(v: InsufficientSizeError) -> Self {
- Self::InsufficientSize(v)
- }
-}
-
-impl fmt::Display for EncryptError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::InsufficientSize(InsufficientSizeError { required_size }) => write!(
- f,
- "cannot encrypt due to insufficient size, {required_size} bytes are required"
- ),
- Self::EncryptExhausted => f.write_str("encrypter has been exhausted"),
- }
- }
-}
-
-#[cfg(feature = "std")]
-impl StdError for EncryptError {}
-
-/// Provided buffer was too small
-#[derive(Clone, Copy, Debug)]
-pub struct InsufficientSizeError {
- /// buffer must be at least this size
- pub required_size: usize,
-}
diff --git a/vendor/rustls/src/crypto/aws_lc_rs/hpke.rs b/vendor/rustls/src/crypto/aws_lc_rs/hpke.rs
deleted file mode 100644
index de0e5d63..00000000
--- a/vendor/rustls/src/crypto/aws_lc_rs/hpke.rs
+++ /dev/null
@@ -1,1191 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec::Vec;
-use core::fmt::{self, Debug, Formatter};
-
-use aws_lc_rs::aead::{
- self, Aad, BoundKey, NONCE_LEN, Nonce, NonceSequence, OpeningKey, SealingKey, UnboundKey,
-};
-use aws_lc_rs::agreement;
-use aws_lc_rs::cipher::{AES_128_KEY_LEN, AES_256_KEY_LEN};
-use aws_lc_rs::digest::{SHA256_OUTPUT_LEN, SHA384_OUTPUT_LEN, SHA512_OUTPUT_LEN};
-use aws_lc_rs::encoding::{AsBigEndian, Curve25519SeedBin, EcPrivateKeyBin};
-use zeroize::Zeroize;
-
-use crate::crypto::aws_lc_rs::hmac::{HMAC_SHA256, HMAC_SHA384, HMAC_SHA512};
-use crate::crypto::aws_lc_rs::unspecified_err;
-use crate::crypto::hpke::{
- EncapsulatedSecret, Hpke, HpkeOpener, HpkePrivateKey, HpkePublicKey, HpkeSealer, HpkeSuite,
-};
-use crate::crypto::tls13::{HkdfExpander, HkdfPrkExtract, HkdfUsingHmac, expand};
-use crate::msgs::enums::{HpkeAead, HpkeKdf, HpkeKem};
-use crate::msgs::handshake::HpkeSymmetricCipherSuite;
-#[cfg(feature = "std")]
-use crate::sync::Arc;
-use crate::{Error, OtherError};
-
-/// Default [RFC 9180] Hybrid Public Key Encryption (HPKE) suites supported by aws-lc-rs cryptography.
-pub static ALL_SUPPORTED_SUITES: &[&dyn Hpke] = &[
- DH_KEM_P256_HKDF_SHA256_AES_128,
- DH_KEM_P256_HKDF_SHA256_AES_256,
- #[cfg(not(feature = "fips"))]
- DH_KEM_P256_HKDF_SHA256_CHACHA20_POLY1305,
- DH_KEM_P384_HKDF_SHA384_AES_128,
- DH_KEM_P384_HKDF_SHA384_AES_256,
- #[cfg(not(feature = "fips"))]
- DH_KEM_P384_HKDF_SHA384_CHACHA20_POLY1305,
- DH_KEM_P521_HKDF_SHA512_AES_128,
- DH_KEM_P521_HKDF_SHA512_AES_256,
- #[cfg(not(feature = "fips"))]
- DH_KEM_P521_HKDF_SHA512_CHACHA20_POLY1305,
- #[cfg(not(feature = "fips"))]
- DH_KEM_X25519_HKDF_SHA256_AES_128,
- #[cfg(not(feature = "fips"))]
- DH_KEM_X25519_HKDF_SHA256_AES_256,
- #[cfg(not(feature = "fips"))]
- DH_KEM_X25519_HKDF_SHA256_CHACHA20_POLY1305,
-];
-
-/// HPKE suite using ECDH P-256 for agreement, HKDF SHA-256 for key derivation, and AEAD AES-128-GCM
-/// for symmetric encryption.
-pub static DH_KEM_P256_HKDF_SHA256_AES_128: &HpkeAwsLcRs<AES_128_KEY_LEN, SHA256_OUTPUT_LEN> =
- &HpkeAwsLcRs {
- suite: HpkeSuite {
- kem: HpkeKem::DHKEM_P256_HKDF_SHA256,
- sym: HpkeSymmetricCipherSuite {
- kdf_id: HpkeKdf::HKDF_SHA256,
- aead_id: HpkeAead::AES_128_GCM,
- },
- },
- dh_kem: DH_KEM_P256_HKDF_SHA256,
- hkdf: RING_HKDF_HMAC_SHA256,
- aead: &aead::AES_128_GCM,
- };
-
-/// HPKE suite using ECDH P-256 for agreement, HKDF SHA-256 for key derivation and AEAD AES-256-GCM
-/// for symmetric encryption.
-pub static DH_KEM_P256_HKDF_SHA256_AES_256: &HpkeAwsLcRs<AES_256_KEY_LEN, SHA256_OUTPUT_LEN> =
- &HpkeAwsLcRs {
- suite: HpkeSuite {
- kem: HpkeKem::DHKEM_P256_HKDF_SHA256,
- sym: HpkeSymmetricCipherSuite {
- kdf_id: HpkeKdf::HKDF_SHA256,
- aead_id: HpkeAead::AES_256_GCM,
- },
- },
- dh_kem: DH_KEM_P256_HKDF_SHA256,
- hkdf: RING_HKDF_HMAC_SHA256,
- aead: &aead::AES_256_GCM,
- };
-
-/// HPKE suite using ECDH P-256 for agreement, HKDF SHA-256 for key derivation, and AEAD
-/// CHACHA20-POLY-1305 for symmetric encryption.
-pub static DH_KEM_P256_HKDF_SHA256_CHACHA20_POLY1305: &HpkeAwsLcRs<
- CHACHA_KEY_LEN,
- SHA256_OUTPUT_LEN,
-> = &HpkeAwsLcRs {
- suite: HpkeSuite {
- kem: HpkeKem::DHKEM_P256_HKDF_SHA256,
- sym: HpkeSymmetricCipherSuite {
- kdf_id: HpkeKdf::HKDF_SHA256,
- aead_id: HpkeAead::CHACHA20_POLY_1305,
- },
- },
- dh_kem: DH_KEM_P256_HKDF_SHA256,
- hkdf: RING_HKDF_HMAC_SHA256,
- aead: &aead::CHACHA20_POLY1305,
-};
-
-/// HPKE suite using ECDH P-384 for agreement, HKDF SHA-384 for key derivation, and AEAD AES-128-GCM
-/// for symmetric encryption.
-pub static DH_KEM_P384_HKDF_SHA384_AES_128: &HpkeAwsLcRs<AES_128_KEY_LEN, SHA384_OUTPUT_LEN> =
- &HpkeAwsLcRs {
- suite: HpkeSuite {
- kem: HpkeKem::DHKEM_P384_HKDF_SHA384,
- sym: HpkeSymmetricCipherSuite {
- kdf_id: HpkeKdf::HKDF_SHA384,
- aead_id: HpkeAead::AES_128_GCM,
- },
- },
- dh_kem: DH_KEM_P384_HKDF_SHA384,
- hkdf: RING_HKDF_HMAC_SHA384,
- aead: &aead::AES_128_GCM,
- };
-
-/// HPKE suite using ECDH P-384 for agreement, HKDF SHA-384 for key derivation, and AEAD AES-256-GCM
-/// for symmetric encryption.
-pub static DH_KEM_P384_HKDF_SHA384_AES_256: &HpkeAwsLcRs<AES_256_KEY_LEN, SHA384_OUTPUT_LEN> =
- &HpkeAwsLcRs {
- suite: HpkeSuite {
- kem: HpkeKem::DHKEM_P384_HKDF_SHA384,
- sym: HpkeSymmetricCipherSuite {
- kdf_id: HpkeKdf::HKDF_SHA384,
- aead_id: HpkeAead::AES_256_GCM,
- },
- },
- dh_kem: DH_KEM_P384_HKDF_SHA384,
- hkdf: RING_HKDF_HMAC_SHA384,
- aead: &aead::AES_256_GCM,
- };
-
-/// HPKE suite using ECDH P-384 for agreement, HKDF SHA-384 for key derivation, and AEAD
-/// CHACHA20-POLY-1305 for symmetric encryption.
-pub static DH_KEM_P384_HKDF_SHA384_CHACHA20_POLY1305: &HpkeAwsLcRs<
- CHACHA_KEY_LEN,
- SHA384_OUTPUT_LEN,
-> = &HpkeAwsLcRs {
- suite: HpkeSuite {
- kem: HpkeKem::DHKEM_P384_HKDF_SHA384,
- sym: HpkeSymmetricCipherSuite {
- kdf_id: HpkeKdf::HKDF_SHA384,
- aead_id: HpkeAead::CHACHA20_POLY_1305,
- },
- },
- dh_kem: DH_KEM_P384_HKDF_SHA384,
- hkdf: RING_HKDF_HMAC_SHA384,
- aead: &aead::CHACHA20_POLY1305,
-};
-
-/// HPKE suite using ECDH P-521 for agreement, HKDF SHA-512 for key derivation, and AEAD AES-128-GCM
-/// for symmetric encryption.
-pub static DH_KEM_P521_HKDF_SHA512_AES_128: &HpkeAwsLcRs<AES_128_KEY_LEN, SHA512_OUTPUT_LEN> =
- &HpkeAwsLcRs {
- suite: HpkeSuite {
- kem: HpkeKem::DHKEM_P521_HKDF_SHA512,
- sym: HpkeSymmetricCipherSuite {
- kdf_id: HpkeKdf::HKDF_SHA512,
- aead_id: HpkeAead::AES_128_GCM,
- },
- },
- dh_kem: DH_KEM_P521_HKDF_SHA512,
- hkdf: RING_HKDF_HMAC_SHA512,
- aead: &aead::AES_128_GCM,
- };
-
-/// HPKE suite using ECDH P-521 for agreement, HKDF SHA-512 for key derivation, and AEAD AES-256-GCM
-/// for symmetric encryption.
-pub static DH_KEM_P521_HKDF_SHA512_AES_256: &HpkeAwsLcRs<AES_256_KEY_LEN, SHA512_OUTPUT_LEN> =
- &HpkeAwsLcRs {
- suite: HpkeSuite {
- kem: HpkeKem::DHKEM_P521_HKDF_SHA512,
- sym: HpkeSymmetricCipherSuite {
- kdf_id: HpkeKdf::HKDF_SHA512,
- aead_id: HpkeAead::AES_256_GCM,
- },
- },
- dh_kem: DH_KEM_P521_HKDF_SHA512,
- hkdf: RING_HKDF_HMAC_SHA512,
- aead: &aead::AES_256_GCM,
- };
-
-/// HPKE suite using ECDH P-521 for agreement, HKDF SHA-512 for key derivation, and AEAD
-/// CHACHA20-POLY-1305 for symmetric encryption.
-pub static DH_KEM_P521_HKDF_SHA512_CHACHA20_POLY1305: &HpkeAwsLcRs<
- CHACHA_KEY_LEN,
- SHA512_OUTPUT_LEN,
-> = &HpkeAwsLcRs {
- suite: HpkeSuite {
- kem: HpkeKem::DHKEM_P521_HKDF_SHA512,
- sym: HpkeSymmetricCipherSuite {
- kdf_id: HpkeKdf::HKDF_SHA512,
- aead_id: HpkeAead::CHACHA20_POLY_1305,
- },
- },
- dh_kem: DH_KEM_P521_HKDF_SHA512,
- hkdf: RING_HKDF_HMAC_SHA512,
- aead: &aead::CHACHA20_POLY1305,
-};
-
-/// HPKE suite using ECDH X25519 for agreement, HKDF SHA-256 for key derivation, and AEAD AES-128-GCM
-/// for symmetric encryption.
-pub static DH_KEM_X25519_HKDF_SHA256_AES_128: &HpkeAwsLcRs<AES_128_KEY_LEN, SHA256_OUTPUT_LEN> =
- &HpkeAwsLcRs {
- suite: HpkeSuite {
- kem: HpkeKem::DHKEM_X25519_HKDF_SHA256,
- sym: HpkeSymmetricCipherSuite {
- kdf_id: HpkeKdf::HKDF_SHA256,
- aead_id: HpkeAead::AES_128_GCM,
- },
- },
- dh_kem: DH_KEM_X25519_HKDF_SHA256,
- hkdf: RING_HKDF_HMAC_SHA256,
- aead: &aead::AES_128_GCM,
- };
-
-/// HPKE suite using ECDH X25519 for agreement, HKDF SHA-256 for key derivation, and AEAD AES-256-GCM
-/// for symmetric encryption.
-pub static DH_KEM_X25519_HKDF_SHA256_AES_256: &HpkeAwsLcRs<AES_256_KEY_LEN, SHA256_OUTPUT_LEN> =
- &HpkeAwsLcRs {
- suite: HpkeSuite {
- kem: HpkeKem::DHKEM_X25519_HKDF_SHA256,
- sym: HpkeSymmetricCipherSuite {
- kdf_id: HpkeKdf::HKDF_SHA256,
- aead_id: HpkeAead::AES_256_GCM,
- },
- },
- dh_kem: DH_KEM_X25519_HKDF_SHA256,
- hkdf: RING_HKDF_HMAC_SHA256,
- aead: &aead::AES_256_GCM,
- };
-
-/// HPKE suite using ECDH X25519 for agreement, HKDF SHA-256 for key derivation, and AEAD
-/// CHACHA20-POLY-1305 for symmetric encryption.
-pub static DH_KEM_X25519_HKDF_SHA256_CHACHA20_POLY1305: &HpkeAwsLcRs<
- CHACHA_KEY_LEN,
- SHA256_OUTPUT_LEN,
-> = &HpkeAwsLcRs {
- suite: HpkeSuite {
- kem: HpkeKem::DHKEM_X25519_HKDF_SHA256,
- sym: HpkeSymmetricCipherSuite {
- kdf_id: HpkeKdf::HKDF_SHA256,
- aead_id: HpkeAead::CHACHA20_POLY_1305,
- },
- },
- dh_kem: DH_KEM_X25519_HKDF_SHA256,
- hkdf: RING_HKDF_HMAC_SHA256,
- aead: &aead::CHACHA20_POLY1305,
-};
-
-/// `HpkeAwsLcRs` holds the concrete instantiations of the algorithms specified by the [HpkeSuite].
-pub struct HpkeAwsLcRs<const KEY_SIZE: usize, const KDF_SIZE: usize> {
- suite: HpkeSuite,
- dh_kem: &'static DhKem<KDF_SIZE>,
- hkdf: &'static dyn HkdfPrkExtract,
- aead: &'static aead::Algorithm,
-}
-
-impl<const KEY_SIZE: usize, const KDF_SIZE: usize> HpkeAwsLcRs<KEY_SIZE, KDF_SIZE> {
- /// See [RFC 9180 §5.1 "Creating the Encryption Context"][0].
- ///
- /// [0]: https://www.rfc-editor.org/rfc/rfc9180.html#section-5.1
- fn key_schedule(
- &self,
- shared_secret: KemSharedSecret<KDF_SIZE>,
- info: &[u8],
- ) -> Result<KeySchedule<KEY_SIZE>, Error> {
- // Note: we use an empty IKM for the `psk_id_hash` and `secret` labelled extractions because
- // there is no PSK ID in base mode HPKE.
-
- let suite_id = LabeledSuiteId::Hpke(self.suite);
- let psk_id_hash = labeled_extract_for_prk(self.hkdf, suite_id, None, Label::PskIdHash, &[]);
- let info_hash = labeled_extract_for_prk(self.hkdf, suite_id, None, Label::InfoHash, info);
- let key_schedule_context = [
- &[0][..], // base mode (0x00)
- &psk_id_hash,
- &info_hash,
- ]
- .concat();
-
- let key = AeadKey(self.key_schedule_labeled_expand::<KEY_SIZE>(
- &shared_secret,
- &key_schedule_context,
- Label::Key,
- ));
-
- let base_nonce = self.key_schedule_labeled_expand::<NONCE_LEN>(
- &shared_secret,
- &key_schedule_context,
- Label::BaseNonce,
- );
-
- Ok(KeySchedule {
- aead: self.aead,
- key,
- base_nonce,
- seq_num: 0,
- })
- }
-
- fn key_schedule_labeled_expand<const L: usize>(
- &self,
- shared_secret: &KemSharedSecret<KDF_SIZE>,
- key_schedule_context: &[u8],
- label: Label,
- ) -> [u8; L] {
- let suite_id = LabeledSuiteId::Hpke(self.suite);
- labeled_expand::<L>(
- suite_id,
- labeled_extract_for_expand(
- self.hkdf,
- suite_id,
- Some(&shared_secret.0),
- Label::Secret,
- &[],
- ),
- label,
- key_schedule_context,
- )
- }
-}
-
-impl<const KEY_SIZE: usize, const KDF_SIZE: usize> Hpke for HpkeAwsLcRs<KEY_SIZE, KDF_SIZE> {
- fn seal(
- &self,
- info: &[u8],
- aad: &[u8],
- plaintext: &[u8],
- pub_key: &HpkePublicKey,
- ) -> Result<(EncapsulatedSecret, Vec<u8>), Error> {
- let (encap, mut sealer) = self.setup_sealer(info, pub_key)?;
- Ok((encap, sealer.seal(aad, plaintext)?))
- }
-
- fn setup_sealer(
- &self,
- info: &[u8],
- pub_key: &HpkePublicKey,
- ) -> Result<(EncapsulatedSecret, Box<dyn HpkeSealer + 'static>), Error> {
- let (encap, sealer) = Sealer::new(self, info, pub_key)?;
- Ok((encap, Box::new(sealer)))
- }
-
- fn open(
- &self,
- enc: &EncapsulatedSecret,
- info: &[u8],
- aad: &[u8],
- ciphertext: &[u8],
- secret_key: &HpkePrivateKey,
- ) -> Result<Vec<u8>, Error> {
- self.setup_opener(enc, info, secret_key)?
- .open(aad, ciphertext)
- }
-
- fn setup_opener(
- &self,
- enc: &EncapsulatedSecret,
- info: &[u8],
- secret_key: &HpkePrivateKey,
- ) -> Result<Box<dyn HpkeOpener + 'static>, Error> {
- Ok(Box::new(Opener::new(self, enc, info, secret_key)?))
- }
-
- fn fips(&self) -> bool {
- matches!(
- // We make a FIPS determination based on the suite's DH KEM and AEAD choice.
- // We don't need to examine the KDF choice because all supported KDFs are FIPS
- // compatible.
- (self.suite.kem, self.suite.sym.aead_id),
- (
- // Only the NIST "P-curve" DH KEMs are FIPS compatible.
- HpkeKem::DHKEM_P256_HKDF_SHA256
- | HpkeKem::DHKEM_P384_HKDF_SHA384
- | HpkeKem::DHKEM_P521_HKDF_SHA512,
- // Only the AES AEADs are FIPS compatible.
- HpkeAead::AES_128_GCM | HpkeAead::AES_256_GCM,
- )
- )
- }
-
- fn generate_key_pair(&self) -> Result<(HpkePublicKey, HpkePrivateKey), Error> {
- (self.dh_kem.key_generator)()
- }
-
- fn suite(&self) -> HpkeSuite {
- self.suite
- }
-}
-
-impl<const KEY_SIZE: usize, const KDF_SIZE: usize> Debug for HpkeAwsLcRs<KEY_SIZE, KDF_SIZE> {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- self.suite.fmt(f)
- }
-}
-
-/// Adapts a [KeySchedule] and [AeadKey] for the role of a [HpkeSealer].
-struct Sealer<const KEY_SIZE: usize, const KDF_SIZE: usize> {
- key_schedule: KeySchedule<KEY_SIZE>,
-}
-
-impl<const KEY_SIZE: usize, const KDF_SIZE: usize> Sealer<KEY_SIZE, KDF_SIZE> {
- /// See [RFC 9180 §5.1.1 "Encryption to a Public Key"][0].
- ///
- /// [0]: https://www.rfc-editor.org/rfc/rfc9180.html#section-5.1.1
- fn new(
- suite: &HpkeAwsLcRs<KEY_SIZE, KDF_SIZE>,
- info: &[u8],
- pub_key: &HpkePublicKey,
- ) -> Result<(EncapsulatedSecret, Self), Error> {
- // def SetupBaseS(pkR, info):
- // shared_secret, enc = Encap(pkR)
- // return enc, KeyScheduleS(mode_base, shared_secret, info,
- // default_psk, default_psk_id)
-
- let (shared_secret, enc) = suite.dh_kem.encap(pub_key)?;
- let key_schedule = suite.key_schedule(shared_secret, info)?;
- Ok((enc, Self { key_schedule }))
- }
-
- /// A **test only** constructor that uses a pre-specified ephemeral agreement private key
- /// instead of one that is randomly generated.
- #[cfg(test)]
- fn test_only_new(
- suite: &HpkeAwsLcRs<KEY_SIZE, KDF_SIZE>,
- info: &[u8],
- pub_key: &HpkePublicKey,
- sk_e: &[u8],
- ) -> Result<(EncapsulatedSecret, Self), Error> {
- let (shared_secret, enc) = suite
- .dh_kem
- .test_only_encap(pub_key, sk_e)?;
- let key_schedule = suite.key_schedule(shared_secret, info)?;
- Ok((enc, Self { key_schedule }))
- }
-}
-
-impl<const KEY_SIZE: usize, const KDF_SIZE: usize> HpkeSealer for Sealer<KEY_SIZE, KDF_SIZE> {
- fn seal(&mut self, aad: &[u8], plaintext: &[u8]) -> Result<Vec<u8>, Error> {
- // def ContextS.Seal(aad, pt):
- // ct = Seal(self.key, self.ComputeNonce(self.seq), aad, pt)
- // self.IncrementSeq()
- // return ct
-
- let key = UnboundKey::new(self.key_schedule.aead, &self.key_schedule.key.0)
- .map_err(unspecified_err)?;
- let mut sealing_key = SealingKey::new(key, &mut self.key_schedule);
-
- let mut in_out_buffer = Vec::from(plaintext);
- sealing_key
- .seal_in_place_append_tag(Aad::from(aad), &mut in_out_buffer)
- .map_err(unspecified_err)?;
-
- Ok(in_out_buffer)
- }
-}
-
-impl<const KEY_SIZE: usize, const KDF_SIZE: usize> Debug for Sealer<KEY_SIZE, KDF_SIZE> {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- f.debug_struct("Sealer").finish()
- }
-}
-
-/// Adapts a [KeySchedule] and [AeadKey] for the role of a [HpkeOpener].
-struct Opener<const KEY_SIZE: usize, const KDF_SIZE: usize> {
- key_schedule: KeySchedule<KEY_SIZE>,
-}
-
-impl<const KEY_SIZE: usize, const KDF_SIZE: usize> Opener<KEY_SIZE, KDF_SIZE> {
- /// See [RFC 9180 §5.1.1 "Encryption to a Public Key"][0].
- ///
- /// [0]: https://www.rfc-editor.org/rfc/rfc9180.html#section-5.1.1
- fn new(
- suite: &HpkeAwsLcRs<KEY_SIZE, KDF_SIZE>,
- enc: &EncapsulatedSecret,
- info: &[u8],
- secret_key: &HpkePrivateKey,
- ) -> Result<Self, Error> {
- // def SetupBaseR(enc, skR, info):
- // shared_secret = Decap(enc, skR)
- // return KeyScheduleR(mode_base, shared_secret, info,
- // default_psk, default_psk_id)
- Ok(Self {
- key_schedule: suite.key_schedule(suite.dh_kem.decap(enc, secret_key)?, info)?,
- })
- }
-}
-
-impl<const KEY_SIZE: usize, const KDF_SIZE: usize> HpkeOpener for Opener<KEY_SIZE, KDF_SIZE> {
- fn open(&mut self, aad: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
- // def ContextR.Open(aad, ct):
- // pt = Open(self.key, self.ComputeNonce(self.seq), aad, ct)
- // if pt == OpenError:
- // raise OpenError
- // self.IncrementSeq()
- // return pt
-
- let key = UnboundKey::new(self.key_schedule.aead, &self.key_schedule.key.0)
- .map_err(unspecified_err)?;
- let mut opening_key = OpeningKey::new(key, &mut self.key_schedule);
-
- let mut in_out_buffer = Vec::from(ciphertext);
- let plaintext = opening_key
- .open_in_place(Aad::from(aad), &mut in_out_buffer)
- .map_err(unspecified_err)?;
-
- Ok(plaintext.to_vec())
- }
-}
-
-impl<const KEY_SIZE: usize, const KDF_SIZE: usize> Debug for Opener<KEY_SIZE, KDF_SIZE> {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- f.debug_struct("Opener").finish()
- }
-}
-
-/// A Diffie-Hellman (DH) based Key Encapsulation Mechanism (KEM).
-///
-/// See [RFC 9180 §4.1 "DH-Based KEM (DHKEM)"][0].
-///
-/// [0]: https://www.rfc-editor.org/rfc/rfc9180.html#section-4.1
-struct DhKem<const KDF_SIZE: usize> {
- id: HpkeKem,
- agreement_algorithm: &'static agreement::Algorithm,
- key_generator:
- &'static (dyn Fn() -> Result<(HpkePublicKey, HpkePrivateKey), Error> + Send + Sync),
- hkdf: &'static dyn HkdfPrkExtract,
-}
-
-impl<const KDF_SIZE: usize> DhKem<KDF_SIZE> {
- /// See [RFC 9180 §4.1 "DH-Based KEM (DHKEM)"][0].
- ///
- /// [0]: https://www.rfc-editor.org/rfc/rfc9180.html#section-4.1
- fn encap(
- &self,
- recipient: &HpkePublicKey,
- ) -> Result<(KemSharedSecret<KDF_SIZE>, EncapsulatedSecret), Error> {
- // def Encap(pkR):
- // skE, pkE = GenerateKeyPair()
-
- let sk_e =
- agreement::PrivateKey::generate(self.agreement_algorithm).map_err(unspecified_err)?;
- self.encap_impl(recipient, sk_e)
- }
-
- /// A test-only encap operation that uses a fixed `test_only_ske` instead of generating
- /// one randomly.
- #[cfg(test)]
- fn test_only_encap(
- &self,
- recipient: &HpkePublicKey,
- test_only_ske: &[u8],
- ) -> Result<(KemSharedSecret<KDF_SIZE>, EncapsulatedSecret), Error> {
- // For test contexts only, we accept a static sk_e as an argument.
- let sk_e = agreement::PrivateKey::from_private_key(self.agreement_algorithm, test_only_ske)
- .map_err(key_rejected_err)?;
- self.encap_impl(recipient, sk_e)
- }
-
- fn encap_impl(
- &self,
- recipient: &HpkePublicKey,
- sk_e: agreement::PrivateKey,
- ) -> Result<(KemSharedSecret<KDF_SIZE>, EncapsulatedSecret), Error> {
- // def Encap(pkR):
- // skE, pkE = GenerateKeyPair()
- // dh = DH(skE, pkR)
- // enc = SerializePublicKey(pkE)
- //
- // pkRm = SerializePublicKey(pkR)
- // kem_context = concat(enc, pkRm)
- //
- // shared_secret = ExtractAndExpand(dh, kem_context)
- // return shared_secret, enc
-
- let enc = sk_e
- .compute_public_key()
- .map_err(unspecified_err)?;
- let pk_r = agreement::UnparsedPublicKey::new(self.agreement_algorithm, &recipient.0);
- let kem_context = [enc.as_ref(), pk_r.bytes()].concat();
-
- let shared_secret = agreement::agree(&sk_e, &pk_r, aws_lc_rs::error::Unspecified, |dh| {
- Ok(self.extract_and_expand(dh, &kem_context))
- })
- .map_err(unspecified_err)?;
-
- Ok((
- KemSharedSecret(shared_secret),
- EncapsulatedSecret(enc.as_ref().into()),
- ))
- }
-
- /// See [RFC 9180 §4.1 "DH-Based KEM (DHKEM)"][0].
- ///
- /// [0]: https://www.rfc-editor.org/rfc/rfc9180.html#section-4.1
- fn decap(
- &self,
- enc: &EncapsulatedSecret,
- recipient: &HpkePrivateKey,
- ) -> Result<KemSharedSecret<KDF_SIZE>, Error> {
- // def Decap(enc, skR):
- // pkE = DeserializePublicKey(enc)
- // dh = DH(skR, pkE)
- //
- // pkRm = SerializePublicKey(pk(skR))
- // kem_context = concat(enc, pkRm)
- //
- // shared_secret = ExtractAndExpand(dh, kem_context)
- // return shared_secret
-
- let pk_e = agreement::UnparsedPublicKey::new(self.agreement_algorithm, &enc.0);
- let sk_r = agreement::PrivateKey::from_private_key(
- self.agreement_algorithm,
- recipient.secret_bytes(),
- )
- .map_err(key_rejected_err)?;
- let pk_rm = sk_r
- .compute_public_key()
- .map_err(unspecified_err)?;
- let kem_context = [&enc.0, pk_rm.as_ref()].concat();
-
- let shared_secret = agreement::agree(&sk_r, &pk_e, aws_lc_rs::error::Unspecified, |dh| {
- Ok(self.extract_and_expand(dh, &kem_context))
- })
- .map_err(unspecified_err)?;
-
- Ok(KemSharedSecret(shared_secret))
- }
-
- /// See [RFC 9180 §4.1 "DH-Based KEM (DHKEM)"][0].
- ///
- /// [0]: https://www.rfc-editor.org/rfc/rfc9180.html#section-4.1
- fn extract_and_expand(&self, dh: &[u8], kem_context: &[u8]) -> [u8; KDF_SIZE] {
- // def ExtractAndExpand(dh, kem_context):
- // eae_prk = LabeledExtract("", "eae_prk", dh)
- // shared_secret = LabeledExpand(eae_prk, "shared_secret",
- // kem_context, Nsecret)
- // return shared_secret
-
- let suite_id = LabeledSuiteId::Kem(self.id);
- labeled_expand(
- suite_id,
- labeled_extract_for_expand(self.hkdf, suite_id, None, Label::EaePrk, dh),
- Label::SharedSecret,
- kem_context,
- )
- }
-}
-
-static DH_KEM_P256_HKDF_SHA256: &DhKem<SHA256_OUTPUT_LEN> = &DhKem {
- id: HpkeKem::DHKEM_P256_HKDF_SHA256,
- agreement_algorithm: &agreement::ECDH_P256,
- key_generator: &|| generate_p_curve_key_pair(&agreement::ECDH_P256),
- hkdf: RING_HKDF_HMAC_SHA256,
-};
-
-static DH_KEM_P384_HKDF_SHA384: &DhKem<SHA384_OUTPUT_LEN> = &DhKem {
- id: HpkeKem::DHKEM_P384_HKDF_SHA384,
- agreement_algorithm: &agreement::ECDH_P384,
- key_generator: &|| generate_p_curve_key_pair(&agreement::ECDH_P384),
- hkdf: RING_HKDF_HMAC_SHA384,
-};
-
-static DH_KEM_P521_HKDF_SHA512: &DhKem<SHA512_OUTPUT_LEN> = &DhKem {
- id: HpkeKem::DHKEM_P521_HKDF_SHA512,
- agreement_algorithm: &agreement::ECDH_P521,
- key_generator: &|| generate_p_curve_key_pair(&agreement::ECDH_P521),
- hkdf: RING_HKDF_HMAC_SHA512,
-};
-
-static DH_KEM_X25519_HKDF_SHA256: &DhKem<SHA256_OUTPUT_LEN> = &DhKem {
- id: HpkeKem::DHKEM_X25519_HKDF_SHA256,
- agreement_algorithm: &agreement::X25519,
- key_generator: &generate_x25519_key_pair,
- hkdf: RING_HKDF_HMAC_SHA256,
-};
-
-/// Generate a NIST P-256, P-384 or P-512 key pair expressed as a raw big-endian fixed-length
-/// integer.
-///
-/// We must disambiguate the [`AsBigEndian`] trait in-use and this function uses
-/// [`AsBigEndian<EcPrivateKeyBin>`], which does not support [`agreement::X25519`].
-/// For generating X25519 keys see [`generate_x25519_key_pair`].
-fn generate_p_curve_key_pair(
- alg: &'static agreement::Algorithm,
-) -> Result<(HpkePublicKey, HpkePrivateKey), Error> {
- // We only initialize DH KEM instances that use this function as a key generator
- // for non-X25519 algorithms. Debug assert this just in case since `AsBigEndian<EcPrivateKeyBin>`
- // will panic for this algorithm.
- debug_assert_ne!(alg, &agreement::X25519);
- let (public_key, private_key) = generate_key_pair(alg)?;
- let raw_private_key: EcPrivateKeyBin<'_> = private_key
- .as_be_bytes()
- .map_err(unspecified_err)?;
- Ok((
- public_key,
- HpkePrivateKey::from(raw_private_key.as_ref().to_vec()),
- ))
-}
-
-/// Generate a X25519 key pair expressed as a raw big-endian fixed-length
-/// integer.
-///
-/// We must disambiguate the [`AsBigEndian`] trait in-use and this function uses
-/// [`AsBigEndian<Curve25519SeedBin>`], which only supports [`agreement::X25519`].
-/// For generating P-256, P-384 and P-512 keys see [`generate_p_curve_key_pair`].
-fn generate_x25519_key_pair() -> Result<(HpkePublicKey, HpkePrivateKey), Error> {
- let (public_key, private_key) = generate_key_pair(&agreement::X25519)?;
- let raw_private_key: Curve25519SeedBin<'_> = private_key
- .as_be_bytes()
- .map_err(unspecified_err)?;
- Ok((
- public_key,
- HpkePrivateKey::from(raw_private_key.as_ref().to_vec()),
- ))
-}
-
-fn generate_key_pair(
- alg: &'static agreement::Algorithm,
-) -> Result<(HpkePublicKey, agreement::PrivateKey), Error> {
- let private_key = agreement::PrivateKey::generate(alg).map_err(unspecified_err)?;
- let public_key = HpkePublicKey(
- private_key
- .compute_public_key()
- .map_err(unspecified_err)?
- .as_ref()
- .to_vec(),
- );
- Ok((public_key, private_key))
-}
-
-/// KeySchedule holds the derived AEAD key, base nonce, and seq number
-/// common to both a [Sealer] and [Opener].
-struct KeySchedule<const KEY_SIZE: usize> {
- aead: &'static aead::Algorithm,
- key: AeadKey<KEY_SIZE>,
- base_nonce: [u8; NONCE_LEN],
- seq_num: u32,
-}
-
-impl<const KEY_SIZE: usize> KeySchedule<KEY_SIZE> {
- /// See [RFC 9180 §5.2 "Encryption and Decryption"][0].
- ///
- /// [0]: https://www.rfc-editor.org/rfc/rfc9180.html#section-5.2
- fn compute_nonce(&self) -> [u8; NONCE_LEN] {
- // def Context<ROLE>.ComputeNonce(seq):
- // seq_bytes = I2OSP(seq, Nn)
- // return xor(self.base_nonce, seq_bytes)
-
- // Each new N-byte nonce is conceptually two parts:
- // * N-4 bytes of the base nonce (0s in `nonce` to XOR in as-is).
- // * 4 bytes derived from the sequence number XOR the base nonce.
- let mut nonce = [0; NONCE_LEN];
- let seq_bytes = self.seq_num.to_be_bytes();
- nonce[NONCE_LEN - seq_bytes.len()..].copy_from_slice(&seq_bytes);
-
- for (n, &b) in nonce.iter_mut().zip(&self.base_nonce) {
- *n ^= b;
- }
-
- nonce
- }
-
- /// See [RFC 9180 §5.2 "Encryption and Decryption"][0].
- ///
- /// [0]: https://www.rfc-editor.org/rfc/rfc9180.html#section-5.2
- fn increment_seq_num(&mut self) -> Result<(), aws_lc_rs::error::Unspecified> {
- // def Context<ROLE>.IncrementSeq():
- // if self.seq >= (1 << (8*Nn)) - 1:
- // raise MessageLimitReachedError
- // self.seq += 1
-
- // Determine the maximum sequence number using the AEAD nonce's length in bits.
- // Do this as an u128 to prevent overflowing.
- let max_seq_num = (1u128 << (NONCE_LEN * 8)) - 1;
-
- // Promote the u32 sequence number to an u128 and compare against the maximum allowed
- // sequence number.
- if u128::from(self.seq_num) >= max_seq_num {
- return Err(aws_lc_rs::error::Unspecified);
- }
-
- self.seq_num += 1;
- Ok(())
- }
-}
-
-impl<const KEY_SIZE: usize> NonceSequence for &mut KeySchedule<KEY_SIZE> {
- fn advance(&mut self) -> Result<Nonce, aws_lc_rs::error::Unspecified> {
- let nonce = self.compute_nonce();
- self.increment_seq_num()?;
- Nonce::try_assume_unique_for_key(&nonce)
- }
-}
-
-/// See [RFC 9180 §4 "Cryptographic Dependencies"][0].
-///
-/// [0]: https://www.rfc-editor.org/rfc/rfc9180.html#section-4
-fn labeled_extract_for_expand(
- hkdf: &'static dyn HkdfPrkExtract,
- suite_id: LabeledSuiteId,
- salt: Option<&[u8]>,
- label: Label,
- ikm: &[u8],
-) -> Box<dyn HkdfExpander> {
- // def LabeledExtract(salt, label, ikm):
- // labeled_ikm = concat("HPKE-v1", suite_id, label, ikm)
- // return Extract(salt, labeled_ikm)
-
- let labeled_ikm = [&b"HPKE-v1"[..], &suite_id.encoded(), label.as_ref(), ikm].concat();
- hkdf.extract_from_secret(salt, &labeled_ikm)
-}
-
-/// See [RFC 9180 §4 "Cryptographic Dependencies"][0].
-///
-/// [0]: https://www.rfc-editor.org/rfc/rfc9180.html#section-4
-fn labeled_extract_for_prk(
- hkdf: &'static dyn HkdfPrkExtract,
- suite_id: LabeledSuiteId,
- salt: Option<&[u8]>,
- label: Label,
- ikm: &[u8],
-) -> Vec<u8> {
- // def LabeledExtract(salt, label, ikm):
- // labeled_ikm = concat("HPKE-v1", suite_id, label, ikm)
- // return Extract(salt, labeled_ikm)
-
- let labeled_ikm = [&b"HPKE-v1"[..], &suite_id.encoded(), label.as_ref(), ikm].concat();
- hkdf.extract_prk_from_secret(salt, &labeled_ikm)
-}
-
-/// See [RFC 9180 §4 "Cryptographic Dependencies"][0].
-///
-/// [0]: https://www.rfc-editor.org/rfc/rfc9180.html#section-4
-fn labeled_expand<const L: usize>(
- suite_id: LabeledSuiteId,
- expander: Box<dyn HkdfExpander>,
- label: Label,
- kem_context: &[u8],
-) -> [u8; L] {
- // def LabeledExpand(prk, label, info, L):
- // labeled_info = concat(I2OSP(L, 2), "HPKE-v1", suite_id,
- // label, info)
- // return Expand(prk, labeled_info, L)
-
- let output_len = u16::to_be_bytes(L as u16);
- let info = &[
- &output_len[..],
- b"HPKE-v1",
- &suite_id.encoded(),
- label.as_ref(),
- kem_context,
- ];
-
- expand(&*expander, info)
-}
-
-/// Label describes the possible labels for use with [labeled_extract_for_expand] and [labeled_expand].
-#[derive(Debug)]
-enum Label {
- PskIdHash,
- InfoHash,
- Secret,
- Key,
- BaseNonce,
- EaePrk,
- SharedSecret,
-}
-
-impl AsRef<[u8]> for Label {
- fn as_ref(&self) -> &[u8] {
- match self {
- Self::PskIdHash => b"psk_id_hash",
- Self::InfoHash => b"info_hash",
- Self::Secret => b"secret",
- Self::Key => b"key",
- Self::BaseNonce => b"base_nonce",
- Self::EaePrk => b"eae_prk",
- Self::SharedSecret => b"shared_secret",
- }
- }
-}
-
-/// LabeledSuiteId describes the possible suite ID values for use with [labeled_extract_for_expand] and
-/// [labeled_expand].
-#[derive(Debug, Copy, Clone)]
-enum LabeledSuiteId {
- Hpke(HpkeSuite),
- Kem(HpkeKem),
-}
-
-impl LabeledSuiteId {
- /// The suite ID encoding depends on the context of use. In the general HPKE context,
- /// we use a "HPKE" prefix and encode the entire ciphersuite. In the KEM context we use a
- /// "KEM" prefix and only encode the KEM ID.
- ///
- /// See the bottom of [RFC 9180 §4](https://www.rfc-editor.org/rfc/rfc9180.html#section-4)
- /// for more information.
- fn encoded(&self) -> Vec<u8> {
- match self {
- Self::Hpke(suite) => [
- &b"HPKE"[..],
- &u16::from(suite.kem).to_be_bytes(),
- &u16::from(suite.sym.kdf_id).to_be_bytes(),
- &u16::from(suite.sym.aead_id).to_be_bytes(),
- ]
- .concat(),
- Self::Kem(kem) => [&b"KEM"[..], &u16::from(*kem).to_be_bytes()].concat(),
- }
- }
-}
-
-/// A newtype wrapper for an unbound AEAD key.
-struct AeadKey<const KEY_LEN: usize>([u8; KEY_LEN]);
-
-impl<const KEY_LEN: usize> Drop for AeadKey<KEY_LEN> {
- fn drop(&mut self) {
- self.0.zeroize()
- }
-}
-
-/// A newtype wrapper for a DH KEM shared secret.
-struct KemSharedSecret<const KDF_LEN: usize>([u8; KDF_LEN]);
-
-impl<const KDF_LEN: usize> Drop for KemSharedSecret<KDF_LEN> {
- fn drop(&mut self) {
- self.0.zeroize();
- }
-}
-
-fn key_rejected_err(_e: aws_lc_rs::error::KeyRejected) -> Error {
- #[cfg(feature = "std")]
- {
- Error::Other(OtherError(Arc::new(_e)))
- }
- #[cfg(not(feature = "std"))]
- {
- Error::Other(OtherError())
- }
-}
-
-// The `cipher::chacha::KEY_LEN` const is not exported, so we copy it here:
-// https://github.com/aws/aws-lc-rs/blob/0186ef7bb1a4d7e140bae8074a9871f49afedf1b/aws-lc-rs/src/cipher/chacha.rs#L13
-const CHACHA_KEY_LEN: usize = 32;
-
-static RING_HKDF_HMAC_SHA256: &HkdfUsingHmac<'static> = &HkdfUsingHmac(&HMAC_SHA256);
-static RING_HKDF_HMAC_SHA384: &HkdfUsingHmac<'static> = &HkdfUsingHmac(&HMAC_SHA384);
-static RING_HKDF_HMAC_SHA512: &HkdfUsingHmac<'static> = &HkdfUsingHmac(&HMAC_SHA512);
-
-#[cfg(test)]
-mod tests {
- use alloc::{format, vec};
-
- use super::*;
-
- #[test]
- fn smoke_test() {
- for suite in ALL_SUPPORTED_SUITES {
- _ = format!("{suite:?}"); // HpkeAwsLcRs suites should be Debug.
-
- // We should be able to generate a random keypair.
- let (pk, sk) = suite.generate_key_pair().unwrap();
-
- // Info value corresponds to the first RFC 9180 base mode test vector.
- let info = &[
- 0x4f, 0x64, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0x61, 0x20, 0x47, 0x72, 0x65, 0x63, 0x69,
- 0x61, 0x6e, 0x20, 0x55, 0x72, 0x6e,
- ][..];
-
- // We should be able to set up a sealer.
- let (enc, mut sealer) = suite.setup_sealer(info, &pk).unwrap();
-
- _ = format!("{sealer:?}"); // Sealer should be Debug.
-
- // Setting up a sealer with an invalid public key should fail.
- let bad_setup_res = suite.setup_sealer(info, &HpkePublicKey(vec![]));
- assert!(matches!(bad_setup_res.unwrap_err(), Error::Other(_)));
-
- // We should be able to seal some plaintext.
- let aad = &[0xC0, 0xFF, 0xEE];
- let pt = &[0xF0, 0x0D];
- let ct = sealer.seal(aad, pt).unwrap();
-
- // We should be able to set up an opener.
- let mut opener = suite
- .setup_opener(&enc, info, &sk)
- .unwrap();
- _ = format!("{opener:?}"); // Opener should be Debug.
-
- // Setting up an opener with an invalid private key should fail.
- let bad_key_res = suite.setup_opener(&enc, info, &HpkePrivateKey::from(vec![]));
- assert!(matches!(bad_key_res.unwrap_err(), Error::Other(_)));
-
- // Opening the plaintext should work with the correct opener and aad.
- let pt_prime = opener.open(aad, &ct).unwrap();
- assert_eq!(pt_prime, pt);
-
- // Opening the plaintext with the correct opener and wrong aad should fail.
- let open_res = opener.open(&[0x0], &ct);
- assert!(matches!(open_res.unwrap_err(), Error::Other(_)));
-
- // Opening the plaintext with the wrong opener should fail.
- let mut sk_rm_prime = sk.secret_bytes().to_vec();
- sk_rm_prime[10] ^= 0xFF; // Corrupt a byte of the private key.
- let mut opener_two = suite
- .setup_opener(&enc, info, &HpkePrivateKey::from(sk_rm_prime))
- .unwrap();
- let open_res = opener_two.open(aad, &ct);
- assert!(matches!(open_res.unwrap_err(), Error::Other(_)));
- }
- }
-
- #[cfg(not(feature = "fips"))] // Ensure all supported suites are available to test.
- #[test]
- fn test_fips() {
- let testcases: &[(&dyn Hpke, bool)] = &[
- // FIPS compatible.
- (DH_KEM_P256_HKDF_SHA256_AES_128, true),
- (DH_KEM_P256_HKDF_SHA256_AES_256, true),
- (DH_KEM_P384_HKDF_SHA384_AES_128, true),
- (DH_KEM_P384_HKDF_SHA384_AES_256, true),
- (DH_KEM_P521_HKDF_SHA512_AES_128, true),
- (DH_KEM_P521_HKDF_SHA512_AES_256, true),
- // AEAD is not FIPS compatible.
- (DH_KEM_P256_HKDF_SHA256_CHACHA20_POLY1305, false),
- (DH_KEM_P384_HKDF_SHA384_CHACHA20_POLY1305, false),
- (DH_KEM_P521_HKDF_SHA512_CHACHA20_POLY1305, false),
- // KEM is not FIPS compatible.
- (DH_KEM_X25519_HKDF_SHA256_AES_128, false),
- (DH_KEM_X25519_HKDF_SHA256_AES_256, false),
- (DH_KEM_X25519_HKDF_SHA256_CHACHA20_POLY1305, false),
- ];
- for (suite, expected) in testcases {
- assert_eq!(suite.fips(), *expected);
- }
- }
-}
-
-#[cfg(test)]
-mod rfc_tests {
- use alloc::string::String;
- use std::fs::File;
- use std::println;
-
- use serde::Deserialize;
-
- use super::*;
-
- /// Confirm open/seal operations work using the test vectors from [RFC 9180 Appendix A].
- ///
- /// [RFC 9180 Appendix A]: https://www.rfc-editor.org/rfc/rfc9180#TestVectors
- #[test]
- fn check_test_vectors() {
- for (idx, vec) in test_vectors().into_iter().enumerate() {
- let Some(hpke) = vec.applicable() else {
- println!("skipping inapplicable vector {idx}");
- continue;
- };
-
- println!("testing vector {idx}");
- let pk_r = HpkePublicKey(hex::decode(vec.pk_rm).unwrap());
- let sk_r = HpkePrivateKey::from(hex::decode(vec.sk_rm).unwrap());
- let sk_em = hex::decode(vec.sk_em).unwrap();
- let info = hex::decode(vec.info).unwrap();
- let expected_enc = hex::decode(vec.enc).unwrap();
-
- let (enc, mut sealer) = hpke
- .setup_test_sealer(&info, &pk_r, &sk_em)
- .unwrap();
- assert_eq!(enc.0, expected_enc);
-
- let mut opener = hpke
- .setup_opener(&enc, &info, &sk_r)
- .unwrap();
-
- for test_encryption in vec.encryptions {
- let aad = hex::decode(test_encryption.aad).unwrap();
- let pt = hex::decode(test_encryption.pt).unwrap();
- let expected_ct = hex::decode(test_encryption.ct).unwrap();
-
- let ciphertext = sealer.seal(&aad, &pt).unwrap();
- assert_eq!(ciphertext, expected_ct);
-
- let plaintext = opener.open(&aad, &ciphertext).unwrap();
- assert_eq!(plaintext, pt);
- }
- }
- }
-
- trait TestHpke: Hpke {
- fn setup_test_sealer(
- &self,
- info: &[u8],
- pub_key: &HpkePublicKey,
- sk_em: &[u8],
- ) -> Result<(EncapsulatedSecret, Box<dyn HpkeSealer + 'static>), Error>;
- }
-
- impl<const KEY_SIZE: usize, const KDF_SIZE: usize> TestHpke for HpkeAwsLcRs<KEY_SIZE, KDF_SIZE> {
- fn setup_test_sealer(
- &self,
- info: &[u8],
- pub_key: &HpkePublicKey,
- sk_em: &[u8],
- ) -> Result<(EncapsulatedSecret, Box<dyn HpkeSealer + 'static>), Error> {
- let (encap, sealer) = Sealer::test_only_new(self, info, pub_key, sk_em)?;
- Ok((encap, Box::new(sealer)))
- }
- }
-
- static TEST_SUITES: &[&dyn TestHpke] = &[
- DH_KEM_P256_HKDF_SHA256_AES_128,
- DH_KEM_P256_HKDF_SHA256_AES_256,
- #[cfg(not(feature = "fips"))]
- DH_KEM_P256_HKDF_SHA256_CHACHA20_POLY1305,
- DH_KEM_P384_HKDF_SHA384_AES_128,
- DH_KEM_P384_HKDF_SHA384_AES_256,
- #[cfg(not(feature = "fips"))]
- DH_KEM_P384_HKDF_SHA384_CHACHA20_POLY1305,
- DH_KEM_P521_HKDF_SHA512_AES_128,
- DH_KEM_P521_HKDF_SHA512_AES_256,
- #[cfg(not(feature = "fips"))]
- DH_KEM_P521_HKDF_SHA512_CHACHA20_POLY1305,
- #[cfg(not(feature = "fips"))]
- DH_KEM_X25519_HKDF_SHA256_AES_128,
- #[cfg(not(feature = "fips"))]
- DH_KEM_X25519_HKDF_SHA256_AES_256,
- #[cfg(not(feature = "fips"))]
- DH_KEM_X25519_HKDF_SHA256_CHACHA20_POLY1305,
- ];
-
- #[derive(Deserialize, Debug)]
- struct TestVector {
- mode: u8,
- kem_id: u16,
- kdf_id: u16,
- aead_id: u16,
- info: String,
- #[serde(rename(deserialize = "pkRm"))]
- pk_rm: String,
- #[serde(rename(deserialize = "skRm"))]
- sk_rm: String,
- #[serde(rename(deserialize = "skEm"))]
- sk_em: String,
- enc: String,
- encryptions: Vec<TestEncryption>,
- }
-
- #[derive(Deserialize, Debug)]
- struct TestEncryption {
- aad: String,
- pt: String,
- ct: String,
- }
-
- impl TestVector {
- fn suite(&self) -> HpkeSuite {
- HpkeSuite {
- kem: HpkeKem::from(self.kem_id),
- sym: HpkeSymmetricCipherSuite {
- kdf_id: HpkeKdf::from(self.kdf_id),
- aead_id: HpkeAead::from(self.aead_id),
- },
- }
- }
-
- fn applicable(&self) -> Option<&'static dyn TestHpke> {
- // Only base mode test vectors for supported suites are applicable.
- if self.mode != 0 {
- return None;
- }
-
- Self::lookup_suite(self.suite(), TEST_SUITES)
- }
-
- fn lookup_suite(
- suite: HpkeSuite,
- supported: &[&'static dyn TestHpke],
- ) -> Option<&'static dyn TestHpke> {
- supported
- .iter()
- .find(|s| s.suite() == suite)
- .copied()
- }
- }
-
- fn test_vectors() -> Vec<TestVector> {
- serde_json::from_reader(
- &mut File::open("../rustls-provider-test/tests/rfc-9180-test-vectors.json")
- .expect("failed to open test vectors data file"),
- )
- .expect("failed to deserialize test vectors")
- }
-}
diff --git a/vendor/rustls/src/crypto/aws_lc_rs/mod.rs b/vendor/rustls/src/crypto/aws_lc_rs/mod.rs
deleted file mode 100644
index 1a7d2263..00000000
--- a/vendor/rustls/src/crypto/aws_lc_rs/mod.rs
+++ /dev/null
@@ -1,318 +0,0 @@
-use alloc::vec::Vec;
-
-// aws-lc-rs has a -- roughly -- ring-compatible API, so we just reuse all that
-// glue here. The shared files should always use `super::ring_like` to access a
-// ring-compatible crate, and `super::ring_shim` to bridge the gaps where they are
-// small.
-pub(crate) use aws_lc_rs as ring_like;
-use pki_types::PrivateKeyDer;
-use webpki::aws_lc_rs as webpki_algs;
-
-use crate::crypto::{CryptoProvider, KeyProvider, SecureRandom, SupportedKxGroup};
-use crate::enums::SignatureScheme;
-use crate::rand::GetRandomFailed;
-use crate::sign::SigningKey;
-use crate::suites::SupportedCipherSuite;
-use crate::sync::Arc;
-use crate::webpki::WebPkiSupportedAlgorithms;
-use crate::{Error, OtherError};
-
-/// Hybrid public key encryption (HPKE).
-pub mod hpke;
-/// Post-quantum secure algorithms.
-pub(crate) mod pq;
-/// Using software keys for authentication.
-pub mod sign;
-
-#[path = "../ring/hash.rs"]
-pub(crate) mod hash;
-#[path = "../ring/hmac.rs"]
-pub(crate) mod hmac;
-#[path = "../ring/kx.rs"]
-pub(crate) mod kx;
-#[path = "../ring/quic.rs"]
-pub(crate) mod quic;
-#[cfg(feature = "std")]
-pub(crate) mod ticketer;
-#[cfg(feature = "tls12")]
-pub(crate) mod tls12;
-pub(crate) mod tls13;
-
-/// A `CryptoProvider` backed by aws-lc-rs.
-pub fn default_provider() -> CryptoProvider {
- CryptoProvider {
- cipher_suites: DEFAULT_CIPHER_SUITES.to_vec(),
- kx_groups: default_kx_groups(),
- signature_verification_algorithms: SUPPORTED_SIG_ALGS,
- secure_random: &AwsLcRs,
- key_provider: &AwsLcRs,
- }
-}
-
-fn default_kx_groups() -> Vec<&'static dyn SupportedKxGroup> {
- #[cfg(feature = "fips")]
- {
- DEFAULT_KX_GROUPS
- .iter()
- .filter(|cs| cs.fips())
- .copied()
- .collect()
- }
- #[cfg(not(feature = "fips"))]
- {
- DEFAULT_KX_GROUPS.to_vec()
- }
-}
-
-#[derive(Debug)]
-struct AwsLcRs;
-
-impl SecureRandom for AwsLcRs {
- fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed> {
- use ring_like::rand::SecureRandom;
-
- ring_like::rand::SystemRandom::new()
- .fill(buf)
- .map_err(|_| GetRandomFailed)
- }
-
- fn fips(&self) -> bool {
- fips()
- }
-}
-
-impl KeyProvider for AwsLcRs {
- fn load_private_key(
- &self,
- key_der: PrivateKeyDer<'static>,
- ) -> Result<Arc<dyn SigningKey>, Error> {
- sign::any_supported_type(&key_der)
- }
-
- fn fips(&self) -> bool {
- fips()
- }
-}
-
-/// The cipher suite configuration that an application should use by default.
-///
-/// This will be [`ALL_CIPHER_SUITES`] sans any supported cipher suites that
-/// shouldn't be enabled by most applications.
-pub static DEFAULT_CIPHER_SUITES: &[SupportedCipherSuite] = &[
- // TLS1.3 suites
- tls13::TLS13_AES_256_GCM_SHA384,
- tls13::TLS13_AES_128_GCM_SHA256,
- #[cfg(not(feature = "fips"))]
- tls13::TLS13_CHACHA20_POLY1305_SHA256,
- // TLS1.2 suites
- #[cfg(feature = "tls12")]
- tls12::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
- #[cfg(feature = "tls12")]
- tls12::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- #[cfg(all(feature = "tls12", not(feature = "fips")))]
- tls12::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
- #[cfg(feature = "tls12")]
- tls12::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
- #[cfg(feature = "tls12")]
- tls12::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- #[cfg(all(feature = "tls12", not(feature = "fips")))]
- tls12::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-];
-
-/// A list of all the cipher suites supported by the rustls aws-lc-rs provider.
-pub static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = &[
- // TLS1.3 suites
- tls13::TLS13_AES_256_GCM_SHA384,
- tls13::TLS13_AES_128_GCM_SHA256,
- tls13::TLS13_CHACHA20_POLY1305_SHA256,
- // TLS1.2 suites
- #[cfg(feature = "tls12")]
- tls12::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
- #[cfg(feature = "tls12")]
- tls12::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- #[cfg(feature = "tls12")]
- tls12::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
- #[cfg(feature = "tls12")]
- tls12::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
- #[cfg(feature = "tls12")]
- tls12::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- #[cfg(feature = "tls12")]
- tls12::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-];
-
-/// All defined cipher suites supported by aws-lc-rs appear in this module.
-pub mod cipher_suite {
- #[cfg(feature = "tls12")]
- pub use super::tls12::{
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 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,
- };
- pub use super::tls13::{
- TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384, TLS13_CHACHA20_POLY1305_SHA256,
- };
-}
-
-/// A `WebPkiSupportedAlgorithms` value that reflects webpki's capabilities when
-/// compiled against aws-lc-rs.
-static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms {
- all: &[
- webpki_algs::ECDSA_P256_SHA256,
- webpki_algs::ECDSA_P256_SHA384,
- webpki_algs::ECDSA_P384_SHA256,
- webpki_algs::ECDSA_P384_SHA384,
- webpki_algs::ECDSA_P521_SHA256,
- webpki_algs::ECDSA_P521_SHA384,
- webpki_algs::ECDSA_P521_SHA512,
- webpki_algs::ED25519,
- webpki_algs::RSA_PSS_2048_8192_SHA256_LEGACY_KEY,
- webpki_algs::RSA_PSS_2048_8192_SHA384_LEGACY_KEY,
- webpki_algs::RSA_PSS_2048_8192_SHA512_LEGACY_KEY,
- webpki_algs::RSA_PKCS1_2048_8192_SHA256,
- webpki_algs::RSA_PKCS1_2048_8192_SHA384,
- webpki_algs::RSA_PKCS1_2048_8192_SHA512,
- webpki_algs::RSA_PKCS1_2048_8192_SHA256_ABSENT_PARAMS,
- webpki_algs::RSA_PKCS1_2048_8192_SHA384_ABSENT_PARAMS,
- webpki_algs::RSA_PKCS1_2048_8192_SHA512_ABSENT_PARAMS,
- ],
- mapping: &[
- // Note: for TLS1.2 the curve is not fixed by SignatureScheme. For TLS1.3 it is.
- (
- SignatureScheme::ECDSA_NISTP384_SHA384,
- &[
- webpki_algs::ECDSA_P384_SHA384,
- webpki_algs::ECDSA_P256_SHA384,
- webpki_algs::ECDSA_P521_SHA384,
- ],
- ),
- (
- SignatureScheme::ECDSA_NISTP256_SHA256,
- &[
- webpki_algs::ECDSA_P256_SHA256,
- webpki_algs::ECDSA_P384_SHA256,
- webpki_algs::ECDSA_P521_SHA256,
- ],
- ),
- (
- SignatureScheme::ECDSA_NISTP521_SHA512,
- &[webpki_algs::ECDSA_P521_SHA512],
- ),
- (SignatureScheme::ED25519, &[webpki_algs::ED25519]),
- (
- SignatureScheme::RSA_PSS_SHA512,
- &[webpki_algs::RSA_PSS_2048_8192_SHA512_LEGACY_KEY],
- ),
- (
- SignatureScheme::RSA_PSS_SHA384,
- &[webpki_algs::RSA_PSS_2048_8192_SHA384_LEGACY_KEY],
- ),
- (
- SignatureScheme::RSA_PSS_SHA256,
- &[webpki_algs::RSA_PSS_2048_8192_SHA256_LEGACY_KEY],
- ),
- (
- SignatureScheme::RSA_PKCS1_SHA512,
- &[webpki_algs::RSA_PKCS1_2048_8192_SHA512],
- ),
- (
- SignatureScheme::RSA_PKCS1_SHA384,
- &[webpki_algs::RSA_PKCS1_2048_8192_SHA384],
- ),
- (
- SignatureScheme::RSA_PKCS1_SHA256,
- &[webpki_algs::RSA_PKCS1_2048_8192_SHA256],
- ),
- ],
-};
-
-/// All defined key exchange groups supported by aws-lc-rs appear in this module.
-///
-/// [`ALL_KX_GROUPS`] is provided as an array of all of these values.
-/// [`DEFAULT_KX_GROUPS`] is provided as an array of this provider's defaults.
-pub mod kx_group {
- pub use super::kx::{SECP256R1, SECP384R1, X25519};
- pub use super::pq::{MLKEM768, SECP256R1MLKEM768, X25519MLKEM768};
-}
-
-/// A list of the default key exchange groups supported by this provider.
-///
-/// This does not contain MLKEM768; by default MLKEM768 is only offered
-/// in hybrid with X25519.
-pub static DEFAULT_KX_GROUPS: &[&dyn SupportedKxGroup] = &[
- #[cfg(feature = "prefer-post-quantum")]
- kx_group::X25519MLKEM768,
- kx_group::X25519,
- kx_group::SECP256R1,
- kx_group::SECP384R1,
- #[cfg(not(feature = "prefer-post-quantum"))]
- kx_group::X25519MLKEM768,
-];
-
-/// A list of all the key exchange groups supported by this provider.
-pub static ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[
- #[cfg(feature = "prefer-post-quantum")]
- kx_group::X25519MLKEM768,
- #[cfg(feature = "prefer-post-quantum")]
- kx_group::SECP256R1MLKEM768,
- kx_group::X25519,
- kx_group::SECP256R1,
- kx_group::SECP384R1,
- #[cfg(not(feature = "prefer-post-quantum"))]
- kx_group::X25519MLKEM768,
- #[cfg(not(feature = "prefer-post-quantum"))]
- kx_group::SECP256R1MLKEM768,
- kx_group::MLKEM768,
-];
-
-#[cfg(feature = "std")]
-pub use ticketer::Ticketer;
-
-/// Compatibility shims between ring 0.16.x and 0.17.x API
-mod ring_shim {
- use super::ring_like;
- use crate::crypto::SharedSecret;
-
- pub(super) fn agree_ephemeral(
- priv_key: ring_like::agreement::EphemeralPrivateKey,
- peer_key: &ring_like::agreement::UnparsedPublicKey<&[u8]>,
- ) -> Result<SharedSecret, ()> {
- ring_like::agreement::agree_ephemeral(priv_key, peer_key, (), |secret| {
- Ok(SharedSecret::from(secret))
- })
- }
-}
-
-/// Are we in FIPS mode?
-pub(super) fn fips() -> bool {
- aws_lc_rs::try_fips_mode().is_ok()
-}
-
-pub(super) fn unspecified_err(_e: aws_lc_rs::error::Unspecified) -> Error {
- #[cfg(feature = "std")]
- {
- Error::Other(OtherError(Arc::new(_e)))
- }
- #[cfg(not(feature = "std"))]
- {
- Error::Other(OtherError())
- }
-}
-
-#[cfg(test)]
-mod tests {
- #[cfg(feature = "fips")]
- #[test]
- fn default_suites_are_fips() {
- assert!(
- super::DEFAULT_CIPHER_SUITES
- .iter()
- .all(|scs| scs.fips())
- );
- }
-
- #[cfg(not(feature = "fips"))]
- #[test]
- fn default_suites() {
- assert_eq!(super::DEFAULT_CIPHER_SUITES, super::ALL_CIPHER_SUITES);
- }
-}
diff --git a/vendor/rustls/src/crypto/aws_lc_rs/pq/hybrid.rs b/vendor/rustls/src/crypto/aws_lc_rs/pq/hybrid.rs
deleted file mode 100644
index 8e30d782..00000000
--- a/vendor/rustls/src/crypto/aws_lc_rs/pq/hybrid.rs
+++ /dev/null
@@ -1,205 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec::Vec;
-
-use super::INVALID_KEY_SHARE;
-use crate::crypto::{ActiveKeyExchange, CompletedKeyExchange, SharedSecret, SupportedKxGroup};
-use crate::ffdhe_groups::FfdheGroup;
-use crate::{Error, NamedGroup, ProtocolVersion};
-
-/// A generalization of hybrid key exchange.
-#[derive(Debug)]
-pub(crate) struct Hybrid {
- pub(crate) classical: &'static dyn SupportedKxGroup,
- pub(crate) post_quantum: &'static dyn SupportedKxGroup,
- pub(crate) name: NamedGroup,
- pub(crate) layout: Layout,
-}
-
-impl SupportedKxGroup for Hybrid {
- fn start(&self) -> Result<Box<dyn ActiveKeyExchange>, Error> {
- let classical = self.classical.start()?;
- let post_quantum = self.post_quantum.start()?;
-
- let combined_pub_key = self
- .layout
- .concat(post_quantum.pub_key(), classical.pub_key());
-
- Ok(Box::new(ActiveHybrid {
- classical,
- post_quantum,
- name: self.name,
- layout: self.layout,
- combined_pub_key,
- }))
- }
-
- fn start_and_complete(&self, client_share: &[u8]) -> Result<CompletedKeyExchange, Error> {
- let (post_quantum_share, classical_share) = self
- .layout
- .split_received_client_share(client_share)
- .ok_or(INVALID_KEY_SHARE)?;
-
- let cl = self
- .classical
- .start_and_complete(classical_share)?;
- let pq = self
- .post_quantum
- .start_and_complete(post_quantum_share)?;
-
- let combined_pub_key = self
- .layout
- .concat(&pq.pub_key, &cl.pub_key);
- let secret = self
- .layout
- .concat(pq.secret.secret_bytes(), cl.secret.secret_bytes());
-
- Ok(CompletedKeyExchange {
- group: self.name,
- pub_key: combined_pub_key,
- secret: SharedSecret::from(secret),
- })
- }
-
- fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
- None
- }
-
- fn name(&self) -> NamedGroup {
- self.name
- }
-
- fn fips(&self) -> bool {
- // Behold! The Night Mare: SP800-56C rev 2:
- //
- // "In addition to the currently approved techniques for the generation of the
- // shared secret Z as specified in SP 800-56A and SP 800-56B, this Recommendation
- // permits the use of a "hybrid" shared secret of the form Z′ = Z || T, a
- // concatenation consisting of a "standard" shared secret Z that was generated
- // during the execution of a key-establishment scheme (as currently specified in
- // [SP 800-56A] or [SP 800-56B])"
- //
- // NIST plan to adjust this and allow both orders: see
- // <https://csrc.nist.gov/pubs/sp/800/227/ipd> (Jan 2025) lines 1070-1080.
- //
- // But, for now, we follow the SP800-56C logic: the element appearing first is the
- // one that controls approval.
- match self.layout.post_quantum_first {
- true => self.post_quantum.fips(),
- false => self.classical.fips(),
- }
- }
-
- fn usable_for_version(&self, version: ProtocolVersion) -> bool {
- version == ProtocolVersion::TLSv1_3
- }
-}
-
-struct ActiveHybrid {
- classical: Box<dyn ActiveKeyExchange>,
- post_quantum: Box<dyn ActiveKeyExchange>,
- name: NamedGroup,
- layout: Layout,
- combined_pub_key: Vec<u8>,
-}
-
-impl ActiveKeyExchange for ActiveHybrid {
- fn complete(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, Error> {
- let (post_quantum_share, classical_share) = self
- .layout
- .split_received_server_share(peer_pub_key)
- .ok_or(INVALID_KEY_SHARE)?;
-
- let cl = self
- .classical
- .complete(classical_share)?;
- let pq = self
- .post_quantum
- .complete(post_quantum_share)?;
-
- let secret = self
- .layout
- .concat(pq.secret_bytes(), cl.secret_bytes());
- Ok(SharedSecret::from(secret))
- }
-
- /// Allow the classical computation to be offered and selected separately.
- fn hybrid_component(&self) -> Option<(NamedGroup, &[u8])> {
- Some((self.classical.group(), self.classical.pub_key()))
- }
-
- fn complete_hybrid_component(
- self: Box<Self>,
- peer_pub_key: &[u8],
- ) -> Result<SharedSecret, Error> {
- self.classical.complete(peer_pub_key)
- }
-
- fn pub_key(&self) -> &[u8] {
- &self.combined_pub_key
- }
-
- fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
- None
- }
-
- fn group(&self) -> NamedGroup {
- self.name
- }
-}
-
-#[derive(Clone, Copy, Debug)]
-pub(crate) struct Layout {
- /// Length of classical key share.
- pub(crate) classical_share_len: usize,
-
- /// Length of post-quantum key share sent by client
- pub(crate) post_quantum_client_share_len: usize,
-
- /// Length of post-quantum key share sent by server
- pub(crate) post_quantum_server_share_len: usize,
-
- /// Whether the post-quantum element comes first in shares and secrets.
- ///
- /// For dismal and unprincipled reasons, SECP256R1MLKEM768 has the
- /// classical element first, while X25519MLKEM768 has it second.
- pub(crate) post_quantum_first: bool,
-}
-
-impl Layout {
- fn split_received_client_share<'a>(&self, share: &'a [u8]) -> Option<(&'a [u8], &'a [u8])> {
- self.split(share, self.post_quantum_client_share_len)
- }
-
- fn split_received_server_share<'a>(&self, share: &'a [u8]) -> Option<(&'a [u8], &'a [u8])> {
- self.split(share, self.post_quantum_server_share_len)
- }
-
- /// Return the PQ and classical component of a key share.
- fn split<'a>(
- &self,
- share: &'a [u8],
- post_quantum_share_len: usize,
- ) -> Option<(&'a [u8], &'a [u8])> {
- if share.len() != self.classical_share_len + post_quantum_share_len {
- return None;
- }
-
- Some(match self.post_quantum_first {
- true => {
- let (first_share, second_share) = share.split_at(post_quantum_share_len);
- (first_share, second_share)
- }
- false => {
- let (first_share, second_share) = share.split_at(self.classical_share_len);
- (second_share, first_share)
- }
- })
- }
-
- fn concat(&self, post_quantum: &[u8], classical: &[u8]) -> Vec<u8> {
- match self.post_quantum_first {
- true => [post_quantum, classical].concat(),
- false => [classical, post_quantum].concat(),
- }
- }
-}
diff --git a/vendor/rustls/src/crypto/aws_lc_rs/pq/mlkem.rs b/vendor/rustls/src/crypto/aws_lc_rs/pq/mlkem.rs
deleted file mode 100644
index fa2be078..00000000
--- a/vendor/rustls/src/crypto/aws_lc_rs/pq/mlkem.rs
+++ /dev/null
@@ -1,103 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec::Vec;
-
-use aws_lc_rs::kem;
-
-use super::INVALID_KEY_SHARE;
-use crate::crypto::{ActiveKeyExchange, CompletedKeyExchange, SharedSecret, SupportedKxGroup};
-use crate::ffdhe_groups::FfdheGroup;
-use crate::{Error, NamedGroup, ProtocolVersion};
-
-#[derive(Debug)]
-pub(crate) struct MlKem768;
-
-impl SupportedKxGroup for MlKem768 {
- fn start(&self) -> Result<Box<dyn ActiveKeyExchange>, Error> {
- let decaps_key = kem::DecapsulationKey::generate(&kem::ML_KEM_768)
- .map_err(|_| Error::General("key generation failed".into()))?;
-
- let pub_key_bytes = decaps_key
- .encapsulation_key()
- .and_then(|encaps_key| encaps_key.key_bytes())
- .map_err(|_| Error::General("encaps failed".into()))?;
-
- Ok(Box::new(Active {
- decaps_key: Box::new(decaps_key),
- encaps_key_bytes: Vec::from(pub_key_bytes.as_ref()),
- }))
- }
-
- fn start_and_complete(&self, client_share: &[u8]) -> Result<CompletedKeyExchange, Error> {
- let encaps_key = kem::EncapsulationKey::new(&kem::ML_KEM_768, client_share)
- .map_err(|_| INVALID_KEY_SHARE)?;
-
- let (ciphertext, shared_secret) = encaps_key
- .encapsulate()
- .map_err(|_| INVALID_KEY_SHARE)?;
-
- Ok(CompletedKeyExchange {
- group: self.name(),
- pub_key: Vec::from(ciphertext.as_ref()),
- secret: SharedSecret::from(shared_secret.as_ref()),
- })
- }
-
- fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
- None
- }
-
- fn name(&self) -> NamedGroup {
- NamedGroup::MLKEM768
- }
-
- fn fips(&self) -> bool {
- // AUDITORS:
- // At the time of writing, the ML-KEM implementation in AWS-LC-FIPS module 3.0
- // is FIPS-pending. Some regulatory regimes (eg, FedRAMP rev 5 SC-13) allow
- // use of implementations in this state, as if they are already approved.
- //
- // We follow this liberal interpretation, and say MlKem768 is FIPS-compliant
- // if the underlying library is in FIPS mode.
- //
- // TODO: adjust the `fips()` function return type to allow more policies to
- // be expressed, perhaps following something like
- // <https://github.com/golang/go/issues/70200#issuecomment-2490017956> --
- // see <https://github.com/rustls/rustls/issues/2309>
- super::super::fips()
- }
-
- fn usable_for_version(&self, version: ProtocolVersion) -> bool {
- version == ProtocolVersion::TLSv1_3
- }
-}
-
-struct Active {
- decaps_key: Box<kem::DecapsulationKey<kem::AlgorithmId>>,
- encaps_key_bytes: Vec<u8>,
-}
-
-impl ActiveKeyExchange for Active {
- // The received 'peer_pub_key' is actually the ML-KEM ciphertext,
- // which when decapsulated with our `decaps_key` produces the shared
- // secret.
- fn complete(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, Error> {
- let shared_secret = self
- .decaps_key
- .decapsulate(peer_pub_key.into())
- .map_err(|_| INVALID_KEY_SHARE)?;
-
- Ok(SharedSecret::from(shared_secret.as_ref()))
- }
-
- fn pub_key(&self) -> &[u8] {
- &self.encaps_key_bytes
- }
-
- fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
- None
- }
-
- fn group(&self) -> NamedGroup {
- NamedGroup::MLKEM768
- }
-}
diff --git a/vendor/rustls/src/crypto/aws_lc_rs/pq/mod.rs b/vendor/rustls/src/crypto/aws_lc_rs/pq/mod.rs
deleted file mode 100644
index a2252da5..00000000
--- a/vendor/rustls/src/crypto/aws_lc_rs/pq/mod.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-use crate::crypto::SupportedKxGroup;
-use crate::crypto::aws_lc_rs::kx_group;
-use crate::{Error, NamedGroup, PeerMisbehaved};
-
-mod hybrid;
-mod mlkem;
-
-/// This is the [X25519MLKEM768] key exchange.
-///
-/// [X25519MLKEM768]: <https://datatracker.ietf.org/doc/draft-ietf-tls-ecdhe-mlkem/>
-pub static X25519MLKEM768: &dyn SupportedKxGroup = &hybrid::Hybrid {
- classical: kx_group::X25519,
- post_quantum: MLKEM768,
- name: NamedGroup::X25519MLKEM768,
- layout: hybrid::Layout {
- classical_share_len: X25519_LEN,
- post_quantum_client_share_len: MLKEM768_ENCAP_LEN,
- post_quantum_server_share_len: MLKEM768_CIPHERTEXT_LEN,
- post_quantum_first: true,
- },
-};
-
-/// This is the [SECP256R1MLKEM768] key exchange.
-///
-/// [SECP256R1MLKEM768]: <https://datatracker.ietf.org/doc/draft-ietf-tls-ecdhe-mlkem/>
-pub static SECP256R1MLKEM768: &dyn SupportedKxGroup = &hybrid::Hybrid {
- classical: kx_group::SECP256R1,
- post_quantum: MLKEM768,
- name: NamedGroup::secp256r1MLKEM768,
- layout: hybrid::Layout {
- classical_share_len: SECP256R1_LEN,
- post_quantum_client_share_len: MLKEM768_ENCAP_LEN,
- post_quantum_server_share_len: MLKEM768_CIPHERTEXT_LEN,
- post_quantum_first: false,
- },
-};
-
-/// This is the [MLKEM] key exchange.
-///
-/// [MLKEM]: https://datatracker.ietf.org/doc/draft-connolly-tls-mlkem-key-agreement
-pub static MLKEM768: &dyn SupportedKxGroup = &mlkem::MlKem768;
-
-const INVALID_KEY_SHARE: Error = Error::PeerMisbehaved(PeerMisbehaved::InvalidKeyShare);
-
-const X25519_LEN: usize = 32;
-const SECP256R1_LEN: usize = 65;
-const MLKEM768_CIPHERTEXT_LEN: usize = 1088;
-const MLKEM768_ENCAP_LEN: usize = 1184;
diff --git a/vendor/rustls/src/crypto/aws_lc_rs/sign.rs b/vendor/rustls/src/crypto/aws_lc_rs/sign.rs
deleted file mode 100644
index 0c874abf..00000000
--- a/vendor/rustls/src/crypto/aws_lc_rs/sign.rs
+++ /dev/null
@@ -1,876 +0,0 @@
-#![allow(clippy::duplicate_mod)]
-
-use alloc::boxed::Box;
-use alloc::string::ToString;
-use alloc::vec::Vec;
-use alloc::{format, vec};
-use core::fmt::{self, Debug, Formatter};
-
-use pki_types::{PrivateKeyDer, PrivatePkcs8KeyDer, SubjectPublicKeyInfoDer, alg_id};
-
-use super::ring_like::rand::SystemRandom;
-use super::ring_like::signature::{self, EcdsaKeyPair, Ed25519KeyPair, KeyPair, RsaKeyPair};
-use crate::crypto::signer::{Signer, SigningKey, public_key_to_spki};
-use crate::enums::{SignatureAlgorithm, SignatureScheme};
-use crate::error::Error;
-use crate::sync::Arc;
-
-/// Parse `der` as any supported key encoding/type, returning
-/// the first which works.
-pub fn any_supported_type(der: &PrivateKeyDer<'_>) -> Result<Arc<dyn SigningKey>, Error> {
- if let Ok(rsa) = RsaSigningKey::new(der) {
- return Ok(Arc::new(rsa));
- }
-
- if let Ok(ecdsa) = any_ecdsa_type(der) {
- return Ok(ecdsa);
- }
-
- if let PrivateKeyDer::Pkcs8(pkcs8) = der {
- if let Ok(eddsa) = any_eddsa_type(pkcs8) {
- return Ok(eddsa);
- }
- }
-
- Err(Error::General(
- "failed to parse private key as RSA, ECDSA, or EdDSA".into(),
- ))
-}
-
-/// Parse `der` as any ECDSA key type, returning the first which works.
-///
-/// Both SEC1 (PEM section starting with 'BEGIN EC PRIVATE KEY') and PKCS8
-/// (PEM section starting with 'BEGIN PRIVATE KEY') encodings are supported.
-pub fn any_ecdsa_type(der: &PrivateKeyDer<'_>) -> Result<Arc<dyn SigningKey>, Error> {
- if let Ok(ecdsa_p256) = EcdsaSigningKey::new(
- der,
- SignatureScheme::ECDSA_NISTP256_SHA256,
- &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
- ) {
- return Ok(Arc::new(ecdsa_p256));
- }
-
- if let Ok(ecdsa_p384) = EcdsaSigningKey::new(
- der,
- SignatureScheme::ECDSA_NISTP384_SHA384,
- &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
- ) {
- return Ok(Arc::new(ecdsa_p384));
- }
-
- if let Ok(ecdsa_p521) = EcdsaSigningKey::new(
- der,
- SignatureScheme::ECDSA_NISTP521_SHA512,
- &signature::ECDSA_P521_SHA512_ASN1_SIGNING,
- ) {
- return Ok(Arc::new(ecdsa_p521));
- }
-
- Err(Error::General(
- "failed to parse ECDSA private key as PKCS#8 or SEC1".into(),
- ))
-}
-
-/// Parse `der` as any EdDSA key type, returning the first which works.
-///
-/// Note that, at the time of writing, Ed25519 does not have wide support
-/// in browsers. It is also not supported by the WebPKI, because the
-/// CA/Browser Forum Baseline Requirements do not support it for publicly
-/// trusted certificates.
-pub fn any_eddsa_type(der: &PrivatePkcs8KeyDer<'_>) -> Result<Arc<dyn SigningKey>, Error> {
- // TODO: Add support for Ed448
- Ok(Arc::new(Ed25519SigningKey::new(
- der,
- SignatureScheme::ED25519,
- )?))
-}
-
-/// A `SigningKey` for RSA-PKCS1 or RSA-PSS.
-///
-/// This is used by the test suite, so it must be `pub`, but it isn't part of
-/// the public, stable, API.
-#[doc(hidden)]
-pub struct RsaSigningKey {
- key: Arc<RsaKeyPair>,
-}
-
-static ALL_RSA_SCHEMES: &[SignatureScheme] = &[
- SignatureScheme::RSA_PSS_SHA512,
- SignatureScheme::RSA_PSS_SHA384,
- SignatureScheme::RSA_PSS_SHA256,
- SignatureScheme::RSA_PKCS1_SHA512,
- SignatureScheme::RSA_PKCS1_SHA384,
- SignatureScheme::RSA_PKCS1_SHA256,
-];
-
-impl RsaSigningKey {
- /// Make a new `RsaSigningKey` from a DER encoding, in either
- /// PKCS#1 or PKCS#8 format.
- pub fn new(der: &PrivateKeyDer<'_>) -> Result<Self, Error> {
- let key_pair = match der {
- PrivateKeyDer::Pkcs1(pkcs1) => RsaKeyPair::from_der(pkcs1.secret_pkcs1_der()),
- PrivateKeyDer::Pkcs8(pkcs8) => RsaKeyPair::from_pkcs8(pkcs8.secret_pkcs8_der()),
- _ => {
- return Err(Error::General(
- "failed to parse RSA private key as either PKCS#1 or PKCS#8".into(),
- ));
- }
- }
- .map_err(|key_rejected| {
- Error::General(format!("failed to parse RSA private key: {key_rejected}"))
- })?;
-
- Ok(Self {
- key: Arc::new(key_pair),
- })
- }
-}
-
-impl SigningKey for RsaSigningKey {
- fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
- ALL_RSA_SCHEMES
- .iter()
- .find(|scheme| offered.contains(scheme))
- .map(|scheme| RsaSigner::new(self.key.clone(), *scheme))
- }
-
- fn public_key(&self) -> Option<SubjectPublicKeyInfoDer<'_>> {
- Some(public_key_to_spki(
- &alg_id::RSA_ENCRYPTION,
- self.key.public_key(),
- ))
- }
-
- fn algorithm(&self) -> SignatureAlgorithm {
- SignatureAlgorithm::RSA
- }
-}
-
-impl Debug for RsaSigningKey {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- f.debug_struct("RsaSigningKey")
- .field("algorithm", &self.algorithm())
- .finish()
- }
-}
-
-struct RsaSigner {
- key: Arc<RsaKeyPair>,
- scheme: SignatureScheme,
- encoding: &'static dyn signature::RsaEncoding,
-}
-
-impl RsaSigner {
- fn new(key: Arc<RsaKeyPair>, scheme: SignatureScheme) -> Box<dyn Signer> {
- let encoding: &dyn signature::RsaEncoding = match scheme {
- SignatureScheme::RSA_PKCS1_SHA256 => &signature::RSA_PKCS1_SHA256,
- SignatureScheme::RSA_PKCS1_SHA384 => &signature::RSA_PKCS1_SHA384,
- SignatureScheme::RSA_PKCS1_SHA512 => &signature::RSA_PKCS1_SHA512,
- SignatureScheme::RSA_PSS_SHA256 => &signature::RSA_PSS_SHA256,
- SignatureScheme::RSA_PSS_SHA384 => &signature::RSA_PSS_SHA384,
- SignatureScheme::RSA_PSS_SHA512 => &signature::RSA_PSS_SHA512,
- _ => unreachable!(),
- };
-
- Box::new(Self {
- key,
- scheme,
- encoding,
- })
- }
-}
-
-impl Signer for RsaSigner {
- fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
- let mut sig = vec![0; self.key.public_modulus_len()];
-
- let rng = SystemRandom::new();
- self.key
- .sign(self.encoding, &rng, message, &mut sig)
- .map(|_| sig)
- .map_err(|_| Error::General("signing failed".to_string()))
- }
-
- fn scheme(&self) -> SignatureScheme {
- self.scheme
- }
-}
-
-impl Debug for RsaSigner {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- f.debug_struct("RsaSigner")
- .field("scheme", &self.scheme)
- .finish()
- }
-}
-
-/// A SigningKey that uses exactly one TLS-level SignatureScheme
-/// and one ring-level signature::SigningAlgorithm.
-///
-/// Compare this to RsaSigningKey, which for a particular key is
-/// willing to sign with several algorithms. This is quite poor
-/// cryptography practice, but is necessary because a given RSA key
-/// is expected to work in TLS1.2 (PKCS#1 signatures) and TLS1.3
-/// (PSS signatures) -- nobody is willing to obtain certificates for
-/// different protocol versions.
-///
-/// Currently this is only implemented for ECDSA keys.
-struct EcdsaSigningKey {
- key: Arc<EcdsaKeyPair>,
- scheme: SignatureScheme,
-}
-
-impl EcdsaSigningKey {
- /// Make a new `ECDSASigningKey` from a DER encoding in PKCS#8 or SEC1
- /// format, expecting a key usable with precisely the given signature
- /// scheme.
- fn new(
- der: &PrivateKeyDer<'_>,
- scheme: SignatureScheme,
- sigalg: &'static signature::EcdsaSigningAlgorithm,
- ) -> Result<Self, ()> {
- let key_pair = match der {
- PrivateKeyDer::Sec1(sec1) => {
- EcdsaKeyPair::from_private_key_der(sigalg, sec1.secret_sec1_der())
- .map_err(|_| ())?
- }
- PrivateKeyDer::Pkcs8(pkcs8) => {
- EcdsaKeyPair::from_pkcs8(sigalg, pkcs8.secret_pkcs8_der()).map_err(|_| ())?
- }
- _ => return Err(()),
- };
-
- Ok(Self {
- key: Arc::new(key_pair),
- scheme,
- })
- }
-}
-
-impl SigningKey for EcdsaSigningKey {
- fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
- if offered.contains(&self.scheme) {
- Some(Box::new(EcdsaSigner {
- key: self.key.clone(),
- scheme: self.scheme,
- }))
- } else {
- None
- }
- }
-
- fn public_key(&self) -> Option<SubjectPublicKeyInfoDer<'_>> {
- let id = match self.scheme {
- SignatureScheme::ECDSA_NISTP256_SHA256 => alg_id::ECDSA_P256,
- SignatureScheme::ECDSA_NISTP384_SHA384 => alg_id::ECDSA_P384,
- SignatureScheme::ECDSA_NISTP521_SHA512 => alg_id::ECDSA_P521,
- _ => unreachable!(),
- };
-
- Some(public_key_to_spki(&id, self.key.public_key()))
- }
-
- fn algorithm(&self) -> SignatureAlgorithm {
- self.scheme.algorithm()
- }
-}
-
-impl Debug for EcdsaSigningKey {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- f.debug_struct("EcdsaSigningKey")
- .field("algorithm", &self.algorithm())
- .finish()
- }
-}
-
-struct EcdsaSigner {
- key: Arc<EcdsaKeyPair>,
- scheme: SignatureScheme,
-}
-
-impl Signer for EcdsaSigner {
- fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
- let rng = SystemRandom::new();
- self.key
- .sign(&rng, message)
- .map_err(|_| Error::General("signing failed".into()))
- .map(|sig| sig.as_ref().into())
- }
-
- fn scheme(&self) -> SignatureScheme {
- self.scheme
- }
-}
-
-impl Debug for EcdsaSigner {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- f.debug_struct("EcdsaSigner")
- .field("scheme", &self.scheme)
- .finish()
- }
-}
-
-/// A SigningKey that uses exactly one TLS-level SignatureScheme
-/// and one ring-level signature::SigningAlgorithm.
-///
-/// Compare this to RsaSigningKey, which for a particular key is
-/// willing to sign with several algorithms. This is quite poor
-/// cryptography practice, but is necessary because a given RSA key
-/// is expected to work in TLS1.2 (PKCS#1 signatures) and TLS1.3
-/// (PSS signatures) -- nobody is willing to obtain certificates for
-/// different protocol versions.
-///
-/// Currently this is only implemented for Ed25519 keys.
-struct Ed25519SigningKey {
- key: Arc<Ed25519KeyPair>,
- scheme: SignatureScheme,
-}
-
-impl Ed25519SigningKey {
- /// Make a new `Ed25519SigningKey` from a DER encoding in PKCS#8 format,
- /// expecting a key usable with precisely the given signature scheme.
- fn new(der: &PrivatePkcs8KeyDer<'_>, scheme: SignatureScheme) -> Result<Self, Error> {
- match Ed25519KeyPair::from_pkcs8_maybe_unchecked(der.secret_pkcs8_der()) {
- Ok(key_pair) => Ok(Self {
- key: Arc::new(key_pair),
- scheme,
- }),
- Err(e) => Err(Error::General(format!(
- "failed to parse Ed25519 private key: {e}"
- ))),
- }
- }
-}
-
-impl SigningKey for Ed25519SigningKey {
- fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
- if offered.contains(&self.scheme) {
- Some(Box::new(Ed25519Signer {
- key: self.key.clone(),
- scheme: self.scheme,
- }))
- } else {
- None
- }
- }
-
- fn public_key(&self) -> Option<SubjectPublicKeyInfoDer<'_>> {
- Some(public_key_to_spki(&alg_id::ED25519, self.key.public_key()))
- }
-
- fn algorithm(&self) -> SignatureAlgorithm {
- self.scheme.algorithm()
- }
-}
-
-impl Debug for Ed25519SigningKey {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- f.debug_struct("Ed25519SigningKey")
- .field("algorithm", &self.algorithm())
- .finish()
- }
-}
-
-struct Ed25519Signer {
- key: Arc<Ed25519KeyPair>,
- scheme: SignatureScheme,
-}
-
-impl Signer for Ed25519Signer {
- fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
- Ok(self.key.sign(message).as_ref().into())
- }
-
- fn scheme(&self) -> SignatureScheme {
- self.scheme
- }
-}
-
-impl Debug for Ed25519Signer {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- f.debug_struct("Ed25519Signer")
- .field("scheme", &self.scheme)
- .finish()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use alloc::format;
-
- use pki_types::{PrivatePkcs1KeyDer, PrivateSec1KeyDer};
-
- use super::*;
-
- #[test]
- fn can_load_ecdsa_nistp256_pkcs8() {
- let key =
- PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/nistp256key.pkcs8.der")[..]);
- assert!(any_eddsa_type(&key).is_err());
- let key = PrivateKeyDer::Pkcs8(key);
- assert!(any_supported_type(&key).is_ok());
- assert!(any_ecdsa_type(&key).is_ok());
- }
-
- #[test]
- fn can_load_ecdsa_nistp256_sec1() {
- let key = PrivateKeyDer::Sec1(PrivateSec1KeyDer::from(
- &include_bytes!("../../testdata/nistp256key.der")[..],
- ));
- assert!(any_supported_type(&key).is_ok());
- assert!(any_ecdsa_type(&key).is_ok());
- }
-
- #[test]
- fn can_sign_ecdsa_nistp256() {
- let key = PrivateKeyDer::Sec1(PrivateSec1KeyDer::from(
- &include_bytes!("../../testdata/nistp256key.der")[..],
- ));
-
- let k = any_supported_type(&key).unwrap();
- assert_eq!(format!("{k:?}"), "EcdsaSigningKey { algorithm: ECDSA }");
- assert_eq!(k.algorithm(), SignatureAlgorithm::ECDSA);
-
- assert!(
- k.choose_scheme(&[SignatureScheme::RSA_PKCS1_SHA256])
- .is_none()
- );
- assert!(
- k.choose_scheme(&[SignatureScheme::ECDSA_NISTP384_SHA384])
- .is_none()
- );
- let s = k
- .choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256])
- .unwrap();
- assert_eq!(
- format!("{s:?}"),
- "EcdsaSigner { scheme: ECDSA_NISTP256_SHA256 }"
- );
- assert_eq!(s.scheme(), SignatureScheme::ECDSA_NISTP256_SHA256);
- // nb. signature is variable length and asn.1-encoded
- assert!(
- s.sign(b"hello")
- .unwrap()
- .starts_with(&[0x30])
- );
- }
-
- #[test]
- fn can_load_ecdsa_nistp384_pkcs8() {
- let key =
- PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/nistp384key.pkcs8.der")[..]);
- assert!(any_eddsa_type(&key).is_err());
- let key = PrivateKeyDer::Pkcs8(key);
- assert!(any_supported_type(&key).is_ok());
- assert!(any_ecdsa_type(&key).is_ok());
- }
-
- #[test]
- fn can_load_ecdsa_nistp384_sec1() {
- let key = PrivateKeyDer::Sec1(PrivateSec1KeyDer::from(
- &include_bytes!("../../testdata/nistp384key.der")[..],
- ));
- assert!(any_supported_type(&key).is_ok());
- assert!(any_ecdsa_type(&key).is_ok());
- }
-
- #[test]
- fn can_sign_ecdsa_nistp384() {
- let key = PrivateKeyDer::Sec1(PrivateSec1KeyDer::from(
- &include_bytes!("../../testdata/nistp384key.der")[..],
- ));
-
- let k = any_supported_type(&key).unwrap();
- assert_eq!(format!("{k:?}"), "EcdsaSigningKey { algorithm: ECDSA }");
- assert_eq!(k.algorithm(), SignatureAlgorithm::ECDSA);
-
- assert!(
- k.choose_scheme(&[SignatureScheme::RSA_PKCS1_SHA256])
- .is_none()
- );
- assert!(
- k.choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256])
- .is_none()
- );
- let s = k
- .choose_scheme(&[SignatureScheme::ECDSA_NISTP384_SHA384])
- .unwrap();
- assert_eq!(
- format!("{s:?}"),
- "EcdsaSigner { scheme: ECDSA_NISTP384_SHA384 }"
- );
- assert_eq!(s.scheme(), SignatureScheme::ECDSA_NISTP384_SHA384);
- // nb. signature is variable length and asn.1-encoded
- assert!(
- s.sign(b"hello")
- .unwrap()
- .starts_with(&[0x30])
- );
- }
-
- #[test]
- fn can_load_ecdsa_nistp521_pkcs8() {
- let key =
- PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/nistp521key.pkcs8.der")[..]);
- assert!(any_eddsa_type(&key).is_err());
- let key = PrivateKeyDer::Pkcs8(key);
- assert!(any_supported_type(&key).is_ok());
- assert!(any_ecdsa_type(&key).is_ok());
- }
-
- #[test]
- fn can_load_ecdsa_nistp521_sec1() {
- let key = PrivateKeyDer::Sec1(PrivateSec1KeyDer::from(
- &include_bytes!("../../testdata/nistp521key.der")[..],
- ));
- assert!(any_supported_type(&key).is_ok());
- assert!(any_ecdsa_type(&key).is_ok());
- }
-
- #[test]
- fn can_sign_ecdsa_nistp521() {
- let key = PrivateKeyDer::Sec1(PrivateSec1KeyDer::from(
- &include_bytes!("../../testdata/nistp521key.der")[..],
- ));
-
- let k = any_supported_type(&key).unwrap();
- assert_eq!(format!("{k:?}"), "EcdsaSigningKey { algorithm: ECDSA }");
- assert_eq!(k.algorithm(), SignatureAlgorithm::ECDSA);
-
- assert!(
- k.choose_scheme(&[SignatureScheme::RSA_PKCS1_SHA256])
- .is_none()
- );
- assert!(
- k.choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256])
- .is_none()
- );
- assert!(
- k.choose_scheme(&[SignatureScheme::ECDSA_NISTP384_SHA384])
- .is_none()
- );
- let s = k
- .choose_scheme(&[SignatureScheme::ECDSA_NISTP521_SHA512])
- .unwrap();
- assert_eq!(
- format!("{s:?}"),
- "EcdsaSigner { scheme: ECDSA_NISTP521_SHA512 }"
- );
- assert_eq!(s.scheme(), SignatureScheme::ECDSA_NISTP521_SHA512);
- // nb. signature is variable length and asn.1-encoded
- assert!(
- s.sign(b"hello")
- .unwrap()
- .starts_with(&[0x30])
- );
- }
-
- #[test]
- fn can_load_eddsa_pkcs8() {
- let key = PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/eddsakey.der")[..]);
- assert!(any_eddsa_type(&key).is_ok());
- let key = PrivateKeyDer::Pkcs8(key);
- assert!(any_supported_type(&key).is_ok());
- assert!(any_ecdsa_type(&key).is_err());
- }
-
- #[test]
- fn can_sign_eddsa() {
- let key = PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/eddsakey.der")[..]);
-
- let k = any_eddsa_type(&key).unwrap();
- assert_eq!(format!("{k:?}"), "Ed25519SigningKey { algorithm: ED25519 }");
- assert_eq!(k.algorithm(), SignatureAlgorithm::ED25519);
-
- assert!(
- k.choose_scheme(&[SignatureScheme::RSA_PKCS1_SHA256])
- .is_none()
- );
- assert!(
- k.choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256])
- .is_none()
- );
- let s = k
- .choose_scheme(&[SignatureScheme::ED25519])
- .unwrap();
- assert_eq!(format!("{s:?}"), "Ed25519Signer { scheme: ED25519 }");
- assert_eq!(s.scheme(), SignatureScheme::ED25519);
- assert_eq!(s.sign(b"hello").unwrap().len(), 64);
- }
-
- #[test]
- fn can_load_rsa2048_pkcs8() {
- let key =
- PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/rsa2048key.pkcs8.der")[..]);
- assert!(any_eddsa_type(&key).is_err());
- let key = PrivateKeyDer::Pkcs8(key);
- assert!(any_supported_type(&key).is_ok());
- assert!(any_ecdsa_type(&key).is_err());
- }
-
- #[test]
- fn can_load_rsa2048_pkcs1() {
- let key = PrivateKeyDer::Pkcs1(PrivatePkcs1KeyDer::from(
- &include_bytes!("../../testdata/rsa2048key.pkcs1.der")[..],
- ));
- assert!(any_supported_type(&key).is_ok());
- assert!(any_ecdsa_type(&key).is_err());
- }
-
- #[test]
- fn can_sign_rsa2048() {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/rsa2048key.pkcs8.der")[..],
- ));
-
- let k = any_supported_type(&key).unwrap();
- assert_eq!(format!("{k:?}"), "RsaSigningKey { algorithm: RSA }");
- assert_eq!(k.algorithm(), SignatureAlgorithm::RSA);
-
- assert!(
- k.choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256])
- .is_none()
- );
- assert!(
- k.choose_scheme(&[SignatureScheme::ED25519])
- .is_none()
- );
-
- let s = k
- .choose_scheme(&[SignatureScheme::RSA_PSS_SHA256])
- .unwrap();
- assert_eq!(format!("{s:?}"), "RsaSigner { scheme: RSA_PSS_SHA256 }");
- assert_eq!(s.scheme(), SignatureScheme::RSA_PSS_SHA256);
- assert_eq!(s.sign(b"hello").unwrap().len(), 256);
-
- for scheme in &[
- SignatureScheme::RSA_PKCS1_SHA256,
- SignatureScheme::RSA_PKCS1_SHA384,
- SignatureScheme::RSA_PKCS1_SHA512,
- SignatureScheme::RSA_PSS_SHA256,
- SignatureScheme::RSA_PSS_SHA384,
- SignatureScheme::RSA_PSS_SHA512,
- ] {
- k.choose_scheme(&[*scheme]).unwrap();
- }
- }
-
- #[test]
- fn cannot_load_invalid_pkcs8_encoding() {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(&b"invalid"[..]));
- assert_eq!(
- any_supported_type(&key).err(),
- Some(Error::General(
- "failed to parse private key as RSA, ECDSA, or EdDSA".into()
- ))
- );
- assert_eq!(
- any_ecdsa_type(&key).err(),
- Some(Error::General(
- "failed to parse ECDSA private key as PKCS#8 or SEC1".into()
- ))
- );
- assert_eq!(
- RsaSigningKey::new(&key).err(),
- Some(Error::General(
- "failed to parse RSA private key: InvalidEncoding".into()
- ))
- );
- }
-}
-
-#[cfg(bench)]
-mod benchmarks {
- use super::{PrivateKeyDer, PrivatePkcs8KeyDer, SignatureScheme};
-
- #[bench]
- fn bench_rsa2048_pkcs1_sha256(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/rsa2048key.pkcs8.der")[..],
- ));
- let sk = super::any_supported_type(&key).unwrap();
- let signer = sk
- .choose_scheme(&[SignatureScheme::RSA_PKCS1_SHA256])
- .unwrap();
-
- b.iter(|| {
- test::black_box(
- signer
- .sign(SAMPLE_TLS13_MESSAGE)
- .unwrap(),
- );
- });
- }
-
- #[bench]
- fn bench_rsa2048_pss_sha256(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/rsa2048key.pkcs8.der")[..],
- ));
- let sk = super::any_supported_type(&key).unwrap();
- let signer = sk
- .choose_scheme(&[SignatureScheme::RSA_PSS_SHA256])
- .unwrap();
-
- b.iter(|| {
- test::black_box(
- signer
- .sign(SAMPLE_TLS13_MESSAGE)
- .unwrap(),
- );
- });
- }
-
- #[bench]
- fn bench_eddsa(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/eddsakey.der")[..],
- ));
- let sk = super::any_supported_type(&key).unwrap();
- let signer = sk
- .choose_scheme(&[SignatureScheme::ED25519])
- .unwrap();
-
- b.iter(|| {
- test::black_box(
- signer
- .sign(SAMPLE_TLS13_MESSAGE)
- .unwrap(),
- );
- });
- }
-
- #[bench]
- fn bench_ecdsa_p256_sha256(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/nistp256key.pkcs8.der")[..],
- ));
- let sk = super::any_supported_type(&key).unwrap();
- let signer = sk
- .choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256])
- .unwrap();
-
- b.iter(|| {
- test::black_box(
- signer
- .sign(SAMPLE_TLS13_MESSAGE)
- .unwrap(),
- );
- });
- }
-
- #[bench]
- fn bench_ecdsa_p384_sha384(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/nistp384key.pkcs8.der")[..],
- ));
- let sk = super::any_supported_type(&key).unwrap();
- let signer = sk
- .choose_scheme(&[SignatureScheme::ECDSA_NISTP384_SHA384])
- .unwrap();
-
- b.iter(|| {
- test::black_box(
- signer
- .sign(SAMPLE_TLS13_MESSAGE)
- .unwrap(),
- );
- });
- }
-
- #[bench]
- fn bench_ecdsa_p521_sha512(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/nistp521key.pkcs8.der")[..],
- ));
- let sk = super::any_supported_type(&key).unwrap();
- let signer = sk
- .choose_scheme(&[SignatureScheme::ECDSA_NISTP521_SHA512])
- .unwrap();
-
- b.iter(|| {
- test::black_box(
- signer
- .sign(SAMPLE_TLS13_MESSAGE)
- .unwrap(),
- );
- });
- }
-
- #[bench]
- fn bench_load_and_validate_rsa2048(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/rsa2048key.pkcs8.der")[..],
- ));
-
- b.iter(|| {
- test::black_box(super::any_supported_type(&key).unwrap());
- });
- }
-
- #[bench]
- fn bench_load_and_validate_rsa4096(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/rsa4096key.pkcs8.der")[..],
- ));
-
- b.iter(|| {
- test::black_box(super::any_supported_type(&key).unwrap());
- });
- }
-
- #[bench]
- fn bench_load_and_validate_p256(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/nistp256key.pkcs8.der")[..],
- ));
-
- b.iter(|| {
- test::black_box(super::any_ecdsa_type(&key).unwrap());
- });
- }
-
- #[bench]
- fn bench_load_and_validate_p384(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/nistp384key.pkcs8.der")[..],
- ));
-
- b.iter(|| {
- test::black_box(super::any_ecdsa_type(&key).unwrap());
- });
- }
-
- #[bench]
- fn bench_load_and_validate_p521(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/nistp521key.pkcs8.der")[..],
- ));
-
- b.iter(|| {
- test::black_box(super::any_ecdsa_type(&key).unwrap());
- });
- }
-
- #[bench]
- fn bench_load_and_validate_eddsa(b: &mut test::Bencher) {
- let key = PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/eddsakey.der")[..]);
-
- b.iter(|| {
- test::black_box(super::any_eddsa_type(&key).unwrap());
- });
- }
-
- const SAMPLE_TLS13_MESSAGE: &[u8] = &[
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x54, 0x4c, 0x53, 0x20, 0x31, 0x2e, 0x33, 0x2c, 0x20, 0x73, 0x65,
- 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
- 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x00, 0x04, 0xca, 0xc4, 0x48, 0x0e, 0x70, 0xf2,
- 0x1b, 0xa9, 0x1c, 0x16, 0xca, 0x90, 0x48, 0xbe, 0x28, 0x2f, 0xc7, 0xf8, 0x9b, 0x87, 0x72,
- 0x93, 0xda, 0x4d, 0x2f, 0x80, 0x80, 0x60, 0x1a, 0xd3, 0x08, 0xe2, 0xb7, 0x86, 0x14, 0x1b,
- 0x54, 0xda, 0x9a, 0xc9, 0x6d, 0xe9, 0x66, 0xb4, 0x9f, 0xe2, 0x2c,
- ];
-}
diff --git a/vendor/rustls/src/crypto/aws_lc_rs/ticketer.rs b/vendor/rustls/src/crypto/aws_lc_rs/ticketer.rs
deleted file mode 100644
index 44c7c21b..00000000
--- a/vendor/rustls/src/crypto/aws_lc_rs/ticketer.rs
+++ /dev/null
@@ -1,397 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec::Vec;
-use core::fmt;
-use core::fmt::{Debug, Formatter};
-use core::sync::atomic::{AtomicUsize, Ordering};
-
-use aws_lc_rs::cipher::{
- AES_256, AES_256_KEY_LEN, AES_CBC_IV_LEN, DecryptionContext, PaddedBlockDecryptingKey,
- PaddedBlockEncryptingKey, UnboundCipherKey,
-};
-use aws_lc_rs::{hmac, iv};
-
-use super::ring_like::rand::{SecureRandom, SystemRandom};
-use super::unspecified_err;
-use crate::error::Error;
-#[cfg(debug_assertions)]
-use crate::log::debug;
-use crate::polyfill::try_split_at;
-use crate::rand::GetRandomFailed;
-use crate::server::ProducesTickets;
-use crate::sync::Arc;
-
-/// A concrete, safe ticket creation mechanism.
-pub struct Ticketer {}
-
-impl Ticketer {
- /// Make the recommended `Ticketer`. This produces tickets
- /// with a 12 hour life and randomly generated keys.
- ///
- /// The `Ticketer` uses the [RFC 5077 §4] "Recommended Ticket Construction",
- /// using AES 256 for encryption and HMAC-SHA256 for ciphertext authentication.
- ///
- /// [RFC 5077 §4]: https://www.rfc-editor.org/rfc/rfc5077#section-4
- #[cfg(feature = "std")]
- pub fn new() -> Result<Arc<dyn ProducesTickets>, Error> {
- Ok(Arc::new(crate::ticketer::TicketRotator::new(
- 6 * 60 * 60,
- make_ticket_generator,
- )?))
- }
-}
-
-fn make_ticket_generator() -> Result<Box<dyn ProducesTickets>, GetRandomFailed> {
- // NOTE(XXX): Unconditionally mapping errors to `GetRandomFailed` here is slightly
- // misleading in some cases (e.g. failure to construct a padded block cipher encrypting key).
- // However, we can't change the return type expected from a `TicketSwitcher` `generator`
- // without breaking semver.
- // Tracking in https://github.com/rustls/rustls/issues/2074
- Ok(Box::new(
- Rfc5077Ticketer::new().map_err(|_| GetRandomFailed)?,
- ))
-}
-
-/// An RFC 5077 "Recommended Ticket Construction" implementation of a [`Ticketer`].
-struct Rfc5077Ticketer {
- aes_encrypt_key: PaddedBlockEncryptingKey,
- aes_decrypt_key: PaddedBlockDecryptingKey,
- hmac_key: hmac::Key,
- key_name: [u8; 16],
- lifetime: u32,
- maximum_ciphertext_len: AtomicUsize,
-}
-
-impl Rfc5077Ticketer {
- fn new() -> Result<Self, Error> {
- let rand = SystemRandom::new();
-
- // Generate a random AES 256 key to use for AES CBC encryption.
- let mut aes_key = [0u8; AES_256_KEY_LEN];
- rand.fill(&mut aes_key)
- .map_err(|_| GetRandomFailed)?;
-
- // Convert the raw AES 256 key bytes into encrypting and decrypting keys using CBC mode and
- // PKCS#7 padding. We don't want to store just the raw key bytes as constructing the
- // cipher keys has some setup overhead. We can't store just the `UnboundCipherKey` since
- // constructing the padded encrypt/decrypt specific types consume the `UnboundCipherKey`.
- let aes_encrypt_key =
- UnboundCipherKey::new(&AES_256, &aes_key[..]).map_err(unspecified_err)?;
- let aes_encrypt_key =
- PaddedBlockEncryptingKey::cbc_pkcs7(aes_encrypt_key).map_err(unspecified_err)?;
-
- // Convert the raw AES 256 key bytes into a decrypting key using CBC PKCS#7 padding.
- let aes_decrypt_key =
- UnboundCipherKey::new(&AES_256, &aes_key[..]).map_err(unspecified_err)?;
- let aes_decrypt_key =
- PaddedBlockDecryptingKey::cbc_pkcs7(aes_decrypt_key).map_err(unspecified_err)?;
-
- // Generate a random HMAC SHA256 key to use for HMAC authentication.
- let hmac_key = hmac::Key::generate(hmac::HMAC_SHA256, &rand).map_err(unspecified_err)?;
-
- // Generate a random key name.
- let mut key_name = [0u8; 16];
- rand.fill(&mut key_name)
- .map_err(|_| GetRandomFailed)?;
-
- Ok(Self {
- aes_encrypt_key,
- aes_decrypt_key,
- hmac_key,
- key_name,
- lifetime: 60 * 60 * 12,
- maximum_ciphertext_len: AtomicUsize::new(0),
- })
- }
-}
-
-impl ProducesTickets for Rfc5077Ticketer {
- fn enabled(&self) -> bool {
- true
- }
-
- fn lifetime(&self) -> u32 {
- self.lifetime
- }
-
- /// Encrypt `message` and return the ciphertext.
- fn encrypt(&self, message: &[u8]) -> Option<Vec<u8>> {
- // Encrypt the ticket state - the cipher module handles generating a random IV of
- // appropriate size, returning it in the `DecryptionContext`.
- let mut encrypted_state = Vec::from(message);
- let dec_ctx = self
- .aes_encrypt_key
- .encrypt(&mut encrypted_state)
- .ok()?;
- let iv: &[u8] = (&dec_ctx).try_into().ok()?;
-
- // Produce the MAC tag over the relevant context & encrypted state.
- // Quoting RFC 5077:
- // "The Message Authentication Code (MAC) is calculated using HMAC-SHA-256 over
- // key_name (16 octets) and IV (16 octets), followed by the length of
- // the encrypted_state field (2 octets) and its contents (variable
- // length)."
- let mut hmac_data =
- Vec::with_capacity(self.key_name.len() + iv.len() + 2 + encrypted_state.len());
- hmac_data.extend(&self.key_name);
- hmac_data.extend(iv);
- hmac_data.extend(
- u16::try_from(encrypted_state.len())
- .ok()?
- .to_be_bytes(),
- );
- hmac_data.extend(&encrypted_state);
- let tag = hmac::sign(&self.hmac_key, &hmac_data);
- let tag = tag.as_ref();
-
- // Combine the context, the encrypted state, and the tag to produce the final ciphertext.
- // Ciphertext structure is:
- // key_name: [u8; 16]
- // iv: [u8; 16]
- // encrypted_state: [u8, _]
- // mac tag: [u8; 32]
- let mut ciphertext =
- Vec::with_capacity(self.key_name.len() + iv.len() + encrypted_state.len() + tag.len());
- ciphertext.extend(self.key_name);
- ciphertext.extend(iv);
- ciphertext.extend(encrypted_state);
- ciphertext.extend(tag);
-
- self.maximum_ciphertext_len
- .fetch_max(ciphertext.len(), Ordering::SeqCst);
-
- Some(ciphertext)
- }
-
- fn decrypt(&self, ciphertext: &[u8]) -> Option<Vec<u8>> {
- if ciphertext.len()
- > self
- .maximum_ciphertext_len
- .load(Ordering::SeqCst)
- {
- #[cfg(debug_assertions)]
- debug!("rejected over-length ticket");
- return None;
- }
-
- // Split off the key name from the remaining ciphertext.
- let (alleged_key_name, ciphertext) = try_split_at(ciphertext, self.key_name.len())?;
-
- // Split off the IV from the remaining ciphertext.
- let (iv, ciphertext) = try_split_at(ciphertext, AES_CBC_IV_LEN)?;
-
- // And finally, split the encrypted state from the tag.
- let tag_len = self
- .hmac_key
- .algorithm()
- .digest_algorithm()
- .output_len();
- let (enc_state, mac) = try_split_at(ciphertext, ciphertext.len() - tag_len)?;
-
- // Reconstitute the HMAC data to verify the tag.
- let mut hmac_data =
- Vec::with_capacity(alleged_key_name.len() + iv.len() + 2 + enc_state.len());
- hmac_data.extend(alleged_key_name);
- hmac_data.extend(iv);
- hmac_data.extend(
- u16::try_from(enc_state.len())
- .ok()?
- .to_be_bytes(),
- );
- hmac_data.extend(enc_state);
- hmac::verify(&self.hmac_key, &hmac_data, mac).ok()?;
-
- // Convert the raw IV back into an appropriate decryption context.
- let iv = iv::FixedLength::try_from(iv).ok()?;
- let dec_context = DecryptionContext::Iv128(iv);
-
- // And finally, decrypt the encrypted state.
- let mut out = Vec::from(enc_state);
- let plaintext = self
- .aes_decrypt_key
- .decrypt(&mut out, dec_context)
- .ok()?;
-
- Some(plaintext.into())
- }
-}
-
-impl Debug for Rfc5077Ticketer {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- // Note: we deliberately omit keys from the debug output.
- f.debug_struct("Rfc5077Ticketer")
- .field("lifetime", &self.lifetime)
- .finish()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use core::time::Duration;
-
- use pki_types::UnixTime;
-
- use super::*;
-
- #[test]
- fn basic_pairwise_test() {
- let t = Ticketer::new().unwrap();
- assert!(t.enabled());
- let cipher = t.encrypt(b"hello world").unwrap();
- let plain = t.decrypt(&cipher).unwrap();
- assert_eq!(plain, b"hello world");
- }
-
- #[test]
- fn refuses_decrypt_before_encrypt() {
- let t = Ticketer::new().unwrap();
- assert_eq!(t.decrypt(b"hello"), None);
- }
-
- #[test]
- fn refuses_decrypt_larger_than_largest_encryption() {
- let t = Ticketer::new().unwrap();
- let mut cipher = t.encrypt(b"hello world").unwrap();
- assert_eq!(t.decrypt(&cipher), Some(b"hello world".to_vec()));
-
- // obviously this would never work anyway, but this
- // and `cannot_decrypt_before_encrypt` exercise the
- // first branch in `decrypt()`
- cipher.push(0);
- assert_eq!(t.decrypt(&cipher), None);
- }
-
- #[test]
- fn ticketrotator_switching_test() {
- let t = Arc::new(crate::ticketer::TicketRotator::new(1, make_ticket_generator).unwrap());
- let now = UnixTime::now();
- let cipher1 = t.encrypt(b"ticket 1").unwrap();
- assert_eq!(t.decrypt(&cipher1).unwrap(), b"ticket 1");
- {
- // Trigger new ticketer
- t.maybe_roll(UnixTime::since_unix_epoch(Duration::from_secs(
- now.as_secs() + 10,
- )));
- }
- let cipher2 = t.encrypt(b"ticket 2").unwrap();
- assert_eq!(t.decrypt(&cipher1).unwrap(), b"ticket 1");
- assert_eq!(t.decrypt(&cipher2).unwrap(), b"ticket 2");
- {
- // Trigger new ticketer
- t.maybe_roll(UnixTime::since_unix_epoch(Duration::from_secs(
- now.as_secs() + 20,
- )));
- }
- let cipher3 = t.encrypt(b"ticket 3").unwrap();
- assert!(t.decrypt(&cipher1).is_none());
- assert_eq!(t.decrypt(&cipher2).unwrap(), b"ticket 2");
- assert_eq!(t.decrypt(&cipher3).unwrap(), b"ticket 3");
- }
-
- #[test]
- fn ticketrotator_remains_usable_over_temporary_ticketer_creation_failure() {
- let mut t = crate::ticketer::TicketRotator::new(1, make_ticket_generator).unwrap();
- let now = UnixTime::now();
- let cipher1 = t.encrypt(b"ticket 1").unwrap();
- assert_eq!(t.decrypt(&cipher1).unwrap(), b"ticket 1");
- t.generator = fail_generator;
- {
- // Failed new ticketer; this means we still need to
- // rotate.
- t.maybe_roll(UnixTime::since_unix_epoch(Duration::from_secs(
- now.as_secs() + 10,
- )));
- }
-
- // check post-failure encryption/decryption still works
- let cipher2 = t.encrypt(b"ticket 2").unwrap();
- assert_eq!(t.decrypt(&cipher1).unwrap(), b"ticket 1");
- assert_eq!(t.decrypt(&cipher2).unwrap(), b"ticket 2");
-
- // do the rotation for real
- t.generator = make_ticket_generator;
- {
- t.maybe_roll(UnixTime::since_unix_epoch(Duration::from_secs(
- now.as_secs() + 20,
- )));
- }
- let cipher3 = t.encrypt(b"ticket 3").unwrap();
- assert!(t.decrypt(&cipher1).is_some());
- assert_eq!(t.decrypt(&cipher2).unwrap(), b"ticket 2");
- assert_eq!(t.decrypt(&cipher3).unwrap(), b"ticket 3");
- }
-
- #[test]
- fn ticketswitcher_switching_test() {
- #[expect(deprecated)]
- let t = Arc::new(crate::ticketer::TicketSwitcher::new(1, make_ticket_generator).unwrap());
- let now = UnixTime::now();
- let cipher1 = t.encrypt(b"ticket 1").unwrap();
- assert_eq!(t.decrypt(&cipher1).unwrap(), b"ticket 1");
- {
- // Trigger new ticketer
- t.maybe_roll(UnixTime::since_unix_epoch(Duration::from_secs(
- now.as_secs() + 10,
- )));
- }
- let cipher2 = t.encrypt(b"ticket 2").unwrap();
- assert_eq!(t.decrypt(&cipher1).unwrap(), b"ticket 1");
- assert_eq!(t.decrypt(&cipher2).unwrap(), b"ticket 2");
- {
- // Trigger new ticketer
- t.maybe_roll(UnixTime::since_unix_epoch(Duration::from_secs(
- now.as_secs() + 20,
- )));
- }
- let cipher3 = t.encrypt(b"ticket 3").unwrap();
- assert!(t.decrypt(&cipher1).is_none());
- assert_eq!(t.decrypt(&cipher2).unwrap(), b"ticket 2");
- assert_eq!(t.decrypt(&cipher3).unwrap(), b"ticket 3");
- }
-
- #[test]
- fn ticketswitcher_recover_test() {
- #[expect(deprecated)]
- let mut t = crate::ticketer::TicketSwitcher::new(1, make_ticket_generator).unwrap();
- let now = UnixTime::now();
- let cipher1 = t.encrypt(b"ticket 1").unwrap();
- assert_eq!(t.decrypt(&cipher1).unwrap(), b"ticket 1");
- t.generator = fail_generator;
- {
- // Failed new ticketer
- t.maybe_roll(UnixTime::since_unix_epoch(Duration::from_secs(
- now.as_secs() + 10,
- )));
- }
- t.generator = make_ticket_generator;
- let cipher2 = t.encrypt(b"ticket 2").unwrap();
- assert_eq!(t.decrypt(&cipher1).unwrap(), b"ticket 1");
- assert_eq!(t.decrypt(&cipher2).unwrap(), b"ticket 2");
- {
- // recover
- t.maybe_roll(UnixTime::since_unix_epoch(Duration::from_secs(
- now.as_secs() + 20,
- )));
- }
- let cipher3 = t.encrypt(b"ticket 3").unwrap();
- assert!(t.decrypt(&cipher1).is_none());
- assert_eq!(t.decrypt(&cipher2).unwrap(), b"ticket 2");
- assert_eq!(t.decrypt(&cipher3).unwrap(), b"ticket 3");
- }
-
- #[test]
- fn rfc5077ticketer_is_debug_and_producestickets() {
- use alloc::format;
-
- use super::*;
-
- let t = make_ticket_generator().unwrap();
-
- assert_eq!(format!("{t:?}"), "Rfc5077Ticketer { lifetime: 43200 }");
- assert!(t.enabled());
- assert_eq!(t.lifetime(), 43200);
- }
-
- fn fail_generator() -> Result<Box<dyn ProducesTickets>, GetRandomFailed> {
- Err(GetRandomFailed)
- }
-}
diff --git a/vendor/rustls/src/crypto/aws_lc_rs/tls12.rs b/vendor/rustls/src/crypto/aws_lc_rs/tls12.rs
deleted file mode 100644
index 3845af58..00000000
--- a/vendor/rustls/src/crypto/aws_lc_rs/tls12.rs
+++ /dev/null
@@ -1,465 +0,0 @@
-use alloc::boxed::Box;
-
-use aws_lc_rs::{aead, tls_prf};
-
-use crate::crypto::cipher::{
- AeadKey, InboundOpaqueMessage, Iv, KeyBlockShape, MessageDecrypter, MessageEncrypter,
- NONCE_LEN, Nonce, Tls12AeadAlgorithm, UnsupportedOperationError, make_tls12_aad,
-};
-use crate::crypto::tls12::Prf;
-use crate::crypto::{ActiveKeyExchange, KeyExchangeAlgorithm};
-use crate::enums::{CipherSuite, SignatureScheme};
-use crate::error::Error;
-use crate::msgs::fragmenter::MAX_FRAGMENT_LEN;
-use crate::msgs::message::{
- InboundPlainMessage, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload,
-};
-use crate::suites::{CipherSuiteCommon, ConnectionTrafficSecrets, SupportedCipherSuite};
-use crate::tls12::Tls12CipherSuite;
-use crate::version::TLS12;
-
-/// The TLS1.2 ciphersuite TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256.
-pub static TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
- SupportedCipherSuite::Tls12(&Tls12CipherSuite {
- common: CipherSuiteCommon {
- suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
- hash_provider: &super::hash::SHA256,
- confidentiality_limit: u64::MAX,
- },
- kx: KeyExchangeAlgorithm::ECDHE,
- sign: TLS12_ECDSA_SCHEMES,
- aead_alg: &ChaCha20Poly1305,
- prf_provider: &Tls12Prf(&tls_prf::P_SHA256),
- });
-
-/// The TLS1.2 ciphersuite TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
-pub static TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
- SupportedCipherSuite::Tls12(&Tls12CipherSuite {
- common: CipherSuiteCommon {
- suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
- hash_provider: &super::hash::SHA256,
- confidentiality_limit: u64::MAX,
- },
- kx: KeyExchangeAlgorithm::ECDHE,
- sign: TLS12_RSA_SCHEMES,
- aead_alg: &ChaCha20Poly1305,
- prf_provider: &Tls12Prf(&tls_prf::P_SHA256),
- });
-
-/// The TLS1.2 ciphersuite TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
-pub static 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: &super::hash::SHA256,
- confidentiality_limit: 1 << 24,
- },
- kx: KeyExchangeAlgorithm::ECDHE,
- sign: TLS12_RSA_SCHEMES,
- aead_alg: &AES128_GCM,
- prf_provider: &Tls12Prf(&tls_prf::P_SHA256),
- });
-
-/// The TLS1.2 ciphersuite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
-pub static 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: &super::hash::SHA384,
- confidentiality_limit: 1 << 24,
- },
- kx: KeyExchangeAlgorithm::ECDHE,
- sign: TLS12_RSA_SCHEMES,
- aead_alg: &AES256_GCM,
- prf_provider: &Tls12Prf(&tls_prf::P_SHA384),
- });
-
-/// The TLS1.2 ciphersuite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
-pub static 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: &super::hash::SHA256,
- confidentiality_limit: 1 << 24,
- },
- kx: KeyExchangeAlgorithm::ECDHE,
- sign: TLS12_ECDSA_SCHEMES,
- aead_alg: &AES128_GCM,
- prf_provider: &Tls12Prf(&tls_prf::P_SHA256),
- });
-
-/// The TLS1.2 ciphersuite TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
-pub static 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: &super::hash::SHA384,
- confidentiality_limit: 1 << 24,
- },
- kx: KeyExchangeAlgorithm::ECDHE,
- sign: TLS12_ECDSA_SCHEMES,
- aead_alg: &AES256_GCM,
- prf_provider: &Tls12Prf(&tls_prf::P_SHA384),
- });
-
-static TLS12_ECDSA_SCHEMES: &[SignatureScheme] = &[
- SignatureScheme::ED25519,
- SignatureScheme::ECDSA_NISTP521_SHA512,
- SignatureScheme::ECDSA_NISTP384_SHA384,
- SignatureScheme::ECDSA_NISTP256_SHA256,
-];
-
-static TLS12_RSA_SCHEMES: &[SignatureScheme] = &[
- SignatureScheme::RSA_PSS_SHA512,
- SignatureScheme::RSA_PSS_SHA384,
- SignatureScheme::RSA_PSS_SHA256,
- SignatureScheme::RSA_PKCS1_SHA512,
- SignatureScheme::RSA_PKCS1_SHA384,
- SignatureScheme::RSA_PKCS1_SHA256,
-];
-
-pub(crate) static AES128_GCM: GcmAlgorithm = GcmAlgorithm(&aead::AES_128_GCM);
-pub(crate) static AES256_GCM: GcmAlgorithm = GcmAlgorithm(&aead::AES_256_GCM);
-
-pub(crate) struct GcmAlgorithm(&'static aead::Algorithm);
-
-impl Tls12AeadAlgorithm for GcmAlgorithm {
- fn decrypter(&self, dec_key: AeadKey, dec_iv: &[u8]) -> Box<dyn MessageDecrypter> {
- // safety: see `encrypter()`.
- let dec_key =
- aead::TlsRecordOpeningKey::new(self.0, aead::TlsProtocolId::TLS12, dec_key.as_ref())
- .unwrap();
-
- let mut ret = GcmMessageDecrypter {
- dec_key,
- dec_salt: [0u8; 4],
- };
-
- debug_assert_eq!(dec_iv.len(), 4);
- ret.dec_salt.copy_from_slice(dec_iv);
- Box::new(ret)
- }
-
- fn encrypter(
- &self,
- enc_key: AeadKey,
- write_iv: &[u8],
- explicit: &[u8],
- ) -> Box<dyn MessageEncrypter> {
- // safety: `TlsRecordSealingKey::new` fails if
- // - `enc_key`'s length is wrong for `algorithm`. But the length is defined by
- // `algorithm.key_len()` in `key_block_shape()`, below.
- // - `algorithm` is not supported: but `AES_128_GCM` and `AES_256_GCM` is.
- // thus, this `unwrap()` is unreachable.
- //
- // `TlsProtocolId::TLS13` is deliberate: we reuse the nonce construction from
- // RFC7905 and TLS13: a random starting point, XOR'd with the sequence number. This means
- // `TlsProtocolId::TLS12` (which wants to see a plain sequence number) is unsuitable.
- //
- // The most important property is that nonce is unique per key, which is satisfied by
- // this construction, even if the nonce is not monotonically increasing.
- let enc_key =
- aead::TlsRecordSealingKey::new(self.0, aead::TlsProtocolId::TLS13, enc_key.as_ref())
- .unwrap();
- let iv = gcm_iv(write_iv, explicit);
- Box::new(GcmMessageEncrypter { enc_key, iv })
- }
-
- fn key_block_shape(&self) -> KeyBlockShape {
- KeyBlockShape {
- enc_key_len: self.0.key_len(),
- fixed_iv_len: 4,
- explicit_nonce_len: 8,
- }
- }
-
- fn extract_keys(
- &self,
- key: AeadKey,
- write_iv: &[u8],
- explicit: &[u8],
- ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
- let iv = gcm_iv(write_iv, explicit);
- Ok(match self.0.key_len() {
- 16 => ConnectionTrafficSecrets::Aes128Gcm { key, iv },
- 32 => ConnectionTrafficSecrets::Aes256Gcm { key, iv },
- _ => unreachable!(),
- })
- }
-
- fn fips(&self) -> bool {
- super::fips()
- }
-}
-
-pub(crate) struct ChaCha20Poly1305;
-
-impl Tls12AeadAlgorithm for ChaCha20Poly1305 {
- fn decrypter(&self, dec_key: AeadKey, iv: &[u8]) -> Box<dyn MessageDecrypter> {
- let dec_key = aead::LessSafeKey::new(
- aead::UnboundKey::new(&aead::CHACHA20_POLY1305, dec_key.as_ref()).unwrap(),
- );
- Box::new(ChaCha20Poly1305MessageDecrypter {
- dec_key,
- dec_offset: Iv::copy(iv),
- })
- }
-
- fn encrypter(&self, enc_key: AeadKey, enc_iv: &[u8], _: &[u8]) -> Box<dyn MessageEncrypter> {
- let enc_key = aead::LessSafeKey::new(
- aead::UnboundKey::new(&aead::CHACHA20_POLY1305, enc_key.as_ref()).unwrap(),
- );
- Box::new(ChaCha20Poly1305MessageEncrypter {
- enc_key,
- enc_offset: Iv::copy(enc_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<ConnectionTrafficSecrets, UnsupportedOperationError> {
- // This should always be true because KeyBlockShape and the Iv nonce len are in agreement.
- debug_assert_eq!(aead::NONCE_LEN, iv.len());
- Ok(ConnectionTrafficSecrets::Chacha20Poly1305 {
- key,
- iv: Iv::new(iv[..].try_into().unwrap()),
- })
- }
-
- fn fips(&self) -> bool {
- false // not FIPS approved
- }
-}
-
-/// A `MessageEncrypter` for AES-GCM AEAD ciphersuites. TLS 1.2 only.
-struct GcmMessageEncrypter {
- enc_key: aead::TlsRecordSealingKey,
- iv: Iv,
-}
-
-/// A `MessageDecrypter` for AES-GCM AEAD ciphersuites. TLS1.2 only.
-struct GcmMessageDecrypter {
- dec_key: aead::TlsRecordOpeningKey,
- dec_salt: [u8; 4],
-}
-
-const GCM_EXPLICIT_NONCE_LEN: usize = 8;
-const GCM_OVERHEAD: usize = GCM_EXPLICIT_NONCE_LEN + 16;
-
-impl MessageDecrypter for GcmMessageDecrypter {
- fn decrypt<'a>(
- &mut self,
- mut msg: InboundOpaqueMessage<'a>,
- seq: u64,
- ) -> Result<InboundPlainMessage<'a>, Error> {
- let payload = &msg.payload;
- if payload.len() < GCM_OVERHEAD {
- return Err(Error::DecryptError);
- }
-
- let nonce = {
- let mut nonce = [0u8; 12];
- nonce[..4].copy_from_slice(&self.dec_salt);
- nonce[4..].copy_from_slice(&payload[..8]);
- aead::Nonce::assume_unique_for_key(nonce)
- };
-
- let aad = aead::Aad::from(make_tls12_aad(
- seq,
- msg.typ,
- msg.version,
- payload.len() - GCM_OVERHEAD,
- ));
-
- let payload = &mut msg.payload;
- let plain_len = self
- .dec_key
- .open_in_place(nonce, aad, &mut payload[GCM_EXPLICIT_NONCE_LEN..])
- .map_err(|_| Error::DecryptError)?
- .len();
-
- if plain_len > MAX_FRAGMENT_LEN {
- return Err(Error::PeerSentOversizedRecord);
- }
-
- Ok(
- msg.into_plain_message_range(
- GCM_EXPLICIT_NONCE_LEN..GCM_EXPLICIT_NONCE_LEN + plain_len,
- ),
- )
- }
-}
-
-impl MessageEncrypter for GcmMessageEncrypter {
- fn encrypt(
- &mut self,
- msg: OutboundPlainMessage<'_>,
- seq: u64,
- ) -> Result<OutboundOpaqueMessage, Error> {
- let total_len = self.encrypted_payload_len(msg.payload.len());
- let mut payload = PrefixedPayload::with_capacity(total_len);
-
- let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
- let aad = aead::Aad::from(make_tls12_aad(seq, msg.typ, msg.version, msg.payload.len()));
- payload.extend_from_slice(&nonce.as_ref()[4..]);
- payload.extend_from_chunks(&msg.payload);
-
- self.enc_key
- .seal_in_place_separate_tag(nonce, aad, &mut payload.as_mut()[GCM_EXPLICIT_NONCE_LEN..])
- .map(|tag| payload.extend_from_slice(tag.as_ref()))
- .map_err(|_| Error::EncryptError)?;
-
- Ok(OutboundOpaqueMessage::new(msg.typ, msg.version, payload))
- }
-
- fn encrypted_payload_len(&self, payload_len: usize) -> usize {
- payload_len + GCM_EXPLICIT_NONCE_LEN + self.enc_key.algorithm().tag_len()
- }
-}
-
-/// The RFC7905/RFC7539 ChaCha20Poly1305 construction.
-/// This implementation does the AAD construction required in TLS1.2.
-/// TLS1.3 uses `TLS13MessageEncrypter`.
-struct ChaCha20Poly1305MessageEncrypter {
- enc_key: aead::LessSafeKey,
- enc_offset: Iv,
-}
-
-/// The RFC7905/RFC7539 ChaCha20Poly1305 construction.
-/// This implementation does the AAD construction required in TLS1.2.
-/// TLS1.3 uses `TLS13MessageDecrypter`.
-struct ChaCha20Poly1305MessageDecrypter {
- dec_key: aead::LessSafeKey,
- dec_offset: Iv,
-}
-
-const CHACHAPOLY1305_OVERHEAD: usize = 16;
-
-impl MessageDecrypter for ChaCha20Poly1305MessageDecrypter {
- fn decrypt<'a>(
- &mut self,
- mut msg: InboundOpaqueMessage<'a>,
- seq: u64,
- ) -> Result<InboundPlainMessage<'a>, Error> {
- let payload = &msg.payload;
-
- if payload.len() < CHACHAPOLY1305_OVERHEAD {
- return Err(Error::DecryptError);
- }
-
- let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.dec_offset, seq).0);
- let aad = aead::Aad::from(make_tls12_aad(
- seq,
- msg.typ,
- msg.version,
- payload.len() - CHACHAPOLY1305_OVERHEAD,
- ));
-
- let payload = &mut msg.payload;
- let plain_len = self
- .dec_key
- .open_in_place(nonce, aad, payload)
- .map_err(|_| Error::DecryptError)?
- .len();
-
- if plain_len > MAX_FRAGMENT_LEN {
- return Err(Error::PeerSentOversizedRecord);
- }
-
- payload.truncate(plain_len);
- Ok(msg.into_plain_message())
- }
-}
-
-impl MessageEncrypter for ChaCha20Poly1305MessageEncrypter {
- fn encrypt(
- &mut self,
- msg: OutboundPlainMessage<'_>,
- seq: u64,
- ) -> Result<OutboundOpaqueMessage, Error> {
- let total_len = self.encrypted_payload_len(msg.payload.len());
- let mut payload = PrefixedPayload::with_capacity(total_len);
-
- let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.enc_offset, seq).0);
- let aad = aead::Aad::from(make_tls12_aad(seq, msg.typ, msg.version, msg.payload.len()));
- payload.extend_from_chunks(&msg.payload);
-
- self.enc_key
- .seal_in_place_append_tag(nonce, aad, &mut payload)
- .map_err(|_| Error::EncryptError)?;
-
- Ok(OutboundOpaqueMessage::new(msg.typ, msg.version, payload))
- }
-
- fn encrypted_payload_len(&self, payload_len: usize) -> usize {
- payload_len + self.enc_key.algorithm().tag_len()
- }
-}
-
-fn gcm_iv(write_iv: &[u8], explicit: &[u8]) -> Iv {
- debug_assert_eq!(write_iv.len(), 4);
- debug_assert_eq!(explicit.len(), 8);
-
- // The GCM nonce is constructed from a 32-bit 'salt' derived
- // from the master-secret, and a 64-bit explicit part,
- // with no specified construction. Thanks for that.
- //
- // We use the same construction as TLS1.3/ChaCha20Poly1305:
- // a starting point extracted from the key block, xored with
- // the sequence number.
- let mut iv = [0; NONCE_LEN];
- iv[..4].copy_from_slice(write_iv);
- iv[4..].copy_from_slice(explicit);
-
- Iv::new(iv)
-}
-
-struct Tls12Prf(&'static tls_prf::Algorithm);
-
-impl Prf for Tls12Prf {
- fn for_secret(&self, output: &mut [u8], secret: &[u8], label: &[u8], seed: &[u8]) {
- // safety:
- // - [1] is safe because our caller guarantees `secret` is non-empty; this is
- // the only documented error case.
- // - [2] is safe in practice because the only failure from `derive()` is due
- // to zero `output.len()`; this is outlawed at higher levels
- let derived = tls_prf::Secret::new(self.0, secret)
- .unwrap() // [1]
- .derive(label, seed, output.len())
- .unwrap(); // [2]
- output.copy_from_slice(derived.as_ref());
- }
-
- fn for_key_exchange(
- &self,
- output: &mut [u8; 48],
- kx: Box<dyn ActiveKeyExchange>,
- peer_pub_key: &[u8],
- label: &[u8],
- seed: &[u8],
- ) -> Result<(), Error> {
- self.for_secret(
- output,
- kx.complete_for_tls_version(peer_pub_key, &TLS12)?
- .secret_bytes(),
- label,
- seed,
- );
- Ok(())
- }
-
- fn fips(&self) -> bool {
- super::fips()
- }
-}
diff --git a/vendor/rustls/src/crypto/aws_lc_rs/tls13.rs b/vendor/rustls/src/crypto/aws_lc_rs/tls13.rs
deleted file mode 100644
index dbc9d912..00000000
--- a/vendor/rustls/src/crypto/aws_lc_rs/tls13.rs
+++ /dev/null
@@ -1,425 +0,0 @@
-use alloc::boxed::Box;
-
-use aws_lc_rs::hkdf::KeyType;
-use aws_lc_rs::{aead, hkdf, hmac};
-
-use crate::crypto;
-use crate::crypto::cipher::{
- AeadKey, InboundOpaqueMessage, Iv, MessageDecrypter, MessageEncrypter, Nonce,
- Tls13AeadAlgorithm, UnsupportedOperationError, make_tls13_aad,
-};
-use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock, OutputLengthError};
-use crate::enums::{CipherSuite, ContentType, ProtocolVersion};
-use crate::error::Error;
-use crate::msgs::message::{
- InboundPlainMessage, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload,
-};
-use crate::suites::{CipherSuiteCommon, ConnectionTrafficSecrets, SupportedCipherSuite};
-use crate::tls13::Tls13CipherSuite;
-
-/// The TLS1.3 ciphersuite TLS_CHACHA20_POLY1305_SHA256
-pub static TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
- SupportedCipherSuite::Tls13(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
-
-pub(crate) static TLS13_CHACHA20_POLY1305_SHA256_INTERNAL: &Tls13CipherSuite = &Tls13CipherSuite {
- common: CipherSuiteCommon {
- suite: CipherSuite::TLS13_CHACHA20_POLY1305_SHA256,
- hash_provider: &super::hash::SHA256,
- // ref: <https://www.ietf.org/archive/id/draft-irtf-cfrg-aead-limits-08.html#section-5.2.1>
- confidentiality_limit: u64::MAX,
- },
- hkdf_provider: &AwsLcHkdf(hkdf::HKDF_SHA256, hmac::HMAC_SHA256),
- aead_alg: &Chacha20Poly1305Aead(AeadAlgorithm(&aead::CHACHA20_POLY1305)),
- quic: Some(&super::quic::KeyBuilder {
- packet_alg: &aead::CHACHA20_POLY1305,
- header_alg: &aead::quic::CHACHA20,
- // ref: <https://datatracker.ietf.org/doc/html/rfc9001#section-6.6>
- confidentiality_limit: u64::MAX,
- // ref: <https://datatracker.ietf.org/doc/html/rfc9001#section-6.6>
- integrity_limit: 1 << 36,
- }),
-};
-
-/// The TLS1.3 ciphersuite TLS_AES_256_GCM_SHA384
-pub static TLS13_AES_256_GCM_SHA384: SupportedCipherSuite =
- SupportedCipherSuite::Tls13(&Tls13CipherSuite {
- common: CipherSuiteCommon {
- suite: CipherSuite::TLS13_AES_256_GCM_SHA384,
- hash_provider: &super::hash::SHA384,
- confidentiality_limit: 1 << 24,
- },
- hkdf_provider: &AwsLcHkdf(hkdf::HKDF_SHA384, hmac::HMAC_SHA384),
- aead_alg: &Aes256GcmAead(AeadAlgorithm(&aead::AES_256_GCM)),
- quic: Some(&super::quic::KeyBuilder {
- packet_alg: &aead::AES_256_GCM,
- header_alg: &aead::quic::AES_256,
- // ref: <https://datatracker.ietf.org/doc/html/rfc9001#section-b.1.1>
- confidentiality_limit: 1 << 23,
- // ref: <https://datatracker.ietf.org/doc/html/rfc9001#section-b.1.2>
- integrity_limit: 1 << 52,
- }),
- });
-
-/// The TLS1.3 ciphersuite TLS_AES_128_GCM_SHA256
-pub static TLS13_AES_128_GCM_SHA256: SupportedCipherSuite =
- SupportedCipherSuite::Tls13(TLS13_AES_128_GCM_SHA256_INTERNAL);
-
-pub(crate) static TLS13_AES_128_GCM_SHA256_INTERNAL: &Tls13CipherSuite = &Tls13CipherSuite {
- common: CipherSuiteCommon {
- suite: CipherSuite::TLS13_AES_128_GCM_SHA256,
- hash_provider: &super::hash::SHA256,
- confidentiality_limit: 1 << 24,
- },
- hkdf_provider: &AwsLcHkdf(hkdf::HKDF_SHA256, hmac::HMAC_SHA256),
- aead_alg: &Aes128GcmAead(AeadAlgorithm(&aead::AES_128_GCM)),
- quic: Some(&super::quic::KeyBuilder {
- packet_alg: &aead::AES_128_GCM,
- header_alg: &aead::quic::AES_128,
- // ref: <https://datatracker.ietf.org/doc/html/rfc9001#section-b.1.1>
- confidentiality_limit: 1 << 23,
- // ref: <https://datatracker.ietf.org/doc/html/rfc9001#section-b.1.2>
- integrity_limit: 1 << 52,
- }),
-};
-
-struct Chacha20Poly1305Aead(AeadAlgorithm);
-
-impl Tls13AeadAlgorithm for Chacha20Poly1305Aead {
- fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> {
- // safety: the caller arranges that `key` is `key_len()` in bytes, so this unwrap is safe.
- Box::new(AeadMessageEncrypter {
- enc_key: aead::LessSafeKey::new(aead::UnboundKey::new(self.0.0, key.as_ref()).unwrap()),
- iv,
- })
- }
-
- fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
- // safety: the caller arranges that `key` is `key_len()` in bytes, so this unwrap is safe.
- Box::new(AeadMessageDecrypter {
- dec_key: aead::LessSafeKey::new(aead::UnboundKey::new(self.0.0, key.as_ref()).unwrap()),
- iv,
- })
- }
-
- fn key_len(&self) -> usize {
- self.0.key_len()
- }
-
- fn extract_keys(
- &self,
- key: AeadKey,
- iv: Iv,
- ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
- Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv })
- }
-
- fn fips(&self) -> bool {
- false // not FIPS approved
- }
-}
-
-struct Aes256GcmAead(AeadAlgorithm);
-
-impl Tls13AeadAlgorithm for Aes256GcmAead {
- fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> {
- self.0.encrypter(key, iv)
- }
-
- fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
- self.0.decrypter(key, iv)
- }
-
- fn key_len(&self) -> usize {
- self.0.key_len()
- }
-
- fn extract_keys(
- &self,
- key: AeadKey,
- iv: Iv,
- ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
- Ok(ConnectionTrafficSecrets::Aes256Gcm { key, iv })
- }
-
- fn fips(&self) -> bool {
- super::fips()
- }
-}
-
-struct Aes128GcmAead(AeadAlgorithm);
-
-impl Tls13AeadAlgorithm for Aes128GcmAead {
- fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> {
- self.0.encrypter(key, iv)
- }
-
- fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
- self.0.decrypter(key, iv)
- }
-
- fn key_len(&self) -> usize {
- self.0.key_len()
- }
-
- fn extract_keys(
- &self,
- key: AeadKey,
- iv: Iv,
- ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
- Ok(ConnectionTrafficSecrets::Aes128Gcm { key, iv })
- }
-
- fn fips(&self) -> bool {
- super::fips()
- }
-}
-
-// common encrypter/decrypter/key_len items for above Tls13AeadAlgorithm impls
-struct AeadAlgorithm(&'static aead::Algorithm);
-
-impl AeadAlgorithm {
- // using aead::TlsRecordSealingKey
- fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> {
- // safety:
- // - the caller arranges that `key` is `key_len()` in bytes, so this unwrap is safe.
- // - this function should only be used for `Algorithm::AES_128_GCM` or `Algorithm::AES_256_GCM`
- Box::new(GcmMessageEncrypter {
- enc_key: aead::TlsRecordSealingKey::new(
- self.0,
- aead::TlsProtocolId::TLS13,
- key.as_ref(),
- )
- .unwrap(),
- iv,
- })
- }
-
- // using aead::TlsRecordOpeningKey
- fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
- // safety:
- // - the caller arranges that `key` is `key_len()` in bytes, so this unwrap is safe.
- // - this function should only be used for `Algorithm::AES_128_GCM` or `Algorithm::AES_256_GCM`
- Box::new(GcmMessageDecrypter {
- dec_key: aead::TlsRecordOpeningKey::new(
- self.0,
- aead::TlsProtocolId::TLS13,
- key.as_ref(),
- )
- .unwrap(),
- iv,
- })
- }
-
- fn key_len(&self) -> usize {
- self.0.key_len()
- }
-}
-
-struct AeadMessageEncrypter {
- enc_key: aead::LessSafeKey,
- iv: Iv,
-}
-
-struct AeadMessageDecrypter {
- dec_key: aead::LessSafeKey,
- iv: Iv,
-}
-
-impl MessageEncrypter for AeadMessageEncrypter {
- fn encrypt(
- &mut self,
- msg: OutboundPlainMessage<'_>,
- seq: u64,
- ) -> Result<OutboundOpaqueMessage, Error> {
- let total_len = self.encrypted_payload_len(msg.payload.len());
- let mut payload = PrefixedPayload::with_capacity(total_len);
-
- let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
- let aad = aead::Aad::from(make_tls13_aad(total_len));
- payload.extend_from_chunks(&msg.payload);
- payload.extend_from_slice(&msg.typ.to_array());
-
- self.enc_key
- .seal_in_place_append_tag(nonce, aad, &mut payload)
- .map_err(|_| Error::EncryptError)?;
-
- Ok(OutboundOpaqueMessage::new(
- ContentType::ApplicationData,
- // Note: all TLS 1.3 application data records use TLSv1_2 (0x0303) as the legacy record
- // protocol version, see https://www.rfc-editor.org/rfc/rfc8446#section-5.1
- ProtocolVersion::TLSv1_2,
- payload,
- ))
- }
-
- fn encrypted_payload_len(&self, payload_len: usize) -> usize {
- payload_len + 1 + self.enc_key.algorithm().tag_len()
- }
-}
-
-impl MessageDecrypter for AeadMessageDecrypter {
- fn decrypt<'a>(
- &mut self,
- mut msg: InboundOpaqueMessage<'a>,
- seq: u64,
- ) -> Result<InboundPlainMessage<'a>, Error> {
- let payload = &mut msg.payload;
- if payload.len() < self.dec_key.algorithm().tag_len() {
- return Err(Error::DecryptError);
- }
-
- let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
- let aad = aead::Aad::from(make_tls13_aad(payload.len()));
- let plain_len = self
- .dec_key
- .open_in_place(nonce, aad, payload)
- .map_err(|_| Error::DecryptError)?
- .len();
-
- payload.truncate(plain_len);
- msg.into_tls13_unpadded_message()
- }
-}
-
-struct GcmMessageEncrypter {
- enc_key: aead::TlsRecordSealingKey,
- iv: Iv,
-}
-
-impl MessageEncrypter for GcmMessageEncrypter {
- fn encrypt(
- &mut self,
- msg: OutboundPlainMessage<'_>,
- seq: u64,
- ) -> Result<OutboundOpaqueMessage, Error> {
- let total_len = self.encrypted_payload_len(msg.payload.len());
- let mut payload = PrefixedPayload::with_capacity(total_len);
-
- let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
- let aad = aead::Aad::from(make_tls13_aad(total_len));
- payload.extend_from_chunks(&msg.payload);
- payload.extend_from_slice(&msg.typ.to_array());
-
- self.enc_key
- .seal_in_place_append_tag(nonce, aad, &mut payload)
- .map_err(|_| Error::EncryptError)?;
-
- Ok(OutboundOpaqueMessage::new(
- ContentType::ApplicationData,
- ProtocolVersion::TLSv1_2,
- payload,
- ))
- }
-
- fn encrypted_payload_len(&self, payload_len: usize) -> usize {
- payload_len + 1 + self.enc_key.algorithm().tag_len()
- }
-}
-
-struct GcmMessageDecrypter {
- dec_key: aead::TlsRecordOpeningKey,
- iv: Iv,
-}
-
-impl MessageDecrypter for GcmMessageDecrypter {
- fn decrypt<'a>(
- &mut self,
- mut msg: InboundOpaqueMessage<'a>,
- seq: u64,
- ) -> Result<InboundPlainMessage<'a>, Error> {
- let payload = &mut msg.payload;
- if payload.len() < self.dec_key.algorithm().tag_len() {
- return Err(Error::DecryptError);
- }
-
- let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
- let aad = aead::Aad::from(make_tls13_aad(payload.len()));
- let plain_len = self
- .dec_key
- .open_in_place(nonce, aad, payload)
- .map_err(|_| Error::DecryptError)?
- .len();
-
- payload.truncate(plain_len);
- msg.into_tls13_unpadded_message()
- }
-}
-
-struct AwsLcHkdf(hkdf::Algorithm, hmac::Algorithm);
-
-impl Hkdf for AwsLcHkdf {
- fn extract_from_zero_ikm(&self, salt: Option<&[u8]>) -> Box<dyn HkdfExpander> {
- let zeroes = [0u8; OkmBlock::MAX_LEN];
- let salt = match salt {
- Some(salt) => salt,
- None => &zeroes[..self.0.len()],
- };
- Box::new(AwsLcHkdfExpander {
- alg: self.0,
- prk: hkdf::Salt::new(self.0, salt).extract(&zeroes[..self.0.len()]),
- })
- }
-
- fn extract_from_secret(&self, salt: Option<&[u8]>, secret: &[u8]) -> Box<dyn HkdfExpander> {
- let zeroes = [0u8; OkmBlock::MAX_LEN];
- let salt = match salt {
- Some(salt) => salt,
- None => &zeroes[..self.0.len()],
- };
- Box::new(AwsLcHkdfExpander {
- alg: self.0,
- prk: hkdf::Salt::new(self.0, salt).extract(secret),
- })
- }
-
- fn expander_for_okm(&self, okm: &OkmBlock) -> Box<dyn HkdfExpander> {
- Box::new(AwsLcHkdfExpander {
- alg: self.0,
- prk: hkdf::Prk::new_less_safe(self.0, okm.as_ref()),
- })
- }
-
- fn hmac_sign(&self, key: &OkmBlock, message: &[u8]) -> crypto::hmac::Tag {
- crypto::hmac::Tag::new(hmac::sign(&hmac::Key::new(self.1, key.as_ref()), message).as_ref())
- }
-
- fn fips(&self) -> bool {
- super::fips()
- }
-}
-
-struct AwsLcHkdfExpander {
- alg: hkdf::Algorithm,
- prk: hkdf::Prk,
-}
-
-impl HkdfExpander for AwsLcHkdfExpander {
- fn expand_slice(&self, info: &[&[u8]], output: &mut [u8]) -> Result<(), OutputLengthError> {
- self.prk
- .expand(info, Len(output.len()))
- .and_then(|okm| okm.fill(output))
- .map_err(|_| OutputLengthError)
- }
-
- fn expand_block(&self, info: &[&[u8]]) -> OkmBlock {
- let mut buf = [0u8; OkmBlock::MAX_LEN];
- let output = &mut buf[..self.hash_len()];
- self.prk
- .expand(info, Len(output.len()))
- .and_then(|okm| okm.fill(output))
- .unwrap();
- OkmBlock::new(output)
- }
-
- fn hash_len(&self) -> usize {
- self.alg.len()
- }
-}
-
-struct Len(usize);
-
-impl KeyType for Len {
- fn len(&self) -> usize {
- self.0
- }
-}
diff --git a/vendor/rustls/src/crypto/cipher.rs b/vendor/rustls/src/crypto/cipher.rs
deleted file mode 100644
index 64901a57..00000000
--- a/vendor/rustls/src/crypto/cipher.rs
+++ /dev/null
@@ -1,350 +0,0 @@
-use alloc::boxed::Box;
-use alloc::string::ToString;
-use core::fmt;
-
-use zeroize::Zeroize;
-
-use crate::enums::{ContentType, ProtocolVersion};
-use crate::error::Error;
-use crate::msgs::codec;
-pub use crate::msgs::message::{
- BorrowedPayload, InboundOpaqueMessage, InboundPlainMessage, OutboundChunks,
- OutboundOpaqueMessage, OutboundPlainMessage, PlainMessage, PrefixedPayload,
-};
-use crate::suites::ConnectionTrafficSecrets;
-
-/// Factory trait for building `MessageEncrypter` and `MessageDecrypter` for a TLS1.3 cipher suite.
-pub trait Tls13AeadAlgorithm: Send + Sync {
- /// Build a `MessageEncrypter` for the given key/iv.
- fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter>;
-
- /// Build a `MessageDecrypter` for the given key/iv.
- fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter>;
-
- /// The length of key in bytes required by `encrypter()` and `decrypter()`.
- fn key_len(&self) -> usize;
-
- /// Convert the key material from `key`/`iv`, into a `ConnectionTrafficSecrets` item.
- ///
- /// May return [`UnsupportedOperationError`] if the AEAD algorithm is not a supported
- /// variant of `ConnectionTrafficSecrets`.
- fn extract_keys(
- &self,
- key: AeadKey,
- iv: Iv,
- ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError>;
-
- /// Return `true` if this is backed by a FIPS-approved implementation.
- fn fips(&self) -> bool {
- false
- }
-}
-
-/// Factory trait for building `MessageEncrypter` and `MessageDecrypter` for a TLS1.2 cipher suite.
-pub trait Tls12AeadAlgorithm: Send + Sync + 'static {
- /// Build a `MessageEncrypter` for the given key/iv and extra key block (which can be used for
- /// improving explicit nonce size security, if needed).
- ///
- /// The length of `key` is set by [`KeyBlockShape::enc_key_len`].
- ///
- /// The length of `iv` is set by [`KeyBlockShape::fixed_iv_len`].
- ///
- /// The length of `extra` is set by [`KeyBlockShape::explicit_nonce_len`].
- fn encrypter(&self, key: AeadKey, iv: &[u8], extra: &[u8]) -> Box<dyn MessageEncrypter>;
-
- /// Build a `MessageDecrypter` for the given key/iv.
- ///
- /// The length of `key` is set by [`KeyBlockShape::enc_key_len`].
- ///
- /// The length of `iv` is set by [`KeyBlockShape::fixed_iv_len`].
- fn decrypter(&self, key: AeadKey, iv: &[u8]) -> Box<dyn MessageDecrypter>;
-
- /// Return a `KeyBlockShape` that defines how large the `key_block` is and how it
- /// is split up prior to calling `encrypter()`, `decrypter()` and/or `extract_keys()`.
- fn key_block_shape(&self) -> KeyBlockShape;
-
- /// Convert the key material from `key`/`iv`, into a `ConnectionTrafficSecrets` item.
- ///
- /// The length of `key` is set by [`KeyBlockShape::enc_key_len`].
- ///
- /// The length of `iv` is set by [`KeyBlockShape::fixed_iv_len`].
- ///
- /// The length of `extra` is set by [`KeyBlockShape::explicit_nonce_len`].
- ///
- /// May return [`UnsupportedOperationError`] if the AEAD algorithm is not a supported
- /// variant of `ConnectionTrafficSecrets`.
- fn extract_keys(
- &self,
- key: AeadKey,
- iv: &[u8],
- explicit: &[u8],
- ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError>;
-
- /// Return `true` if this is backed by a FIPS-approved implementation.
- fn fips(&self) -> bool {
- false
- }
-}
-
-/// An error indicating that the AEAD algorithm does not support the requested operation.
-#[derive(Debug, Eq, PartialEq, Clone, Copy)]
-pub struct UnsupportedOperationError;
-
-impl From<UnsupportedOperationError> for Error {
- fn from(value: UnsupportedOperationError) -> Self {
- Self::General(value.to_string())
- }
-}
-
-impl fmt::Display for UnsupportedOperationError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "operation not supported")
- }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for UnsupportedOperationError {}
-
-/// How a TLS1.2 `key_block` is partitioned.
-///
-/// Note: ciphersuites with non-zero `mac_key_length` are not currently supported.
-pub struct KeyBlockShape {
- /// How long keys are.
- ///
- /// `enc_key_length` terminology is from the standard ([RFC5246 A.6]).
- ///
- /// [RFC5246 A.6]: <https://www.rfc-editor.org/rfc/rfc5246#appendix-A.6>
- pub enc_key_len: usize,
-
- /// How long the fixed part of the 'IV' is.
- ///
- /// `fixed_iv_length` terminology is from the standard ([RFC5246 A.6]).
- ///
- /// This isn't usually an IV, but we continue the
- /// terminology misuse to match the standard.
- ///
- /// [RFC5246 A.6]: <https://www.rfc-editor.org/rfc/rfc5246#appendix-A.6>
- pub fixed_iv_len: usize,
-
- /// This is a non-standard extension which extends the
- /// key block to provide an initial explicit nonce offset,
- /// in a deterministic and safe way. GCM needs this,
- /// chacha20poly1305 works this way by design.
- pub explicit_nonce_len: usize,
-}
-
-/// Objects with this trait can decrypt TLS messages.
-pub trait MessageDecrypter: Send + Sync {
- /// Decrypt the given TLS message `msg`, using the sequence number
- /// `seq` which can be used to derive a unique [`Nonce`].
- fn decrypt<'a>(
- &mut self,
- msg: InboundOpaqueMessage<'a>,
- seq: u64,
- ) -> Result<InboundPlainMessage<'a>, Error>;
-}
-
-/// Objects with this trait can encrypt TLS messages.
-pub trait MessageEncrypter: Send + Sync {
- /// Encrypt the given TLS message `msg`, using the sequence number
- /// `seq` which can be used to derive a unique [`Nonce`].
- fn encrypt(
- &mut self,
- msg: OutboundPlainMessage<'_>,
- seq: u64,
- ) -> Result<OutboundOpaqueMessage, Error>;
-
- /// Return the length of the ciphertext that results from encrypting plaintext of
- /// length `payload_len`
- fn encrypted_payload_len(&self, payload_len: usize) -> usize;
-}
-
-impl dyn MessageEncrypter {
- pub(crate) fn invalid() -> Box<dyn MessageEncrypter> {
- Box::new(InvalidMessageEncrypter {})
- }
-}
-
-impl dyn MessageDecrypter {
- pub(crate) fn invalid() -> Box<dyn MessageDecrypter> {
- Box::new(InvalidMessageDecrypter {})
- }
-}
-
-/// A write or read IV.
-#[derive(Default)]
-pub struct Iv([u8; NONCE_LEN]);
-
-impl Iv {
- /// Create a new `Iv` from a byte array, of precisely `NONCE_LEN` bytes.
- #[cfg(feature = "tls12")]
- pub fn new(value: [u8; NONCE_LEN]) -> Self {
- Self(value)
- }
-
- /// Create a new `Iv` from a byte slice, of precisely `NONCE_LEN` bytes.
- #[cfg(feature = "tls12")]
- pub fn copy(value: &[u8]) -> Self {
- debug_assert_eq!(value.len(), NONCE_LEN);
- let mut iv = Self::new(Default::default());
- iv.0.copy_from_slice(value);
- iv
- }
-}
-
-impl From<[u8; NONCE_LEN]> for Iv {
- fn from(bytes: [u8; NONCE_LEN]) -> Self {
- Self(bytes)
- }
-}
-
-impl AsRef<[u8]> for Iv {
- fn as_ref(&self) -> &[u8] {
- self.0.as_ref()
- }
-}
-
-/// A nonce. This is unique for all messages on a connection.
-pub struct Nonce(pub [u8; NONCE_LEN]);
-
-impl Nonce {
- /// Combine an `Iv` and sequence number to produce a unique nonce.
- ///
- /// This is `iv ^ seq` where `seq` is encoded as a 96-bit big-endian integer.
- #[inline]
- pub fn new(iv: &Iv, seq: u64) -> Self {
- let mut nonce = Self([0u8; NONCE_LEN]);
- codec::put_u64(seq, &mut nonce.0[4..]);
-
- nonce
- .0
- .iter_mut()
- .zip(iv.0.iter())
- .for_each(|(nonce, iv)| {
- *nonce ^= *iv;
- });
-
- nonce
- }
-}
-
-/// Size of TLS nonces (incorrectly termed "IV" in standard) for all supported ciphersuites
-/// (AES-GCM, Chacha20Poly1305)
-pub const NONCE_LEN: usize = 12;
-
-/// Returns a TLS1.3 `additional_data` encoding.
-///
-/// See RFC8446 s5.2 for the `additional_data` definition.
-#[inline]
-pub fn make_tls13_aad(payload_len: usize) -> [u8; 5] {
- let version = ProtocolVersion::TLSv1_2.to_array();
- [
- ContentType::ApplicationData.into(),
- // Note: this is `legacy_record_version`, i.e. TLS1.2 even for TLS1.3.
- version[0],
- version[1],
- (payload_len >> 8) as u8,
- (payload_len & 0xff) as u8,
- ]
-}
-
-/// Returns a TLS1.2 `additional_data` encoding.
-///
-/// See RFC5246 s6.2.3.3 for the `additional_data` definition.
-#[inline]
-pub fn make_tls12_aad(
- seq: u64,
- typ: ContentType,
- vers: ProtocolVersion,
- len: usize,
-) -> [u8; TLS12_AAD_SIZE] {
- let mut out = [0; TLS12_AAD_SIZE];
- codec::put_u64(seq, &mut out[0..]);
- out[8] = typ.into();
- codec::put_u16(vers.into(), &mut out[9..]);
- codec::put_u16(len as u16, &mut out[11..]);
- out
-}
-
-const TLS12_AAD_SIZE: usize = 8 + 1 + 2 + 2;
-
-/// A key for an AEAD algorithm.
-///
-/// This is a value type for a byte string up to `AeadKey::MAX_LEN` bytes in length.
-pub struct AeadKey {
- buf: [u8; Self::MAX_LEN],
- used: usize,
-}
-
-impl AeadKey {
- #[cfg(feature = "tls12")]
- pub(crate) fn new(buf: &[u8]) -> Self {
- debug_assert!(buf.len() <= Self::MAX_LEN);
- let mut key = Self::from([0u8; Self::MAX_LEN]);
- key.buf[..buf.len()].copy_from_slice(buf);
- key.used = buf.len();
- key
- }
-
- pub(crate) fn with_length(self, len: usize) -> Self {
- assert!(len <= self.used);
- Self {
- buf: self.buf,
- used: len,
- }
- }
-
- /// Largest possible AEAD key in the ciphersuites we support.
- pub(crate) const MAX_LEN: usize = 32;
-}
-
-impl Drop for AeadKey {
- fn drop(&mut self) {
- self.buf.zeroize();
- }
-}
-
-impl AsRef<[u8]> for AeadKey {
- fn as_ref(&self) -> &[u8] {
- &self.buf[..self.used]
- }
-}
-
-impl From<[u8; Self::MAX_LEN]> for AeadKey {
- fn from(bytes: [u8; Self::MAX_LEN]) -> Self {
- Self {
- buf: bytes,
- used: Self::MAX_LEN,
- }
- }
-}
-
-/// A `MessageEncrypter` which doesn't work.
-struct InvalidMessageEncrypter {}
-
-impl MessageEncrypter for InvalidMessageEncrypter {
- fn encrypt(
- &mut self,
- _m: OutboundPlainMessage<'_>,
- _seq: u64,
- ) -> Result<OutboundOpaqueMessage, Error> {
- Err(Error::EncryptError)
- }
-
- fn encrypted_payload_len(&self, payload_len: usize) -> usize {
- payload_len
- }
-}
-
-/// A `MessageDecrypter` which doesn't work.
-struct InvalidMessageDecrypter {}
-
-impl MessageDecrypter for InvalidMessageDecrypter {
- fn decrypt<'a>(
- &mut self,
- _m: InboundOpaqueMessage<'a>,
- _seq: u64,
- ) -> Result<InboundPlainMessage<'a>, Error> {
- Err(Error::DecryptError)
- }
-}
diff --git a/vendor/rustls/src/crypto/hash.rs b/vendor/rustls/src/crypto/hash.rs
deleted file mode 100644
index 214dad4e..00000000
--- a/vendor/rustls/src/crypto/hash.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-use alloc::boxed::Box;
-
-pub use crate::msgs::enums::HashAlgorithm;
-
-/// Describes a single cryptographic hash function.
-///
-/// This interface can do both one-shot and incremental hashing, using
-/// [`Hash::hash()`] and [`Hash::start()`] respectively.
-pub trait Hash: Send + Sync {
- /// Start an incremental hash computation.
- fn start(&self) -> Box<dyn Context>;
-
- /// Return the output of this hash function with input `data`.
- fn hash(&self, data: &[u8]) -> Output;
-
- /// The length in bytes of this hash function's output.
- fn output_len(&self) -> usize;
-
- /// Which hash function this is, eg, `HashAlgorithm::SHA256`.
- fn algorithm(&self) -> HashAlgorithm;
-
- /// Return `true` if this is backed by a FIPS-approved implementation.
- fn fips(&self) -> bool {
- false
- }
-}
-
-/// A hash output, stored as a value.
-pub struct Output {
- buf: [u8; Self::MAX_LEN],
- used: usize,
-}
-
-impl Output {
- /// Build a `hash::Output` from a slice of no more than `Output::MAX_LEN` bytes.
- pub fn new(bytes: &[u8]) -> Self {
- let mut output = Self {
- buf: [0u8; Self::MAX_LEN],
- used: bytes.len(),
- };
- debug_assert!(bytes.len() <= Self::MAX_LEN);
- output.buf[..bytes.len()].copy_from_slice(bytes);
- output
- }
-
- /// Maximum supported hash output size: supports up to SHA512.
- pub const MAX_LEN: usize = 64;
-}
-
-impl AsRef<[u8]> for Output {
- fn as_ref(&self) -> &[u8] {
- &self.buf[..self.used]
- }
-}
-
-/// How to incrementally compute a hash.
-pub trait Context: Send + Sync {
- /// Finish the computation, returning the resulting output.
- ///
- /// The computation remains valid, and more data can be added later with
- /// [`Context::update()`].
- ///
- /// Compare with [`Context::finish()`] which consumes the computation
- /// and prevents any further data being added. This can be more efficient
- /// because it avoids a hash context copy to apply Merkle-Damgård padding
- /// (if required).
- fn fork_finish(&self) -> Output;
-
- /// Fork the computation, producing another context that has the
- /// same prefix as this one.
- fn fork(&self) -> Box<dyn Context>;
-
- /// Terminate and finish the computation, returning the resulting output.
- ///
- /// Further data cannot be added after this, because the context is consumed.
- /// Compare [`Context::fork_finish()`].
- fn finish(self: Box<Self>) -> Output;
-
- /// Add `data` to computation.
- fn update(&mut self, data: &[u8]);
-}
diff --git a/vendor/rustls/src/crypto/hmac.rs b/vendor/rustls/src/crypto/hmac.rs
deleted file mode 100644
index 6960b7e6..00000000
--- a/vendor/rustls/src/crypto/hmac.rs
+++ /dev/null
@@ -1,73 +0,0 @@
-use alloc::boxed::Box;
-
-use zeroize::Zeroize;
-
-/// A concrete HMAC implementation, for a single cryptographic hash function.
-///
-/// You should have one object that implements this trait for HMAC-SHA256, another
-/// for HMAC-SHA384, etc.
-pub trait Hmac: Send + Sync {
- /// Prepare to use `key` as a HMAC key.
- fn with_key(&self, key: &[u8]) -> Box<dyn Key>;
-
- /// Give the length of the underlying hash function. In RFC2104 terminology this is `L`.
- fn hash_output_len(&self) -> usize;
-
- /// Return `true` if this is backed by a FIPS-approved implementation.
- fn fips(&self) -> bool {
- false
- }
-}
-
-/// A HMAC tag, stored as a value.
-#[derive(Clone)]
-pub struct Tag {
- buf: [u8; Self::MAX_LEN],
- used: usize,
-}
-
-impl Tag {
- /// Build a tag by copying a byte slice.
- ///
- /// The slice can be up to [`Tag::MAX_LEN`] bytes in length.
- pub fn new(bytes: &[u8]) -> Self {
- let mut tag = Self {
- buf: [0u8; Self::MAX_LEN],
- used: bytes.len(),
- };
- tag.buf[..bytes.len()].copy_from_slice(bytes);
- tag
- }
-
- /// Maximum supported HMAC tag size: supports up to SHA512.
- pub const MAX_LEN: usize = 64;
-}
-
-impl Drop for Tag {
- fn drop(&mut self) {
- self.buf.zeroize();
- }
-}
-
-impl AsRef<[u8]> for Tag {
- fn as_ref(&self) -> &[u8] {
- &self.buf[..self.used]
- }
-}
-
-/// A HMAC key that is ready for use.
-///
-/// The algorithm used is implicit in the `Hmac` object that produced the key.
-pub trait Key: Send + Sync {
- /// Calculates a tag over `data` -- a slice of byte slices.
- fn sign(&self, data: &[&[u8]]) -> Tag {
- self.sign_concat(&[], data, &[])
- }
-
- /// Calculates a tag over the concatenation of `first`, the items in `middle`, and `last`.
- fn sign_concat(&self, first: &[u8], middle: &[&[u8]], last: &[u8]) -> Tag;
-
- /// Returns the length of the tag returned by a computation using
- /// this key.
- fn tag_len(&self) -> usize;
-}
diff --git a/vendor/rustls/src/crypto/hpke.rs b/vendor/rustls/src/crypto/hpke.rs
deleted file mode 100644
index 62074150..00000000
--- a/vendor/rustls/src/crypto/hpke.rs
+++ /dev/null
@@ -1,145 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec::Vec;
-use core::fmt::Debug;
-
-use zeroize::Zeroize;
-
-use crate::Error;
-use crate::msgs::enums::HpkeKem;
-use crate::msgs::handshake::HpkeSymmetricCipherSuite;
-
-/// An HPKE suite, specifying a key encapsulation mechanism and a symmetric cipher suite.
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub struct HpkeSuite {
- /// The choice of HPKE key encapsulation mechanism.
- pub kem: HpkeKem,
-
- /// The choice of HPKE symmetric cipher suite.
- ///
- /// This combines a choice of authenticated encryption with additional data (AEAD) algorithm
- /// and a key derivation function (KDF).
- pub sym: HpkeSymmetricCipherSuite,
-}
-
-/// An HPKE instance that can be used for base-mode single-shot encryption and decryption.
-pub trait Hpke: Debug + Send + Sync {
- /// Seal the provided `plaintext` to the recipient public key `pub_key` with application supplied
- /// `info`, and additional data `aad`.
- ///
- /// Returns ciphertext that can be used with [Self::open] by the recipient to recover plaintext
- /// using the same `info` and `aad` and the private key corresponding to `pub_key`. RFC 9180
- /// refers to `pub_key` as `pkR`.
- fn seal(
- &self,
- info: &[u8],
- aad: &[u8],
- plaintext: &[u8],
- pub_key: &HpkePublicKey,
- ) -> Result<(EncapsulatedSecret, Vec<u8>), Error>;
-
- /// Set up a sealer context for the receiver public key `pub_key` with application supplied `info`.
- ///
- /// Returns both an encapsulated ciphertext and a sealer context that can be used to seal
- /// messages to the recipient. RFC 9180 refers to `pub_key` as `pkR`.
- fn setup_sealer(
- &self,
- info: &[u8],
- pub_key: &HpkePublicKey,
- ) -> Result<(EncapsulatedSecret, Box<dyn HpkeSealer + 'static>), Error>;
-
- /// Open the provided `ciphertext` using the encapsulated secret `enc`, with application
- /// supplied `info`, and additional data `aad`.
- ///
- /// Returns plaintext if the `info` and `aad` match those used with [Self::seal], and
- /// decryption with `secret_key` succeeds. RFC 9180 refers to `secret_key` as `skR`.
- fn open(
- &self,
- enc: &EncapsulatedSecret,
- info: &[u8],
- aad: &[u8],
- ciphertext: &[u8],
- secret_key: &HpkePrivateKey,
- ) -> Result<Vec<u8>, Error>;
-
- /// Set up an opener context for the secret key `secret_key` with application supplied `info`.
- ///
- /// Returns an opener context that can be used to open sealed messages encrypted to the
- /// public key corresponding to `secret_key`. RFC 9180 refers to `secret_key` as `skR`.
- fn setup_opener(
- &self,
- enc: &EncapsulatedSecret,
- info: &[u8],
- secret_key: &HpkePrivateKey,
- ) -> Result<Box<dyn HpkeOpener + 'static>, Error>;
-
- /// Generate a new public key and private key pair compatible with this HPKE instance.
- ///
- /// Key pairs should be encoded as raw big endian fixed length integers sized based
- /// on the suite's DH KEM algorithm.
- fn generate_key_pair(&self) -> Result<(HpkePublicKey, HpkePrivateKey), Error>;
-
- /// Return whether the HPKE instance is FIPS compatible.
- fn fips(&self) -> bool {
- false
- }
-
- /// Return the [HpkeSuite] that this HPKE instance supports.
- fn suite(&self) -> HpkeSuite;
-}
-
-/// An HPKE sealer context.
-///
-/// This is a stateful object that can be used to seal messages for receipt by
-/// a receiver.
-pub trait HpkeSealer: Debug + Send + Sync + 'static {
- /// Seal the provided `plaintext` with additional data `aad`, returning
- /// ciphertext.
- fn seal(&mut self, aad: &[u8], plaintext: &[u8]) -> Result<Vec<u8>, Error>;
-}
-
-/// An HPKE opener context.
-///
-/// This is a stateful object that can be used to open sealed messages sealed
-/// by a sender.
-pub trait HpkeOpener: Debug + Send + Sync + 'static {
- /// Open the provided `ciphertext` with additional data `aad`, returning plaintext.
- fn open(&mut self, aad: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, Error>;
-}
-
-/// An HPKE public key.
-#[derive(Clone, Debug)]
-pub struct HpkePublicKey(pub Vec<u8>);
-
-/// An HPKE private key.
-pub struct HpkePrivateKey(Vec<u8>);
-
-impl HpkePrivateKey {
- /// Return the private key bytes.
- pub fn secret_bytes(&self) -> &[u8] {
- self.0.as_slice()
- }
-}
-
-impl From<Vec<u8>> for HpkePrivateKey {
- fn from(bytes: Vec<u8>) -> Self {
- Self(bytes)
- }
-}
-
-impl Drop for HpkePrivateKey {
- fn drop(&mut self) {
- self.0.zeroize();
- }
-}
-
-/// An HPKE key pair, made of a matching public and private key.
-pub struct HpkeKeyPair {
- /// A HPKE public key.
- pub public_key: HpkePublicKey,
- /// A HPKE private key.
- pub private_key: HpkePrivateKey,
-}
-
-/// An encapsulated secret returned from setting up a sender or receiver context.
-#[derive(Debug)]
-pub struct EncapsulatedSecret(pub Vec<u8>);
diff --git a/vendor/rustls/src/crypto/mod.rs b/vendor/rustls/src/crypto/mod.rs
deleted file mode 100644
index 3ce026b9..00000000
--- a/vendor/rustls/src/crypto/mod.rs
+++ /dev/null
@@ -1,756 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec::Vec;
-use core::fmt::Debug;
-
-use pki_types::PrivateKeyDer;
-use zeroize::Zeroize;
-
-#[cfg(all(doc, feature = "tls12"))]
-use crate::Tls12CipherSuite;
-use crate::msgs::ffdhe_groups::FfdheGroup;
-use crate::sign::SigningKey;
-use crate::sync::Arc;
-pub use crate::webpki::{
- WebPkiSupportedAlgorithms, verify_tls12_signature, verify_tls13_signature,
- verify_tls13_signature_with_raw_key,
-};
-#[cfg(doc)]
-use crate::{
- ClientConfig, ConfigBuilder, ServerConfig, SupportedCipherSuite, Tls13CipherSuite, client,
- crypto, server, sign,
-};
-use crate::{Error, NamedGroup, ProtocolVersion, SupportedProtocolVersion, suites};
-
-/// *ring* based CryptoProvider.
-#[cfg(feature = "ring")]
-pub mod ring;
-
-/// aws-lc-rs-based CryptoProvider.
-#[cfg(feature = "aws_lc_rs")]
-pub mod aws_lc_rs;
-
-/// TLS message encryption/decryption interfaces.
-pub mod cipher;
-
-/// Hashing interfaces.
-pub mod hash;
-
-/// HMAC interfaces.
-pub mod hmac;
-
-#[cfg(feature = "tls12")]
-/// Cryptography specific to TLS1.2.
-pub mod tls12;
-
-/// Cryptography specific to TLS1.3.
-pub mod tls13;
-
-/// Hybrid public key encryption (RFC 9180).
-pub mod hpke;
-
-// Message signing interfaces. Re-exported under rustls::sign. Kept crate-internal here to
-// avoid having two import paths to the same types.
-pub(crate) mod signer;
-
-pub use crate::msgs::handshake::KeyExchangeAlgorithm;
-pub use crate::rand::GetRandomFailed;
-pub use crate::suites::CipherSuiteCommon;
-
-/// Controls core cryptography used by rustls.
-///
-/// This crate comes with two built-in options, provided as
-/// `CryptoProvider` structures:
-///
-/// - [`crypto::aws_lc_rs::default_provider`]: (behind the `aws_lc_rs` crate feature,
-/// which is enabled by default). This provider uses the [aws-lc-rs](https://github.com/aws/aws-lc-rs)
-/// crate. The `fips` crate feature makes this option use FIPS140-3-approved cryptography.
-/// - [`crypto::ring::default_provider`]: (behind the `ring` crate feature, which
-/// is optional). This provider uses the [*ring*](https://github.com/briansmith/ring)
-/// crate.
-///
-/// This structure provides defaults. Everything in it can be overridden at
-/// runtime by replacing field values as needed.
-///
-/// # Using the per-process default `CryptoProvider`
-///
-/// There is the concept of an implicit default provider, configured at run-time once in
-/// a given process.
-///
-/// It is used for functions like [`ClientConfig::builder()`] and [`ServerConfig::builder()`].
-///
-/// The intention is that an application can specify the [`CryptoProvider`] they wish to use
-/// once, and have that apply to the variety of places where their application does TLS
-/// (which may be wrapped inside other libraries).
-/// They should do this by calling [`CryptoProvider::install_default()`] early on.
-///
-/// To achieve this goal:
-///
-/// - _libraries_ should use [`ClientConfig::builder()`]/[`ServerConfig::builder()`]
-/// or otherwise rely on the [`CryptoProvider::get_default()`] provider.
-/// - _applications_ should call [`CryptoProvider::install_default()`] early
-/// in their `fn main()`. If _applications_ uses a custom provider based on the one built-in,
-/// they can activate the `custom-provider` feature to ensure its usage.
-///
-/// # Using a specific `CryptoProvider`
-///
-/// Supply the provider when constructing your [`ClientConfig`] or [`ServerConfig`]:
-///
-/// - [`ClientConfig::builder_with_provider()`]
-/// - [`ServerConfig::builder_with_provider()`]
-///
-/// When creating and configuring a webpki-backed client or server certificate verifier, a choice of
-/// provider is also needed to start the configuration process:
-///
-/// - [`client::WebPkiServerVerifier::builder_with_provider()`]
-/// - [`server::WebPkiClientVerifier::builder_with_provider()`]
-///
-/// If you install a custom provider and want to avoid any accidental use of a built-in provider, the feature
-/// `custom-provider` can be activated to ensure your custom provider is used everywhere
-/// and not a built-in one. This will disable any implicit use of a built-in provider.
-///
-/// # Making a custom `CryptoProvider`
-///
-/// Your goal will be to populate an instance of this `CryptoProvider` struct.
-///
-/// ## Which elements are required?
-///
-/// There is no requirement that the individual elements ([`SupportedCipherSuite`], [`SupportedKxGroup`],
-/// [`SigningKey`], etc.) come from the same crate. It is allowed and expected that uninteresting
-/// elements would be delegated back to one of the default providers (statically) or a parent
-/// provider (dynamically).
-///
-/// For example, if we want to make a provider that just overrides key loading in the config builder
-/// API (with [`ConfigBuilder::with_single_cert`], etc.), it might look like this:
-///
-/// ```
-/// # #[cfg(feature = "aws_lc_rs")] {
-/// # use std::sync::Arc;
-/// # mod fictious_hsm_api { pub fn load_private_key(key_der: pki_types::PrivateKeyDer<'static>) -> ! { unreachable!(); } }
-/// use rustls::crypto::aws_lc_rs;
-///
-/// pub fn provider() -> rustls::crypto::CryptoProvider {
-/// rustls::crypto::CryptoProvider{
-/// key_provider: &HsmKeyLoader,
-/// ..aws_lc_rs::default_provider()
-/// }
-/// }
-///
-/// #[derive(Debug)]
-/// struct HsmKeyLoader;
-///
-/// impl rustls::crypto::KeyProvider for HsmKeyLoader {
-/// fn load_private_key(&self, key_der: pki_types::PrivateKeyDer<'static>) -> Result<Arc<dyn rustls::sign::SigningKey>, rustls::Error> {
-/// fictious_hsm_api::load_private_key(key_der)
-/// }
-/// }
-/// # }
-/// ```
-///
-/// ## References to the individual elements
-///
-/// The elements are documented separately:
-///
-/// - **Random** - see [`crypto::SecureRandom::fill()`].
-/// - **Cipher suites** - see [`SupportedCipherSuite`], [`Tls12CipherSuite`], and
-/// [`Tls13CipherSuite`].
-/// - **Key exchange groups** - see [`crypto::SupportedKxGroup`].
-/// - **Signature verification algorithms** - see [`crypto::WebPkiSupportedAlgorithms`].
-/// - **Authentication key loading** - see [`crypto::KeyProvider::load_private_key()`] and
-/// [`sign::SigningKey`].
-///
-/// # Example code
-///
-/// See custom [`provider-example/`] for a full client and server example that uses
-/// cryptography from the [`RustCrypto`] and [`dalek-cryptography`] projects.
-///
-/// ```shell
-/// $ cargo run --example client | head -3
-/// Current ciphersuite: TLS13_CHACHA20_POLY1305_SHA256
-/// HTTP/1.1 200 OK
-/// Content-Type: text/html; charset=utf-8
-/// Content-Length: 19899
-/// ```
-///
-/// [`provider-example/`]: https://github.com/rustls/rustls/tree/main/provider-example/
-/// [`RustCrypto`]: https://github.com/RustCrypto
-/// [`dalek-cryptography`]: https://github.com/dalek-cryptography
-///
-/// # FIPS-approved cryptography
-/// The `fips` crate feature enables use of the `aws-lc-rs` crate in FIPS mode.
-///
-/// You can verify the configuration at runtime by checking
-/// [`ServerConfig::fips()`]/[`ClientConfig::fips()`] return `true`.
-#[derive(Debug, Clone)]
-pub struct CryptoProvider {
- /// List of supported ciphersuites, in preference order -- the first element
- /// is the highest priority.
- ///
- /// The `SupportedCipherSuite` type carries both configuration and implementation.
- ///
- /// A valid `CryptoProvider` must ensure that all cipher suites are accompanied by at least
- /// one matching key exchange group in [`CryptoProvider::kx_groups`].
- pub cipher_suites: Vec<suites::SupportedCipherSuite>,
-
- /// List of supported key exchange groups, in preference order -- the
- /// first element is the highest priority.
- ///
- /// The first element in this list is the _default key share algorithm_,
- /// and in TLS1.3 a key share for it is sent in the client hello.
- ///
- /// The `SupportedKxGroup` type carries both configuration and implementation.
- pub kx_groups: Vec<&'static dyn SupportedKxGroup>,
-
- /// List of signature verification algorithms for use with webpki.
- ///
- /// These are used for both certificate chain verification and handshake signature verification.
- ///
- /// This is called by [`ConfigBuilder::with_root_certificates()`],
- /// [`server::WebPkiClientVerifier::builder_with_provider()`] and
- /// [`client::WebPkiServerVerifier::builder_with_provider()`].
- pub signature_verification_algorithms: WebPkiSupportedAlgorithms,
-
- /// Source of cryptographically secure random numbers.
- pub secure_random: &'static dyn SecureRandom,
-
- /// Provider for loading private [`SigningKey`]s from [`PrivateKeyDer`].
- pub key_provider: &'static dyn KeyProvider,
-}
-
-impl CryptoProvider {
- /// Sets this `CryptoProvider` as the default for this process.
- ///
- /// This can be called successfully at most once in any process execution.
- ///
- /// Call this early in your process to configure which provider is used for
- /// the provider. The configuration should happen before any use of
- /// [`ClientConfig::builder()`] or [`ServerConfig::builder()`].
- pub fn install_default(self) -> Result<(), Arc<Self>> {
- static_default::install_default(self)
- }
-
- /// Returns the default `CryptoProvider` for this process.
- ///
- /// This will be `None` if no default has been set yet.
- pub fn get_default() -> Option<&'static Arc<Self>> {
- static_default::get_default()
- }
-
- /// An internal function that:
- ///
- /// - gets the pre-installed default, or
- /// - installs one `from_crate_features()`, or else
- /// - panics about the need to call [`CryptoProvider::install_default()`]
- pub(crate) fn get_default_or_install_from_crate_features() -> &'static Arc<Self> {
- if let Some(provider) = Self::get_default() {
- return provider;
- }
-
- let provider = Self::from_crate_features()
- .expect("no process-level CryptoProvider available -- call CryptoProvider::install_default() before this point");
- // Ignore the error resulting from us losing a race, and accept the outcome.
- let _ = provider.install_default();
- Self::get_default().unwrap()
- }
-
- /// Returns a provider named unambiguously by rustls crate features.
- ///
- /// This function returns `None` if the crate features are ambiguous (ie, specify two
- /// providers), or specify no providers, or the feature `custom-provider` is activated.
- /// In all cases the application should explicitly specify the provider to use
- /// with [`CryptoProvider::install_default`].
- fn from_crate_features() -> Option<Self> {
- #[cfg(all(
- feature = "ring",
- not(feature = "aws_lc_rs"),
- not(feature = "custom-provider")
- ))]
- {
- return Some(ring::default_provider());
- }
-
- #[cfg(all(
- feature = "aws_lc_rs",
- not(feature = "ring"),
- not(feature = "custom-provider")
- ))]
- {
- return Some(aws_lc_rs::default_provider());
- }
-
- #[allow(unreachable_code)]
- None
- }
-
- /// Returns `true` if this `CryptoProvider` is operating in FIPS mode.
- ///
- /// This covers only the cryptographic parts of FIPS approval. There are
- /// also TLS protocol-level recommendations made by NIST. You should
- /// prefer to call [`ClientConfig::fips()`] or [`ServerConfig::fips()`]
- /// which take these into account.
- pub fn fips(&self) -> bool {
- let Self {
- cipher_suites,
- kx_groups,
- signature_verification_algorithms,
- secure_random,
- key_provider,
- } = self;
- cipher_suites.iter().all(|cs| cs.fips())
- && kx_groups.iter().all(|kx| kx.fips())
- && signature_verification_algorithms.fips()
- && secure_random.fips()
- && key_provider.fips()
- }
-}
-
-/// A source of cryptographically secure randomness.
-pub trait SecureRandom: Send + Sync + Debug {
- /// Fill the given buffer with random bytes.
- ///
- /// The bytes must be sourced from a cryptographically secure random number
- /// generator seeded with good quality, secret entropy.
- ///
- /// This is used for all randomness required by rustls, but not necessarily
- /// randomness required by the underlying cryptography library. For example:
- /// [`SupportedKxGroup::start()`] requires random material to generate
- /// an ephemeral key exchange key, but this is not included in the interface with
- /// rustls: it is assumed that the cryptography library provides for this itself.
- fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed>;
-
- /// Return `true` if this is backed by a FIPS-approved implementation.
- fn fips(&self) -> bool {
- false
- }
-}
-
-/// A mechanism for loading private [`SigningKey`]s from [`PrivateKeyDer`].
-///
-/// This trait is intended to be used with private key material that is sourced from DER,
-/// such as a private-key that may be present on-disk. It is not intended to be used with
-/// keys held in hardware security modules (HSMs) or physical tokens. For these use-cases
-/// see the Rustls manual section on [customizing private key usage].
-///
-/// [customizing private key usage]: <https://docs.rs/rustls/latest/rustls/manual/_03_howto/index.html#customising-private-key-usage>
-pub trait KeyProvider: Send + Sync + Debug {
- /// Decode and validate a private signing key from `key_der`.
- ///
- /// This is used by [`ConfigBuilder::with_client_auth_cert()`], [`ConfigBuilder::with_single_cert()`],
- /// and [`ConfigBuilder::with_single_cert_with_ocsp()`]. The key types and formats supported by this
- /// function directly defines the key types and formats supported in those APIs.
- ///
- /// Return an error if the key type encoding is not supported, or if the key fails validation.
- fn load_private_key(
- &self,
- key_der: PrivateKeyDer<'static>,
- ) -> Result<Arc<dyn SigningKey>, Error>;
-
- /// Return `true` if this is backed by a FIPS-approved implementation.
- ///
- /// If this returns `true`, that must be the case for all possible key types
- /// supported by [`KeyProvider::load_private_key()`].
- fn fips(&self) -> bool {
- false
- }
-}
-
-/// A supported key exchange group.
-///
-/// This type carries both configuration and implementation. Specifically,
-/// it has a TLS-level name expressed using the [`NamedGroup`] enum, and
-/// a function which produces a [`ActiveKeyExchange`].
-///
-/// Compare with [`NamedGroup`], which carries solely a protocol identifier.
-pub trait SupportedKxGroup: Send + Sync + Debug {
- /// Start a key exchange.
- ///
- /// This will prepare an ephemeral secret key in the supported group, and a corresponding
- /// public key. The key exchange can be completed by calling [ActiveKeyExchange#complete]
- /// or discarded.
- ///
- /// # Errors
- ///
- /// This can fail if the random source fails during ephemeral key generation.
- fn start(&self) -> Result<Box<dyn ActiveKeyExchange>, Error>;
-
- /// Start and complete a key exchange, in one operation.
- ///
- /// The default implementation for this calls `start()` and then calls
- /// `complete()` on the result. This is suitable for Diffie-Hellman-like
- /// key exchange algorithms, where there is not a data dependency between
- /// our key share (named "pub_key" in this API) and the peer's (`peer_pub_key`).
- ///
- /// If there is such a data dependency (like key encapsulation mechanisms), this
- /// function should be implemented.
- fn start_and_complete(&self, peer_pub_key: &[u8]) -> Result<CompletedKeyExchange, Error> {
- let kx = self.start()?;
-
- Ok(CompletedKeyExchange {
- group: kx.group(),
- pub_key: kx.pub_key().to_vec(),
- secret: kx.complete(peer_pub_key)?,
- })
- }
-
- /// FFDHE group the `SupportedKxGroup` operates in.
- ///
- /// Return `None` if this group is not a FFDHE one.
- ///
- /// The default implementation calls `FfdheGroup::from_named_group`: this function
- /// is extremely linker-unfriendly so it is recommended all key exchange implementers
- /// provide this function.
- ///
- /// `rustls::ffdhe_groups` contains suitable values to return from this,
- /// for example [`rustls::ffdhe_groups::FFDHE2048`][crate::ffdhe_groups::FFDHE2048].
- fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
- #[allow(deprecated)]
- FfdheGroup::from_named_group(self.name())
- }
-
- /// Named group the SupportedKxGroup operates in.
- ///
- /// If the `NamedGroup` enum does not have a name for the algorithm you are implementing,
- /// you can use [`NamedGroup::Unknown`].
- fn name(&self) -> NamedGroup;
-
- /// Return `true` if this is backed by a FIPS-approved implementation.
- fn fips(&self) -> bool {
- false
- }
-
- /// Return `true` if this should be offered/selected with the given version.
- ///
- /// The default implementation returns true for all versions.
- fn usable_for_version(&self, _version: ProtocolVersion) -> bool {
- true
- }
-}
-
-/// An in-progress key exchange originating from a [`SupportedKxGroup`].
-pub trait ActiveKeyExchange: Send + Sync {
- /// Completes the key exchange, given the peer's public key.
- ///
- /// This method must return an error if `peer_pub_key` is invalid: either
- /// mis-encoded, or an invalid public key (such as, but not limited to, being
- /// in a small order subgroup).
- ///
- /// If the key exchange algorithm is FFDHE, the result must be left-padded with zeros,
- /// as required by [RFC 8446](https://www.rfc-editor.org/rfc/rfc8446#section-7.4.1)
- /// (see [`complete_for_tls_version()`](Self::complete_for_tls_version) for more details).
- ///
- /// The shared secret is returned as a [`SharedSecret`] which can be constructed
- /// from a `&[u8]`.
- ///
- /// This consumes and so terminates the [`ActiveKeyExchange`].
- fn complete(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, Error>;
-
- /// Completes the key exchange for the given TLS version, given the peer's public key.
- ///
- /// Note that finite-field Diffie–Hellman key exchange has different requirements for the derived
- /// shared secret in TLS 1.2 and TLS 1.3 (ECDHE key exchange is the same in TLS 1.2 and TLS 1.3):
- ///
- /// In TLS 1.2, the calculated secret is required to be stripped of leading zeros
- /// [(RFC 5246)](https://www.rfc-editor.org/rfc/rfc5246#section-8.1.2).
- ///
- /// In TLS 1.3, the calculated secret is required to be padded with leading zeros to be the same
- /// byte-length as the group modulus [(RFC 8446)](https://www.rfc-editor.org/rfc/rfc8446#section-7.4.1).
- ///
- /// The default implementation of this method delegates to [`complete()`](Self::complete) assuming it is
- /// implemented for TLS 1.3 (i.e., for FFDHE KX, removes padding as needed). Implementers of this trait
- /// are encouraged to just implement [`complete()`](Self::complete) assuming TLS 1.3, and let the default
- /// implementation of this method handle TLS 1.2-specific requirements.
- ///
- /// This method must return an error if `peer_pub_key` is invalid: either
- /// mis-encoded, or an invalid public key (such as, but not limited to, being
- /// in a small order subgroup).
- ///
- /// The shared secret is returned as a [`SharedSecret`] which can be constructed
- /// from a `&[u8]`.
- ///
- /// This consumes and so terminates the [`ActiveKeyExchange`].
- fn complete_for_tls_version(
- self: Box<Self>,
- peer_pub_key: &[u8],
- tls_version: &SupportedProtocolVersion,
- ) -> Result<SharedSecret, Error> {
- if tls_version.version != ProtocolVersion::TLSv1_2 {
- return self.complete(peer_pub_key);
- }
-
- let group = self.group();
- let mut complete_res = self.complete(peer_pub_key)?;
- if group.key_exchange_algorithm() == KeyExchangeAlgorithm::DHE {
- complete_res.strip_leading_zeros();
- }
- Ok(complete_res)
- }
-
- /// For hybrid key exchanges, returns the [`NamedGroup`] and key share
- /// for the classical half of this key exchange.
- ///
- /// There is no requirement for a hybrid scheme (or any other!) to implement
- /// `hybrid_component()`. It only enables an optimization; described below.
- ///
- /// "Hybrid" means a key exchange algorithm which is constructed from two
- /// (or more) independent component algorithms. Usually one is post-quantum-secure,
- /// and the other is "classical". See
- /// <https://datatracker.ietf.org/doc/draft-ietf-tls-hybrid-design/11/>
- ///
- /// # Background
- /// Rustls always sends a presumptive key share in its `ClientHello`, using
- /// (absent any other information) the first item in [`CryptoProvider::kx_groups`].
- /// If the server accepts the client's selection, it can complete the handshake
- /// using that key share. If not, the server sends a `HelloRetryRequest` instructing
- /// the client to send a different key share instead.
- ///
- /// This request costs an extra round trip, and wastes the key exchange computation
- /// (in [`SupportedKxGroup::start()`]) the client already did. We would
- /// like to avoid those wastes if possible.
- ///
- /// It is early days for post-quantum-secure hybrid key exchange deployment.
- /// This means (commonly) continuing to offer both the hybrid and classical
- /// key exchanges, so the handshake can be completed without a `HelloRetryRequest`
- /// for servers that support the offered hybrid or classical schemes.
- ///
- /// Implementing `hybrid_component()` enables two optimizations:
- ///
- /// 1. Sending both the hybrid and classical key shares in the `ClientHello`.
- ///
- /// 2. Performing the classical key exchange setup only once. This is important
- /// because the classical key exchange setup is relatively expensive.
- /// This optimization is permitted and described in
- /// <https://www.ietf.org/archive/id/draft-ietf-tls-hybrid-design-11.html#section-3.2>
- ///
- /// Both of these only happen if the classical algorithm appears separately in
- /// the client's [`CryptoProvider::kx_groups`], and if the hybrid algorithm appears
- /// first in that list.
- ///
- /// # How it works
- /// This function is only called by rustls for clients. It is called when
- /// constructing the initial `ClientHello`. rustls follows these steps:
- ///
- /// 1. If the return value is `None`, nothing further happens.
- /// 2. If the given [`NamedGroup`] does not appear in
- /// [`CryptoProvider::kx_groups`], nothing further happens.
- /// 3. The given key share is added to the `ClientHello`, after the hybrid entry.
- ///
- /// Then, one of three things may happen when the server replies to the `ClientHello`:
- ///
- /// 1. The server sends a `HelloRetryRequest`. Everything is thrown away and
- /// we start again.
- /// 2. The server agrees to our hybrid key exchange: rustls calls
- /// [`ActiveKeyExchange::complete()`] consuming `self`.
- /// 3. The server agrees to our classical key exchange: rustls calls
- /// [`ActiveKeyExchange::complete_hybrid_component()`] which
- /// discards the hybrid key data, and completes just the classical key exchange.
- fn hybrid_component(&self) -> Option<(NamedGroup, &[u8])> {
- None
- }
-
- /// Completes the classical component of the key exchange, given the peer's public key.
- ///
- /// This is only called if `hybrid_component` returns `Some(_)`.
- ///
- /// This method must return an error if `peer_pub_key` is invalid: either
- /// mis-encoded, or an invalid public key (such as, but not limited to, being
- /// in a small order subgroup).
- ///
- /// The shared secret is returned as a [`SharedSecret`] which can be constructed
- /// from a `&[u8]`.
- ///
- /// See the documentation on [`Self::hybrid_component()`] for explanation.
- fn complete_hybrid_component(
- self: Box<Self>,
- _peer_pub_key: &[u8],
- ) -> Result<SharedSecret, Error> {
- unreachable!("only called if `hybrid_component()` implemented")
- }
-
- /// Return the public key being used.
- ///
- /// For ECDHE, the encoding required is defined in
- /// [RFC8446 section 4.2.8.2](https://www.rfc-editor.org/rfc/rfc8446#section-4.2.8.2).
- ///
- /// For FFDHE, the encoding required is defined in
- /// [RFC8446 section 4.2.8.1](https://www.rfc-editor.org/rfc/rfc8446#section-4.2.8.1).
- fn pub_key(&self) -> &[u8];
-
- /// FFDHE group the `ActiveKeyExchange` is operating in.
- ///
- /// Return `None` if this group is not a FFDHE one.
- ///
- /// The default implementation calls `FfdheGroup::from_named_group`: this function
- /// is extremely linker-unfriendly so it is recommended all key exchange implementers
- /// provide this function.
- ///
- /// `rustls::ffdhe_groups` contains suitable values to return from this,
- /// for example [`rustls::ffdhe_groups::FFDHE2048`][crate::ffdhe_groups::FFDHE2048].
- fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
- #[allow(deprecated)]
- FfdheGroup::from_named_group(self.group())
- }
-
- /// Return the group being used.
- fn group(&self) -> NamedGroup;
-}
-
-/// The result from [`SupportedKxGroup::start_and_complete()`].
-pub struct CompletedKeyExchange {
- /// Which group was used.
- pub group: NamedGroup,
-
- /// Our key share (sometimes a public key).
- pub pub_key: Vec<u8>,
-
- /// The computed shared secret.
- pub secret: SharedSecret,
-}
-
-/// The result from [`ActiveKeyExchange::complete`] or [`ActiveKeyExchange::complete_hybrid_component`].
-pub struct SharedSecret {
- buf: Vec<u8>,
- offset: usize,
-}
-
-impl SharedSecret {
- /// Returns the shared secret as a slice of bytes.
- pub fn secret_bytes(&self) -> &[u8] {
- &self.buf[self.offset..]
- }
-
- /// Removes leading zeros from `secret_bytes()` by adjusting the `offset`.
- ///
- /// This function does not re-allocate.
- fn strip_leading_zeros(&mut self) {
- let start = self
- .secret_bytes()
- .iter()
- .enumerate()
- .find(|(_i, x)| **x != 0)
- .map(|(i, _x)| i)
- .unwrap_or(self.secret_bytes().len());
- self.offset += start;
- }
-}
-
-impl Drop for SharedSecret {
- fn drop(&mut self) {
- self.buf.zeroize();
- }
-}
-
-impl From<&[u8]> for SharedSecret {
- fn from(source: &[u8]) -> Self {
- Self {
- buf: source.to_vec(),
- offset: 0,
- }
- }
-}
-
-impl From<Vec<u8>> for SharedSecret {
- fn from(buf: Vec<u8>) -> Self {
- Self { buf, offset: 0 }
- }
-}
-
-/// This function returns a [`CryptoProvider`] that uses
-/// FIPS140-3-approved cryptography.
-///
-/// Using this function expresses in your code that you require
-/// FIPS-approved cryptography, and will not compile if you make
-/// a mistake with cargo features.
-///
-/// See our [FIPS documentation](crate::manual::_06_fips) for
-/// more detail.
-///
-/// Install this as the process-default provider, like:
-///
-/// ```rust
-/// # #[cfg(feature = "fips")] {
-/// rustls::crypto::default_fips_provider().install_default()
-/// .expect("default provider already set elsewhere");
-/// # }
-/// ```
-///
-/// You can also use this explicitly, like:
-///
-/// ```rust
-/// # #[cfg(feature = "fips")] {
-/// # let root_store = rustls::RootCertStore::empty();
-/// let config = rustls::ClientConfig::builder_with_provider(
-/// rustls::crypto::default_fips_provider().into()
-/// )
-/// .with_safe_default_protocol_versions()
-/// .unwrap()
-/// .with_root_certificates(root_store)
-/// .with_no_client_auth();
-/// # }
-/// ```
-#[cfg(all(feature = "aws_lc_rs", any(feature = "fips", docsrs)))]
-#[cfg_attr(docsrs, doc(cfg(feature = "fips")))]
-pub fn default_fips_provider() -> CryptoProvider {
- aws_lc_rs::default_provider()
-}
-
-mod static_default {
- #[cfg(not(feature = "std"))]
- use alloc::boxed::Box;
- #[cfg(feature = "std")]
- use std::sync::OnceLock;
-
- #[cfg(not(feature = "std"))]
- use once_cell::race::OnceBox;
-
- use super::CryptoProvider;
- use crate::sync::Arc;
-
- #[cfg(feature = "std")]
- pub(crate) fn install_default(
- default_provider: CryptoProvider,
- ) -> Result<(), Arc<CryptoProvider>> {
- PROCESS_DEFAULT_PROVIDER.set(Arc::new(default_provider))
- }
-
- #[cfg(not(feature = "std"))]
- pub(crate) fn install_default(
- default_provider: CryptoProvider,
- ) -> Result<(), Arc<CryptoProvider>> {
- PROCESS_DEFAULT_PROVIDER
- .set(Box::new(Arc::new(default_provider)))
- .map_err(|e| *e)
- }
-
- pub(crate) fn get_default() -> Option<&'static Arc<CryptoProvider>> {
- PROCESS_DEFAULT_PROVIDER.get()
- }
-
- #[cfg(feature = "std")]
- static PROCESS_DEFAULT_PROVIDER: OnceLock<Arc<CryptoProvider>> = OnceLock::new();
- #[cfg(not(feature = "std"))]
- static PROCESS_DEFAULT_PROVIDER: OnceBox<Arc<CryptoProvider>> = OnceBox::new();
-}
-
-#[cfg(test)]
-mod tests {
- use std::vec;
-
- use super::SharedSecret;
-
- #[test]
- fn test_shared_secret_strip_leading_zeros() {
- let test_cases = [
- (vec![0, 1], vec![1]),
- (vec![1], vec![1]),
- (vec![1, 0, 2], vec![1, 0, 2]),
- (vec![0, 0, 1, 2], vec![1, 2]),
- (vec![0, 0, 0], vec![]),
- (vec![], vec![]),
- ];
- for (buf, expected) in test_cases {
- let mut secret = SharedSecret::from(&buf[..]);
- assert_eq!(secret.secret_bytes(), buf);
- secret.strip_leading_zeros();
- assert_eq!(secret.secret_bytes(), expected);
- }
- }
-}
diff --git a/vendor/rustls/src/crypto/ring/hash.rs b/vendor/rustls/src/crypto/ring/hash.rs
deleted file mode 100644
index 220dc536..00000000
--- a/vendor/rustls/src/crypto/ring/hash.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-#![allow(clippy::duplicate_mod)]
-
-use alloc::boxed::Box;
-
-use super::ring_like::digest;
-use crate::crypto;
-use crate::msgs::enums::HashAlgorithm;
-
-pub(crate) static SHA256: Hash = Hash(&digest::SHA256, HashAlgorithm::SHA256);
-pub(crate) static SHA384: Hash = Hash(&digest::SHA384, HashAlgorithm::SHA384);
-
-pub(crate) struct Hash(&'static digest::Algorithm, HashAlgorithm);
-
-impl crypto::hash::Hash for Hash {
- fn start(&self) -> Box<dyn crypto::hash::Context> {
- Box::new(Context(digest::Context::new(self.0)))
- }
-
- fn hash(&self, bytes: &[u8]) -> crypto::hash::Output {
- let mut ctx = digest::Context::new(self.0);
- ctx.update(bytes);
- convert(ctx.finish())
- }
-
- fn output_len(&self) -> usize {
- self.0.output_len()
- }
-
- fn algorithm(&self) -> HashAlgorithm {
- self.1
- }
-
- fn fips(&self) -> bool {
- super::fips()
- }
-}
-
-struct Context(digest::Context);
-
-impl crypto::hash::Context for Context {
- fn fork_finish(&self) -> crypto::hash::Output {
- convert(self.0.clone().finish())
- }
-
- fn fork(&self) -> Box<dyn crypto::hash::Context> {
- Box::new(Self(self.0.clone()))
- }
-
- fn finish(self: Box<Self>) -> crypto::hash::Output {
- convert(self.0.finish())
- }
-
- fn update(&mut self, data: &[u8]) {
- self.0.update(data);
- }
-}
-
-fn convert(val: digest::Digest) -> crypto::hash::Output {
- crypto::hash::Output::new(val.as_ref())
-}
diff --git a/vendor/rustls/src/crypto/ring/hmac.rs b/vendor/rustls/src/crypto/ring/hmac.rs
deleted file mode 100644
index 7f30aba4..00000000
--- a/vendor/rustls/src/crypto/ring/hmac.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-#![allow(clippy::duplicate_mod)]
-
-use alloc::boxed::Box;
-
-use super::ring_like;
-use crate::crypto;
-
-pub(crate) static HMAC_SHA256: Hmac = Hmac(&ring_like::hmac::HMAC_SHA256);
-pub(crate) static HMAC_SHA384: Hmac = Hmac(&ring_like::hmac::HMAC_SHA384);
-#[allow(dead_code)] // Only used for TLS 1.2 prf test, and aws-lc-rs HPKE suites.
-pub(crate) static HMAC_SHA512: Hmac = Hmac(&ring_like::hmac::HMAC_SHA512);
-
-pub(crate) struct Hmac(&'static ring_like::hmac::Algorithm);
-
-impl crypto::hmac::Hmac for Hmac {
- fn with_key(&self, key: &[u8]) -> Box<dyn crypto::hmac::Key> {
- Box::new(Key(ring_like::hmac::Key::new(*self.0, key)))
- }
-
- fn hash_output_len(&self) -> usize {
- self.0.digest_algorithm().output_len()
- }
-
- fn fips(&self) -> bool {
- super::fips()
- }
-}
-
-struct Key(ring_like::hmac::Key);
-
-impl crypto::hmac::Key for Key {
- fn sign_concat(&self, first: &[u8], middle: &[&[u8]], last: &[u8]) -> crypto::hmac::Tag {
- let mut ctx = ring_like::hmac::Context::with_key(&self.0);
- ctx.update(first);
- for d in middle {
- ctx.update(d);
- }
- ctx.update(last);
- crypto::hmac::Tag::new(ctx.sign().as_ref())
- }
-
- fn tag_len(&self) -> usize {
- self.0
- .algorithm()
- .digest_algorithm()
- .output_len()
- }
-}
diff --git a/vendor/rustls/src/crypto/ring/kx.rs b/vendor/rustls/src/crypto/ring/kx.rs
deleted file mode 100644
index 6e0da227..00000000
--- a/vendor/rustls/src/crypto/ring/kx.rs
+++ /dev/null
@@ -1,188 +0,0 @@
-#![allow(clippy::duplicate_mod)]
-
-use alloc::boxed::Box;
-use core::fmt;
-
-use super::ring_like::agreement;
-use super::ring_like::rand::SystemRandom;
-use crate::crypto::{ActiveKeyExchange, FfdheGroup, SharedSecret, SupportedKxGroup};
-use crate::error::{Error, PeerMisbehaved};
-use crate::msgs::enums::NamedGroup;
-use crate::rand::GetRandomFailed;
-
-/// A key-exchange group supported by *ring*.
-struct KxGroup {
- /// The IANA "TLS Supported Groups" name of the group
- name: NamedGroup,
-
- /// The corresponding ring agreement::Algorithm
- agreement_algorithm: &'static agreement::Algorithm,
-
- /// Whether the algorithm is allowed by FIPS
- ///
- /// `SupportedKxGroup::fips()` is true if and only if the algorithm is allowed,
- /// _and_ the implementation is FIPS-validated.
- fips_allowed: bool,
-
- /// aws-lc-rs 1.9 and later accepts more formats of public keys than
- /// just uncompressed.
- ///
- /// That is not compatible with TLS:
- /// - TLS1.3 outlaws other encodings,
- /// - TLS1.2 negotiates other encodings (we only offer uncompressed), and
- /// defaults to uncompressed if negotiation is not done.
- ///
- /// This function should return `true` if the basic shape of its argument
- /// is consistent with an uncompressed point encoding. It does not need
- /// to verify that the point is on the curve (if the curve requires that
- /// for security); aws-lc-rs/ring must do that.
- pub_key_validator: fn(&[u8]) -> bool,
-}
-
-impl SupportedKxGroup for KxGroup {
- fn start(&self) -> Result<Box<dyn ActiveKeyExchange>, Error> {
- let rng = SystemRandom::new();
- let priv_key = agreement::EphemeralPrivateKey::generate(self.agreement_algorithm, &rng)
- .map_err(|_| GetRandomFailed)?;
-
- let pub_key = priv_key
- .compute_public_key()
- .map_err(|_| GetRandomFailed)?;
-
- Ok(Box::new(KeyExchange {
- name: self.name,
- agreement_algorithm: self.agreement_algorithm,
- priv_key,
- pub_key,
- pub_key_validator: self.pub_key_validator,
- }))
- }
-
- fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
- None
- }
-
- fn name(&self) -> NamedGroup {
- self.name
- }
-
- fn fips(&self) -> bool {
- self.fips_allowed && super::fips()
- }
-}
-
-impl fmt::Debug for KxGroup {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.name.fmt(f)
- }
-}
-
-/// Ephemeral ECDH on curve25519 (see RFC7748)
-pub static X25519: &dyn SupportedKxGroup = &KxGroup {
- name: NamedGroup::X25519,
- agreement_algorithm: &agreement::X25519,
-
- // "Curves that are included in SP 800-186 but not included in SP 800-56Arev3 are
- // not approved for key agreement. E.g., the ECDH X25519 and X448 key agreement
- // schemes (defined in RFC 7748) that use Curve25519 and Curve448, respectively,
- // are not compliant to SP 800-56Arev3."
- // -- <https://csrc.nist.gov/csrc/media/Projects/cryptographic-module-validation-program/documents/fips%20140-3/FIPS%20140-3%20IG.pdf>
- fips_allowed: false,
-
- pub_key_validator: |point: &[u8]| point.len() == 32,
-};
-
-/// Ephemeral ECDH on secp256r1 (aka NIST-P256)
-pub static SECP256R1: &dyn SupportedKxGroup = &KxGroup {
- name: NamedGroup::secp256r1,
- agreement_algorithm: &agreement::ECDH_P256,
- fips_allowed: true,
- pub_key_validator: uncompressed_point,
-};
-
-/// Ephemeral ECDH on secp384r1 (aka NIST-P384)
-pub static SECP384R1: &dyn SupportedKxGroup = &KxGroup {
- name: NamedGroup::secp384r1,
- agreement_algorithm: &agreement::ECDH_P384,
- fips_allowed: true,
- pub_key_validator: uncompressed_point,
-};
-
-fn uncompressed_point(point: &[u8]) -> bool {
- // See `UncompressedPointRepresentation`, which is a retelling of
- // SEC1 section 2.3.3 "Elliptic-Curve-Point-to-Octet-String Conversion"
- // <https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.8.2>
- matches!(point.first(), Some(0x04))
-}
-
-/// An in-progress key exchange. This has the algorithm,
-/// our private key, and our public key.
-struct KeyExchange {
- name: NamedGroup,
- agreement_algorithm: &'static agreement::Algorithm,
- priv_key: agreement::EphemeralPrivateKey,
- pub_key: agreement::PublicKey,
- pub_key_validator: fn(&[u8]) -> bool,
-}
-
-impl ActiveKeyExchange for KeyExchange {
- /// Completes the key exchange, given the peer's public key.
- fn complete(self: Box<Self>, peer: &[u8]) -> Result<SharedSecret, Error> {
- if !(self.pub_key_validator)(peer) {
- return Err(PeerMisbehaved::InvalidKeyShare.into());
- }
- let peer_key = agreement::UnparsedPublicKey::new(self.agreement_algorithm, peer);
- super::ring_shim::agree_ephemeral(self.priv_key, &peer_key)
- .map_err(|_| PeerMisbehaved::InvalidKeyShare.into())
- }
-
- fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
- None
- }
-
- /// Return the group being used.
- fn group(&self) -> NamedGroup {
- self.name
- }
-
- /// Return the public key being used.
- fn pub_key(&self) -> &[u8] {
- self.pub_key.as_ref()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use std::format;
-
- #[test]
- fn kxgroup_fmt_yields_name() {
- assert_eq!("X25519", format!("{:?}", super::X25519));
- }
-}
-
-#[cfg(bench)]
-mod benchmarks {
- #[bench]
- fn bench_x25519(b: &mut test::Bencher) {
- bench_any(b, super::X25519);
- }
-
- #[bench]
- fn bench_ecdh_p256(b: &mut test::Bencher) {
- bench_any(b, super::SECP256R1);
- }
-
- #[bench]
- fn bench_ecdh_p384(b: &mut test::Bencher) {
- bench_any(b, super::SECP384R1);
- }
-
- fn bench_any(b: &mut test::Bencher, kxg: &dyn super::SupportedKxGroup) {
- b.iter(|| {
- let akx = kxg.start().unwrap();
- let pub_key = akx.pub_key().to_vec();
- test::black_box(akx.complete(&pub_key).unwrap());
- });
- }
-}
diff --git a/vendor/rustls/src/crypto/ring/mod.rs b/vendor/rustls/src/crypto/ring/mod.rs
deleted file mode 100644
index 3ce99b15..00000000
--- a/vendor/rustls/src/crypto/ring/mod.rs
+++ /dev/null
@@ -1,203 +0,0 @@
-use pki_types::PrivateKeyDer;
-pub(crate) use ring as ring_like;
-use webpki::ring as webpki_algs;
-
-use crate::Error;
-use crate::crypto::{CryptoProvider, KeyProvider, SecureRandom, SupportedKxGroup};
-use crate::enums::SignatureScheme;
-use crate::rand::GetRandomFailed;
-use crate::sign::SigningKey;
-use crate::suites::SupportedCipherSuite;
-use crate::sync::Arc;
-use crate::webpki::WebPkiSupportedAlgorithms;
-
-/// Using software keys for authentication.
-pub mod sign;
-
-pub(crate) mod hash;
-#[cfg(any(test, feature = "tls12"))]
-pub(crate) mod hmac;
-pub(crate) mod kx;
-pub(crate) mod quic;
-#[cfg(feature = "std")]
-pub(crate) mod ticketer;
-#[cfg(feature = "tls12")]
-pub(crate) mod tls12;
-pub(crate) mod tls13;
-
-/// A `CryptoProvider` backed by the [*ring*] crate.
-///
-/// [*ring*]: https://github.com/briansmith/ring
-pub fn default_provider() -> CryptoProvider {
- CryptoProvider {
- cipher_suites: DEFAULT_CIPHER_SUITES.to_vec(),
- kx_groups: DEFAULT_KX_GROUPS.to_vec(),
- signature_verification_algorithms: SUPPORTED_SIG_ALGS,
- secure_random: &Ring,
- key_provider: &Ring,
- }
-}
-
-/// Default crypto provider.
-#[derive(Debug)]
-struct Ring;
-
-impl SecureRandom for Ring {
- fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed> {
- use ring_like::rand::SecureRandom;
-
- ring_like::rand::SystemRandom::new()
- .fill(buf)
- .map_err(|_| GetRandomFailed)
- }
-}
-
-impl KeyProvider for Ring {
- fn load_private_key(
- &self,
- key_der: PrivateKeyDer<'static>,
- ) -> Result<Arc<dyn SigningKey>, Error> {
- sign::any_supported_type(&key_der)
- }
-}
-
-/// The cipher suite configuration that an application should use by default.
-///
-/// This will be [`ALL_CIPHER_SUITES`] sans any supported cipher suites that
-/// shouldn't be enabled by most applications.
-pub static DEFAULT_CIPHER_SUITES: &[SupportedCipherSuite] = ALL_CIPHER_SUITES;
-
-/// A list of all the cipher suites supported by the rustls *ring* provider.
-pub static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = &[
- // TLS1.3 suites
- tls13::TLS13_AES_256_GCM_SHA384,
- tls13::TLS13_AES_128_GCM_SHA256,
- tls13::TLS13_CHACHA20_POLY1305_SHA256,
- // TLS1.2 suites
- #[cfg(feature = "tls12")]
- tls12::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
- #[cfg(feature = "tls12")]
- tls12::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- #[cfg(feature = "tls12")]
- tls12::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
- #[cfg(feature = "tls12")]
- tls12::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
- #[cfg(feature = "tls12")]
- tls12::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- #[cfg(feature = "tls12")]
- tls12::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-];
-
-/// All defined cipher suites supported by *ring* appear in this module.
-pub mod cipher_suite {
- #[cfg(feature = "tls12")]
- pub use super::tls12::{
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 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,
- };
- pub use super::tls13::{
- TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384, TLS13_CHACHA20_POLY1305_SHA256,
- };
-}
-
-/// A `WebPkiSupportedAlgorithms` value that reflects webpki's capabilities when
-/// compiled against *ring*.
-static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms {
- all: &[
- webpki_algs::ECDSA_P256_SHA256,
- webpki_algs::ECDSA_P256_SHA384,
- webpki_algs::ECDSA_P384_SHA256,
- webpki_algs::ECDSA_P384_SHA384,
- webpki_algs::ED25519,
- webpki_algs::RSA_PSS_2048_8192_SHA256_LEGACY_KEY,
- webpki_algs::RSA_PSS_2048_8192_SHA384_LEGACY_KEY,
- webpki_algs::RSA_PSS_2048_8192_SHA512_LEGACY_KEY,
- webpki_algs::RSA_PKCS1_2048_8192_SHA256,
- webpki_algs::RSA_PKCS1_2048_8192_SHA384,
- webpki_algs::RSA_PKCS1_2048_8192_SHA512,
- webpki_algs::RSA_PKCS1_2048_8192_SHA256_ABSENT_PARAMS,
- webpki_algs::RSA_PKCS1_2048_8192_SHA384_ABSENT_PARAMS,
- webpki_algs::RSA_PKCS1_2048_8192_SHA512_ABSENT_PARAMS,
- ],
- mapping: &[
- // Note: for TLS1.2 the curve is not fixed by SignatureScheme. For TLS1.3 it is.
- (
- SignatureScheme::ECDSA_NISTP384_SHA384,
- &[
- webpki_algs::ECDSA_P384_SHA384,
- webpki_algs::ECDSA_P256_SHA384,
- ],
- ),
- (
- SignatureScheme::ECDSA_NISTP256_SHA256,
- &[
- webpki_algs::ECDSA_P256_SHA256,
- webpki_algs::ECDSA_P384_SHA256,
- ],
- ),
- (SignatureScheme::ED25519, &[webpki_algs::ED25519]),
- (
- SignatureScheme::RSA_PSS_SHA512,
- &[webpki_algs::RSA_PSS_2048_8192_SHA512_LEGACY_KEY],
- ),
- (
- SignatureScheme::RSA_PSS_SHA384,
- &[webpki_algs::RSA_PSS_2048_8192_SHA384_LEGACY_KEY],
- ),
- (
- SignatureScheme::RSA_PSS_SHA256,
- &[webpki_algs::RSA_PSS_2048_8192_SHA256_LEGACY_KEY],
- ),
- (
- SignatureScheme::RSA_PKCS1_SHA512,
- &[webpki_algs::RSA_PKCS1_2048_8192_SHA512],
- ),
- (
- SignatureScheme::RSA_PKCS1_SHA384,
- &[webpki_algs::RSA_PKCS1_2048_8192_SHA384],
- ),
- (
- SignatureScheme::RSA_PKCS1_SHA256,
- &[webpki_algs::RSA_PKCS1_2048_8192_SHA256],
- ),
- ],
-};
-
-/// All defined key exchange groups supported by *ring* appear in this module.
-///
-/// [`ALL_KX_GROUPS`] is provided as an array of all of these values.
-/// [`DEFAULT_KX_GROUPS`] is provided as an array of this provider's defaults.
-pub mod kx_group {
- pub use super::kx::{SECP256R1, SECP384R1, X25519};
-}
-
-/// A list of the default key exchange groups supported by this provider.
-pub static DEFAULT_KX_GROUPS: &[&dyn SupportedKxGroup] = ALL_KX_GROUPS;
-
-/// A list of all the key exchange groups supported by this provider.
-pub static ALL_KX_GROUPS: &[&dyn SupportedKxGroup] =
- &[kx_group::X25519, kx_group::SECP256R1, kx_group::SECP384R1];
-
-#[cfg(feature = "std")]
-pub use ticketer::Ticketer;
-
-/// Compatibility shims between ring 0.16.x and 0.17.x API
-mod ring_shim {
- use super::ring_like;
- use crate::crypto::SharedSecret;
-
- pub(super) fn agree_ephemeral(
- priv_key: ring_like::agreement::EphemeralPrivateKey,
- peer_key: &ring_like::agreement::UnparsedPublicKey<&[u8]>,
- ) -> Result<SharedSecret, ()> {
- ring_like::agreement::agree_ephemeral(priv_key, peer_key, |secret| {
- SharedSecret::from(secret)
- })
- .map_err(|_| ())
- }
-}
-
-pub(super) fn fips() -> bool {
- false
-}
diff --git a/vendor/rustls/src/crypto/ring/quic.rs b/vendor/rustls/src/crypto/ring/quic.rs
deleted file mode 100644
index 3d0dc928..00000000
--- a/vendor/rustls/src/crypto/ring/quic.rs
+++ /dev/null
@@ -1,416 +0,0 @@
-#![allow(clippy::duplicate_mod)]
-
-use alloc::boxed::Box;
-
-use super::ring_like::aead;
-use crate::crypto::cipher::{AeadKey, Iv, Nonce};
-use crate::error::Error;
-use crate::quic;
-
-pub(crate) struct HeaderProtectionKey(aead::quic::HeaderProtectionKey);
-
-impl HeaderProtectionKey {
- pub(crate) fn new(key: AeadKey, alg: &'static aead::quic::Algorithm) -> Self {
- Self(aead::quic::HeaderProtectionKey::new(alg, key.as_ref()).unwrap())
- }
-
- fn xor_in_place(
- &self,
- sample: &[u8],
- first: &mut u8,
- packet_number: &mut [u8],
- masked: bool,
- ) -> Result<(), Error> {
- // This implements "Header Protection Application" almost verbatim.
- // <https://datatracker.ietf.org/doc/html/rfc9001#section-5.4.1>
-
- let mask = self
- .0
- .new_mask(sample)
- .map_err(|_| Error::General("sample of invalid length".into()))?;
-
- // The `unwrap()` will not panic because `new_mask` returns a
- // non-empty result.
- let (first_mask, pn_mask) = mask.split_first().unwrap();
-
- // It is OK for the `mask` to be longer than `packet_number`,
- // but a valid `packet_number` will never be longer than `mask`.
- if packet_number.len() > pn_mask.len() {
- return Err(Error::General("packet number too long".into()));
- }
-
- // Infallible from this point on. Before this point, `first` and
- // `packet_number` are unchanged.
-
- const LONG_HEADER_FORM: u8 = 0x80;
- let bits = match *first & LONG_HEADER_FORM == LONG_HEADER_FORM {
- true => 0x0f, // Long header: 4 bits masked
- false => 0x1f, // Short header: 5 bits masked
- };
-
- let first_plain = match masked {
- // When unmasking, use the packet length bits after unmasking
- true => *first ^ (first_mask & bits),
- // When masking, use the packet length bits before masking
- false => *first,
- };
- let pn_len = (first_plain & 0x03) as usize + 1;
-
- *first ^= first_mask & bits;
- for (dst, m) in packet_number
- .iter_mut()
- .zip(pn_mask)
- .take(pn_len)
- {
- *dst ^= m;
- }
-
- Ok(())
- }
-}
-
-impl quic::HeaderProtectionKey for HeaderProtectionKey {
- fn encrypt_in_place(
- &self,
- sample: &[u8],
- first: &mut u8,
- packet_number: &mut [u8],
- ) -> Result<(), Error> {
- self.xor_in_place(sample, first, packet_number, false)
- }
-
- fn decrypt_in_place(
- &self,
- sample: &[u8],
- first: &mut u8,
- packet_number: &mut [u8],
- ) -> Result<(), Error> {
- self.xor_in_place(sample, first, packet_number, true)
- }
-
- #[inline]
- fn sample_len(&self) -> usize {
- self.0.algorithm().sample_len()
- }
-}
-
-pub(crate) struct PacketKey {
- /// Encrypts or decrypts a packet's payload
- key: aead::LessSafeKey,
- /// Computes unique nonces for each packet
- iv: Iv,
- /// Confidentiality limit (see [`quic::PacketKey::confidentiality_limit`])
- confidentiality_limit: u64,
- /// Integrity limit (see [`quic::PacketKey::integrity_limit`])
- integrity_limit: u64,
-}
-
-impl PacketKey {
- pub(crate) fn new(
- key: AeadKey,
- iv: Iv,
- confidentiality_limit: u64,
- integrity_limit: u64,
- aead_algorithm: &'static aead::Algorithm,
- ) -> Self {
- Self {
- key: aead::LessSafeKey::new(
- aead::UnboundKey::new(aead_algorithm, key.as_ref()).unwrap(),
- ),
- iv,
- confidentiality_limit,
- integrity_limit,
- }
- }
-}
-
-impl quic::PacketKey for PacketKey {
- fn encrypt_in_place(
- &self,
- packet_number: u64,
- header: &[u8],
- payload: &mut [u8],
- ) -> Result<quic::Tag, Error> {
- let aad = aead::Aad::from(header);
- let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, packet_number).0);
- let tag = self
- .key
- .seal_in_place_separate_tag(nonce, aad, payload)
- .map_err(|_| 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,
- header: &[u8],
- payload: &'a mut [u8],
- ) -> Result<&'a [u8], Error> {
- let payload_len = payload.len();
- let aad = aead::Aad::from(header);
- let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, packet_number).0);
- self.key
- .open_in_place(nonce, aad, payload)
- .map_err(|_| Error::DecryptError)?;
-
- let plain_len = payload_len - self.key.algorithm().tag_len();
- Ok(&payload[..plain_len])
- }
-
- /// Tag length for the underlying AEAD algorithm
- #[inline]
- fn tag_len(&self) -> usize {
- self.key.algorithm().tag_len()
- }
-
- /// Confidentiality limit (see [`quic::PacketKey::confidentiality_limit`])
- fn confidentiality_limit(&self) -> u64 {
- self.confidentiality_limit
- }
-
- /// Integrity limit (see [`quic::PacketKey::integrity_limit`])
- fn integrity_limit(&self) -> u64 {
- self.integrity_limit
- }
-}
-
-pub(crate) struct KeyBuilder {
- pub(crate) packet_alg: &'static aead::Algorithm,
- pub(crate) header_alg: &'static aead::quic::Algorithm,
- pub(crate) confidentiality_limit: u64,
- pub(crate) integrity_limit: u64,
-}
-
-impl quic::Algorithm for KeyBuilder {
- fn packet_key(&self, key: AeadKey, iv: Iv) -> Box<dyn quic::PacketKey> {
- Box::new(PacketKey::new(
- key,
- iv,
- self.confidentiality_limit,
- self.integrity_limit,
- self.packet_alg,
- ))
- }
-
- fn header_protection_key(&self, key: AeadKey) -> Box<dyn quic::HeaderProtectionKey> {
- Box::new(HeaderProtectionKey::new(key, self.header_alg))
- }
-
- fn aead_key_len(&self) -> usize {
- self.packet_alg.key_len()
- }
-
- fn fips(&self) -> bool {
- super::fips()
- }
-}
-
-#[cfg(test)]
-#[macro_rules_attribute::apply(test_for_each_provider)]
-mod tests {
- use std::dbg;
-
- use super::provider::tls13::{
- TLS13_AES_128_GCM_SHA256_INTERNAL, TLS13_CHACHA20_POLY1305_SHA256_INTERNAL,
- };
- use crate::common_state::Side;
- use crate::crypto::tls13::OkmBlock;
- use crate::quic::*;
-
- fn test_short_packet(version: Version, expected: &[u8]) {
- const PN: u64 = 654360564;
- const SECRET: &[u8] = &[
- 0x9a, 0xc3, 0x12, 0xa7, 0xf8, 0x77, 0x46, 0x8e, 0xbe, 0x69, 0x42, 0x27, 0x48, 0xad,
- 0x00, 0xa1, 0x54, 0x43, 0xf1, 0x82, 0x03, 0xa0, 0x7d, 0x60, 0x60, 0xf6, 0x88, 0xf3,
- 0x0f, 0x21, 0x63, 0x2b,
- ];
-
- let secret = OkmBlock::new(SECRET);
- let builder = KeyBuilder::new(
- &secret,
- version,
- TLS13_CHACHA20_POLY1305_SHA256_INTERNAL
- .quic
- .unwrap(),
- TLS13_CHACHA20_POLY1305_SHA256_INTERNAL.hkdf_provider,
- );
- let packet = builder.packet_key();
- let hpk = builder.header_protection_key();
-
- const PLAIN: &[u8] = &[0x42, 0x00, 0xbf, 0xf4, 0x01];
-
- let mut buf = PLAIN.to_vec();
- let (header, payload) = buf.split_at_mut(4);
- let tag = packet
- .encrypt_in_place(PN, header, payload)
- .unwrap();
- buf.extend(tag.as_ref());
-
- let pn_offset = 1;
- let (header, sample) = buf.split_at_mut(pn_offset + 4);
- let (first, rest) = header.split_at_mut(1);
- let sample = &sample[..hpk.sample_len()];
- hpk.encrypt_in_place(sample, &mut first[0], dbg!(rest))
- .unwrap();
-
- assert_eq!(&buf, expected);
-
- let (header, sample) = buf.split_at_mut(pn_offset + 4);
- let (first, rest) = header.split_at_mut(1);
- let sample = &sample[..hpk.sample_len()];
- hpk.decrypt_in_place(sample, &mut first[0], rest)
- .unwrap();
-
- let (header, payload_tag) = buf.split_at_mut(4);
- let plain = packet
- .decrypt_in_place(PN, header, payload_tag)
- .unwrap();
-
- assert_eq!(plain, &PLAIN[4..]);
- }
-
- #[test]
- fn short_packet_header_protection() {
- // https://www.rfc-editor.org/rfc/rfc9001.html#name-chacha20-poly1305-short-hea
- test_short_packet(
- Version::V1,
- &[
- 0x4c, 0xfe, 0x41, 0x89, 0x65, 0x5e, 0x5c, 0xd5, 0x5c, 0x41, 0xf6, 0x90, 0x80, 0x57,
- 0x5d, 0x79, 0x99, 0xc2, 0x5a, 0x5b, 0xfb,
- ],
- );
- }
-
- #[test]
- fn key_update_test_vector() {
- fn equal_okm(x: &OkmBlock, y: &OkmBlock) -> bool {
- x.as_ref() == y.as_ref()
- }
-
- let mut secrets = Secrets::new(
- // Constant dummy values for reproducibility
- OkmBlock::new(
- &[
- 0xb8, 0x76, 0x77, 0x08, 0xf8, 0x77, 0x23, 0x58, 0xa6, 0xea, 0x9f, 0xc4, 0x3e,
- 0x4a, 0xdd, 0x2c, 0x96, 0x1b, 0x3f, 0x52, 0x87, 0xa6, 0xd1, 0x46, 0x7e, 0xe0,
- 0xae, 0xab, 0x33, 0x72, 0x4d, 0xbf,
- ][..],
- ),
- OkmBlock::new(
- &[
- 0x42, 0xdc, 0x97, 0x21, 0x40, 0xe0, 0xf2, 0xe3, 0x98, 0x45, 0xb7, 0x67, 0x61,
- 0x34, 0x39, 0xdc, 0x67, 0x58, 0xca, 0x43, 0x25, 0x9b, 0x87, 0x85, 0x06, 0x82,
- 0x4e, 0xb1, 0xe4, 0x38, 0xd8, 0x55,
- ][..],
- ),
- TLS13_AES_128_GCM_SHA256_INTERNAL,
- TLS13_AES_128_GCM_SHA256_INTERNAL
- .quic
- .unwrap(),
- Side::Client,
- Version::V1,
- );
- secrets.update();
-
- assert!(equal_okm(
- &secrets.client,
- &OkmBlock::new(
- &[
- 0x42, 0xca, 0xc8, 0xc9, 0x1c, 0xd5, 0xeb, 0x40, 0x68, 0x2e, 0x43, 0x2e, 0xdf,
- 0x2d, 0x2b, 0xe9, 0xf4, 0x1a, 0x52, 0xca, 0x6b, 0x22, 0xd8, 0xe6, 0xcd, 0xb1,
- 0xe8, 0xac, 0xa9, 0x6, 0x1f, 0xce
- ][..]
- )
- ));
- assert!(equal_okm(
- &secrets.server,
- &OkmBlock::new(
- &[
- 0xeb, 0x7f, 0x5e, 0x2a, 0x12, 0x3f, 0x40, 0x7d, 0xb4, 0x99, 0xe3, 0x61, 0xca,
- 0xe5, 0x90, 0xd4, 0xd9, 0x92, 0xe1, 0x4b, 0x7a, 0xce, 0x3, 0xc2, 0x44, 0xe0,
- 0x42, 0x21, 0x15, 0xb6, 0xd3, 0x8a
- ][..]
- )
- ));
- }
-
- #[test]
- fn short_packet_header_protection_v2() {
- // https://www.ietf.org/archive/id/draft-ietf-quic-v2-10.html#name-chacha20-poly1305-short-head
- test_short_packet(
- Version::V2,
- &[
- 0x55, 0x58, 0xb1, 0xc6, 0x0a, 0xe7, 0xb6, 0xb9, 0x32, 0xbc, 0x27, 0xd7, 0x86, 0xf4,
- 0xbc, 0x2b, 0xb2, 0x0f, 0x21, 0x62, 0xba,
- ],
- );
- }
-
- #[test]
- fn initial_test_vector_v2() {
- // https://www.ietf.org/archive/id/draft-ietf-quic-v2-10.html#name-sample-packet-protection-2
- let icid = [0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08];
- let server = Keys::initial(
- Version::V2,
- TLS13_AES_128_GCM_SHA256_INTERNAL,
- TLS13_AES_128_GCM_SHA256_INTERNAL
- .quic
- .unwrap(),
- &icid,
- Side::Server,
- );
- let mut server_payload = [
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x40, 0x5a, 0x02, 0x00, 0x00, 0x56, 0x03,
- 0x03, 0xee, 0xfc, 0xe7, 0xf7, 0xb3, 0x7b, 0xa1, 0xd1, 0x63, 0x2e, 0x96, 0x67, 0x78,
- 0x25, 0xdd, 0xf7, 0x39, 0x88, 0xcf, 0xc7, 0x98, 0x25, 0xdf, 0x56, 0x6d, 0xc5, 0x43,
- 0x0b, 0x9a, 0x04, 0x5a, 0x12, 0x00, 0x13, 0x01, 0x00, 0x00, 0x2e, 0x00, 0x33, 0x00,
- 0x24, 0x00, 0x1d, 0x00, 0x20, 0x9d, 0x3c, 0x94, 0x0d, 0x89, 0x69, 0x0b, 0x84, 0xd0,
- 0x8a, 0x60, 0x99, 0x3c, 0x14, 0x4e, 0xca, 0x68, 0x4d, 0x10, 0x81, 0x28, 0x7c, 0x83,
- 0x4d, 0x53, 0x11, 0xbc, 0xf3, 0x2b, 0xb9, 0xda, 0x1a, 0x00, 0x2b, 0x00, 0x02, 0x03,
- 0x04,
- ];
- let mut server_header = [
- 0xd1, 0x6b, 0x33, 0x43, 0xcf, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62,
- 0xb5, 0x00, 0x40, 0x75, 0x00, 0x01,
- ];
- let tag = server
- .local
- .packet
- .encrypt_in_place(1, &server_header, &mut server_payload)
- .unwrap();
- let (first, rest) = server_header.split_at_mut(1);
- let rest_len = rest.len();
- server
- .local
- .header
- .encrypt_in_place(
- &server_payload[2..18],
- &mut first[0],
- &mut rest[rest_len - 2..],
- )
- .unwrap();
- let mut server_packet = server_header.to_vec();
- server_packet.extend(server_payload);
- server_packet.extend(tag.as_ref());
- let expected_server_packet = [
- 0xdc, 0x6b, 0x33, 0x43, 0xcf, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62,
- 0xb5, 0x00, 0x40, 0x75, 0xd9, 0x2f, 0xaa, 0xf1, 0x6f, 0x05, 0xd8, 0xa4, 0x39, 0x8c,
- 0x47, 0x08, 0x96, 0x98, 0xba, 0xee, 0xa2, 0x6b, 0x91, 0xeb, 0x76, 0x1d, 0x9b, 0x89,
- 0x23, 0x7b, 0xbf, 0x87, 0x26, 0x30, 0x17, 0x91, 0x53, 0x58, 0x23, 0x00, 0x35, 0xf7,
- 0xfd, 0x39, 0x45, 0xd8, 0x89, 0x65, 0xcf, 0x17, 0xf9, 0xaf, 0x6e, 0x16, 0x88, 0x6c,
- 0x61, 0xbf, 0xc7, 0x03, 0x10, 0x6f, 0xba, 0xf3, 0xcb, 0x4c, 0xfa, 0x52, 0x38, 0x2d,
- 0xd1, 0x6a, 0x39, 0x3e, 0x42, 0x75, 0x75, 0x07, 0x69, 0x80, 0x75, 0xb2, 0xc9, 0x84,
- 0xc7, 0x07, 0xf0, 0xa0, 0x81, 0x2d, 0x8c, 0xd5, 0xa6, 0x88, 0x1e, 0xaf, 0x21, 0xce,
- 0xda, 0x98, 0xf4, 0xbd, 0x23, 0xf6, 0xfe, 0x1a, 0x3e, 0x2c, 0x43, 0xed, 0xd9, 0xce,
- 0x7c, 0xa8, 0x4b, 0xed, 0x85, 0x21, 0xe2, 0xe1, 0x40,
- ];
- assert_eq!(server_packet[..], expected_server_packet[..]);
- }
-}
diff --git a/vendor/rustls/src/crypto/ring/sign.rs b/vendor/rustls/src/crypto/ring/sign.rs
deleted file mode 100644
index ad318270..00000000
--- a/vendor/rustls/src/crypto/ring/sign.rs
+++ /dev/null
@@ -1,822 +0,0 @@
-#![allow(clippy::duplicate_mod)]
-
-use alloc::boxed::Box;
-use alloc::string::ToString;
-use alloc::vec::Vec;
-use alloc::{format, vec};
-use core::fmt::{self, Debug, Formatter};
-
-use pki_types::{PrivateKeyDer, PrivatePkcs8KeyDer, SubjectPublicKeyInfoDer, alg_id};
-
-use super::ring_like::rand::{SecureRandom, SystemRandom};
-use super::ring_like::signature::{self, EcdsaKeyPair, Ed25519KeyPair, KeyPair, RsaKeyPair};
-use crate::crypto::signer::{Signer, SigningKey, public_key_to_spki};
-use crate::enums::{SignatureAlgorithm, SignatureScheme};
-use crate::error::Error;
-use crate::sync::Arc;
-use crate::x509::{wrap_concat_in_sequence, wrap_in_octet_string};
-
-/// Parse `der` as any supported key encoding/type, returning
-/// the first which works.
-pub fn any_supported_type(der: &PrivateKeyDer<'_>) -> Result<Arc<dyn SigningKey>, Error> {
- if let Ok(rsa) = RsaSigningKey::new(der) {
- return Ok(Arc::new(rsa));
- }
-
- if let Ok(ecdsa) = any_ecdsa_type(der) {
- return Ok(ecdsa);
- }
-
- if let PrivateKeyDer::Pkcs8(pkcs8) = der {
- if let Ok(eddsa) = any_eddsa_type(pkcs8) {
- return Ok(eddsa);
- }
- }
-
- Err(Error::General(
- "failed to parse private key as RSA, ECDSA, or EdDSA".into(),
- ))
-}
-
-/// Parse `der` as any ECDSA key type, returning the first which works.
-///
-/// Both SEC1 (PEM section starting with 'BEGIN EC PRIVATE KEY') and PKCS8
-/// (PEM section starting with 'BEGIN PRIVATE KEY') encodings are supported.
-pub fn any_ecdsa_type(der: &PrivateKeyDer<'_>) -> Result<Arc<dyn SigningKey>, Error> {
- if let Ok(ecdsa_p256) = EcdsaSigningKey::new(
- der,
- SignatureScheme::ECDSA_NISTP256_SHA256,
- &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
- ) {
- return Ok(Arc::new(ecdsa_p256));
- }
-
- if let Ok(ecdsa_p384) = EcdsaSigningKey::new(
- der,
- SignatureScheme::ECDSA_NISTP384_SHA384,
- &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
- ) {
- return Ok(Arc::new(ecdsa_p384));
- }
-
- Err(Error::General(
- "failed to parse ECDSA private key as PKCS#8 or SEC1".into(),
- ))
-}
-
-/// Parse `der` as any EdDSA key type, returning the first which works.
-///
-/// Note that, at the time of writing, Ed25519 does not have wide support
-/// in browsers. It is also not supported by the WebPKI, because the
-/// CA/Browser Forum Baseline Requirements do not support it for publicly
-/// trusted certificates.
-pub fn any_eddsa_type(der: &PrivatePkcs8KeyDer<'_>) -> Result<Arc<dyn SigningKey>, Error> {
- // TODO: Add support for Ed448
- Ok(Arc::new(Ed25519SigningKey::new(
- der,
- SignatureScheme::ED25519,
- )?))
-}
-
-/// A `SigningKey` for RSA-PKCS1 or RSA-PSS.
-///
-/// This is used by the test suite, so it must be `pub`, but it isn't part of
-/// the public, stable, API.
-#[doc(hidden)]
-pub struct RsaSigningKey {
- key: Arc<RsaKeyPair>,
-}
-
-static ALL_RSA_SCHEMES: &[SignatureScheme] = &[
- SignatureScheme::RSA_PSS_SHA512,
- SignatureScheme::RSA_PSS_SHA384,
- SignatureScheme::RSA_PSS_SHA256,
- SignatureScheme::RSA_PKCS1_SHA512,
- SignatureScheme::RSA_PKCS1_SHA384,
- SignatureScheme::RSA_PKCS1_SHA256,
-];
-
-impl RsaSigningKey {
- /// Make a new `RsaSigningKey` from a DER encoding, in either
- /// PKCS#1 or PKCS#8 format.
- pub fn new(der: &PrivateKeyDer<'_>) -> Result<Self, Error> {
- let key_pair = match der {
- PrivateKeyDer::Pkcs1(pkcs1) => RsaKeyPair::from_der(pkcs1.secret_pkcs1_der()),
- PrivateKeyDer::Pkcs8(pkcs8) => RsaKeyPair::from_pkcs8(pkcs8.secret_pkcs8_der()),
- _ => {
- return Err(Error::General(
- "failed to parse RSA private key as either PKCS#1 or PKCS#8".into(),
- ));
- }
- }
- .map_err(|key_rejected| {
- Error::General(format!("failed to parse RSA private key: {key_rejected}"))
- })?;
-
- Ok(Self {
- key: Arc::new(key_pair),
- })
- }
-}
-
-impl SigningKey for RsaSigningKey {
- fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
- ALL_RSA_SCHEMES
- .iter()
- .find(|scheme| offered.contains(scheme))
- .map(|scheme| RsaSigner::new(self.key.clone(), *scheme))
- }
-
- fn public_key(&self) -> Option<SubjectPublicKeyInfoDer<'_>> {
- Some(public_key_to_spki(
- &alg_id::RSA_ENCRYPTION,
- self.key.public_key(),
- ))
- }
-
- fn algorithm(&self) -> SignatureAlgorithm {
- SignatureAlgorithm::RSA
- }
-}
-
-impl Debug for RsaSigningKey {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- f.debug_struct("RsaSigningKey")
- .field("algorithm", &self.algorithm())
- .finish()
- }
-}
-
-struct RsaSigner {
- key: Arc<RsaKeyPair>,
- scheme: SignatureScheme,
- encoding: &'static dyn signature::RsaEncoding,
-}
-
-impl RsaSigner {
- fn new(key: Arc<RsaKeyPair>, scheme: SignatureScheme) -> Box<dyn Signer> {
- let encoding: &dyn signature::RsaEncoding = match scheme {
- SignatureScheme::RSA_PKCS1_SHA256 => &signature::RSA_PKCS1_SHA256,
- SignatureScheme::RSA_PKCS1_SHA384 => &signature::RSA_PKCS1_SHA384,
- SignatureScheme::RSA_PKCS1_SHA512 => &signature::RSA_PKCS1_SHA512,
- SignatureScheme::RSA_PSS_SHA256 => &signature::RSA_PSS_SHA256,
- SignatureScheme::RSA_PSS_SHA384 => &signature::RSA_PSS_SHA384,
- SignatureScheme::RSA_PSS_SHA512 => &signature::RSA_PSS_SHA512,
- _ => unreachable!(),
- };
-
- Box::new(Self {
- key,
- scheme,
- encoding,
- })
- }
-}
-
-impl Signer for RsaSigner {
- fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
- let mut sig = vec![0; self.key.public().modulus_len()];
-
- let rng = SystemRandom::new();
- self.key
- .sign(self.encoding, &rng, message, &mut sig)
- .map(|_| sig)
- .map_err(|_| Error::General("signing failed".to_string()))
- }
-
- fn scheme(&self) -> SignatureScheme {
- self.scheme
- }
-}
-
-impl Debug for RsaSigner {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- f.debug_struct("RsaSigner")
- .field("scheme", &self.scheme)
- .finish()
- }
-}
-
-/// A SigningKey that uses exactly one TLS-level SignatureScheme
-/// and one ring-level signature::SigningAlgorithm.
-///
-/// Compare this to RsaSigningKey, which for a particular key is
-/// willing to sign with several algorithms. This is quite poor
-/// cryptography practice, but is necessary because a given RSA key
-/// is expected to work in TLS1.2 (PKCS#1 signatures) and TLS1.3
-/// (PSS signatures) -- nobody is willing to obtain certificates for
-/// different protocol versions.
-///
-/// Currently this is only implemented for ECDSA keys.
-struct EcdsaSigningKey {
- key: Arc<EcdsaKeyPair>,
- scheme: SignatureScheme,
-}
-
-impl EcdsaSigningKey {
- /// Make a new `ECDSASigningKey` from a DER encoding in PKCS#8 or SEC1
- /// format, expecting a key usable with precisely the given signature
- /// scheme.
- fn new(
- der: &PrivateKeyDer<'_>,
- scheme: SignatureScheme,
- sigalg: &'static signature::EcdsaSigningAlgorithm,
- ) -> Result<Self, ()> {
- let rng = SystemRandom::new();
- let key_pair = match der {
- PrivateKeyDer::Sec1(sec1) => {
- Self::convert_sec1_to_pkcs8(scheme, sigalg, sec1.secret_sec1_der(), &rng)?
- }
- PrivateKeyDer::Pkcs8(pkcs8) => {
- EcdsaKeyPair::from_pkcs8(sigalg, pkcs8.secret_pkcs8_der(), &rng).map_err(|_| ())?
- }
- _ => return Err(()),
- };
-
- Ok(Self {
- key: Arc::new(key_pair),
- scheme,
- })
- }
-
- /// Convert a SEC1 encoding to PKCS8, and ask ring to parse it. This
- /// can be removed once <https://github.com/briansmith/ring/pull/1456>
- /// (or equivalent) is landed.
- fn convert_sec1_to_pkcs8(
- scheme: SignatureScheme,
- sigalg: &'static signature::EcdsaSigningAlgorithm,
- maybe_sec1_der: &[u8],
- rng: &dyn SecureRandom,
- ) -> Result<EcdsaKeyPair, ()> {
- let pkcs8_prefix = match scheme {
- SignatureScheme::ECDSA_NISTP256_SHA256 => &PKCS8_PREFIX_ECDSA_NISTP256,
- SignatureScheme::ECDSA_NISTP384_SHA384 => &PKCS8_PREFIX_ECDSA_NISTP384,
- _ => unreachable!(), // all callers are in this file
- };
-
- let sec1_wrap = wrap_in_octet_string(maybe_sec1_der);
- let pkcs8 = wrap_concat_in_sequence(pkcs8_prefix, &sec1_wrap);
-
- EcdsaKeyPair::from_pkcs8(sigalg, &pkcs8, rng).map_err(|_| ())
- }
-}
-
-// This is (line-by-line):
-// - INTEGER Version = 0
-// - SEQUENCE (privateKeyAlgorithm)
-// - id-ecPublicKey OID
-// - prime256v1 OID
-const PKCS8_PREFIX_ECDSA_NISTP256: &[u8] = b"\x02\x01\x00\
- \x30\x13\
- \x06\x07\x2a\x86\x48\xce\x3d\x02\x01\
- \x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07";
-
-// This is (line-by-line):
-// - INTEGER Version = 0
-// - SEQUENCE (privateKeyAlgorithm)
-// - id-ecPublicKey OID
-// - secp384r1 OID
-const PKCS8_PREFIX_ECDSA_NISTP384: &[u8] = b"\x02\x01\x00\
- \x30\x10\
- \x06\x07\x2a\x86\x48\xce\x3d\x02\x01\
- \x06\x05\x2b\x81\x04\x00\x22";
-
-impl SigningKey for EcdsaSigningKey {
- fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
- if offered.contains(&self.scheme) {
- Some(Box::new(EcdsaSigner {
- key: self.key.clone(),
- scheme: self.scheme,
- }))
- } else {
- None
- }
- }
-
- fn public_key(&self) -> Option<SubjectPublicKeyInfoDer<'_>> {
- let id = match self.scheme {
- SignatureScheme::ECDSA_NISTP256_SHA256 => alg_id::ECDSA_P256,
- SignatureScheme::ECDSA_NISTP384_SHA384 => alg_id::ECDSA_P384,
- _ => unreachable!(),
- };
-
- Some(public_key_to_spki(&id, self.key.public_key()))
- }
-
- fn algorithm(&self) -> SignatureAlgorithm {
- self.scheme.algorithm()
- }
-}
-
-impl Debug for EcdsaSigningKey {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- f.debug_struct("EcdsaSigningKey")
- .field("algorithm", &self.algorithm())
- .finish()
- }
-}
-
-struct EcdsaSigner {
- key: Arc<EcdsaKeyPair>,
- scheme: SignatureScheme,
-}
-
-impl Signer for EcdsaSigner {
- fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
- let rng = SystemRandom::new();
- self.key
- .sign(&rng, message)
- .map_err(|_| Error::General("signing failed".into()))
- .map(|sig| sig.as_ref().into())
- }
-
- fn scheme(&self) -> SignatureScheme {
- self.scheme
- }
-}
-
-impl Debug for EcdsaSigner {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- f.debug_struct("EcdsaSigner")
- .field("scheme", &self.scheme)
- .finish()
- }
-}
-
-/// A SigningKey that uses exactly one TLS-level SignatureScheme
-/// and one ring-level signature::SigningAlgorithm.
-///
-/// Compare this to RsaSigningKey, which for a particular key is
-/// willing to sign with several algorithms. This is quite poor
-/// cryptography practice, but is necessary because a given RSA key
-/// is expected to work in TLS1.2 (PKCS#1 signatures) and TLS1.3
-/// (PSS signatures) -- nobody is willing to obtain certificates for
-/// different protocol versions.
-///
-/// Currently this is only implemented for Ed25519 keys.
-struct Ed25519SigningKey {
- key: Arc<Ed25519KeyPair>,
- scheme: SignatureScheme,
-}
-
-impl Ed25519SigningKey {
- /// Make a new `Ed25519SigningKey` from a DER encoding in PKCS#8 format,
- /// expecting a key usable with precisely the given signature scheme.
- fn new(der: &PrivatePkcs8KeyDer<'_>, scheme: SignatureScheme) -> Result<Self, Error> {
- match Ed25519KeyPair::from_pkcs8_maybe_unchecked(der.secret_pkcs8_der()) {
- Ok(key_pair) => Ok(Self {
- key: Arc::new(key_pair),
- scheme,
- }),
- Err(e) => Err(Error::General(format!(
- "failed to parse Ed25519 private key: {e}"
- ))),
- }
- }
-}
-
-impl SigningKey for Ed25519SigningKey {
- fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
- if offered.contains(&self.scheme) {
- Some(Box::new(Ed25519Signer {
- key: self.key.clone(),
- scheme: self.scheme,
- }))
- } else {
- None
- }
- }
-
- fn public_key(&self) -> Option<SubjectPublicKeyInfoDer<'_>> {
- Some(public_key_to_spki(&alg_id::ED25519, self.key.public_key()))
- }
-
- fn algorithm(&self) -> SignatureAlgorithm {
- self.scheme.algorithm()
- }
-}
-
-impl Debug for Ed25519SigningKey {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- f.debug_struct("Ed25519SigningKey")
- .field("algorithm", &self.algorithm())
- .finish()
- }
-}
-
-struct Ed25519Signer {
- key: Arc<Ed25519KeyPair>,
- scheme: SignatureScheme,
-}
-
-impl Signer for Ed25519Signer {
- fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
- Ok(self.key.sign(message).as_ref().into())
- }
-
- fn scheme(&self) -> SignatureScheme {
- self.scheme
- }
-}
-
-impl Debug for Ed25519Signer {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- f.debug_struct("Ed25519Signer")
- .field("scheme", &self.scheme)
- .finish()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use alloc::format;
-
- use pki_types::{PrivatePkcs1KeyDer, PrivateSec1KeyDer};
-
- use super::*;
-
- #[test]
- fn can_load_ecdsa_nistp256_pkcs8() {
- let key =
- PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/nistp256key.pkcs8.der")[..]);
- assert!(any_eddsa_type(&key).is_err());
- let key = PrivateKeyDer::Pkcs8(key);
- assert!(any_supported_type(&key).is_ok());
- assert!(any_ecdsa_type(&key).is_ok());
- }
-
- #[test]
- fn can_load_ecdsa_nistp256_sec1() {
- let key = PrivateKeyDer::Sec1(PrivateSec1KeyDer::from(
- &include_bytes!("../../testdata/nistp256key.der")[..],
- ));
- assert!(any_supported_type(&key).is_ok());
- assert!(any_ecdsa_type(&key).is_ok());
- }
-
- #[test]
- fn can_sign_ecdsa_nistp256() {
- let key = PrivateKeyDer::Sec1(PrivateSec1KeyDer::from(
- &include_bytes!("../../testdata/nistp256key.der")[..],
- ));
-
- let k = any_supported_type(&key).unwrap();
- assert_eq!(format!("{k:?}"), "EcdsaSigningKey { algorithm: ECDSA }");
- assert_eq!(k.algorithm(), SignatureAlgorithm::ECDSA);
-
- assert!(
- k.choose_scheme(&[SignatureScheme::RSA_PKCS1_SHA256])
- .is_none()
- );
- assert!(
- k.choose_scheme(&[SignatureScheme::ECDSA_NISTP384_SHA384])
- .is_none()
- );
- let s = k
- .choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256])
- .unwrap();
- assert_eq!(
- format!("{s:?}"),
- "EcdsaSigner { scheme: ECDSA_NISTP256_SHA256 }"
- );
- assert_eq!(s.scheme(), SignatureScheme::ECDSA_NISTP256_SHA256);
- // nb. signature is variable length and asn.1-encoded
- assert!(
- s.sign(b"hello")
- .unwrap()
- .starts_with(&[0x30])
- );
- }
-
- #[test]
- fn can_load_ecdsa_nistp384_pkcs8() {
- let key =
- PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/nistp384key.pkcs8.der")[..]);
- assert!(any_eddsa_type(&key).is_err());
- let key = PrivateKeyDer::Pkcs8(key);
- assert!(any_supported_type(&key).is_ok());
- assert!(any_ecdsa_type(&key).is_ok());
- }
-
- #[test]
- fn can_load_ecdsa_nistp384_sec1() {
- let key = PrivateKeyDer::Sec1(PrivateSec1KeyDer::from(
- &include_bytes!("../../testdata/nistp384key.der")[..],
- ));
- assert!(any_supported_type(&key).is_ok());
- assert!(any_ecdsa_type(&key).is_ok());
- }
-
- #[test]
- fn can_sign_ecdsa_nistp384() {
- let key = PrivateKeyDer::Sec1(PrivateSec1KeyDer::from(
- &include_bytes!("../../testdata/nistp384key.der")[..],
- ));
-
- let k = any_supported_type(&key).unwrap();
- assert_eq!(format!("{k:?}"), "EcdsaSigningKey { algorithm: ECDSA }");
- assert_eq!(k.algorithm(), SignatureAlgorithm::ECDSA);
-
- assert!(
- k.choose_scheme(&[SignatureScheme::RSA_PKCS1_SHA256])
- .is_none()
- );
- assert!(
- k.choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256])
- .is_none()
- );
- let s = k
- .choose_scheme(&[SignatureScheme::ECDSA_NISTP384_SHA384])
- .unwrap();
- assert_eq!(
- format!("{s:?}"),
- "EcdsaSigner { scheme: ECDSA_NISTP384_SHA384 }"
- );
- assert_eq!(s.scheme(), SignatureScheme::ECDSA_NISTP384_SHA384);
- // nb. signature is variable length and asn.1-encoded
- assert!(
- s.sign(b"hello")
- .unwrap()
- .starts_with(&[0x30])
- );
- }
-
- #[test]
- fn can_load_eddsa_pkcs8() {
- let key = PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/eddsakey.der")[..]);
- assert!(any_eddsa_type(&key).is_ok());
- let key = PrivateKeyDer::Pkcs8(key);
- assert!(any_supported_type(&key).is_ok());
- assert!(any_ecdsa_type(&key).is_err());
- }
-
- #[test]
- fn can_sign_eddsa() {
- let key = PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/eddsakey.der")[..]);
-
- let k = any_eddsa_type(&key).unwrap();
- assert_eq!(format!("{k:?}"), "Ed25519SigningKey { algorithm: ED25519 }");
- assert_eq!(k.algorithm(), SignatureAlgorithm::ED25519);
-
- assert!(
- k.choose_scheme(&[SignatureScheme::RSA_PKCS1_SHA256])
- .is_none()
- );
- assert!(
- k.choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256])
- .is_none()
- );
- let s = k
- .choose_scheme(&[SignatureScheme::ED25519])
- .unwrap();
- assert_eq!(format!("{s:?}"), "Ed25519Signer { scheme: ED25519 }");
- assert_eq!(s.scheme(), SignatureScheme::ED25519);
- assert_eq!(s.sign(b"hello").unwrap().len(), 64);
- }
-
- #[test]
- fn can_load_rsa2048_pkcs8() {
- let key =
- PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/rsa2048key.pkcs8.der")[..]);
- assert!(any_eddsa_type(&key).is_err());
- let key = PrivateKeyDer::Pkcs8(key);
- assert!(any_supported_type(&key).is_ok());
- assert!(any_ecdsa_type(&key).is_err());
- }
-
- #[test]
- fn can_load_rsa2048_pkcs1() {
- let key = PrivateKeyDer::Pkcs1(PrivatePkcs1KeyDer::from(
- &include_bytes!("../../testdata/rsa2048key.pkcs1.der")[..],
- ));
- assert!(any_supported_type(&key).is_ok());
- assert!(any_ecdsa_type(&key).is_err());
- }
-
- #[test]
- fn can_sign_rsa2048() {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/rsa2048key.pkcs8.der")[..],
- ));
-
- let k = any_supported_type(&key).unwrap();
- assert_eq!(format!("{k:?}"), "RsaSigningKey { algorithm: RSA }");
- assert_eq!(k.algorithm(), SignatureAlgorithm::RSA);
-
- assert!(
- k.choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256])
- .is_none()
- );
- assert!(
- k.choose_scheme(&[SignatureScheme::ED25519])
- .is_none()
- );
-
- let s = k
- .choose_scheme(&[SignatureScheme::RSA_PSS_SHA256])
- .unwrap();
- assert_eq!(format!("{s:?}"), "RsaSigner { scheme: RSA_PSS_SHA256 }");
- assert_eq!(s.scheme(), SignatureScheme::RSA_PSS_SHA256);
- assert_eq!(s.sign(b"hello").unwrap().len(), 256);
-
- for scheme in &[
- SignatureScheme::RSA_PKCS1_SHA256,
- SignatureScheme::RSA_PKCS1_SHA384,
- SignatureScheme::RSA_PKCS1_SHA512,
- SignatureScheme::RSA_PSS_SHA256,
- SignatureScheme::RSA_PSS_SHA384,
- SignatureScheme::RSA_PSS_SHA512,
- ] {
- k.choose_scheme(&[*scheme]).unwrap();
- }
- }
-
- #[test]
- fn cannot_load_invalid_pkcs8_encoding() {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(&b"invalid"[..]));
- assert_eq!(
- any_supported_type(&key).err(),
- Some(Error::General(
- "failed to parse private key as RSA, ECDSA, or EdDSA".into()
- ))
- );
- assert_eq!(
- any_ecdsa_type(&key).err(),
- Some(Error::General(
- "failed to parse ECDSA private key as PKCS#8 or SEC1".into()
- ))
- );
- assert_eq!(
- RsaSigningKey::new(&key).err(),
- Some(Error::General(
- "failed to parse RSA private key: InvalidEncoding".into()
- ))
- );
- }
-}
-
-#[cfg(bench)]
-mod benchmarks {
- use super::{PrivateKeyDer, PrivatePkcs8KeyDer, SignatureScheme};
-
- #[bench]
- fn bench_rsa2048_pkcs1_sha256(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/rsa2048key.pkcs8.der")[..],
- ));
- let sk = super::any_supported_type(&key).unwrap();
- let signer = sk
- .choose_scheme(&[SignatureScheme::RSA_PKCS1_SHA256])
- .unwrap();
-
- b.iter(|| {
- test::black_box(
- signer
- .sign(SAMPLE_TLS13_MESSAGE)
- .unwrap(),
- );
- });
- }
-
- #[bench]
- fn bench_rsa2048_pss_sha256(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/rsa2048key.pkcs8.der")[..],
- ));
- let sk = super::any_supported_type(&key).unwrap();
- let signer = sk
- .choose_scheme(&[SignatureScheme::RSA_PSS_SHA256])
- .unwrap();
-
- b.iter(|| {
- test::black_box(
- signer
- .sign(SAMPLE_TLS13_MESSAGE)
- .unwrap(),
- );
- });
- }
-
- #[bench]
- fn bench_eddsa(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/eddsakey.der")[..],
- ));
- let sk = super::any_supported_type(&key).unwrap();
- let signer = sk
- .choose_scheme(&[SignatureScheme::ED25519])
- .unwrap();
-
- b.iter(|| {
- test::black_box(
- signer
- .sign(SAMPLE_TLS13_MESSAGE)
- .unwrap(),
- );
- });
- }
-
- #[bench]
- fn bench_ecdsa_p256_sha256(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/nistp256key.pkcs8.der")[..],
- ));
- let sk = super::any_supported_type(&key).unwrap();
- let signer = sk
- .choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256])
- .unwrap();
-
- b.iter(|| {
- test::black_box(
- signer
- .sign(SAMPLE_TLS13_MESSAGE)
- .unwrap(),
- );
- });
- }
-
- #[bench]
- fn bench_ecdsa_p384_sha384(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/nistp384key.pkcs8.der")[..],
- ));
- let sk = super::any_supported_type(&key).unwrap();
- let signer = sk
- .choose_scheme(&[SignatureScheme::ECDSA_NISTP384_SHA384])
- .unwrap();
-
- b.iter(|| {
- test::black_box(
- signer
- .sign(SAMPLE_TLS13_MESSAGE)
- .unwrap(),
- );
- });
- }
-
- #[bench]
- fn bench_load_and_validate_rsa2048(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/rsa2048key.pkcs8.der")[..],
- ));
-
- b.iter(|| {
- test::black_box(super::any_supported_type(&key).unwrap());
- });
- }
-
- #[bench]
- fn bench_load_and_validate_rsa4096(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/rsa4096key.pkcs8.der")[..],
- ));
-
- b.iter(|| {
- test::black_box(super::any_supported_type(&key).unwrap());
- });
- }
-
- #[bench]
- fn bench_load_and_validate_p256(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/nistp256key.pkcs8.der")[..],
- ));
-
- b.iter(|| {
- test::black_box(super::any_ecdsa_type(&key).unwrap());
- });
- }
-
- #[bench]
- fn bench_load_and_validate_p384(b: &mut test::Bencher) {
- let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
- &include_bytes!("../../testdata/nistp384key.pkcs8.der")[..],
- ));
-
- b.iter(|| {
- test::black_box(super::any_ecdsa_type(&key).unwrap());
- });
- }
-
- #[bench]
- fn bench_load_and_validate_eddsa(b: &mut test::Bencher) {
- let key = PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/eddsakey.der")[..]);
-
- b.iter(|| {
- test::black_box(super::any_eddsa_type(&key).unwrap());
- });
- }
-
- const SAMPLE_TLS13_MESSAGE: &[u8] = &[
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x54, 0x4c, 0x53, 0x20, 0x31, 0x2e, 0x33, 0x2c, 0x20, 0x73, 0x65,
- 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
- 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x00, 0x04, 0xca, 0xc4, 0x48, 0x0e, 0x70, 0xf2,
- 0x1b, 0xa9, 0x1c, 0x16, 0xca, 0x90, 0x48, 0xbe, 0x28, 0x2f, 0xc7, 0xf8, 0x9b, 0x87, 0x72,
- 0x93, 0xda, 0x4d, 0x2f, 0x80, 0x80, 0x60, 0x1a, 0xd3, 0x08, 0xe2, 0xb7, 0x86, 0x14, 0x1b,
- 0x54, 0xda, 0x9a, 0xc9, 0x6d, 0xe9, 0x66, 0xb4, 0x9f, 0xe2, 0x2c,
- ];
-}
diff --git a/vendor/rustls/src/crypto/ring/ticketer.rs b/vendor/rustls/src/crypto/ring/ticketer.rs
deleted file mode 100644
index 45dcc27a..00000000
--- a/vendor/rustls/src/crypto/ring/ticketer.rs
+++ /dev/null
@@ -1,366 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec::Vec;
-use core::fmt;
-use core::fmt::{Debug, Formatter};
-use core::sync::atomic::{AtomicUsize, Ordering};
-
-use subtle::ConstantTimeEq;
-
-use super::ring_like::aead;
-use super::ring_like::rand::{SecureRandom, SystemRandom};
-use crate::error::Error;
-#[cfg(debug_assertions)]
-use crate::log::debug;
-use crate::polyfill::try_split_at;
-use crate::rand::GetRandomFailed;
-use crate::server::ProducesTickets;
-use crate::sync::Arc;
-
-/// A concrete, safe ticket creation mechanism.
-pub struct Ticketer {}
-
-impl Ticketer {
- /// Make the recommended `Ticketer`. This produces tickets
- /// with a 12 hour life and randomly generated keys.
- ///
- /// The encryption mechanism used is Chacha20Poly1305.
- #[cfg(feature = "std")]
- pub fn new() -> Result<Arc<dyn ProducesTickets>, Error> {
- Ok(Arc::new(crate::ticketer::TicketRotator::new(
- 6 * 60 * 60,
- make_ticket_generator,
- )?))
- }
-}
-
-fn make_ticket_generator() -> Result<Box<dyn ProducesTickets>, GetRandomFailed> {
- Ok(Box::new(AeadTicketer::new()?))
-}
-
-/// This is a `ProducesTickets` implementation which uses
-/// any *ring* `aead::Algorithm` to encrypt and authentication
-/// the ticket payload. It does not enforce any lifetime
-/// constraint.
-struct AeadTicketer {
- alg: &'static aead::Algorithm,
- key: aead::LessSafeKey,
- key_name: [u8; 16],
- lifetime: u32,
-
- /// Tracks the largest ciphertext produced by `encrypt`, and
- /// uses it to early-reject `decrypt` queries that are too long.
- ///
- /// Accepting excessively long ciphertexts means a "Partitioning
- /// Oracle Attack" (see <https://eprint.iacr.org/2020/1491.pdf>)
- /// can be more efficient, though also note that these are thought
- /// to be cryptographically hard if the key is full-entropy (as it
- /// is here).
- maximum_ciphertext_len: AtomicUsize,
-}
-
-impl AeadTicketer {
- fn new() -> Result<Self, GetRandomFailed> {
- let mut key = [0u8; 32];
- SystemRandom::new()
- .fill(&mut key)
- .map_err(|_| GetRandomFailed)?;
-
- let key = aead::UnboundKey::new(TICKETER_AEAD, &key).unwrap();
-
- let mut key_name = [0u8; 16];
- SystemRandom::new()
- .fill(&mut key_name)
- .map_err(|_| GetRandomFailed)?;
-
- Ok(Self {
- alg: TICKETER_AEAD,
- key: aead::LessSafeKey::new(key),
- key_name,
- lifetime: 60 * 60 * 12,
- maximum_ciphertext_len: AtomicUsize::new(0),
- })
- }
-}
-
-impl ProducesTickets for AeadTicketer {
- fn enabled(&self) -> bool {
- true
- }
-
- fn lifetime(&self) -> u32 {
- self.lifetime
- }
-
- /// Encrypt `message` and return the ciphertext.
- fn encrypt(&self, message: &[u8]) -> Option<Vec<u8>> {
- // Random nonce, because a counter is a privacy leak.
- let mut nonce_buf = [0u8; 12];
- SystemRandom::new()
- .fill(&mut nonce_buf)
- .ok()?;
- let nonce = aead::Nonce::assume_unique_for_key(nonce_buf);
- let aad = aead::Aad::from(self.key_name);
-
- // ciphertext structure is:
- // key_name: [u8; 16]
- // nonce: [u8; 12]
- // message: [u8, _]
- // tag: [u8; 16]
-
- let mut ciphertext = Vec::with_capacity(
- self.key_name.len() + nonce_buf.len() + message.len() + self.key.algorithm().tag_len(),
- );
- ciphertext.extend(self.key_name);
- ciphertext.extend(nonce_buf);
- ciphertext.extend(message);
- let ciphertext = self
- .key
- .seal_in_place_separate_tag(
- nonce,
- aad,
- &mut ciphertext[self.key_name.len() + nonce_buf.len()..],
- )
- .map(|tag| {
- ciphertext.extend(tag.as_ref());
- ciphertext
- })
- .ok()?;
-
- self.maximum_ciphertext_len
- .fetch_max(ciphertext.len(), Ordering::SeqCst);
- Some(ciphertext)
- }
-
- /// Decrypt `ciphertext` and recover the original message.
- fn decrypt(&self, ciphertext: &[u8]) -> Option<Vec<u8>> {
- if ciphertext.len()
- > self
- .maximum_ciphertext_len
- .load(Ordering::SeqCst)
- {
- #[cfg(debug_assertions)]
- debug!("rejected over-length ticket");
- return None;
- }
-
- let (alleged_key_name, ciphertext) = try_split_at(ciphertext, self.key_name.len())?;
-
- let (nonce, ciphertext) = try_split_at(ciphertext, self.alg.nonce_len())?;
-
- // checking the key_name is the expected one, *and* then putting it into the
- // additionally authenticated data is duplicative. this check quickly rejects
- // tickets for a different ticketer (see `TicketSwitcher`), while including it
- // in the AAD ensures it is authenticated independent of that check and that
- // any attempted attack on the integrity such as [^1] must happen for each
- // `key_label`, not over a population of potential keys. this approach
- // is overall similar to [^2].
- //
- // [^1]: https://eprint.iacr.org/2020/1491.pdf
- // [^2]: "Authenticated Encryption with Key Identification", fig 6
- // <https://eprint.iacr.org/2022/1680.pdf>
- if ConstantTimeEq::ct_ne(&self.key_name[..], alleged_key_name).into() {
- #[cfg(debug_assertions)]
- debug!("rejected ticket with wrong ticket_name");
- return None;
- }
-
- // This won't fail since `nonce` has the required length.
- let nonce = aead::Nonce::try_assume_unique_for_key(nonce).ok()?;
-
- let mut out = Vec::from(ciphertext);
-
- let plain_len = self
- .key
- .open_in_place(nonce, aead::Aad::from(alleged_key_name), &mut out)
- .ok()?
- .len();
- out.truncate(plain_len);
-
- Some(out)
- }
-}
-
-impl Debug for AeadTicketer {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- // Note: we deliberately omit the key from the debug output.
- f.debug_struct("AeadTicketer")
- .field("alg", &self.alg)
- .field("lifetime", &self.lifetime)
- .finish()
- }
-}
-
-static TICKETER_AEAD: &aead::Algorithm = &aead::CHACHA20_POLY1305;
-
-#[cfg(test)]
-mod tests {
- use core::time::Duration;
-
- use pki_types::UnixTime;
-
- use super::*;
-
- #[test]
- fn basic_pairwise_test() {
- let t = Ticketer::new().unwrap();
- assert!(t.enabled());
- let cipher = t.encrypt(b"hello world").unwrap();
- let plain = t.decrypt(&cipher).unwrap();
- assert_eq!(plain, b"hello world");
- }
-
- #[test]
- fn refuses_decrypt_before_encrypt() {
- let t = Ticketer::new().unwrap();
- assert_eq!(t.decrypt(b"hello"), None);
- }
-
- #[test]
- fn refuses_decrypt_larger_than_largest_encryption() {
- let t = Ticketer::new().unwrap();
- let mut cipher = t.encrypt(b"hello world").unwrap();
- assert_eq!(t.decrypt(&cipher), Some(b"hello world".to_vec()));
-
- // obviously this would never work anyway, but this
- // and `cannot_decrypt_before_encrypt` exercise the
- // first branch in `decrypt()`
- cipher.push(0);
- assert_eq!(t.decrypt(&cipher), None);
- }
-
- #[test]
- fn ticketrotator_switching_test() {
- let t = Arc::new(crate::ticketer::TicketRotator::new(1, make_ticket_generator).unwrap());
- let now = UnixTime::now();
- let cipher1 = t.encrypt(b"ticket 1").unwrap();
- assert_eq!(t.decrypt(&cipher1).unwrap(), b"ticket 1");
- {
- // Trigger new ticketer
- t.maybe_roll(UnixTime::since_unix_epoch(Duration::from_secs(
- now.as_secs() + 10,
- )));
- }
- let cipher2 = t.encrypt(b"ticket 2").unwrap();
- assert_eq!(t.decrypt(&cipher1).unwrap(), b"ticket 1");
- assert_eq!(t.decrypt(&cipher2).unwrap(), b"ticket 2");
- {
- // Trigger new ticketer
- t.maybe_roll(UnixTime::since_unix_epoch(Duration::from_secs(
- now.as_secs() + 20,
- )));
- }
- let cipher3 = t.encrypt(b"ticket 3").unwrap();
- assert!(t.decrypt(&cipher1).is_none());
- assert_eq!(t.decrypt(&cipher2).unwrap(), b"ticket 2");
- assert_eq!(t.decrypt(&cipher3).unwrap(), b"ticket 3");
- }
-
- #[test]
- fn ticketrotator_remains_usable_over_temporary_ticketer_creation_failure() {
- let mut t = crate::ticketer::TicketRotator::new(1, make_ticket_generator).unwrap();
- let now = UnixTime::now();
- let cipher1 = t.encrypt(b"ticket 1").unwrap();
- assert_eq!(t.decrypt(&cipher1).unwrap(), b"ticket 1");
- t.generator = fail_generator;
- {
- // Failed new ticketer; this means we still need to
- // rotate.
- t.maybe_roll(UnixTime::since_unix_epoch(Duration::from_secs(
- now.as_secs() + 10,
- )));
- }
-
- // check post-failure encryption/decryption still works
- let cipher2 = t.encrypt(b"ticket 2").unwrap();
- assert_eq!(t.decrypt(&cipher1).unwrap(), b"ticket 1");
- assert_eq!(t.decrypt(&cipher2).unwrap(), b"ticket 2");
-
- // do the rotation for real
- t.generator = make_ticket_generator;
- {
- t.maybe_roll(UnixTime::since_unix_epoch(Duration::from_secs(
- now.as_secs() + 20,
- )));
- }
- let cipher3 = t.encrypt(b"ticket 3").unwrap();
- assert!(t.decrypt(&cipher1).is_some());
- assert_eq!(t.decrypt(&cipher2).unwrap(), b"ticket 2");
- assert_eq!(t.decrypt(&cipher3).unwrap(), b"ticket 3");
- }
-
- #[test]
- fn ticketswitcher_switching_test() {
- #[expect(deprecated)]
- let t = Arc::new(crate::ticketer::TicketSwitcher::new(1, make_ticket_generator).unwrap());
- let now = UnixTime::now();
- let cipher1 = t.encrypt(b"ticket 1").unwrap();
- assert_eq!(t.decrypt(&cipher1).unwrap(), b"ticket 1");
- {
- // Trigger new ticketer
- t.maybe_roll(UnixTime::since_unix_epoch(Duration::from_secs(
- now.as_secs() + 10,
- )));
- }
- let cipher2 = t.encrypt(b"ticket 2").unwrap();
- assert_eq!(t.decrypt(&cipher1).unwrap(), b"ticket 1");
- assert_eq!(t.decrypt(&cipher2).unwrap(), b"ticket 2");
- {
- // Trigger new ticketer
- t.maybe_roll(UnixTime::since_unix_epoch(Duration::from_secs(
- now.as_secs() + 20,
- )));
- }
- let cipher3 = t.encrypt(b"ticket 3").unwrap();
- assert!(t.decrypt(&cipher1).is_none());
- assert_eq!(t.decrypt(&cipher2).unwrap(), b"ticket 2");
- assert_eq!(t.decrypt(&cipher3).unwrap(), b"ticket 3");
- }
-
- #[test]
- fn ticketswitcher_recover_test() {
- #[expect(deprecated)]
- let mut t = crate::ticketer::TicketSwitcher::new(1, make_ticket_generator).unwrap();
- let now = UnixTime::now();
- let cipher1 = t.encrypt(b"ticket 1").unwrap();
- assert_eq!(t.decrypt(&cipher1).unwrap(), b"ticket 1");
- t.generator = fail_generator;
- {
- // Failed new ticketer
- t.maybe_roll(UnixTime::since_unix_epoch(Duration::from_secs(
- now.as_secs() + 10,
- )));
- }
- t.generator = make_ticket_generator;
- let cipher2 = t.encrypt(b"ticket 2").unwrap();
- assert_eq!(t.decrypt(&cipher1).unwrap(), b"ticket 1");
- assert_eq!(t.decrypt(&cipher2).unwrap(), b"ticket 2");
- {
- // recover
- t.maybe_roll(UnixTime::since_unix_epoch(Duration::from_secs(
- now.as_secs() + 20,
- )));
- }
- let cipher3 = t.encrypt(b"ticket 3").unwrap();
- assert!(t.decrypt(&cipher1).is_none());
- assert_eq!(t.decrypt(&cipher2).unwrap(), b"ticket 2");
- assert_eq!(t.decrypt(&cipher3).unwrap(), b"ticket 3");
- }
-
- #[test]
- fn aeadticketer_is_debug_and_producestickets() {
- use alloc::format;
-
- use super::*;
-
- let t = make_ticket_generator().unwrap();
-
- let expect = format!("AeadTicketer {{ alg: {TICKETER_AEAD:?}, lifetime: 43200 }}");
- assert_eq!(format!("{t:?}"), expect);
- assert!(t.enabled());
- assert_eq!(t.lifetime(), 43200);
- }
-
- fn fail_generator() -> Result<Box<dyn ProducesTickets>, GetRandomFailed> {
- Err(GetRandomFailed)
- }
-}
diff --git a/vendor/rustls/src/crypto/ring/tls12.rs b/vendor/rustls/src/crypto/ring/tls12.rs
deleted file mode 100644
index 63dfae8b..00000000
--- a/vendor/rustls/src/crypto/ring/tls12.rs
+++ /dev/null
@@ -1,406 +0,0 @@
-use alloc::boxed::Box;
-
-use super::ring_like::aead;
-use crate::crypto::KeyExchangeAlgorithm;
-use crate::crypto::cipher::{
- AeadKey, InboundOpaqueMessage, Iv, KeyBlockShape, MessageDecrypter, MessageEncrypter,
- NONCE_LEN, Nonce, Tls12AeadAlgorithm, UnsupportedOperationError, make_tls12_aad,
-};
-use crate::crypto::tls12::PrfUsingHmac;
-use crate::enums::{CipherSuite, SignatureScheme};
-use crate::error::Error;
-use crate::msgs::fragmenter::MAX_FRAGMENT_LEN;
-use crate::msgs::message::{
- InboundPlainMessage, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload,
-};
-use crate::suites::{CipherSuiteCommon, ConnectionTrafficSecrets, SupportedCipherSuite};
-use crate::tls12::Tls12CipherSuite;
-
-/// The TLS1.2 ciphersuite TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256.
-pub static TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
- SupportedCipherSuite::Tls12(&Tls12CipherSuite {
- common: CipherSuiteCommon {
- suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
- hash_provider: &super::hash::SHA256,
- confidentiality_limit: u64::MAX,
- },
- kx: KeyExchangeAlgorithm::ECDHE,
- sign: TLS12_ECDSA_SCHEMES,
- aead_alg: &ChaCha20Poly1305,
- prf_provider: &PrfUsingHmac(&super::hmac::HMAC_SHA256),
- });
-
-/// The TLS1.2 ciphersuite TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
-pub static TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
- SupportedCipherSuite::Tls12(&Tls12CipherSuite {
- common: CipherSuiteCommon {
- suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
- hash_provider: &super::hash::SHA256,
- confidentiality_limit: u64::MAX,
- },
- kx: KeyExchangeAlgorithm::ECDHE,
- sign: TLS12_RSA_SCHEMES,
- aead_alg: &ChaCha20Poly1305,
- prf_provider: &PrfUsingHmac(&super::hmac::HMAC_SHA256),
- });
-
-/// The TLS1.2 ciphersuite TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
-pub static 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: &super::hash::SHA256,
- confidentiality_limit: 1 << 24,
- },
- kx: KeyExchangeAlgorithm::ECDHE,
- sign: TLS12_RSA_SCHEMES,
- aead_alg: &AES128_GCM,
- prf_provider: &PrfUsingHmac(&super::hmac::HMAC_SHA256),
- });
-
-/// The TLS1.2 ciphersuite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
-pub static 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: &super::hash::SHA384,
- confidentiality_limit: 1 << 24,
- },
- kx: KeyExchangeAlgorithm::ECDHE,
- sign: TLS12_RSA_SCHEMES,
- aead_alg: &AES256_GCM,
- prf_provider: &PrfUsingHmac(&super::hmac::HMAC_SHA384),
- });
-
-/// The TLS1.2 ciphersuite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
-pub static 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: &super::hash::SHA256,
- confidentiality_limit: 1 << 24,
- },
- kx: KeyExchangeAlgorithm::ECDHE,
- sign: TLS12_ECDSA_SCHEMES,
- aead_alg: &AES128_GCM,
- prf_provider: &PrfUsingHmac(&super::hmac::HMAC_SHA256),
- });
-
-/// The TLS1.2 ciphersuite TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
-pub static 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: &super::hash::SHA384,
- confidentiality_limit: 1 << 24,
- },
- kx: KeyExchangeAlgorithm::ECDHE,
- sign: TLS12_ECDSA_SCHEMES,
- aead_alg: &AES256_GCM,
- prf_provider: &PrfUsingHmac(&super::hmac::HMAC_SHA384),
- });
-
-static TLS12_ECDSA_SCHEMES: &[SignatureScheme] = &[
- SignatureScheme::ED25519,
- SignatureScheme::ECDSA_NISTP521_SHA512,
- SignatureScheme::ECDSA_NISTP384_SHA384,
- SignatureScheme::ECDSA_NISTP256_SHA256,
-];
-
-static TLS12_RSA_SCHEMES: &[SignatureScheme] = &[
- SignatureScheme::RSA_PSS_SHA512,
- SignatureScheme::RSA_PSS_SHA384,
- SignatureScheme::RSA_PSS_SHA256,
- SignatureScheme::RSA_PKCS1_SHA512,
- SignatureScheme::RSA_PKCS1_SHA384,
- SignatureScheme::RSA_PKCS1_SHA256,
-];
-
-pub(crate) static AES128_GCM: GcmAlgorithm = GcmAlgorithm(&aead::AES_128_GCM);
-pub(crate) static AES256_GCM: GcmAlgorithm = GcmAlgorithm(&aead::AES_256_GCM);
-
-pub(crate) struct GcmAlgorithm(&'static aead::Algorithm);
-
-impl Tls12AeadAlgorithm for GcmAlgorithm {
- fn decrypter(&self, dec_key: AeadKey, dec_iv: &[u8]) -> Box<dyn MessageDecrypter> {
- let dec_key =
- aead::LessSafeKey::new(aead::UnboundKey::new(self.0, dec_key.as_ref()).unwrap());
-
- let mut ret = GcmMessageDecrypter {
- dec_key,
- dec_salt: [0u8; 4],
- };
-
- debug_assert_eq!(dec_iv.len(), 4);
- ret.dec_salt.copy_from_slice(dec_iv);
- Box::new(ret)
- }
-
- fn encrypter(
- &self,
- enc_key: AeadKey,
- write_iv: &[u8],
- explicit: &[u8],
- ) -> Box<dyn MessageEncrypter> {
- let enc_key =
- aead::LessSafeKey::new(aead::UnboundKey::new(self.0, enc_key.as_ref()).unwrap());
- let iv = gcm_iv(write_iv, explicit);
- Box::new(GcmMessageEncrypter { enc_key, iv })
- }
-
- fn key_block_shape(&self) -> KeyBlockShape {
- KeyBlockShape {
- enc_key_len: self.0.key_len(),
- fixed_iv_len: 4,
- explicit_nonce_len: 8,
- }
- }
-
- fn extract_keys(
- &self,
- key: AeadKey,
- write_iv: &[u8],
- explicit: &[u8],
- ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
- let iv = gcm_iv(write_iv, explicit);
- Ok(match self.0.key_len() {
- 16 => ConnectionTrafficSecrets::Aes128Gcm { key, iv },
- 32 => ConnectionTrafficSecrets::Aes256Gcm { key, iv },
- _ => unreachable!(),
- })
- }
-
- fn fips(&self) -> bool {
- super::fips()
- }
-}
-
-pub(crate) struct ChaCha20Poly1305;
-
-impl Tls12AeadAlgorithm for ChaCha20Poly1305 {
- fn decrypter(&self, dec_key: AeadKey, iv: &[u8]) -> Box<dyn MessageDecrypter> {
- let dec_key = aead::LessSafeKey::new(
- aead::UnboundKey::new(&aead::CHACHA20_POLY1305, dec_key.as_ref()).unwrap(),
- );
- Box::new(ChaCha20Poly1305MessageDecrypter {
- dec_key,
- dec_offset: Iv::copy(iv),
- })
- }
-
- fn encrypter(&self, enc_key: AeadKey, enc_iv: &[u8], _: &[u8]) -> Box<dyn MessageEncrypter> {
- let enc_key = aead::LessSafeKey::new(
- aead::UnboundKey::new(&aead::CHACHA20_POLY1305, enc_key.as_ref()).unwrap(),
- );
- Box::new(ChaCha20Poly1305MessageEncrypter {
- enc_key,
- enc_offset: Iv::copy(enc_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<ConnectionTrafficSecrets, UnsupportedOperationError> {
- // This should always be true because KeyBlockShape and the Iv nonce len are in agreement.
- debug_assert_eq!(aead::NONCE_LEN, iv.len());
- Ok(ConnectionTrafficSecrets::Chacha20Poly1305 {
- key,
- iv: Iv::new(iv[..].try_into().unwrap()),
- })
- }
-
- fn fips(&self) -> bool {
- false // not fips approved
- }
-}
-
-/// A `MessageEncrypter` for AES-GCM AEAD ciphersuites. TLS 1.2 only.
-struct GcmMessageEncrypter {
- enc_key: aead::LessSafeKey,
- iv: Iv,
-}
-
-/// A `MessageDecrypter` for AES-GCM AEAD ciphersuites. TLS1.2 only.
-struct GcmMessageDecrypter {
- dec_key: aead::LessSafeKey,
- dec_salt: [u8; 4],
-}
-
-const GCM_EXPLICIT_NONCE_LEN: usize = 8;
-const GCM_OVERHEAD: usize = GCM_EXPLICIT_NONCE_LEN + 16;
-
-impl MessageDecrypter for GcmMessageDecrypter {
- fn decrypt<'a>(
- &mut self,
- mut msg: InboundOpaqueMessage<'a>,
- seq: u64,
- ) -> Result<InboundPlainMessage<'a>, Error> {
- let payload = &msg.payload;
- if payload.len() < GCM_OVERHEAD {
- return Err(Error::DecryptError);
- }
-
- let nonce = {
- let mut nonce = [0u8; 12];
- nonce[..4].copy_from_slice(&self.dec_salt);
- nonce[4..].copy_from_slice(&payload[..8]);
- aead::Nonce::assume_unique_for_key(nonce)
- };
-
- let aad = aead::Aad::from(make_tls12_aad(
- seq,
- msg.typ,
- msg.version,
- payload.len() - GCM_OVERHEAD,
- ));
-
- let payload = &mut msg.payload;
- let plain_len = self
- .dec_key
- .open_within(nonce, aad, payload, GCM_EXPLICIT_NONCE_LEN..)
- .map_err(|_| Error::DecryptError)?
- .len();
-
- if plain_len > MAX_FRAGMENT_LEN {
- return Err(Error::PeerSentOversizedRecord);
- }
-
- payload.truncate(plain_len);
- Ok(msg.into_plain_message())
- }
-}
-
-impl MessageEncrypter for GcmMessageEncrypter {
- fn encrypt(
- &mut self,
- msg: OutboundPlainMessage<'_>,
- seq: u64,
- ) -> Result<OutboundOpaqueMessage, Error> {
- let total_len = self.encrypted_payload_len(msg.payload.len());
- let mut payload = PrefixedPayload::with_capacity(total_len);
-
- let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
- let aad = aead::Aad::from(make_tls12_aad(seq, msg.typ, msg.version, msg.payload.len()));
- payload.extend_from_slice(&nonce.as_ref()[4..]);
- payload.extend_from_chunks(&msg.payload);
-
- self.enc_key
- .seal_in_place_separate_tag(nonce, aad, &mut payload.as_mut()[GCM_EXPLICIT_NONCE_LEN..])
- .map(|tag| payload.extend_from_slice(tag.as_ref()))
- .map_err(|_| Error::EncryptError)?;
-
- Ok(OutboundOpaqueMessage::new(msg.typ, msg.version, payload))
- }
-
- fn encrypted_payload_len(&self, payload_len: usize) -> usize {
- payload_len + GCM_EXPLICIT_NONCE_LEN + self.enc_key.algorithm().tag_len()
- }
-}
-
-/// The RFC7905/RFC7539 ChaCha20Poly1305 construction.
-/// This implementation does the AAD construction required in TLS1.2.
-/// TLS1.3 uses `TLS13MessageEncrypter`.
-struct ChaCha20Poly1305MessageEncrypter {
- enc_key: aead::LessSafeKey,
- enc_offset: Iv,
-}
-
-/// The RFC7905/RFC7539 ChaCha20Poly1305 construction.
-/// This implementation does the AAD construction required in TLS1.2.
-/// TLS1.3 uses `TLS13MessageDecrypter`.
-struct ChaCha20Poly1305MessageDecrypter {
- dec_key: aead::LessSafeKey,
- dec_offset: Iv,
-}
-
-const CHACHAPOLY1305_OVERHEAD: usize = 16;
-
-impl MessageDecrypter for ChaCha20Poly1305MessageDecrypter {
- fn decrypt<'a>(
- &mut self,
- mut msg: InboundOpaqueMessage<'a>,
- seq: u64,
- ) -> Result<InboundPlainMessage<'a>, Error> {
- let payload = &msg.payload;
-
- if payload.len() < CHACHAPOLY1305_OVERHEAD {
- return Err(Error::DecryptError);
- }
-
- let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.dec_offset, seq).0);
- let aad = aead::Aad::from(make_tls12_aad(
- seq,
- msg.typ,
- msg.version,
- payload.len() - CHACHAPOLY1305_OVERHEAD,
- ));
-
- let payload = &mut msg.payload;
- let plain_len = self
- .dec_key
- .open_in_place(nonce, aad, payload)
- .map_err(|_| Error::DecryptError)?
- .len();
-
- if plain_len > MAX_FRAGMENT_LEN {
- return Err(Error::PeerSentOversizedRecord);
- }
-
- payload.truncate(plain_len);
- Ok(msg.into_plain_message())
- }
-}
-
-impl MessageEncrypter for ChaCha20Poly1305MessageEncrypter {
- fn encrypt(
- &mut self,
- msg: OutboundPlainMessage<'_>,
- seq: u64,
- ) -> Result<OutboundOpaqueMessage, Error> {
- let total_len = self.encrypted_payload_len(msg.payload.len());
- let mut payload = PrefixedPayload::with_capacity(total_len);
-
- let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.enc_offset, seq).0);
- let aad = aead::Aad::from(make_tls12_aad(seq, msg.typ, msg.version, msg.payload.len()));
- payload.extend_from_chunks(&msg.payload);
-
- self.enc_key
- .seal_in_place_append_tag(nonce, aad, &mut payload)
- .map_err(|_| Error::EncryptError)?;
-
- Ok(OutboundOpaqueMessage::new(msg.typ, msg.version, payload))
- }
-
- fn encrypted_payload_len(&self, payload_len: usize) -> usize {
- payload_len + self.enc_key.algorithm().tag_len()
- }
-}
-
-fn gcm_iv(write_iv: &[u8], explicit: &[u8]) -> Iv {
- debug_assert_eq!(write_iv.len(), 4);
- debug_assert_eq!(explicit.len(), 8);
-
- // The GCM nonce is constructed from a 32-bit 'salt' derived
- // from the master-secret, and a 64-bit explicit part,
- // with no specified construction. Thanks for that.
- //
- // We use the same construction as TLS1.3/ChaCha20Poly1305:
- // a starting point extracted from the key block, xored with
- // the sequence number.
- let mut iv = [0; NONCE_LEN];
- iv[..4].copy_from_slice(write_iv);
- iv[4..].copy_from_slice(explicit);
-
- Iv::new(iv)
-}
diff --git a/vendor/rustls/src/crypto/ring/tls13.rs b/vendor/rustls/src/crypto/ring/tls13.rs
deleted file mode 100644
index ef488b62..00000000
--- a/vendor/rustls/src/crypto/ring/tls13.rs
+++ /dev/null
@@ -1,336 +0,0 @@
-use alloc::boxed::Box;
-
-use super::ring_like::hkdf::KeyType;
-use super::ring_like::{aead, hkdf, hmac};
-use crate::crypto;
-use crate::crypto::cipher::{
- AeadKey, InboundOpaqueMessage, Iv, MessageDecrypter, MessageEncrypter, Nonce,
- Tls13AeadAlgorithm, UnsupportedOperationError, make_tls13_aad,
-};
-use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock, OutputLengthError};
-use crate::enums::{CipherSuite, ContentType, ProtocolVersion};
-use crate::error::Error;
-use crate::msgs::message::{
- InboundPlainMessage, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload,
-};
-use crate::suites::{CipherSuiteCommon, ConnectionTrafficSecrets, SupportedCipherSuite};
-use crate::tls13::Tls13CipherSuite;
-
-/// The TLS1.3 ciphersuite TLS_CHACHA20_POLY1305_SHA256
-pub static TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
- SupportedCipherSuite::Tls13(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
-
-pub(crate) static TLS13_CHACHA20_POLY1305_SHA256_INTERNAL: &Tls13CipherSuite = &Tls13CipherSuite {
- common: CipherSuiteCommon {
- suite: CipherSuite::TLS13_CHACHA20_POLY1305_SHA256,
- hash_provider: &super::hash::SHA256,
- // ref: <https://www.ietf.org/archive/id/draft-irtf-cfrg-aead-limits-08.html#section-5.2.1>
- confidentiality_limit: u64::MAX,
- },
- hkdf_provider: &RingHkdf(hkdf::HKDF_SHA256, hmac::HMAC_SHA256),
- aead_alg: &Chacha20Poly1305Aead(AeadAlgorithm(&aead::CHACHA20_POLY1305)),
- quic: Some(&super::quic::KeyBuilder {
- packet_alg: &aead::CHACHA20_POLY1305,
- header_alg: &aead::quic::CHACHA20,
- // ref: <https://datatracker.ietf.org/doc/html/rfc9001#section-6.6>
- confidentiality_limit: u64::MAX,
- // ref: <https://datatracker.ietf.org/doc/html/rfc9001#section-6.6>
- integrity_limit: 1 << 36,
- }),
-};
-
-/// The TLS1.3 ciphersuite TLS_AES_256_GCM_SHA384
-pub static TLS13_AES_256_GCM_SHA384: SupportedCipherSuite =
- SupportedCipherSuite::Tls13(&Tls13CipherSuite {
- common: CipherSuiteCommon {
- suite: CipherSuite::TLS13_AES_256_GCM_SHA384,
- hash_provider: &super::hash::SHA384,
- confidentiality_limit: 1 << 24,
- },
- hkdf_provider: &RingHkdf(hkdf::HKDF_SHA384, hmac::HMAC_SHA384),
- aead_alg: &Aes256GcmAead(AeadAlgorithm(&aead::AES_256_GCM)),
- quic: Some(&super::quic::KeyBuilder {
- packet_alg: &aead::AES_256_GCM,
- header_alg: &aead::quic::AES_256,
- // ref: <https://datatracker.ietf.org/doc/html/rfc9001#section-b.1.1>
- confidentiality_limit: 1 << 23,
- // ref: <https://datatracker.ietf.org/doc/html/rfc9001#section-b.1.2>
- integrity_limit: 1 << 52,
- }),
- });
-
-/// The TLS1.3 ciphersuite TLS_AES_128_GCM_SHA256
-pub static TLS13_AES_128_GCM_SHA256: SupportedCipherSuite =
- SupportedCipherSuite::Tls13(TLS13_AES_128_GCM_SHA256_INTERNAL);
-
-pub(crate) static TLS13_AES_128_GCM_SHA256_INTERNAL: &Tls13CipherSuite = &Tls13CipherSuite {
- common: CipherSuiteCommon {
- suite: CipherSuite::TLS13_AES_128_GCM_SHA256,
- hash_provider: &super::hash::SHA256,
- confidentiality_limit: 1 << 24,
- },
- hkdf_provider: &RingHkdf(hkdf::HKDF_SHA256, hmac::HMAC_SHA256),
- aead_alg: &Aes128GcmAead(AeadAlgorithm(&aead::AES_128_GCM)),
- quic: Some(&super::quic::KeyBuilder {
- packet_alg: &aead::AES_128_GCM,
- header_alg: &aead::quic::AES_128,
- // ref: <https://datatracker.ietf.org/doc/html/rfc9001#section-b.1.1>
- confidentiality_limit: 1 << 23,
- // ref: <https://datatracker.ietf.org/doc/html/rfc9001#section-b.1.2>
- integrity_limit: 1 << 52,
- }),
-};
-
-struct Chacha20Poly1305Aead(AeadAlgorithm);
-
-impl Tls13AeadAlgorithm for Chacha20Poly1305Aead {
- fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> {
- self.0.encrypter(key, iv)
- }
-
- fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
- self.0.decrypter(key, iv)
- }
-
- fn key_len(&self) -> usize {
- self.0.key_len()
- }
-
- fn extract_keys(
- &self,
- key: AeadKey,
- iv: Iv,
- ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
- Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv })
- }
-
- fn fips(&self) -> bool {
- false // chacha20poly1305 not FIPS approved
- }
-}
-
-struct Aes256GcmAead(AeadAlgorithm);
-
-impl Tls13AeadAlgorithm for Aes256GcmAead {
- fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> {
- self.0.encrypter(key, iv)
- }
-
- fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
- self.0.decrypter(key, iv)
- }
-
- fn key_len(&self) -> usize {
- self.0.key_len()
- }
-
- fn extract_keys(
- &self,
- key: AeadKey,
- iv: Iv,
- ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
- Ok(ConnectionTrafficSecrets::Aes256Gcm { key, iv })
- }
-
- fn fips(&self) -> bool {
- super::fips()
- }
-}
-
-struct Aes128GcmAead(AeadAlgorithm);
-
-impl Tls13AeadAlgorithm for Aes128GcmAead {
- fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> {
- self.0.encrypter(key, iv)
- }
-
- fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
- self.0.decrypter(key, iv)
- }
-
- fn key_len(&self) -> usize {
- self.0.key_len()
- }
-
- fn extract_keys(
- &self,
- key: AeadKey,
- iv: Iv,
- ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
- Ok(ConnectionTrafficSecrets::Aes128Gcm { key, iv })
- }
-
- fn fips(&self) -> bool {
- super::fips()
- }
-}
-
-// common encrypter/decrypter/key_len items for above Tls13AeadAlgorithm impls
-struct AeadAlgorithm(&'static aead::Algorithm);
-
-impl AeadAlgorithm {
- fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> {
- // safety: the caller arranges that `key` is `key_len()` in bytes, so this unwrap is safe.
- Box::new(Tls13MessageEncrypter {
- enc_key: aead::LessSafeKey::new(aead::UnboundKey::new(self.0, key.as_ref()).unwrap()),
- iv,
- })
- }
-
- fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
- // safety: the caller arranges that `key` is `key_len()` in bytes, so this unwrap is safe.
- Box::new(Tls13MessageDecrypter {
- dec_key: aead::LessSafeKey::new(aead::UnboundKey::new(self.0, key.as_ref()).unwrap()),
- iv,
- })
- }
-
- fn key_len(&self) -> usize {
- self.0.key_len()
- }
-}
-
-struct Tls13MessageEncrypter {
- enc_key: aead::LessSafeKey,
- iv: Iv,
-}
-
-struct Tls13MessageDecrypter {
- dec_key: aead::LessSafeKey,
- iv: Iv,
-}
-
-impl MessageEncrypter for Tls13MessageEncrypter {
- fn encrypt(
- &mut self,
- msg: OutboundPlainMessage<'_>,
- seq: u64,
- ) -> Result<OutboundOpaqueMessage, Error> {
- let total_len = self.encrypted_payload_len(msg.payload.len());
- let mut payload = PrefixedPayload::with_capacity(total_len);
-
- let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
- let aad = aead::Aad::from(make_tls13_aad(total_len));
- payload.extend_from_chunks(&msg.payload);
- payload.extend_from_slice(&msg.typ.to_array());
-
- self.enc_key
- .seal_in_place_append_tag(nonce, aad, &mut payload)
- .map_err(|_| Error::EncryptError)?;
-
- Ok(OutboundOpaqueMessage::new(
- ContentType::ApplicationData,
- // Note: all TLS 1.3 application data records use TLSv1_2 (0x0303) as the legacy record
- // protocol version, see https://www.rfc-editor.org/rfc/rfc8446#section-5.1
- ProtocolVersion::TLSv1_2,
- payload,
- ))
- }
-
- fn encrypted_payload_len(&self, payload_len: usize) -> usize {
- payload_len + 1 + self.enc_key.algorithm().tag_len()
- }
-}
-
-impl MessageDecrypter for Tls13MessageDecrypter {
- fn decrypt<'a>(
- &mut self,
- mut msg: InboundOpaqueMessage<'a>,
- seq: u64,
- ) -> Result<InboundPlainMessage<'a>, Error> {
- let payload = &mut msg.payload;
- if payload.len() < self.dec_key.algorithm().tag_len() {
- return Err(Error::DecryptError);
- }
-
- let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
- let aad = aead::Aad::from(make_tls13_aad(payload.len()));
- let plain_len = self
- .dec_key
- .open_in_place(nonce, aad, payload)
- .map_err(|_| Error::DecryptError)?
- .len();
-
- payload.truncate(plain_len);
- msg.into_tls13_unpadded_message()
- }
-}
-
-struct RingHkdf(hkdf::Algorithm, hmac::Algorithm);
-
-impl Hkdf for RingHkdf {
- fn extract_from_zero_ikm(&self, salt: Option<&[u8]>) -> Box<dyn HkdfExpander> {
- let zeroes = [0u8; OkmBlock::MAX_LEN];
- let salt = match salt {
- Some(salt) => salt,
- None => &zeroes[..self.0.len()],
- };
- Box::new(RingHkdfExpander {
- alg: self.0,
- prk: hkdf::Salt::new(self.0, salt).extract(&zeroes[..self.0.len()]),
- })
- }
-
- fn extract_from_secret(&self, salt: Option<&[u8]>, secret: &[u8]) -> Box<dyn HkdfExpander> {
- let zeroes = [0u8; OkmBlock::MAX_LEN];
- let salt = match salt {
- Some(salt) => salt,
- None => &zeroes[..self.0.len()],
- };
- Box::new(RingHkdfExpander {
- alg: self.0,
- prk: hkdf::Salt::new(self.0, salt).extract(secret),
- })
- }
-
- fn expander_for_okm(&self, okm: &OkmBlock) -> Box<dyn HkdfExpander> {
- Box::new(RingHkdfExpander {
- alg: self.0,
- prk: hkdf::Prk::new_less_safe(self.0, okm.as_ref()),
- })
- }
-
- fn hmac_sign(&self, key: &OkmBlock, message: &[u8]) -> crypto::hmac::Tag {
- crypto::hmac::Tag::new(hmac::sign(&hmac::Key::new(self.1, key.as_ref()), message).as_ref())
- }
-
- fn fips(&self) -> bool {
- super::fips()
- }
-}
-
-struct RingHkdfExpander {
- alg: hkdf::Algorithm,
- prk: hkdf::Prk,
-}
-
-impl HkdfExpander for RingHkdfExpander {
- fn expand_slice(&self, info: &[&[u8]], output: &mut [u8]) -> Result<(), OutputLengthError> {
- self.prk
- .expand(info, Len(output.len()))
- .and_then(|okm| okm.fill(output))
- .map_err(|_| OutputLengthError)
- }
-
- fn expand_block(&self, info: &[&[u8]]) -> OkmBlock {
- let mut buf = [0u8; OkmBlock::MAX_LEN];
- let output = &mut buf[..self.hash_len()];
- self.prk
- .expand(info, Len(output.len()))
- .and_then(|okm| okm.fill(output))
- .unwrap();
- OkmBlock::new(output)
- }
-
- fn hash_len(&self) -> usize {
- self.alg.len()
- }
-}
-
-struct Len(usize);
-
-impl KeyType for Len {
- fn len(&self) -> usize {
- self.0
- }
-}
diff --git a/vendor/rustls/src/crypto/signer.rs b/vendor/rustls/src/crypto/signer.rs
deleted file mode 100644
index 8028e74b..00000000
--- a/vendor/rustls/src/crypto/signer.rs
+++ /dev/null
@@ -1,233 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec::Vec;
-use core::fmt::Debug;
-
-use pki_types::{AlgorithmIdentifier, CertificateDer, PrivateKeyDer, SubjectPublicKeyInfoDer};
-
-use super::CryptoProvider;
-use crate::client::ResolvesClientCert;
-use crate::enums::{SignatureAlgorithm, SignatureScheme};
-use crate::error::{Error, InconsistentKeys};
-use crate::server::{ClientHello, ParsedCertificate, ResolvesServerCert};
-use crate::sync::Arc;
-use crate::x509;
-
-/// An abstract signing key.
-///
-/// This interface is used by rustls to use a private signing key
-/// for authentication. This includes server and client authentication.
-///
-/// Objects of this type are always used within Rustls as
-/// `Arc<dyn SigningKey>`. There are no concrete public structs in Rustls
-/// that implement this trait.
-///
-/// There are two main ways to get a signing key:
-///
-/// - [`KeyProvider::load_private_key()`], or
-/// - some other method outside of the `KeyProvider` extension trait,
-/// for instance:
-/// - [`crypto::ring::sign::any_ecdsa_type()`]
-/// - [`crypto::ring::sign::any_eddsa_type()`]
-/// - [`crypto::ring::sign::any_supported_type()`]
-/// - [`crypto::aws_lc_rs::sign::any_ecdsa_type()`]
-/// - [`crypto::aws_lc_rs::sign::any_eddsa_type()`]
-/// - [`crypto::aws_lc_rs::sign::any_supported_type()`]
-///
-/// The `KeyProvider` method `load_private_key()` is called under the hood by
-/// [`ConfigBuilder::with_single_cert()`],
-/// [`ConfigBuilder::with_client_auth_cert()`], and
-/// [`ConfigBuilder::with_single_cert_with_ocsp()`].
-///
-/// A signing key created outside of the `KeyProvider` extension trait can be used
-/// to create a [`CertifiedKey`], which in turn can be used to create a
-/// [`ResolvesServerCertUsingSni`]. Alternately, a `CertifiedKey` can be returned from a
-/// custom implementation of the [`ResolvesServerCert`] or [`ResolvesClientCert`] traits.
-///
-/// [`KeyProvider::load_private_key()`]: crate::crypto::KeyProvider::load_private_key
-/// [`ConfigBuilder::with_single_cert()`]: crate::ConfigBuilder::with_single_cert
-/// [`ConfigBuilder::with_single_cert_with_ocsp()`]: crate::ConfigBuilder::with_single_cert_with_ocsp
-/// [`ConfigBuilder::with_client_auth_cert()`]: crate::ConfigBuilder::with_client_auth_cert
-/// [`crypto::ring::sign::any_ecdsa_type()`]: crate::crypto::ring::sign::any_ecdsa_type
-/// [`crypto::ring::sign::any_eddsa_type()`]: crate::crypto::ring::sign::any_eddsa_type
-/// [`crypto::ring::sign::any_supported_type()`]: crate::crypto::ring::sign::any_supported_type
-/// [`crypto::aws_lc_rs::sign::any_ecdsa_type()`]: crate::crypto::aws_lc_rs::sign::any_ecdsa_type
-/// [`crypto::aws_lc_rs::sign::any_eddsa_type()`]: crate::crypto::aws_lc_rs::sign::any_eddsa_type
-/// [`crypto::aws_lc_rs::sign::any_supported_type()`]: crate::crypto::aws_lc_rs::sign::any_supported_type
-/// [`ResolvesServerCertUsingSni`]: crate::server::ResolvesServerCertUsingSni
-/// [`ResolvesServerCert`]: crate::server::ResolvesServerCert
-/// [`ResolvesClientCert`]: crate::client::ResolvesClientCert
-pub trait SigningKey: Debug + Send + Sync {
- /// Choose a `SignatureScheme` from those offered.
- ///
- /// Expresses the choice by returning something that implements `Signer`,
- /// using the chosen scheme.
- fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>>;
-
- /// Get the RFC 5280-compliant SubjectPublicKeyInfo (SPKI) of this [`SigningKey`] if available.
- fn public_key(&self) -> Option<SubjectPublicKeyInfoDer<'_>> {
- // Opt-out by default
- None
- }
-
- /// What kind of key we have.
- fn algorithm(&self) -> SignatureAlgorithm;
-}
-
-/// A thing that can sign a message.
-pub trait Signer: Debug + Send + Sync {
- /// Signs `message` using the selected scheme.
- ///
- /// `message` is not hashed; the implementer must hash it using the hash function
- /// implicit in [`Self::scheme()`].
- ///
- /// The returned signature format is also defined by [`Self::scheme()`].
- fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error>;
-
- /// Reveals which scheme will be used when you call [`Self::sign()`].
- fn scheme(&self) -> SignatureScheme;
-}
-
-/// Server certificate resolver which always resolves to the same certificate and key.
-///
-/// For use with [`ConfigBuilder::with_cert_resolver()`].
-///
-/// [`ConfigBuilder::with_cert_resolver()`]: crate::ConfigBuilder::with_cert_resolver
-#[derive(Debug)]
-pub struct SingleCertAndKey(Arc<CertifiedKey>);
-
-impl From<CertifiedKey> for SingleCertAndKey {
- fn from(certified_key: CertifiedKey) -> Self {
- Self(Arc::new(certified_key))
- }
-}
-
-impl From<Arc<CertifiedKey>> for SingleCertAndKey {
- fn from(certified_key: Arc<CertifiedKey>) -> Self {
- Self(certified_key)
- }
-}
-
-impl ResolvesClientCert for SingleCertAndKey {
- fn resolve(
- &self,
- _root_hint_subjects: &[&[u8]],
- _sigschemes: &[SignatureScheme],
- ) -> Option<Arc<CertifiedKey>> {
- Some(self.0.clone())
- }
-
- fn has_certs(&self) -> bool {
- true
- }
-}
-
-impl ResolvesServerCert for SingleCertAndKey {
- fn resolve(&self, _client_hello: ClientHello<'_>) -> Option<Arc<CertifiedKey>> {
- Some(self.0.clone())
- }
-}
-
-/// A packaged-together certificate chain, matching `SigningKey` and
-/// optional stapled OCSP response.
-///
-/// Note: this struct is also used to represent an [RFC 7250] raw public key,
-/// when the client/server is configured to use raw public keys instead of
-/// certificates.
-///
-/// [RFC 7250]: https://tools.ietf.org/html/rfc7250
-#[derive(Clone, Debug)]
-pub struct CertifiedKey {
- /// The certificate chain or raw public key.
- pub cert: Vec<CertificateDer<'static>>,
-
- /// The certified key.
- pub key: Arc<dyn SigningKey>,
-
- /// An optional OCSP response from the certificate issuer,
- /// attesting to its continued validity.
- pub ocsp: Option<Vec<u8>>,
-}
-
-impl CertifiedKey {
- /// Create a new `CertifiedKey` from a certificate chain and DER-encoded private key.
- ///
- /// Attempt to parse the private key with the given [`CryptoProvider`]'s [`KeyProvider`] and
- /// verify that it matches the public key in the first certificate of the `cert_chain`
- /// if possible.
- ///
- /// [`KeyProvider`]: crate::crypto::KeyProvider
- pub fn from_der(
- cert_chain: Vec<CertificateDer<'static>>,
- key: PrivateKeyDer<'static>,
- provider: &CryptoProvider,
- ) -> Result<Self, Error> {
- let private_key = provider
- .key_provider
- .load_private_key(key)?;
-
- let certified_key = Self::new(cert_chain, private_key);
- match certified_key.keys_match() {
- // Don't treat unknown consistency as an error
- Ok(()) | Err(Error::InconsistentKeys(InconsistentKeys::Unknown)) => Ok(certified_key),
- Err(err) => Err(err),
- }
- }
-
- /// Make a new CertifiedKey, with the given chain and key.
- ///
- /// The cert chain must not be empty. The first certificate in the chain
- /// must be the end-entity certificate.
- pub fn new(cert: Vec<CertificateDer<'static>>, key: Arc<dyn SigningKey>) -> Self {
- Self {
- cert,
- key,
- ocsp: None,
- }
- }
-
- /// Verify the consistency of this [`CertifiedKey`]'s public and private keys.
- /// This is done by performing a comparison of SubjectPublicKeyInfo bytes.
- pub fn keys_match(&self) -> Result<(), Error> {
- let Some(key_spki) = self.key.public_key() else {
- return Err(InconsistentKeys::Unknown.into());
- };
-
- let cert = ParsedCertificate::try_from(self.end_entity_cert()?)?;
- match key_spki == cert.subject_public_key_info() {
- true => Ok(()),
- false => Err(InconsistentKeys::KeyMismatch.into()),
- }
- }
-
- /// The end-entity certificate.
- pub fn end_entity_cert(&self) -> Result<&CertificateDer<'_>, Error> {
- self.cert
- .first()
- .ok_or(Error::NoCertificatesPresented)
- }
-}
-
-#[cfg_attr(not(any(feature = "aws_lc_rs", feature = "ring")), allow(dead_code))]
-pub(crate) fn public_key_to_spki(
- alg_id: &AlgorithmIdentifier,
- public_key: impl AsRef<[u8]>,
-) -> SubjectPublicKeyInfoDer<'static> {
- // SubjectPublicKeyInfo ::= SEQUENCE {
- // algorithm AlgorithmIdentifier,
- // subjectPublicKey BIT STRING }
- //
- // AlgorithmIdentifier ::= SEQUENCE {
- // algorithm OBJECT IDENTIFIER,
- // parameters ANY DEFINED BY algorithm OPTIONAL }
- //
- // note that the `pki_types::AlgorithmIdentifier` type is the
- // concatenation of `algorithm` and `parameters`, but misses the
- // outer `Sequence`.
-
- let mut spki_inner = x509::wrap_in_sequence(alg_id.as_ref());
- spki_inner.extend(&x509::wrap_in_bit_string(public_key.as_ref()));
-
- let spki = x509::wrap_in_sequence(&spki_inner);
-
- SubjectPublicKeyInfoDer::from(spki)
-}
diff --git a/vendor/rustls/src/crypto/tls12.rs b/vendor/rustls/src/crypto/tls12.rs
deleted file mode 100644
index 7128de4b..00000000
--- a/vendor/rustls/src/crypto/tls12.rs
+++ /dev/null
@@ -1,169 +0,0 @@
-use alloc::boxed::Box;
-
-use super::{ActiveKeyExchange, hmac};
-use crate::error::Error;
-use crate::version::TLS12;
-
-/// Implements [`Prf`] using a [`hmac::Hmac`].
-pub struct PrfUsingHmac<'a>(pub &'a dyn hmac::Hmac);
-
-impl Prf for PrfUsingHmac<'_> {
- fn for_key_exchange(
- &self,
- output: &mut [u8; 48],
- kx: Box<dyn ActiveKeyExchange>,
- peer_pub_key: &[u8],
- label: &[u8],
- seed: &[u8],
- ) -> Result<(), Error> {
- prf(
- output,
- self.0
- .with_key(
- kx.complete_for_tls_version(peer_pub_key, &TLS12)?
- .secret_bytes(),
- )
- .as_ref(),
- label,
- seed,
- );
- Ok(())
- }
-
- fn for_secret(&self, output: &mut [u8], secret: &[u8], label: &[u8], seed: &[u8]) {
- prf(output, self.0.with_key(secret).as_ref(), label, seed);
- }
-}
-
-/// An instantiation of the TLS1.2 PRF with a specific, implicit hash function.
-///
-/// See the definition in [RFC5246 section 5](https://www.rfc-editor.org/rfc/rfc5246#section-5).
-///
-/// See [`PrfUsingHmac`] as a route to implementing this trait with just
-/// an implementation of [`hmac::Hmac`].
-pub trait Prf: Send + Sync {
- /// Computes `PRF(secret, label, seed)` using the secret from a completed key exchange.
- ///
- /// Completes the given key exchange, and then uses the resulting shared secret
- /// to compute the PRF, writing the result into `output`.
- ///
- /// The caller guarantees that `label`, `seed` are non-empty. The caller makes no
- /// guarantees about the contents of `peer_pub_key`. It must be validated by
- /// [`ActiveKeyExchange::complete`].
- fn for_key_exchange(
- &self,
- output: &mut [u8; 48],
- kx: Box<dyn ActiveKeyExchange>,
- peer_pub_key: &[u8],
- label: &[u8],
- seed: &[u8],
- ) -> Result<(), Error>;
-
- /// Computes `PRF(secret, label, seed)`, writing the result into `output`.
- ///
- /// The caller guarantees that `secret`, `label`, and `seed` are non-empty.
- fn for_secret(&self, output: &mut [u8], secret: &[u8], label: &[u8], seed: &[u8]);
-
- /// Return `true` if this is backed by a FIPS-approved implementation.
- fn fips(&self) -> bool {
- false
- }
-}
-
-pub(crate) fn prf(out: &mut [u8], hmac_key: &dyn hmac::Key, label: &[u8], seed: &[u8]) {
- // A(1)
- let mut current_a = hmac_key.sign(&[label, seed]);
-
- let chunk_size = hmac_key.tag_len();
- for chunk in out.chunks_mut(chunk_size) {
- // P_hash[i] = HMAC_hash(secret, A(i) + seed)
- let p_term = hmac_key.sign(&[current_a.as_ref(), label, seed]);
- chunk.copy_from_slice(&p_term.as_ref()[..chunk.len()]);
-
- // A(i+1) = HMAC_hash(secret, A(i))
- current_a = hmac_key.sign(&[current_a.as_ref()]);
- }
-}
-
-#[cfg(all(test, feature = "ring"))]
-mod tests {
- use crate::crypto::hmac::Hmac;
- // nb: crypto::aws_lc_rs provider doesn't provide (or need) hmac,
- // so cannot be used for this test.
- use crate::crypto::ring::hmac;
-
- // Below known answer tests come from https://mailarchive.ietf.org/arch/msg/tls/fzVCzk-z3FShgGJ6DOXqM1ydxms/
-
- #[test]
- fn check_sha256() {
- let secret = b"\x9b\xbe\x43\x6b\xa9\x40\xf0\x17\xb1\x76\x52\x84\x9a\x71\xdb\x35";
- let seed = b"\xa0\xba\x9f\x93\x6c\xda\x31\x18\x27\xa6\xf7\x96\xff\xd5\x19\x8c";
- let label = b"test label";
- let expect = include_bytes!("../testdata/prf-result.1.bin");
- let mut output = [0u8; 100];
-
- super::prf(
- &mut output,
- &*hmac::HMAC_SHA256.with_key(secret),
- label,
- seed,
- );
- assert_eq!(expect.len(), output.len());
- assert_eq!(expect.to_vec(), output.to_vec());
- }
-
- #[test]
- fn check_sha512() {
- let secret = b"\xb0\x32\x35\x23\xc1\x85\x35\x99\x58\x4d\x88\x56\x8b\xbb\x05\xeb";
- let seed = b"\xd4\x64\x0e\x12\xe4\xbc\xdb\xfb\x43\x7f\x03\xe6\xae\x41\x8e\xe5";
- let label = b"test label";
- let expect = include_bytes!("../testdata/prf-result.2.bin");
- let mut output = [0u8; 196];
-
- super::prf(
- &mut output,
- &*hmac::HMAC_SHA512.with_key(secret),
- label,
- seed,
- );
- assert_eq!(expect.len(), output.len());
- assert_eq!(expect.to_vec(), output.to_vec());
- }
-
- #[test]
- fn check_sha384() {
- let secret = b"\xb8\x0b\x73\x3d\x6c\xee\xfc\xdc\x71\x56\x6e\xa4\x8e\x55\x67\xdf";
- let seed = b"\xcd\x66\x5c\xf6\xa8\x44\x7d\xd6\xff\x8b\x27\x55\x5e\xdb\x74\x65";
- let label = b"test label";
- let expect = include_bytes!("../testdata/prf-result.3.bin");
- let mut output = [0u8; 148];
-
- super::prf(
- &mut output,
- &*hmac::HMAC_SHA384.with_key(secret),
- label,
- seed,
- );
- assert_eq!(expect.len(), output.len());
- assert_eq!(expect.to_vec(), output.to_vec());
- }
-}
-
-#[cfg(all(bench, feature = "ring"))]
-mod benchmarks {
- #[bench]
- fn bench_sha256(b: &mut test::Bencher) {
- use crate::crypto::hmac::Hmac;
- use crate::crypto::ring::hmac;
-
- let label = &b"extended master secret"[..];
- let seed = [0u8; 32];
- let key = &b"secret"[..];
-
- b.iter(|| {
- let mut out = [0u8; 48];
- super::prf(&mut out, &*hmac::HMAC_SHA256.with_key(key), &label, &seed);
- test::black_box(out);
- });
- }
-}
diff --git a/vendor/rustls/src/crypto/tls13.rs b/vendor/rustls/src/crypto/tls13.rs
deleted file mode 100644
index 50ecaa89..00000000
--- a/vendor/rustls/src/crypto/tls13.rs
+++ /dev/null
@@ -1,406 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec::Vec;
-
-use zeroize::Zeroize;
-
-use super::{ActiveKeyExchange, hmac};
-use crate::error::Error;
-use crate::version::TLS13;
-
-/// Implementation of `HkdfExpander` via `hmac::Key`.
-pub struct HkdfExpanderUsingHmac(Box<dyn hmac::Key>);
-
-impl HkdfExpanderUsingHmac {
- fn expand_unchecked(&self, info: &[&[u8]], output: &mut [u8]) {
- let mut term = hmac::Tag::new(b"");
-
- for (n, chunk) in output
- .chunks_mut(self.0.tag_len())
- .enumerate()
- {
- term = self
- .0
- .sign_concat(term.as_ref(), info, &[(n + 1) as u8]);
- chunk.copy_from_slice(&term.as_ref()[..chunk.len()]);
- }
- }
-}
-
-impl HkdfExpander for HkdfExpanderUsingHmac {
- fn expand_slice(&self, info: &[&[u8]], output: &mut [u8]) -> Result<(), OutputLengthError> {
- if output.len() > 255 * self.0.tag_len() {
- return Err(OutputLengthError);
- }
-
- self.expand_unchecked(info, output);
- Ok(())
- }
-
- fn expand_block(&self, info: &[&[u8]]) -> OkmBlock {
- let mut tag = [0u8; hmac::Tag::MAX_LEN];
- let reduced_tag = &mut tag[..self.0.tag_len()];
- self.expand_unchecked(info, reduced_tag);
- OkmBlock::new(reduced_tag)
- }
-
- fn hash_len(&self) -> usize {
- self.0.tag_len()
- }
-}
-
-/// Implementation of `Hkdf` (and thence `HkdfExpander`) via `hmac::Hmac`.
-pub struct HkdfUsingHmac<'a>(pub &'a dyn hmac::Hmac);
-
-impl Hkdf for HkdfUsingHmac<'_> {
- fn extract_from_zero_ikm(&self, salt: Option<&[u8]>) -> Box<dyn HkdfExpander> {
- let zeroes = [0u8; hmac::Tag::MAX_LEN];
- Box::new(HkdfExpanderUsingHmac(self.0.with_key(
- &self.extract_prk_from_secret(salt, &zeroes[..self.0.hash_output_len()]),
- )))
- }
-
- fn extract_from_secret(&self, salt: Option<&[u8]>, secret: &[u8]) -> Box<dyn HkdfExpander> {
- Box::new(HkdfExpanderUsingHmac(
- self.0
- .with_key(&self.extract_prk_from_secret(salt, secret)),
- ))
- }
-
- fn expander_for_okm(&self, okm: &OkmBlock) -> Box<dyn HkdfExpander> {
- Box::new(HkdfExpanderUsingHmac(self.0.with_key(okm.as_ref())))
- }
-
- fn hmac_sign(&self, key: &OkmBlock, message: &[u8]) -> hmac::Tag {
- self.0
- .with_key(key.as_ref())
- .sign(&[message])
- }
-}
-
-impl HkdfPrkExtract for HkdfUsingHmac<'_> {
- fn extract_prk_from_secret(&self, salt: Option<&[u8]>, secret: &[u8]) -> Vec<u8> {
- let zeroes = [0u8; hmac::Tag::MAX_LEN];
- let salt = match salt {
- Some(salt) => salt,
- None => &zeroes[..self.0.hash_output_len()],
- };
- self.0
- .with_key(salt)
- .sign(&[secret])
- .as_ref()
- .to_vec()
- }
-}
-
-/// Implementation of `HKDF-Expand` with an implicitly stored and immutable `PRK`.
-pub trait HkdfExpander: Send + Sync {
- /// `HKDF-Expand(PRK, info, L)` into a slice.
- ///
- /// Where:
- ///
- /// - `PRK` is the implicit key material represented by this instance.
- /// - `L` is `output.len()`.
- /// - `info` is a slice of byte slices, which should be processed sequentially
- /// (or concatenated if that is not possible).
- ///
- /// Returns `Err(OutputLengthError)` if `L` is larger than `255 * HashLen`.
- /// Otherwise, writes to `output`.
- fn expand_slice(&self, info: &[&[u8]], output: &mut [u8]) -> Result<(), OutputLengthError>;
-
- /// `HKDF-Expand(PRK, info, L=HashLen)` returned as a value.
- ///
- /// - `PRK` is the implicit key material represented by this instance.
- /// - `L := HashLen`.
- /// - `info` is a slice of byte slices, which should be processed sequentially
- /// (or concatenated if that is not possible).
- ///
- /// This is infallible, because by definition `OkmBlock` is always exactly
- /// `HashLen` bytes long.
- fn expand_block(&self, info: &[&[u8]]) -> OkmBlock;
-
- /// Return what `HashLen` is for this instance.
- ///
- /// This must be no larger than [`OkmBlock::MAX_LEN`].
- fn hash_len(&self) -> usize;
-}
-
-/// A HKDF implementation oriented to the needs of TLS1.3.
-///
-/// See [RFC5869](https://datatracker.ietf.org/doc/html/rfc5869) for the terminology
-/// used in this definition.
-///
-/// You can use [`HkdfUsingHmac`] which implements this trait on top of an implementation
-/// of [`hmac::Hmac`].
-pub trait Hkdf: Send + Sync {
- /// `HKDF-Extract(salt, 0_HashLen)`
- ///
- /// `0_HashLen` is a string of `HashLen` zero bytes.
- ///
- /// A `salt` of `None` should be treated as a sequence of `HashLen` zero bytes.
- fn extract_from_zero_ikm(&self, salt: Option<&[u8]>) -> Box<dyn HkdfExpander>;
-
- /// `HKDF-Extract(salt, secret)`
- ///
- /// A `salt` of `None` should be treated as a sequence of `HashLen` zero bytes.
- fn extract_from_secret(&self, salt: Option<&[u8]>, secret: &[u8]) -> Box<dyn HkdfExpander>;
-
- /// `HKDF-Extract(salt, shared_secret)` where `shared_secret` is the result of a key exchange.
- ///
- /// Custom implementations should complete the key exchange by calling
- /// `kx.complete(peer_pub_key)` and then using this as the input keying material to
- /// `HKDF-Extract`.
- ///
- /// A `salt` of `None` should be treated as a sequence of `HashLen` zero bytes.
- fn extract_from_kx_shared_secret(
- &self,
- salt: Option<&[u8]>,
- kx: Box<dyn ActiveKeyExchange>,
- peer_pub_key: &[u8],
- ) -> Result<Box<dyn HkdfExpander>, Error> {
- Ok(self.extract_from_secret(
- salt,
- kx.complete_for_tls_version(peer_pub_key, &TLS13)?
- .secret_bytes(),
- ))
- }
-
- /// Build a `HkdfExpander` using `okm` as the secret PRK.
- fn expander_for_okm(&self, okm: &OkmBlock) -> Box<dyn HkdfExpander>;
-
- /// Signs `message` using `key` viewed as a HMAC key.
- ///
- /// This should use the same hash function as the HKDF functions in this
- /// trait.
- ///
- /// See [RFC2104](https://datatracker.ietf.org/doc/html/rfc2104) for the
- /// definition of HMAC.
- fn hmac_sign(&self, key: &OkmBlock, message: &[u8]) -> hmac::Tag;
-
- /// Return `true` if this is backed by a FIPS-approved implementation.
- fn fips(&self) -> bool {
- false
- }
-}
-
-/// An extended HKDF implementation that supports directly extracting a pseudo-random key (PRK).
-///
-/// The base [`Hkdf`] trait is tailored to the needs of TLS 1.3, where all extracted PRKs
-/// are expanded as-is, and so can be safely encapsulated without exposing the caller
-/// to the key material.
-///
-/// In other contexts (for example, hybrid public key encryption (HPKE)) it may be necessary
-/// to use the extracted PRK directly for purposes other than an immediate expansion.
-/// This trait can be implemented to offer this functionality when it is required.
-pub(crate) trait HkdfPrkExtract: Hkdf {
- /// `HKDF-Extract(salt, secret)`
- ///
- /// A `salt` of `None` should be treated as a sequence of `HashLen` zero bytes.
- ///
- /// In most cases you should prefer [`Hkdf::extract_from_secret`] and using the
- /// returned [HkdfExpander] instead of handling the PRK directly.
- fn extract_prk_from_secret(&self, salt: Option<&[u8]>, secret: &[u8]) -> Vec<u8>;
-}
-
-/// `HKDF-Expand(PRK, info, L)` to construct any type from a byte array.
-///
-/// - `PRK` is the implicit key material represented by this instance.
-/// - `L := N`; N is the size of the byte array.
-/// - `info` is a slice of byte slices, which should be processed sequentially
-/// (or concatenated if that is not possible).
-///
-/// This is infallible, because the set of types (and therefore their length) is known
-/// at compile time.
-pub fn expand<T, const N: usize>(expander: &dyn HkdfExpander, info: &[&[u8]]) -> T
-where
- T: From<[u8; N]>,
-{
- let mut output = [0u8; N];
- expander
- .expand_slice(info, &mut output)
- .expect("expand type parameter T is too large");
- T::from(output)
-}
-
-/// Output key material from HKDF, as a value type.
-#[derive(Clone)]
-pub struct OkmBlock {
- buf: [u8; Self::MAX_LEN],
- used: usize,
-}
-
-impl OkmBlock {
- /// Build a single OKM block by copying a byte slice.
- ///
- /// The slice can be up to [`OkmBlock::MAX_LEN`] bytes in length.
- pub fn new(bytes: &[u8]) -> Self {
- let mut tag = Self {
- buf: [0u8; Self::MAX_LEN],
- used: bytes.len(),
- };
- tag.buf[..bytes.len()].copy_from_slice(bytes);
- tag
- }
-
- /// Maximum supported HMAC tag size: supports up to SHA512.
- pub const MAX_LEN: usize = 64;
-}
-
-impl Drop for OkmBlock {
- fn drop(&mut self) {
- self.buf.zeroize();
- }
-}
-
-impl AsRef<[u8]> for OkmBlock {
- fn as_ref(&self) -> &[u8] {
- &self.buf[..self.used]
- }
-}
-
-/// An error type used for `HkdfExpander::expand_slice` when
-/// the slice exceeds the maximum HKDF output length.
-#[derive(Debug)]
-pub struct OutputLengthError;
-
-#[cfg(all(test, feature = "ring"))]
-mod tests {
- use std::prelude::v1::*;
-
- use super::{Hkdf, HkdfUsingHmac, expand};
- // nb: crypto::aws_lc_rs provider doesn't provide (or need) hmac,
- // so cannot be used for this test.
- use crate::crypto::ring::hmac;
-
- struct ByteArray<const N: usize>([u8; N]);
-
- impl<const N: usize> From<[u8; N]> for ByteArray<N> {
- fn from(array: [u8; N]) -> Self {
- Self(array)
- }
- }
-
- /// Test cases from appendix A in the RFC, minus cases requiring SHA1.
-
- #[test]
- fn test_case_1() {
- let hkdf = HkdfUsingHmac(&hmac::HMAC_SHA256);
- let ikm = &[0x0b; 22];
- let salt = &[
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
- ];
- let info: &[&[u8]] = &[
- &[0xf0, 0xf1, 0xf2],
- &[0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9],
- ];
-
- let output: ByteArray<42> = expand(
- hkdf.extract_from_secret(Some(salt), ikm)
- .as_ref(),
- info,
- );
-
- assert_eq!(
- &output.0,
- &[
- 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36,
- 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56,
- 0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65
- ]
- );
- }
-
- #[test]
- fn test_case_2() {
- let hkdf = HkdfUsingHmac(&hmac::HMAC_SHA256);
- let ikm: Vec<u8> = (0x00u8..=0x4f).collect();
- let salt: Vec<u8> = (0x60u8..=0xaf).collect();
- let info: Vec<u8> = (0xb0u8..=0xff).collect();
-
- let output: ByteArray<82> = expand(
- hkdf.extract_from_secret(Some(&salt), &ikm)
- .as_ref(),
- &[&info],
- );
-
- assert_eq!(
- &output.0,
- &[
- 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a,
- 0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, 0xa0, 0x50, 0xcc, 0x4c,
- 0x19, 0xaf, 0xa9, 0x7c, 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb,
- 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8,
- 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec,
- 0x3e, 0x87, 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, 0x1d, 0x87
- ]
- );
- }
-
- #[test]
- fn test_case_3() {
- let hkdf = HkdfUsingHmac(&hmac::HMAC_SHA256);
- let ikm = &[0x0b; 22];
- let salt = &[];
- let info = &[];
-
- let output: ByteArray<42> = expand(
- hkdf.extract_from_secret(Some(salt), ikm)
- .as_ref(),
- info,
- );
-
- assert_eq!(
- &output.0,
- &[
- 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c,
- 0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, 0xc3, 0x45, 0x4e, 0x5f,
- 0x3c, 0x73, 0x8d, 0x2d, 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, 0x96, 0xc8
- ]
- );
- }
-
- #[test]
- fn test_salt_not_provided() {
- // can't use test case 7, because we don't have (or want) SHA1.
- //
- // this output is generated with cryptography.io:
- //
- // >>> hkdf.HKDF(algorithm=hashes.SHA384(), length=96, salt=None, info=b"hello").derive(b"\x0b" * 40)
-
- let hkdf = HkdfUsingHmac(&hmac::HMAC_SHA384);
- let ikm = &[0x0b; 40];
- let info = &[&b"hel"[..], &b"lo"[..]];
-
- let output: ByteArray<96> = expand(
- hkdf.extract_from_secret(None, ikm)
- .as_ref(),
- info,
- );
-
- assert_eq!(
- &output.0,
- &[
- 0xd5, 0x45, 0xdd, 0x3a, 0xff, 0x5b, 0x19, 0x46, 0xd4, 0x86, 0xfd, 0xb8, 0xd8, 0x88,
- 0x2e, 0xe0, 0x1c, 0xc1, 0xa5, 0x48, 0xb6, 0x05, 0x75, 0xe4, 0xd7, 0x5d, 0x0f, 0x5f,
- 0x23, 0x40, 0xee, 0x6c, 0x9e, 0x7c, 0x65, 0xd0, 0xee, 0x79, 0xdb, 0xb2, 0x07, 0x1d,
- 0x66, 0xa5, 0x50, 0xc4, 0x8a, 0xa3, 0x93, 0x86, 0x8b, 0x7c, 0x69, 0x41, 0x6b, 0x3e,
- 0x61, 0x44, 0x98, 0xb8, 0xc2, 0xfc, 0x82, 0x82, 0xae, 0xcd, 0x46, 0xcf, 0xb1, 0x47,
- 0xdc, 0xd0, 0x69, 0x0d, 0x19, 0xad, 0xe6, 0x6c, 0x70, 0xfe, 0x87, 0x92, 0x04, 0xb6,
- 0x82, 0x2d, 0x97, 0x7e, 0x46, 0x80, 0x4c, 0xe5, 0x76, 0x72, 0xb4, 0xb8
- ]
- );
- }
-
- #[test]
- fn test_output_length_bounds() {
- let hkdf = HkdfUsingHmac(&hmac::HMAC_SHA256);
- let ikm = &[];
- let info = &[];
-
- let mut output = [0u8; 32 * 255 + 1];
- assert!(
- hkdf.extract_from_secret(None, ikm)
- .expand_slice(info, &mut output)
- .is_err()
- );
- }
-}
diff --git a/vendor/rustls/src/enums.rs b/vendor/rustls/src/enums.rs
deleted file mode 100644
index f59ca3f9..00000000
--- a/vendor/rustls/src/enums.rs
+++ /dev/null
@@ -1,691 +0,0 @@
-#![allow(non_camel_case_types)]
-#![allow(missing_docs)]
-use crate::msgs::codec::{Codec, Reader};
-use crate::msgs::enums::HashAlgorithm;
-
-enum_builder! {
- /// The `AlertDescription` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u8)]
- pub enum AlertDescription {
- CloseNotify => 0x00,
- UnexpectedMessage => 0x0a,
- BadRecordMac => 0x14,
- DecryptionFailed => 0x15,
- RecordOverflow => 0x16,
- DecompressionFailure => 0x1e,
- HandshakeFailure => 0x28,
- NoCertificate => 0x29,
- BadCertificate => 0x2a,
- UnsupportedCertificate => 0x2b,
- CertificateRevoked => 0x2c,
- CertificateExpired => 0x2d,
- CertificateUnknown => 0x2e,
- IllegalParameter => 0x2f,
- UnknownCA => 0x30,
- AccessDenied => 0x31,
- DecodeError => 0x32,
- DecryptError => 0x33,
- ExportRestriction => 0x3c,
- ProtocolVersion => 0x46,
- InsufficientSecurity => 0x47,
- InternalError => 0x50,
- InappropriateFallback => 0x56,
- UserCanceled => 0x5a,
- NoRenegotiation => 0x64,
- MissingExtension => 0x6d,
- UnsupportedExtension => 0x6e,
- CertificateUnobtainable => 0x6f,
- UnrecognisedName => 0x70,
- BadCertificateStatusResponse => 0x71,
- BadCertificateHashValue => 0x72,
- UnknownPSKIdentity => 0x73,
- CertificateRequired => 0x74,
- NoApplicationProtocol => 0x78,
- EncryptedClientHelloRequired => 0x79, // https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#section-11.2
- }
-}
-
-enum_builder! {
- /// The `HandshakeType` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u8)]
- pub enum HandshakeType {
- HelloRequest => 0x00,
- ClientHello => 0x01,
- ServerHello => 0x02,
- HelloVerifyRequest => 0x03,
- NewSessionTicket => 0x04,
- EndOfEarlyData => 0x05,
- HelloRetryRequest => 0x06,
- EncryptedExtensions => 0x08,
- Certificate => 0x0b,
- ServerKeyExchange => 0x0c,
- CertificateRequest => 0x0d,
- ServerHelloDone => 0x0e,
- CertificateVerify => 0x0f,
- ClientKeyExchange => 0x10,
- Finished => 0x14,
- CertificateURL => 0x15,
- CertificateStatus => 0x16,
- KeyUpdate => 0x18,
- CompressedCertificate => 0x19,
- MessageHash => 0xfe,
- }
-}
-
-enum_builder! {
- /// The `ContentType` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u8)]
- pub enum ContentType {
- ChangeCipherSpec => 0x14,
- Alert => 0x15,
- Handshake => 0x16,
- ApplicationData => 0x17,
- Heartbeat => 0x18,
- }
-}
-
-enum_builder! {
- /// The `ProtocolVersion` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u16)]
- pub enum ProtocolVersion {
- SSLv2 => 0x0002,
- SSLv3 => 0x0300,
- TLSv1_0 => 0x0301,
- TLSv1_1 => 0x0302,
- TLSv1_2 => 0x0303,
- TLSv1_3 => 0x0304,
- DTLSv1_0 => 0xFEFF,
- DTLSv1_2 => 0xFEFD,
- DTLSv1_3 => 0xFEFC,
- }
-}
-
-enum_builder! {
- /// The `CipherSuite` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u16)]
- pub enum CipherSuite {
- TLS_NULL_WITH_NULL_NULL => 0x0000,
- TLS_PSK_WITH_AES_128_GCM_SHA256 => 0x00a8,
- TLS_PSK_WITH_AES_256_GCM_SHA384 => 0x00a9,
- TLS_EMPTY_RENEGOTIATION_INFO_SCSV => 0x00ff,
- TLS13_AES_128_GCM_SHA256 => 0x1301,
- TLS13_AES_256_GCM_SHA384 => 0x1302,
- TLS13_CHACHA20_POLY1305_SHA256 => 0x1303,
- TLS13_AES_128_CCM_SHA256 => 0x1304,
- TLS13_AES_128_CCM_8_SHA256 => 0x1305,
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA => 0xc009,
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA => 0xc00a,
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA => 0xc013,
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA => 0xc014,
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 => 0xc023,
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 => 0xc024,
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 => 0xc027,
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 => 0xc028,
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 => 0xc02b,
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 => 0xc02c,
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 => 0xc02f,
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 => 0xc030,
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 => 0xcca8,
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 => 0xcca9,
-
- !Debug:
- TLS_RSA_WITH_NULL_MD5 => 0x0001,
- TLS_RSA_WITH_NULL_SHA => 0x0002,
- TLS_RSA_EXPORT_WITH_RC4_40_MD5 => 0x0003,
- TLS_RSA_WITH_RC4_128_MD5 => 0x0004,
- TLS_RSA_WITH_RC4_128_SHA => 0x0005,
- TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 => 0x0006,
- TLS_RSA_WITH_IDEA_CBC_SHA => 0x0007,
- TLS_RSA_EXPORT_WITH_DES40_CBC_SHA => 0x0008,
- TLS_RSA_WITH_DES_CBC_SHA => 0x0009,
- TLS_RSA_WITH_3DES_EDE_CBC_SHA => 0x000a,
- TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA => 0x000b,
- TLS_DH_DSS_WITH_DES_CBC_SHA => 0x000c,
- TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA => 0x000d,
- TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA => 0x000e,
- TLS_DH_RSA_WITH_DES_CBC_SHA => 0x000f,
- TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA => 0x0010,
- TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA => 0x0011,
- TLS_DHE_DSS_WITH_DES_CBC_SHA => 0x0012,
- TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA => 0x0013,
- TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA => 0x0014,
- TLS_DHE_RSA_WITH_DES_CBC_SHA => 0x0015,
- TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA => 0x0016,
- TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 => 0x0017,
- TLS_DH_anon_WITH_RC4_128_MD5 => 0x0018,
- TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA => 0x0019,
- TLS_DH_anon_WITH_DES_CBC_SHA => 0x001a,
- TLS_DH_anon_WITH_3DES_EDE_CBC_SHA => 0x001b,
- SSL_FORTEZZA_KEA_WITH_NULL_SHA => 0x001c,
- SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA => 0x001d,
- TLS_KRB5_WITH_DES_CBC_SHA_or_SSL_FORTEZZA_KEA_WITH_RC4_128_SHA => 0x001e,
- TLS_KRB5_WITH_3DES_EDE_CBC_SHA => 0x001f,
- TLS_KRB5_WITH_RC4_128_SHA => 0x0020,
- TLS_KRB5_WITH_IDEA_CBC_SHA => 0x0021,
- TLS_KRB5_WITH_DES_CBC_MD5 => 0x0022,
- TLS_KRB5_WITH_3DES_EDE_CBC_MD5 => 0x0023,
- TLS_KRB5_WITH_RC4_128_MD5 => 0x0024,
- TLS_KRB5_WITH_IDEA_CBC_MD5 => 0x0025,
- TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA => 0x0026,
- TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA => 0x0027,
- TLS_KRB5_EXPORT_WITH_RC4_40_SHA => 0x0028,
- TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 => 0x0029,
- TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 => 0x002a,
- TLS_KRB5_EXPORT_WITH_RC4_40_MD5 => 0x002b,
- TLS_PSK_WITH_NULL_SHA => 0x002c,
- TLS_DHE_PSK_WITH_NULL_SHA => 0x002d,
- TLS_RSA_PSK_WITH_NULL_SHA => 0x002e,
- TLS_RSA_WITH_AES_128_CBC_SHA => 0x002f,
- TLS_DH_DSS_WITH_AES_128_CBC_SHA => 0x0030,
- TLS_DH_RSA_WITH_AES_128_CBC_SHA => 0x0031,
- TLS_DHE_DSS_WITH_AES_128_CBC_SHA => 0x0032,
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA => 0x0033,
- TLS_DH_anon_WITH_AES_128_CBC_SHA => 0x0034,
- TLS_RSA_WITH_AES_256_CBC_SHA => 0x0035,
- TLS_DH_DSS_WITH_AES_256_CBC_SHA => 0x0036,
- TLS_DH_RSA_WITH_AES_256_CBC_SHA => 0x0037,
- TLS_DHE_DSS_WITH_AES_256_CBC_SHA => 0x0038,
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA => 0x0039,
- TLS_DH_anon_WITH_AES_256_CBC_SHA => 0x003a,
- TLS_RSA_WITH_NULL_SHA256 => 0x003b,
- TLS_RSA_WITH_AES_128_CBC_SHA256 => 0x003c,
- TLS_RSA_WITH_AES_256_CBC_SHA256 => 0x003d,
- TLS_DH_DSS_WITH_AES_128_CBC_SHA256 => 0x003e,
- TLS_DH_RSA_WITH_AES_128_CBC_SHA256 => 0x003f,
- TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 => 0x0040,
- TLS_RSA_WITH_CAMELLIA_128_CBC_SHA => 0x0041,
- TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA => 0x0042,
- TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA => 0x0043,
- TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA => 0x0044,
- TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA => 0x0045,
- TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA => 0x0046,
- TLS_ECDH_ECDSA_WITH_NULL_SHA_draft => 0x0047,
- TLS_ECDH_ECDSA_WITH_RC4_128_SHA_draft => 0x0048,
- TLS_ECDH_ECDSA_WITH_DES_CBC_SHA_draft => 0x0049,
- TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA_draft => 0x004a,
- TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA_draft => 0x004b,
- TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA_draft => 0x004c,
- TLS_ECDH_ECNRA_WITH_DES_CBC_SHA_draft => 0x004d,
- TLS_ECDH_ECNRA_WITH_3DES_EDE_CBC_SHA_draft => 0x004e,
- TLS_ECMQV_ECDSA_NULL_SHA_draft => 0x004f,
- TLS_ECMQV_ECDSA_WITH_RC4_128_SHA_draft => 0x0050,
- TLS_ECMQV_ECDSA_WITH_DES_CBC_SHA_draft => 0x0051,
- TLS_ECMQV_ECDSA_WITH_3DES_EDE_CBC_SHA_draft => 0x0052,
- TLS_ECMQV_ECNRA_NULL_SHA_draft => 0x0053,
- TLS_ECMQV_ECNRA_WITH_RC4_128_SHA_draft => 0x0054,
- TLS_ECMQV_ECNRA_WITH_DES_CBC_SHA_draft => 0x0055,
- TLS_ECMQV_ECNRA_WITH_3DES_EDE_CBC_SHA_draft => 0x0056,
- TLS_ECDH_anon_NULL_WITH_SHA_draft => 0x0057,
- TLS_ECDH_anon_WITH_RC4_128_SHA_draft => 0x0058,
- TLS_ECDH_anon_WITH_DES_CBC_SHA_draft => 0x0059,
- TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA_draft => 0x005a,
- TLS_ECDH_anon_EXPORT_WITH_DES40_CBC_SHA_draft => 0x005b,
- TLS_ECDH_anon_EXPORT_WITH_RC4_40_SHA_draft => 0x005c,
- TLS_RSA_EXPORT1024_WITH_RC4_56_MD5 => 0x0060,
- TLS_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 => 0x0061,
- TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA => 0x0062,
- TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA => 0x0063,
- TLS_RSA_EXPORT1024_WITH_RC4_56_SHA => 0x0064,
- TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA => 0x0065,
- TLS_DHE_DSS_WITH_RC4_128_SHA => 0x0066,
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 => 0x0067,
- TLS_DH_DSS_WITH_AES_256_CBC_SHA256 => 0x0068,
- TLS_DH_RSA_WITH_AES_256_CBC_SHA256 => 0x0069,
- TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 => 0x006a,
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 => 0x006b,
- TLS_DH_anon_WITH_AES_128_CBC_SHA256 => 0x006c,
- TLS_DH_anon_WITH_AES_256_CBC_SHA256 => 0x006d,
- TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD => 0x0072,
- TLS_DHE_DSS_WITH_AES_128_CBC_RMD => 0x0073,
- TLS_DHE_DSS_WITH_AES_256_CBC_RMD => 0x0074,
- TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD => 0x0077,
- TLS_DHE_RSA_WITH_AES_128_CBC_RMD => 0x0078,
- TLS_DHE_RSA_WITH_AES_256_CBC_RMD => 0x0079,
- TLS_RSA_WITH_3DES_EDE_CBC_RMD => 0x007c,
- TLS_RSA_WITH_AES_128_CBC_RMD => 0x007d,
- TLS_RSA_WITH_AES_256_CBC_RMD => 0x007e,
- TLS_GOSTR341094_WITH_28147_CNT_IMIT => 0x0080,
- TLS_GOSTR341001_WITH_28147_CNT_IMIT => 0x0081,
- TLS_GOSTR341094_WITH_NULL_GOSTR3411 => 0x0082,
- TLS_GOSTR341001_WITH_NULL_GOSTR3411 => 0x0083,
- TLS_RSA_WITH_CAMELLIA_256_CBC_SHA => 0x0084,
- TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA => 0x0085,
- TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA => 0x0086,
- TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA => 0x0087,
- TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA => 0x0088,
- TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA => 0x0089,
- TLS_PSK_WITH_RC4_128_SHA => 0x008a,
- TLS_PSK_WITH_3DES_EDE_CBC_SHA => 0x008b,
- TLS_PSK_WITH_AES_128_CBC_SHA => 0x008c,
- TLS_PSK_WITH_AES_256_CBC_SHA => 0x008d,
- TLS_DHE_PSK_WITH_RC4_128_SHA => 0x008e,
- TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA => 0x008f,
- TLS_DHE_PSK_WITH_AES_128_CBC_SHA => 0x0090,
- TLS_DHE_PSK_WITH_AES_256_CBC_SHA => 0x0091,
- TLS_RSA_PSK_WITH_RC4_128_SHA => 0x0092,
- TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA => 0x0093,
- TLS_RSA_PSK_WITH_AES_128_CBC_SHA => 0x0094,
- TLS_RSA_PSK_WITH_AES_256_CBC_SHA => 0x0095,
- TLS_RSA_WITH_SEED_CBC_SHA => 0x0096,
- TLS_DH_DSS_WITH_SEED_CBC_SHA => 0x0097,
- TLS_DH_RSA_WITH_SEED_CBC_SHA => 0x0098,
- TLS_DHE_DSS_WITH_SEED_CBC_SHA => 0x0099,
- TLS_DHE_RSA_WITH_SEED_CBC_SHA => 0x009a,
- TLS_DH_anon_WITH_SEED_CBC_SHA => 0x009b,
- TLS_RSA_WITH_AES_128_GCM_SHA256 => 0x009c,
- TLS_RSA_WITH_AES_256_GCM_SHA384 => 0x009d,
- TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 => 0x009e,
- TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 => 0x009f,
- TLS_DH_RSA_WITH_AES_128_GCM_SHA256 => 0x00a0,
- TLS_DH_RSA_WITH_AES_256_GCM_SHA384 => 0x00a1,
- TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 => 0x00a2,
- TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 => 0x00a3,
- TLS_DH_DSS_WITH_AES_128_GCM_SHA256 => 0x00a4,
- TLS_DH_DSS_WITH_AES_256_GCM_SHA384 => 0x00a5,
- TLS_DH_anon_WITH_AES_128_GCM_SHA256 => 0x00a6,
- TLS_DH_anon_WITH_AES_256_GCM_SHA384 => 0x00a7,
- TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 => 0x00aa,
- TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 => 0x00ab,
- TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 => 0x00ac,
- TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 => 0x00ad,
- TLS_PSK_WITH_AES_128_CBC_SHA256 => 0x00ae,
- TLS_PSK_WITH_AES_256_CBC_SHA384 => 0x00af,
- TLS_PSK_WITH_NULL_SHA256 => 0x00b0,
- TLS_PSK_WITH_NULL_SHA384 => 0x00b1,
- TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 => 0x00b2,
- TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 => 0x00b3,
- TLS_DHE_PSK_WITH_NULL_SHA256 => 0x00b4,
- TLS_DHE_PSK_WITH_NULL_SHA384 => 0x00b5,
- TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 => 0x00b6,
- TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 => 0x00b7,
- TLS_RSA_PSK_WITH_NULL_SHA256 => 0x00b8,
- TLS_RSA_PSK_WITH_NULL_SHA384 => 0x00b9,
- TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 => 0x00ba,
- TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 => 0x00bb,
- TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 => 0x00bc,
- TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 => 0x00bd,
- TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 => 0x00be,
- TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 => 0x00bf,
- TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 => 0x00c0,
- TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 => 0x00c1,
- TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 => 0x00c2,
- TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 => 0x00c3,
- TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 => 0x00c4,
- TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 => 0x00c5,
- TLS_ECDH_ECDSA_WITH_NULL_SHA => 0xc001,
- TLS_ECDH_ECDSA_WITH_RC4_128_SHA => 0xc002,
- TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA => 0xc003,
- TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA => 0xc004,
- TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA => 0xc005,
- TLS_ECDHE_ECDSA_WITH_NULL_SHA => 0xc006,
- TLS_ECDHE_ECDSA_WITH_RC4_128_SHA => 0xc007,
- TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA => 0xc008,
- TLS_ECDH_RSA_WITH_NULL_SHA => 0xc00b,
- TLS_ECDH_RSA_WITH_RC4_128_SHA => 0xc00c,
- TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA => 0xc00d,
- TLS_ECDH_RSA_WITH_AES_128_CBC_SHA => 0xc00e,
- TLS_ECDH_RSA_WITH_AES_256_CBC_SHA => 0xc00f,
- TLS_ECDHE_RSA_WITH_NULL_SHA => 0xc010,
- TLS_ECDHE_RSA_WITH_RC4_128_SHA => 0xc011,
- TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA => 0xc012,
- TLS_ECDH_anon_WITH_NULL_SHA => 0xc015,
- TLS_ECDH_anon_WITH_RC4_128_SHA => 0xc016,
- TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA => 0xc017,
- TLS_ECDH_anon_WITH_AES_128_CBC_SHA => 0xc018,
- TLS_ECDH_anon_WITH_AES_256_CBC_SHA => 0xc019,
- TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA => 0xc01a,
- TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA => 0xc01b,
- TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA => 0xc01c,
- TLS_SRP_SHA_WITH_AES_128_CBC_SHA => 0xc01d,
- TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA => 0xc01e,
- TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA => 0xc01f,
- TLS_SRP_SHA_WITH_AES_256_CBC_SHA => 0xc020,
- TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA => 0xc021,
- TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA => 0xc022,
- TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 => 0xc025,
- TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 => 0xc026,
- TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 => 0xc029,
- TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 => 0xc02a,
- TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 => 0xc02d,
- TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 => 0xc02e,
- TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 => 0xc031,
- TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 => 0xc032,
- TLS_ECDHE_PSK_WITH_RC4_128_SHA => 0xc033,
- TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA => 0xc034,
- TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA => 0xc035,
- TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA => 0xc036,
- TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 => 0xc037,
- TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 => 0xc038,
- TLS_ECDHE_PSK_WITH_NULL_SHA => 0xc039,
- TLS_ECDHE_PSK_WITH_NULL_SHA256 => 0xc03a,
- TLS_ECDHE_PSK_WITH_NULL_SHA384 => 0xc03b,
- TLS_RSA_WITH_ARIA_128_CBC_SHA256 => 0xc03c,
- TLS_RSA_WITH_ARIA_256_CBC_SHA384 => 0xc03d,
- TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 => 0xc03e,
- TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 => 0xc03f,
- TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 => 0xc040,
- TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 => 0xc041,
- TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 => 0xc042,
- TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 => 0xc043,
- TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 => 0xc044,
- TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 => 0xc045,
- TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 => 0xc046,
- TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 => 0xc047,
- TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 => 0xc048,
- TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 => 0xc049,
- TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 => 0xc04a,
- TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 => 0xc04b,
- TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 => 0xc04c,
- TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 => 0xc04d,
- TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 => 0xc04e,
- TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 => 0xc04f,
- TLS_RSA_WITH_ARIA_128_GCM_SHA256 => 0xc050,
- TLS_RSA_WITH_ARIA_256_GCM_SHA384 => 0xc051,
- TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 => 0xc052,
- TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 => 0xc053,
- TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 => 0xc054,
- TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 => 0xc055,
- TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 => 0xc056,
- TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 => 0xc057,
- TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 => 0xc058,
- TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 => 0xc059,
- TLS_DH_anon_WITH_ARIA_128_GCM_SHA256 => 0xc05a,
- TLS_DH_anon_WITH_ARIA_256_GCM_SHA384 => 0xc05b,
- TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 => 0xc05c,
- TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 => 0xc05d,
- TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 => 0xc05e,
- TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 => 0xc05f,
- TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 => 0xc060,
- TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 => 0xc061,
- TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 => 0xc062,
- TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 => 0xc063,
- TLS_PSK_WITH_ARIA_128_CBC_SHA256 => 0xc064,
- TLS_PSK_WITH_ARIA_256_CBC_SHA384 => 0xc065,
- TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 => 0xc066,
- TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 => 0xc067,
- TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 => 0xc068,
- TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 => 0xc069,
- TLS_PSK_WITH_ARIA_128_GCM_SHA256 => 0xc06a,
- TLS_PSK_WITH_ARIA_256_GCM_SHA384 => 0xc06b,
- TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 => 0xc06c,
- TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 => 0xc06d,
- TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 => 0xc06e,
- TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 => 0xc06f,
- TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 => 0xc070,
- TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 => 0xc071,
- TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 => 0xc072,
- TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 => 0xc073,
- TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 => 0xc074,
- TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 => 0xc075,
- TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 => 0xc076,
- TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 => 0xc077,
- TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 => 0xc078,
- TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 => 0xc079,
- TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 => 0xc07a,
- TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 => 0xc07b,
- TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 => 0xc07c,
- TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 => 0xc07d,
- TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 => 0xc07e,
- TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 => 0xc07f,
- TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 => 0xc080,
- TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 => 0xc081,
- TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 => 0xc082,
- TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 => 0xc083,
- TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 => 0xc084,
- TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 => 0xc085,
- TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 => 0xc086,
- TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 => 0xc087,
- TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 => 0xc088,
- TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 => 0xc089,
- TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 => 0xc08a,
- TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 => 0xc08b,
- TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 => 0xc08c,
- TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 => 0xc08d,
- TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 => 0xc08e,
- TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 => 0xc08f,
- TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 => 0xc090,
- TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 => 0xc091,
- TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 => 0xc092,
- TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 => 0xc093,
- TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 => 0xc094,
- TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 => 0xc095,
- TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 => 0xc096,
- TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 => 0xc097,
- TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 => 0xc098,
- TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 => 0xc099,
- TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 => 0xc09a,
- TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 => 0xc09b,
- TLS_RSA_WITH_AES_128_CCM => 0xc09c,
- TLS_RSA_WITH_AES_256_CCM => 0xc09d,
- TLS_DHE_RSA_WITH_AES_128_CCM => 0xc09e,
- TLS_DHE_RSA_WITH_AES_256_CCM => 0xc09f,
- TLS_RSA_WITH_AES_128_CCM_8 => 0xc0a0,
- TLS_RSA_WITH_AES_256_CCM_8 => 0xc0a1,
- TLS_DHE_RSA_WITH_AES_128_CCM_8 => 0xc0a2,
- TLS_DHE_RSA_WITH_AES_256_CCM_8 => 0xc0a3,
- TLS_PSK_WITH_AES_128_CCM => 0xc0a4,
- TLS_PSK_WITH_AES_256_CCM => 0xc0a5,
- TLS_DHE_PSK_WITH_AES_128_CCM => 0xc0a6,
- TLS_DHE_PSK_WITH_AES_256_CCM => 0xc0a7,
- TLS_PSK_WITH_AES_128_CCM_8 => 0xc0a8,
- TLS_PSK_WITH_AES_256_CCM_8 => 0xc0a9,
- TLS_PSK_DHE_WITH_AES_128_CCM_8 => 0xc0aa,
- TLS_PSK_DHE_WITH_AES_256_CCM_8 => 0xc0ab,
- TLS_ECDHE_ECDSA_WITH_AES_128_CCM => 0xc0ac,
- TLS_ECDHE_ECDSA_WITH_AES_256_CCM => 0xc0ad,
- TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 => 0xc0ae,
- TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 => 0xc0af,
- TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 => 0xccaa,
- TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 => 0xccab,
- TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 => 0xccac,
- TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 => 0xccad,
- TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 => 0xccae,
- SSL_RSA_FIPS_WITH_DES_CBC_SHA => 0xfefe,
- SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA => 0xfeff,
- }
-}
-
-enum_builder! {
- /// The `SignatureScheme` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u16)]
- pub enum SignatureScheme {
- RSA_PKCS1_SHA1 => 0x0201,
- ECDSA_SHA1_Legacy => 0x0203,
- RSA_PKCS1_SHA256 => 0x0401,
- ECDSA_NISTP256_SHA256 => 0x0403,
- RSA_PKCS1_SHA384 => 0x0501,
- ECDSA_NISTP384_SHA384 => 0x0503,
- RSA_PKCS1_SHA512 => 0x0601,
- ECDSA_NISTP521_SHA512 => 0x0603,
- RSA_PSS_SHA256 => 0x0804,
- RSA_PSS_SHA384 => 0x0805,
- RSA_PSS_SHA512 => 0x0806,
- ED25519 => 0x0807,
- ED448 => 0x0808,
- // https://datatracker.ietf.org/doc/html/draft-ietf-tls-mldsa-00#name-iana-considerations
- ML_DSA_44 => 0x0904,
- ML_DSA_65 => 0x0905,
- ML_DSA_87 => 0x0906,
- }
-}
-
-impl SignatureScheme {
- pub(crate) fn algorithm(&self) -> SignatureAlgorithm {
- match *self {
- Self::RSA_PKCS1_SHA1
- | Self::RSA_PKCS1_SHA256
- | Self::RSA_PKCS1_SHA384
- | Self::RSA_PKCS1_SHA512
- | Self::RSA_PSS_SHA256
- | Self::RSA_PSS_SHA384
- | Self::RSA_PSS_SHA512 => SignatureAlgorithm::RSA,
- Self::ECDSA_SHA1_Legacy
- | Self::ECDSA_NISTP256_SHA256
- | Self::ECDSA_NISTP384_SHA384
- | Self::ECDSA_NISTP521_SHA512 => SignatureAlgorithm::ECDSA,
- Self::ED25519 => SignatureAlgorithm::ED25519,
- Self::ED448 => SignatureAlgorithm::ED448,
- _ => SignatureAlgorithm::Unknown(0),
- }
- }
-
- /// Whether a particular `SignatureScheme` is allowed for TLS protocol signatures
- /// in TLS1.3.
- ///
- /// This prevents (eg) RSA_PKCS1_SHA256 being offered or accepted, even if our
- /// verifier supports it for other protocol versions.
- ///
- /// See RFC8446 s4.2.3: <https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.3>
- ///
- /// This is a denylist so that newly-allocated `SignatureScheme`s values are
- /// allowed in TLS1.3 by default.
- pub(crate) fn supported_in_tls13(&self) -> bool {
- let [hash, sign] = self.to_array();
-
- // This covers both disallowing SHA1 items in `SignatureScheme`, and
- // old hash functions. See the section beginning "Legacy algorithms:"
- // and item starting "In TLS 1.2, the extension contained hash/signature
- // pairs" in RFC8446 section 4.2.3.
- match HashAlgorithm::from(hash) {
- HashAlgorithm::NONE
- | HashAlgorithm::MD5
- | HashAlgorithm::SHA1
- | HashAlgorithm::SHA224 => return false,
- _ => (),
- };
-
- // RSA-PKCS1 is also disallowed for TLS1.3, see the section beginning
- // "RSASSA-PKCS1-v1_5 algorithms:" in RFC8446 section 4.2.3.
- //
- // (nb. SignatureAlgorithm::RSA is RSA-PKCS1, and does not cover RSA-PSS
- // or RSAE-PSS.)
- //
- // This also covers the outlawing of DSA mentioned elsewhere in 4.2.3.
- !matches!(
- SignatureAlgorithm::from(sign),
- SignatureAlgorithm::Anonymous | SignatureAlgorithm::RSA | SignatureAlgorithm::DSA
- )
- }
-}
-
-enum_builder! {
- /// The `SignatureAlgorithm` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u8)]
- pub enum SignatureAlgorithm {
- Anonymous => 0x00,
- RSA => 0x01,
- DSA => 0x02,
- ECDSA => 0x03,
- ED25519 => 0x07,
- ED448 => 0x08,
- }
-}
-
-enum_builder! {
- /// The "TLS Certificate Compression Algorithm IDs" TLS protocol enum.
- /// Values in this enum are taken from [RFC8879].
- ///
- /// [RFC8879]: https://www.rfc-editor.org/rfc/rfc8879.html#section-7.3
- #[repr(u16)]
- pub enum CertificateCompressionAlgorithm {
- Zlib => 1,
- Brotli => 2,
- Zstd => 3,
- }
-}
-
-enum_builder! {
- /// The `CertificateType` enum sent in the cert_type extensions.
- /// Values in this enum are taken from the various RFCs covering TLS, and are listed by IANA.
- ///
- /// [RFC 6091 Section 5]: <https://datatracker.ietf.org/doc/html/rfc6091#section-5>
- /// [RFC 7250 Section 7]: <https://datatracker.ietf.org/doc/html/rfc7250#section-7>
- #[repr(u8)]
- pub enum CertificateType {
- X509 => 0x00,
- RawPublicKey => 0x02,
- }
-}
-
-enum_builder! {
- /// The type of Encrypted Client Hello (`EchClientHelloType`).
- ///
- /// Specified in [draft-ietf-tls-esni Section 5].
- ///
- /// [draft-ietf-tls-esni Section 5]: <https://www.ietf.org/archive/id/draft-ietf-tls-esni-18.html#section-5>
- #[repr(u8)]
- pub enum EchClientHelloType {
- ClientHelloOuter => 0,
- ClientHelloInner => 1
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::msgs::enums::tests::{test_enum8, test_enum16};
-
- #[test]
- fn test_enums() {
- test_enum8::<SignatureAlgorithm>(SignatureAlgorithm::Anonymous, SignatureAlgorithm::ECDSA);
- test_enum8::<ContentType>(ContentType::ChangeCipherSpec, ContentType::Heartbeat);
- test_enum8::<HandshakeType>(HandshakeType::HelloRequest, HandshakeType::MessageHash);
- test_enum8::<AlertDescription>(
- AlertDescription::CloseNotify,
- AlertDescription::NoApplicationProtocol,
- );
- test_enum16::<CertificateCompressionAlgorithm>(
- CertificateCompressionAlgorithm::Zlib,
- CertificateCompressionAlgorithm::Zstd,
- );
- test_enum8::<CertificateType>(CertificateType::X509, CertificateType::RawPublicKey);
- }
-
- #[test]
- fn tls13_signature_restrictions() {
- // rsa-pkcs1 denied
- assert!(!SignatureScheme::RSA_PKCS1_SHA1.supported_in_tls13());
- assert!(!SignatureScheme::RSA_PKCS1_SHA256.supported_in_tls13());
- assert!(!SignatureScheme::RSA_PKCS1_SHA384.supported_in_tls13());
- assert!(!SignatureScheme::RSA_PKCS1_SHA512.supported_in_tls13());
-
- // dsa denied
- assert!(!SignatureScheme::from(0x0201).supported_in_tls13());
- assert!(!SignatureScheme::from(0x0202).supported_in_tls13());
- assert!(!SignatureScheme::from(0x0203).supported_in_tls13());
- assert!(!SignatureScheme::from(0x0204).supported_in_tls13());
- assert!(!SignatureScheme::from(0x0205).supported_in_tls13());
- assert!(!SignatureScheme::from(0x0206).supported_in_tls13());
-
- // common
- assert!(SignatureScheme::ED25519.supported_in_tls13());
- assert!(SignatureScheme::ED448.supported_in_tls13());
- assert!(SignatureScheme::RSA_PSS_SHA256.supported_in_tls13());
- assert!(SignatureScheme::RSA_PSS_SHA384.supported_in_tls13());
- assert!(SignatureScheme::RSA_PSS_SHA512.supported_in_tls13());
-
- // rsa_pss_rsae_*
- assert!(SignatureScheme::from(0x0804).supported_in_tls13());
- assert!(SignatureScheme::from(0x0805).supported_in_tls13());
- assert!(SignatureScheme::from(0x0806).supported_in_tls13());
-
- // ecdsa_brainpool*
- assert!(SignatureScheme::from(0x081a).supported_in_tls13());
- assert!(SignatureScheme::from(0x081b).supported_in_tls13());
- assert!(SignatureScheme::from(0x081c).supported_in_tls13());
- }
-}
diff --git a/vendor/rustls/src/error.rs b/vendor/rustls/src/error.rs
deleted file mode 100644
index 3aaf3bb3..00000000
--- a/vendor/rustls/src/error.rs
+++ /dev/null
@@ -1,1387 +0,0 @@
-use alloc::format;
-use alloc::string::String;
-use alloc::vec::Vec;
-use core::fmt;
-#[cfg(feature = "std")]
-use std::time::SystemTimeError;
-
-use pki_types::{AlgorithmIdentifier, ServerName, UnixTime};
-use webpki::KeyUsage;
-
-use crate::enums::{AlertDescription, ContentType, HandshakeType};
-use crate::msgs::handshake::{EchConfigPayload, KeyExchangeAlgorithm};
-use crate::rand;
-
-/// rustls reports protocol errors using this type.
-#[non_exhaustive]
-#[derive(Debug, PartialEq, Clone)]
-pub enum Error {
- /// We received a TLS message that isn't valid right now.
- /// `expect_types` lists the message types we can expect right now.
- /// `got_type` is the type we found. This error is typically
- /// caused by a buggy TLS stack (the peer or this one), a broken
- /// network, or an attack.
- InappropriateMessage {
- /// Which types we expected
- expect_types: Vec<ContentType>,
- /// What type we received
- got_type: ContentType,
- },
-
- /// We received a TLS handshake message that isn't valid right now.
- /// `expect_types` lists the handshake message types we can expect
- /// right now. `got_type` is the type we found.
- InappropriateHandshakeMessage {
- /// Which handshake type we expected
- expect_types: Vec<HandshakeType>,
- /// What handshake type we received
- got_type: HandshakeType,
- },
-
- /// An error occurred while handling Encrypted Client Hello (ECH).
- InvalidEncryptedClientHello(EncryptedClientHelloError),
-
- /// The peer sent us a TLS message with invalid contents.
- InvalidMessage(InvalidMessage),
-
- /// The peer didn't give us any certificates.
- NoCertificatesPresented,
-
- /// The certificate verifier doesn't support the given type of name.
- UnsupportedNameType,
-
- /// We couldn't decrypt a message. This is invariably fatal.
- DecryptError,
-
- /// We couldn't encrypt a message because it was larger than the allowed message size.
- /// This should never happen if the application is using valid record sizes.
- EncryptError,
-
- /// The peer doesn't support a protocol version/feature we require.
- /// The parameter gives a hint as to what version/feature it is.
- PeerIncompatible(PeerIncompatible),
-
- /// The peer deviated from the standard TLS protocol.
- /// The parameter gives a hint where.
- PeerMisbehaved(PeerMisbehaved),
-
- /// We received a fatal alert. This means the peer is unhappy.
- AlertReceived(AlertDescription),
-
- /// We saw an invalid certificate.
- ///
- /// The contained error is from the certificate validation trait
- /// implementation.
- InvalidCertificate(CertificateError),
-
- /// A provided certificate revocation list (CRL) was invalid.
- InvalidCertRevocationList(CertRevocationListError),
-
- /// A catch-all error for unlikely errors.
- General(String),
-
- /// We failed to figure out what time it currently is.
- FailedToGetCurrentTime,
-
- /// We failed to acquire random bytes from the system.
- FailedToGetRandomBytes,
-
- /// This function doesn't work until the TLS handshake
- /// is complete.
- HandshakeNotComplete,
-
- /// The peer sent an oversized record/fragment.
- PeerSentOversizedRecord,
-
- /// An incoming connection did not support any known application protocol.
- NoApplicationProtocol,
-
- /// The `max_fragment_size` value supplied in configuration was too small,
- /// or too large.
- BadMaxFragmentSize,
-
- /// Specific failure cases from [`keys_match`] or a [`crate::crypto::signer::SigningKey`] that cannot produce a corresponding public key.
- ///
- /// [`keys_match`]: crate::crypto::signer::CertifiedKey::keys_match
- InconsistentKeys(InconsistentKeys),
-
- /// Any other error.
- ///
- /// This variant should only be used when the error is not better described by a more
- /// specific variant. For example, if a custom crypto provider returns a
- /// provider specific error.
- ///
- /// Enums holding this variant will never compare equal to each other.
- Other(OtherError),
-}
-
-/// Specific failure cases from [`keys_match`] or a [`crate::crypto::signer::SigningKey`] that cannot produce a corresponding public key.
-///
-/// [`keys_match`]: crate::crypto::signer::CertifiedKey::keys_match
-#[non_exhaustive]
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub enum InconsistentKeys {
- /// The public key returned by the [`SigningKey`] does not match the public key information in the certificate.
- ///
- /// [`SigningKey`]: crate::crypto::signer::SigningKey
- KeyMismatch,
-
- /// The [`SigningKey`] cannot produce its corresponding public key.
- ///
- /// [`SigningKey`]: crate::crypto::signer::SigningKey
- Unknown,
-}
-
-impl From<InconsistentKeys> for Error {
- #[inline]
- fn from(e: InconsistentKeys) -> Self {
- Self::InconsistentKeys(e)
- }
-}
-
-/// A corrupt TLS message payload that resulted in an error.
-#[non_exhaustive]
-#[derive(Debug, Clone, Copy, PartialEq)]
-pub enum InvalidMessage {
- /// A certificate payload exceeded rustls's 64KB limit
- CertificatePayloadTooLarge,
- /// An advertised message was larger then expected.
- HandshakePayloadTooLarge,
- /// The peer sent us a syntactically incorrect ChangeCipherSpec payload.
- InvalidCcs,
- /// An unknown content type was encountered during message decoding.
- InvalidContentType,
- /// A peer sent an invalid certificate status type
- InvalidCertificateStatusType,
- /// Context was incorrectly attached to a certificate request during a handshake.
- InvalidCertRequest,
- /// A peer's DH params could not be decoded
- InvalidDhParams,
- /// A message was zero-length when its record kind forbids it.
- InvalidEmptyPayload,
- /// A peer sent an unexpected key update request.
- InvalidKeyUpdate,
- /// A peer's server name could not be decoded
- InvalidServerName,
- /// A TLS message payload was larger then allowed by the specification.
- MessageTooLarge,
- /// Message is shorter than the expected length
- MessageTooShort,
- /// Missing data for the named handshake payload value
- MissingData(&'static str),
- /// A peer did not advertise its supported key exchange groups.
- MissingKeyExchange,
- /// A peer sent an empty list of signature schemes
- NoSignatureSchemes,
- /// Trailing data found for the named handshake payload value
- TrailingData(&'static str),
- /// A peer sent an unexpected message type.
- UnexpectedMessage(&'static str),
- /// An unknown TLS protocol was encountered during message decoding.
- UnknownProtocolVersion,
- /// A peer sent a non-null compression method.
- UnsupportedCompression,
- /// A peer sent an unknown elliptic curve type.
- UnsupportedCurveType,
- /// A peer sent an unsupported key exchange algorithm.
- UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
- /// A server sent an empty ticket
- EmptyTicketValue,
- /// A peer sent an empty list of items, but a non-empty list is required.
- ///
- /// The argument names the context.
- IllegalEmptyList(&'static str),
- /// A peer sent an empty value, but a non-empty value is required.
- IllegalEmptyValue,
- /// A peer sent a message where a given extension type was repeated
- DuplicateExtension(u16),
- /// A peer sent a message with a PSK offer extension in wrong position
- PreSharedKeyIsNotFinalExtension,
- /// A server sent a HelloRetryRequest with an unknown extension
- UnknownHelloRetryRequestExtension,
- /// The peer sent a TLS1.3 Certificate with an unknown extension
- UnknownCertificateExtension,
-}
-
-impl From<InvalidMessage> for Error {
- #[inline]
- fn from(e: InvalidMessage) -> Self {
- Self::InvalidMessage(e)
- }
-}
-
-impl From<InvalidMessage> for AlertDescription {
- fn from(e: InvalidMessage) -> Self {
- match e {
- InvalidMessage::PreSharedKeyIsNotFinalExtension => Self::IllegalParameter,
- InvalidMessage::DuplicateExtension(_) => Self::IllegalParameter,
- InvalidMessage::UnknownHelloRetryRequestExtension => Self::UnsupportedExtension,
- _ => Self::DecodeError,
- }
- }
-}
-
-#[non_exhaustive]
-#[allow(missing_docs)]
-#[derive(Debug, PartialEq, Clone)]
-/// The set of cases where we failed to make a connection because we thought
-/// the peer was misbehaving.
-///
-/// This is `non_exhaustive`: we might add or stop using items here in minor
-/// versions. We also don't document what they mean. Generally a user of
-/// rustls shouldn't vary its behaviour on these error codes, and there is
-/// nothing it can do to improve matters.
-///
-/// Please file a bug against rustls if you see `Error::PeerMisbehaved` in
-/// the wild.
-pub enum PeerMisbehaved {
- AttemptedDowngradeToTls12WhenTls13IsSupported,
- BadCertChainExtensions,
- DisallowedEncryptedExtension,
- DuplicateClientHelloExtensions,
- DuplicateEncryptedExtensions,
- DuplicateHelloRetryRequestExtensions,
- DuplicateNewSessionTicketExtensions,
- DuplicateServerHelloExtensions,
- DuplicateServerNameTypes,
- EarlyDataAttemptedInSecondClientHello,
- EarlyDataExtensionWithoutResumption,
- EarlyDataOfferedWithVariedCipherSuite,
- HandshakeHashVariedAfterRetry,
- IllegalHelloRetryRequestWithEmptyCookie,
- IllegalHelloRetryRequestWithNoChanges,
- IllegalHelloRetryRequestWithOfferedGroup,
- IllegalHelloRetryRequestWithUnofferedCipherSuite,
- IllegalHelloRetryRequestWithUnofferedNamedGroup,
- IllegalHelloRetryRequestWithUnsupportedVersion,
- IllegalHelloRetryRequestWithWrongSessionId,
- IllegalHelloRetryRequestWithInvalidEch,
- IllegalMiddleboxChangeCipherSpec,
- IllegalTlsInnerPlaintext,
- IncorrectBinder,
- InvalidCertCompression,
- InvalidMaxEarlyDataSize,
- InvalidKeyShare,
- KeyEpochWithPendingFragment,
- KeyUpdateReceivedInQuicConnection,
- MessageInterleavedWithHandshakeMessage,
- MissingBinderInPskExtension,
- MissingKeyShare,
- MissingPskModesExtension,
- MissingQuicTransportParameters,
- OfferedDuplicateCertificateCompressions,
- OfferedDuplicateKeyShares,
- OfferedEarlyDataWithOldProtocolVersion,
- OfferedEmptyApplicationProtocol,
- OfferedIncorrectCompressions,
- PskExtensionMustBeLast,
- PskExtensionWithMismatchedIdsAndBinders,
- RefusedToFollowHelloRetryRequest,
- RejectedEarlyDataInterleavedWithHandshakeMessage,
- ResumptionAttemptedWithVariedEms,
- ResumptionOfferedWithVariedCipherSuite,
- ResumptionOfferedWithVariedEms,
- ResumptionOfferedWithIncompatibleCipherSuite,
- SelectedDifferentCipherSuiteAfterRetry,
- SelectedInvalidPsk,
- SelectedTls12UsingTls13VersionExtension,
- SelectedUnofferedApplicationProtocol,
- SelectedUnofferedCertCompression,
- SelectedUnofferedCipherSuite,
- SelectedUnofferedCompression,
- SelectedUnofferedKxGroup,
- SelectedUnofferedPsk,
- SelectedUnusableCipherSuiteForVersion,
- ServerEchoedCompatibilitySessionId,
- ServerHelloMustOfferUncompressedEcPoints,
- ServerNameDifferedOnRetry,
- ServerNameMustContainOneHostName,
- SignedKxWithWrongAlgorithm,
- SignedHandshakeWithUnadvertisedSigScheme,
- TooManyEmptyFragments,
- TooManyKeyUpdateRequests,
- TooManyRenegotiationRequests,
- TooManyWarningAlertsReceived,
- TooMuchEarlyDataReceived,
- UnexpectedCleartextExtension,
- UnsolicitedCertExtension,
- UnsolicitedEncryptedExtension,
- UnsolicitedSctList,
- UnsolicitedServerHelloExtension,
- WrongGroupForKeyShare,
- UnsolicitedEchExtension,
-}
-
-impl From<PeerMisbehaved> for Error {
- #[inline]
- fn from(e: PeerMisbehaved) -> Self {
- Self::PeerMisbehaved(e)
- }
-}
-
-#[non_exhaustive]
-#[allow(missing_docs)]
-#[derive(Debug, PartialEq, Clone)]
-/// The set of cases where we failed to make a connection because a peer
-/// doesn't support a TLS version/feature we require.
-///
-/// This is `non_exhaustive`: we might add or stop using items here in minor
-/// versions.
-pub enum PeerIncompatible {
- EcPointsExtensionRequired,
- ExtendedMasterSecretExtensionRequired,
- IncorrectCertificateTypeExtension,
- KeyShareExtensionRequired,
- NamedGroupsExtensionRequired,
- NoCertificateRequestSignatureSchemesInCommon,
- NoCipherSuitesInCommon,
- NoEcPointFormatsInCommon,
- NoKxGroupsInCommon,
- NoSignatureSchemesInCommon,
- NullCompressionRequired,
- ServerDoesNotSupportTls12Or13,
- ServerSentHelloRetryRequestWithUnknownExtension,
- ServerTlsVersionIsDisabledByOurConfig,
- SignatureAlgorithmsExtensionRequired,
- SupportedVersionsExtensionRequired,
- Tls12NotOffered,
- Tls12NotOfferedOrEnabled,
- Tls13RequiredForQuic,
- UncompressedEcPointsRequired,
- UnsolicitedCertificateTypeExtension,
- ServerRejectedEncryptedClientHello(Option<Vec<EchConfigPayload>>),
-}
-
-impl From<PeerIncompatible> for Error {
- #[inline]
- fn from(e: PeerIncompatible) -> Self {
- Self::PeerIncompatible(e)
- }
-}
-
-#[non_exhaustive]
-#[derive(Debug, Clone)]
-/// The ways in which certificate validators can express errors.
-///
-/// Note that the rustls TLS protocol code interprets specifically these
-/// error codes to send specific TLS alerts. Therefore, if a
-/// custom certificate validator uses incorrect errors the library as
-/// a whole will send alerts that do not match the standard (this is usually
-/// a minor issue, but could be misleading).
-pub enum CertificateError {
- /// The certificate is not correctly encoded.
- BadEncoding,
-
- /// The current time is after the `notAfter` time in the certificate.
- Expired,
-
- /// The current time is after the `notAfter` time in the certificate.
- ///
- /// This variant is semantically the same as `Expired`, but includes
- /// extra data to improve error reports.
- ExpiredContext {
- /// The validation time.
- time: UnixTime,
- /// The `notAfter` time of the certificate.
- not_after: UnixTime,
- },
-
- /// The current time is before the `notBefore` time in the certificate.
- NotValidYet,
-
- /// The current time is before the `notBefore` time in the certificate.
- ///
- /// This variant is semantically the same as `NotValidYet`, but includes
- /// extra data to improve error reports.
- NotValidYetContext {
- /// The validation time.
- time: UnixTime,
- /// The `notBefore` time of the certificate.
- not_before: UnixTime,
- },
-
- /// The certificate has been revoked.
- Revoked,
-
- /// The certificate contains an extension marked critical, but it was
- /// not processed by the certificate validator.
- UnhandledCriticalExtension,
-
- /// The certificate chain is not issued by a known root certificate.
- UnknownIssuer,
-
- /// The certificate's revocation status could not be determined.
- UnknownRevocationStatus,
-
- /// The certificate's revocation status could not be determined, because the CRL is expired.
- ExpiredRevocationList,
-
- /// The certificate's revocation status could not be determined, because the CRL is expired.
- ///
- /// This variant is semantically the same as `ExpiredRevocationList`, but includes
- /// extra data to improve error reports.
- ExpiredRevocationListContext {
- /// The validation time.
- time: UnixTime,
- /// The nextUpdate time of the CRL.
- next_update: UnixTime,
- },
-
- /// A certificate is not correctly signed by the key of its alleged
- /// issuer.
- BadSignature,
-
- /// A signature inside a certificate or on a handshake was made with an unsupported algorithm.
- #[deprecated(
- since = "0.23.29",
- note = "use `UnsupportedSignatureAlgorithmContext` instead"
- )]
- UnsupportedSignatureAlgorithm,
-
- /// A signature inside a certificate or on a handshake was made with an unsupported algorithm.
- UnsupportedSignatureAlgorithmContext {
- /// The signature algorithm OID that was unsupported.
- signature_algorithm_id: Vec<u8>,
- /// Supported algorithms that were available for signature verification.
- supported_algorithms: Vec<AlgorithmIdentifier>,
- },
-
- /// A signature was made with an algorithm that doesn't match the relevant public key.
- UnsupportedSignatureAlgorithmForPublicKeyContext {
- /// The signature algorithm OID.
- signature_algorithm_id: Vec<u8>,
- /// The public key algorithm OID.
- public_key_algorithm_id: Vec<u8>,
- },
-
- /// The subject names in an end-entity certificate do not include
- /// the expected name.
- NotValidForName,
-
- /// The subject names in an end-entity certificate do not include
- /// the expected name.
- ///
- /// This variant is semantically the same as `NotValidForName`, but includes
- /// extra data to improve error reports.
- NotValidForNameContext {
- /// Expected server name.
- expected: ServerName<'static>,
-
- /// The names presented in the end entity certificate.
- ///
- /// These are the subject names as present in the leaf certificate and may contain DNS names
- /// with or without a wildcard label as well as IP address names.
- presented: Vec<String>,
- },
-
- /// The certificate is being used for a different purpose than allowed.
- InvalidPurpose,
-
- /// The certificate is being used for a different purpose than allowed.
- ///
- /// This variant is semantically the same as `InvalidPurpose`, but includes
- /// extra data to improve error reports.
- InvalidPurposeContext {
- /// Extended key purpose that was required by the application.
- required: ExtendedKeyPurpose,
- /// Extended key purposes that were presented in the peer's certificate.
- presented: Vec<ExtendedKeyPurpose>,
- },
-
- /// The OCSP response provided to the verifier was invalid.
- ///
- /// This should be returned from [`ServerCertVerifier::verify_server_cert()`]
- /// when a verifier checks its `ocsp_response` parameter and finds it invalid.
- ///
- /// This maps to [`AlertDescription::BadCertificateStatusResponse`].
- ///
- /// [`ServerCertVerifier::verify_server_cert()`]: crate::client::danger::ServerCertVerifier::verify_server_cert
- InvalidOcspResponse,
-
- /// The certificate is valid, but the handshake is rejected for other
- /// reasons.
- ApplicationVerificationFailure,
-
- /// Any other error.
- ///
- /// This can be used by custom verifiers to expose the underlying error
- /// (where they are not better described by the more specific errors
- /// above).
- ///
- /// It is also used by the default verifier in case its error is
- /// not covered by the above common cases.
- ///
- /// Enums holding this variant will never compare equal to each other.
- Other(OtherError),
-}
-
-impl PartialEq<Self> for CertificateError {
- fn eq(&self, other: &Self) -> bool {
- use CertificateError::*;
- #[allow(clippy::match_like_matches_macro)]
- match (self, other) {
- (BadEncoding, BadEncoding) => true,
- (Expired, Expired) => true,
- (
- ExpiredContext {
- time: left_time,
- not_after: left_not_after,
- },
- ExpiredContext {
- time: right_time,
- not_after: right_not_after,
- },
- ) => (left_time, left_not_after) == (right_time, right_not_after),
- (NotValidYet, NotValidYet) => true,
- (
- NotValidYetContext {
- time: left_time,
- not_before: left_not_before,
- },
- NotValidYetContext {
- time: right_time,
- not_before: right_not_before,
- },
- ) => (left_time, left_not_before) == (right_time, right_not_before),
- (Revoked, Revoked) => true,
- (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
- (UnknownIssuer, UnknownIssuer) => true,
- (BadSignature, BadSignature) => true,
- #[allow(deprecated)]
- (UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm) => true,
- (
- UnsupportedSignatureAlgorithmContext {
- signature_algorithm_id: left_signature_algorithm_id,
- supported_algorithms: left_supported_algorithms,
- },
- UnsupportedSignatureAlgorithmContext {
- signature_algorithm_id: right_signature_algorithm_id,
- supported_algorithms: right_supported_algorithms,
- },
- ) => {
- (left_signature_algorithm_id, left_supported_algorithms)
- == (right_signature_algorithm_id, right_supported_algorithms)
- }
- (
- UnsupportedSignatureAlgorithmForPublicKeyContext {
- signature_algorithm_id: left_signature_algorithm_id,
- public_key_algorithm_id: left_public_key_algorithm_id,
- },
- UnsupportedSignatureAlgorithmForPublicKeyContext {
- signature_algorithm_id: right_signature_algorithm_id,
- public_key_algorithm_id: right_public_key_algorithm_id,
- },
- ) => {
- (left_signature_algorithm_id, left_public_key_algorithm_id)
- == (right_signature_algorithm_id, right_public_key_algorithm_id)
- }
- (NotValidForName, NotValidForName) => true,
- (
- NotValidForNameContext {
- expected: left_expected,
- presented: left_presented,
- },
- NotValidForNameContext {
- expected: right_expected,
- presented: right_presented,
- },
- ) => (left_expected, left_presented) == (right_expected, right_presented),
- (InvalidPurpose, InvalidPurpose) => true,
- (
- InvalidPurposeContext {
- required: left_required,
- presented: left_presented,
- },
- InvalidPurposeContext {
- required: right_required,
- presented: right_presented,
- },
- ) => (left_required, left_presented) == (right_required, right_presented),
- (InvalidOcspResponse, InvalidOcspResponse) => true,
- (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
- (UnknownRevocationStatus, UnknownRevocationStatus) => true,
- (ExpiredRevocationList, ExpiredRevocationList) => true,
- (
- ExpiredRevocationListContext {
- time: left_time,
- next_update: left_next_update,
- },
- ExpiredRevocationListContext {
- time: right_time,
- next_update: right_next_update,
- },
- ) => (left_time, left_next_update) == (right_time, right_next_update),
- _ => false,
- }
- }
-}
-
-// The following mapping are heavily referenced in:
-// * [OpenSSL Implementation](https://github.com/openssl/openssl/blob/45bb98bfa223efd3258f445ad443f878011450f0/ssl/statem/statem_lib.c#L1434)
-// * [BoringSSL Implementation](https://github.com/google/boringssl/blob/583c60bd4bf76d61b2634a58bcda99a92de106cb/ssl/ssl_x509.cc#L1323)
-impl From<CertificateError> for AlertDescription {
- fn from(e: CertificateError) -> Self {
- use CertificateError::*;
- match e {
- BadEncoding
- | UnhandledCriticalExtension
- | NotValidForName
- | NotValidForNameContext { .. } => Self::BadCertificate,
- // RFC 5246/RFC 8446
- // certificate_expired
- // A certificate has expired or **is not currently valid**.
- Expired | ExpiredContext { .. } | NotValidYet | NotValidYetContext { .. } => {
- Self::CertificateExpired
- }
- Revoked => Self::CertificateRevoked,
- // OpenSSL, BoringSSL and AWS-LC all generate an Unknown CA alert for
- // the case where revocation status can not be determined, so we do the same here.
- UnknownIssuer
- | UnknownRevocationStatus
- | ExpiredRevocationList
- | ExpiredRevocationListContext { .. } => Self::UnknownCA,
- InvalidOcspResponse => Self::BadCertificateStatusResponse,
- #[allow(deprecated)]
- BadSignature
- | UnsupportedSignatureAlgorithm
- | UnsupportedSignatureAlgorithmContext { .. }
- | UnsupportedSignatureAlgorithmForPublicKeyContext { .. } => Self::DecryptError,
- InvalidPurpose | InvalidPurposeContext { .. } => Self::UnsupportedCertificate,
- ApplicationVerificationFailure => Self::AccessDenied,
- // RFC 5246/RFC 8446
- // certificate_unknown
- // Some other (unspecified) issue arose in processing the
- // certificate, rendering it unacceptable.
- Other(..) => Self::CertificateUnknown,
- }
- }
-}
-
-impl fmt::Display for CertificateError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- #[cfg(feature = "std")]
- Self::NotValidForNameContext {
- expected,
- presented,
- } => {
- write!(
- f,
- "certificate not valid for name {:?}; certificate ",
- expected.to_str()
- )?;
-
- match presented.as_slice() {
- &[] => write!(
- f,
- "is not valid for any names (according to its subjectAltName extension)"
- ),
- [one] => write!(f, "is only valid for {one}"),
- many => {
- write!(f, "is only valid for ")?;
-
- let n = many.len();
- let all_but_last = &many[..n - 1];
- let last = &many[n - 1];
-
- for (i, name) in all_but_last.iter().enumerate() {
- write!(f, "{name}")?;
- if i < n - 2 {
- write!(f, ", ")?;
- }
- }
- write!(f, " or {last}")
- }
- }
- }
-
- Self::ExpiredContext { time, not_after } => write!(
- f,
- "certificate expired: verification time {} (UNIX), \
- but certificate is not valid after {} \
- ({} seconds ago)",
- time.as_secs(),
- not_after.as_secs(),
- time.as_secs()
- .saturating_sub(not_after.as_secs())
- ),
-
- Self::NotValidYetContext { time, not_before } => write!(
- f,
- "certificate not valid yet: verification time {} (UNIX), \
- but certificate is not valid before {} \
- ({} seconds in future)",
- time.as_secs(),
- not_before.as_secs(),
- not_before
- .as_secs()
- .saturating_sub(time.as_secs())
- ),
-
- Self::ExpiredRevocationListContext { time, next_update } => write!(
- f,
- "certificate revocation list expired: \
- verification time {} (UNIX), \
- but CRL is not valid after {} \
- ({} seconds ago)",
- time.as_secs(),
- next_update.as_secs(),
- time.as_secs()
- .saturating_sub(next_update.as_secs())
- ),
-
- Self::InvalidPurposeContext {
- required,
- presented,
- } => {
- write!(
- f,
- "certificate does not allow extended key usage for {required}, allows "
- )?;
- for (i, eku) in presented.iter().enumerate() {
- if i > 0 {
- write!(f, ", ")?;
- }
- write!(f, "{eku}")?;
- }
- Ok(())
- }
-
- other => write!(f, "{other:?}"),
- }
- }
-}
-
-impl From<CertificateError> for Error {
- #[inline]
- fn from(e: CertificateError) -> Self {
- Self::InvalidCertificate(e)
- }
-}
-
-/// Extended Key Usage (EKU) purpose values.
-///
-/// These are usually represented as OID values in the certificate's extension (if present), but
-/// we represent the values that are most relevant to rustls as named enum variants.
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub enum ExtendedKeyPurpose {
- /// Client authentication
- ClientAuth,
- /// Server authentication
- ServerAuth,
- /// Other EKU values
- ///
- /// Represented here as a `Vec<usize>` for human readability.
- Other(Vec<usize>),
-}
-
-impl ExtendedKeyPurpose {
- pub(crate) fn for_values(values: impl Iterator<Item = usize>) -> Self {
- let values = values.collect::<Vec<_>>();
- match &*values {
- KeyUsage::CLIENT_AUTH_REPR => Self::ClientAuth,
- KeyUsage::SERVER_AUTH_REPR => Self::ServerAuth,
- _ => Self::Other(values),
- }
- }
-}
-
-impl fmt::Display for ExtendedKeyPurpose {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::ClientAuth => write!(f, "client authentication"),
- Self::ServerAuth => write!(f, "server authentication"),
- Self::Other(values) => {
- for (i, value) in values.iter().enumerate() {
- if i > 0 {
- write!(f, ", ")?;
- }
- write!(f, "{value}")?;
- }
- Ok(())
- }
- }
- }
-}
-
-#[non_exhaustive]
-#[derive(Debug, Clone)]
-/// The ways in which a certificate revocation list (CRL) can be invalid.
-pub enum CertRevocationListError {
- /// The CRL had a bad signature from its issuer.
- BadSignature,
-
- /// The CRL had an unsupported signature from its issuer.
- #[deprecated(
- since = "0.23.29",
- note = "use `UnsupportedSignatureAlgorithmContext` instead"
- )]
- UnsupportedSignatureAlgorithm,
-
- /// A signature inside a certificate or on a handshake was made with an unsupported algorithm.
- UnsupportedSignatureAlgorithmContext {
- /// The signature algorithm OID that was unsupported.
- signature_algorithm_id: Vec<u8>,
- /// Supported algorithms that were available for signature verification.
- supported_algorithms: Vec<AlgorithmIdentifier>,
- },
-
- /// A signature was made with an algorithm that doesn't match the relevant public key.
- UnsupportedSignatureAlgorithmForPublicKeyContext {
- /// The signature algorithm OID.
- signature_algorithm_id: Vec<u8>,
- /// The public key algorithm OID.
- public_key_algorithm_id: Vec<u8>,
- },
-
- /// The CRL contained an invalid CRL number.
- InvalidCrlNumber,
-
- /// The CRL contained a revoked certificate with an invalid serial number.
- InvalidRevokedCertSerialNumber,
-
- /// The CRL issuer does not specify the cRLSign key usage.
- IssuerInvalidForCrl,
-
- /// The CRL is invalid for some other reason.
- ///
- /// Enums holding this variant will never compare equal to each other.
- Other(OtherError),
-
- /// The CRL is not correctly encoded.
- ParseError,
-
- /// The CRL is not a v2 X.509 CRL.
- UnsupportedCrlVersion,
-
- /// The CRL, or a revoked certificate in the CRL, contained an unsupported critical extension.
- UnsupportedCriticalExtension,
-
- /// The CRL is an unsupported delta CRL, containing only changes relative to another CRL.
- UnsupportedDeltaCrl,
-
- /// The CRL is an unsupported indirect CRL, containing revoked certificates issued by a CA
- /// other than the issuer of the CRL.
- UnsupportedIndirectCrl,
-
- /// The CRL contained a revoked certificate with an unsupported revocation reason.
- /// See RFC 5280 Section 5.3.1[^1] for a list of supported revocation reasons.
- ///
- /// [^1]: <https://www.rfc-editor.org/rfc/rfc5280#section-5.3.1>
- UnsupportedRevocationReason,
-}
-
-impl PartialEq<Self> for CertRevocationListError {
- fn eq(&self, other: &Self) -> bool {
- use CertRevocationListError::*;
- #[allow(clippy::match_like_matches_macro)]
- match (self, other) {
- (BadSignature, BadSignature) => true,
- #[allow(deprecated)]
- (UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm) => true,
- (
- UnsupportedSignatureAlgorithmContext {
- signature_algorithm_id: left_signature_algorithm_id,
- supported_algorithms: left_supported_algorithms,
- },
- UnsupportedSignatureAlgorithmContext {
- signature_algorithm_id: right_signature_algorithm_id,
- supported_algorithms: right_supported_algorithms,
- },
- ) => {
- (left_signature_algorithm_id, left_supported_algorithms)
- == (right_signature_algorithm_id, right_supported_algorithms)
- }
- (
- UnsupportedSignatureAlgorithmForPublicKeyContext {
- signature_algorithm_id: left_signature_algorithm_id,
- public_key_algorithm_id: left_public_key_algorithm_id,
- },
- UnsupportedSignatureAlgorithmForPublicKeyContext {
- signature_algorithm_id: right_signature_algorithm_id,
- public_key_algorithm_id: right_public_key_algorithm_id,
- },
- ) => {
- (left_signature_algorithm_id, left_public_key_algorithm_id)
- == (right_signature_algorithm_id, right_public_key_algorithm_id)
- }
- (InvalidCrlNumber, InvalidCrlNumber) => true,
- (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
- (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
- (ParseError, ParseError) => true,
- (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
- (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
- (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
- (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
- (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
- _ => false,
- }
- }
-}
-
-impl From<CertRevocationListError> for Error {
- #[inline]
- fn from(e: CertRevocationListError) -> Self {
- Self::InvalidCertRevocationList(e)
- }
-}
-
-#[non_exhaustive]
-#[derive(Debug, Clone, Eq, PartialEq)]
-/// An error that occurred while handling Encrypted Client Hello (ECH).
-pub enum EncryptedClientHelloError {
- /// The provided ECH configuration list was invalid.
- InvalidConfigList,
- /// No compatible ECH configuration.
- NoCompatibleConfig,
- /// The client configuration has server name indication (SNI) disabled.
- SniRequired,
-}
-
-impl From<EncryptedClientHelloError> for Error {
- #[inline]
- fn from(e: EncryptedClientHelloError) -> Self {
- Self::InvalidEncryptedClientHello(e)
- }
-}
-
-fn join<T: fmt::Debug>(items: &[T]) -> String {
- items
- .iter()
- .map(|x| format!("{x:?}"))
- .collect::<Vec<String>>()
- .join(" or ")
-}
-
-impl fmt::Display for Error {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::InappropriateMessage {
- expect_types,
- got_type,
- } => write!(
- f,
- "received unexpected message: got {:?} when expecting {}",
- got_type,
- join::<ContentType>(expect_types)
- ),
- Self::InappropriateHandshakeMessage {
- expect_types,
- got_type,
- } => write!(
- f,
- "received unexpected handshake message: got {:?} when expecting {}",
- got_type,
- join::<HandshakeType>(expect_types)
- ),
- Self::InvalidMessage(typ) => {
- write!(f, "received corrupt message of type {typ:?}")
- }
- Self::PeerIncompatible(why) => write!(f, "peer is incompatible: {why:?}"),
- Self::PeerMisbehaved(why) => write!(f, "peer misbehaved: {why:?}"),
- Self::AlertReceived(alert) => write!(f, "received fatal alert: {alert:?}"),
- Self::InvalidCertificate(err) => {
- write!(f, "invalid peer certificate: {err}")
- }
- Self::InvalidCertRevocationList(err) => {
- write!(f, "invalid certificate revocation list: {err:?}")
- }
- Self::NoCertificatesPresented => write!(f, "peer sent no certificates"),
- Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
- Self::DecryptError => write!(f, "cannot decrypt peer's message"),
- Self::InvalidEncryptedClientHello(err) => {
- write!(f, "encrypted client hello failure: {err:?}")
- }
- Self::EncryptError => write!(f, "cannot encrypt message"),
- Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
- Self::HandshakeNotComplete => write!(f, "handshake not complete"),
- Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
- Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
- Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
- Self::BadMaxFragmentSize => {
- write!(f, "the supplied max_fragment_size was too small or large")
- }
- Self::InconsistentKeys(why) => {
- write!(f, "keys may not be consistent: {why:?}")
- }
- Self::General(err) => write!(f, "unexpected error: {err}"),
- Self::Other(err) => write!(f, "other error: {err}"),
- }
- }
-}
-
-#[cfg(feature = "std")]
-impl From<SystemTimeError> for Error {
- #[inline]
- fn from(_: SystemTimeError) -> Self {
- Self::FailedToGetCurrentTime
- }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for Error {}
-
-impl From<rand::GetRandomFailed> for Error {
- fn from(_: rand::GetRandomFailed) -> Self {
- Self::FailedToGetRandomBytes
- }
-}
-
-mod other_error {
- use core::fmt;
- #[cfg(feature = "std")]
- use std::error::Error as StdError;
-
- use super::Error;
- #[cfg(feature = "std")]
- use crate::sync::Arc;
-
- /// Any other error that cannot be expressed by a more specific [`Error`] variant.
- ///
- /// For example, an `OtherError` could be produced by a custom crypto provider
- /// exposing a provider specific error.
- ///
- /// Enums holding this type will never compare equal to each other.
- #[derive(Debug, Clone)]
- pub struct OtherError(#[cfg(feature = "std")] pub Arc<dyn StdError + Send + Sync>);
-
- impl PartialEq<Self> for OtherError {
- fn eq(&self, _other: &Self) -> bool {
- false
- }
- }
-
- impl From<OtherError> for Error {
- fn from(value: OtherError) -> Self {
- Self::Other(value)
- }
- }
-
- impl fmt::Display for OtherError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- #[cfg(feature = "std")]
- {
- write!(f, "{}", self.0)
- }
- #[cfg(not(feature = "std"))]
- {
- f.write_str("no further information available")
- }
- }
- }
-
- #[cfg(feature = "std")]
- impl StdError for OtherError {
- fn source(&self) -> Option<&(dyn StdError + 'static)> {
- Some(self.0.as_ref())
- }
- }
-}
-
-pub use other_error::OtherError;
-
-#[cfg(test)]
-mod tests {
- use core::time::Duration;
- use std::prelude::v1::*;
- use std::{println, vec};
-
- use pki_types::ServerName;
-
- use super::{
- CertRevocationListError, Error, InconsistentKeys, InvalidMessage, OtherError, UnixTime,
- };
- #[cfg(feature = "std")]
- use crate::sync::Arc;
-
- #[test]
- fn certificate_error_equality() {
- use super::CertificateError::*;
- assert_eq!(BadEncoding, BadEncoding);
- assert_eq!(Expired, Expired);
- let context = ExpiredContext {
- time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
- not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
- };
- assert_eq!(context, context);
- assert_ne!(
- context,
- ExpiredContext {
- time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
- not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
- }
- );
- assert_ne!(
- context,
- ExpiredContext {
- time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
- not_after: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
- }
- );
- assert_eq!(NotValidYet, NotValidYet);
- let context = NotValidYetContext {
- time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
- not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
- };
- assert_eq!(context, context);
- assert_ne!(
- context,
- NotValidYetContext {
- time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
- not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
- }
- );
- assert_ne!(
- context,
- NotValidYetContext {
- time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
- not_before: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
- }
- );
- assert_eq!(Revoked, Revoked);
- assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
- assert_eq!(UnknownIssuer, UnknownIssuer);
- assert_eq!(ExpiredRevocationList, ExpiredRevocationList);
- assert_eq!(UnknownRevocationStatus, UnknownRevocationStatus);
- let context = ExpiredRevocationListContext {
- time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
- next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
- };
- assert_eq!(context, context);
- assert_ne!(
- context,
- ExpiredRevocationListContext {
- time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
- next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
- }
- );
- assert_ne!(
- context,
- ExpiredRevocationListContext {
- time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
- next_update: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
- }
- );
- assert_eq!(BadSignature, BadSignature);
- #[allow(deprecated)]
- {
- assert_eq!(UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm);
- }
- assert_eq!(
- UnsupportedSignatureAlgorithmContext {
- signature_algorithm_id: vec![1, 2, 3],
- supported_algorithms: vec![]
- },
- UnsupportedSignatureAlgorithmContext {
- signature_algorithm_id: vec![1, 2, 3],
- supported_algorithms: vec![]
- }
- );
- assert_eq!(
- UnsupportedSignatureAlgorithmForPublicKeyContext {
- signature_algorithm_id: vec![1, 2, 3],
- public_key_algorithm_id: vec![4, 5, 6]
- },
- UnsupportedSignatureAlgorithmForPublicKeyContext {
- signature_algorithm_id: vec![1, 2, 3],
- public_key_algorithm_id: vec![4, 5, 6]
- }
- );
- assert_eq!(NotValidForName, NotValidForName);
- let context = NotValidForNameContext {
- expected: ServerName::try_from("example.com")
- .unwrap()
- .to_owned(),
- presented: vec!["other.com".into()],
- };
- assert_eq!(context, context);
- assert_ne!(
- context,
- NotValidForNameContext {
- expected: ServerName::try_from("example.com")
- .unwrap()
- .to_owned(),
- presented: vec![]
- }
- );
- assert_ne!(
- context,
- NotValidForNameContext {
- expected: ServerName::try_from("huh.com")
- .unwrap()
- .to_owned(),
- presented: vec!["other.com".into()],
- }
- );
- assert_eq!(InvalidPurpose, InvalidPurpose);
- assert_eq!(
- ApplicationVerificationFailure,
- ApplicationVerificationFailure
- );
- assert_eq!(InvalidOcspResponse, InvalidOcspResponse);
- let other = Other(OtherError(
- #[cfg(feature = "std")]
- Arc::from(Box::from("")),
- ));
- assert_ne!(other, other);
- assert_ne!(BadEncoding, Expired);
- }
-
- #[test]
- fn crl_error_equality() {
- use super::CertRevocationListError::*;
- assert_eq!(BadSignature, BadSignature);
- #[allow(deprecated)]
- {
- assert_eq!(UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm);
- }
- assert_eq!(
- UnsupportedSignatureAlgorithmContext {
- signature_algorithm_id: vec![1, 2, 3],
- supported_algorithms: vec![]
- },
- UnsupportedSignatureAlgorithmContext {
- signature_algorithm_id: vec![1, 2, 3],
- supported_algorithms: vec![]
- }
- );
- assert_eq!(
- UnsupportedSignatureAlgorithmForPublicKeyContext {
- signature_algorithm_id: vec![1, 2, 3],
- public_key_algorithm_id: vec![4, 5, 6]
- },
- UnsupportedSignatureAlgorithmForPublicKeyContext {
- signature_algorithm_id: vec![1, 2, 3],
- public_key_algorithm_id: vec![4, 5, 6]
- }
- );
- assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
- assert_eq!(
- InvalidRevokedCertSerialNumber,
- InvalidRevokedCertSerialNumber
- );
- assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
- assert_eq!(ParseError, ParseError);
- assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
- assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
- assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
- assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
- assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
- let other = Other(OtherError(
- #[cfg(feature = "std")]
- Arc::from(Box::from("")),
- ));
- assert_ne!(other, other);
- assert_ne!(BadSignature, InvalidCrlNumber);
- }
-
- #[test]
- #[cfg(feature = "std")]
- fn other_error_equality() {
- let other_error = OtherError(Arc::from(Box::from("")));
- assert_ne!(other_error, other_error);
- let other: Error = other_error.into();
- assert_ne!(other, other);
- }
-
- #[test]
- fn smoke() {
- use crate::enums::{AlertDescription, ContentType, HandshakeType};
-
- let all = vec![
- Error::InappropriateMessage {
- expect_types: vec![ContentType::Alert],
- got_type: ContentType::Handshake,
- },
- Error::InappropriateHandshakeMessage {
- expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
- got_type: HandshakeType::ServerHello,
- },
- Error::InvalidMessage(InvalidMessage::InvalidCcs),
- Error::NoCertificatesPresented,
- Error::DecryptError,
- super::PeerIncompatible::Tls12NotOffered.into(),
- super::PeerMisbehaved::UnsolicitedCertExtension.into(),
- Error::AlertReceived(AlertDescription::ExportRestriction),
- super::CertificateError::Expired.into(),
- super::CertificateError::NotValidForNameContext {
- expected: ServerName::try_from("example.com")
- .unwrap()
- .to_owned(),
- presented: vec![],
- }
- .into(),
- super::CertificateError::NotValidForNameContext {
- expected: ServerName::try_from("example.com")
- .unwrap()
- .to_owned(),
- presented: vec!["DnsName(\"hello.com\")".into()],
- }
- .into(),
- super::CertificateError::NotValidForNameContext {
- expected: ServerName::try_from("example.com")
- .unwrap()
- .to_owned(),
- presented: vec![
- "DnsName(\"hello.com\")".into(),
- "DnsName(\"goodbye.com\")".into(),
- ],
- }
- .into(),
- super::CertificateError::NotValidYetContext {
- time: UnixTime::since_unix_epoch(Duration::from_secs(300)),
- not_before: UnixTime::since_unix_epoch(Duration::from_secs(320)),
- }
- .into(),
- super::CertificateError::ExpiredContext {
- time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
- not_after: UnixTime::since_unix_epoch(Duration::from_secs(300)),
- }
- .into(),
- super::CertificateError::ExpiredRevocationListContext {
- time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
- next_update: UnixTime::since_unix_epoch(Duration::from_secs(300)),
- }
- .into(),
- super::CertificateError::InvalidOcspResponse.into(),
- Error::General("undocumented error".to_string()),
- Error::FailedToGetCurrentTime,
- Error::FailedToGetRandomBytes,
- Error::HandshakeNotComplete,
- Error::PeerSentOversizedRecord,
- Error::NoApplicationProtocol,
- Error::BadMaxFragmentSize,
- Error::InconsistentKeys(InconsistentKeys::KeyMismatch),
- Error::InconsistentKeys(InconsistentKeys::Unknown),
- Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
- Error::Other(OtherError(
- #[cfg(feature = "std")]
- Arc::from(Box::from("")),
- )),
- ];
-
- for err in all {
- println!("{err:?}:");
- println!(" fmt '{err}'");
- }
- }
-
- #[test]
- fn rand_error_mapping() {
- use super::rand;
- let err: Error = rand::GetRandomFailed.into();
- assert_eq!(err, Error::FailedToGetRandomBytes);
- }
-
- #[cfg(feature = "std")]
- #[test]
- fn time_error_mapping() {
- use std::time::SystemTime;
-
- let time_error = SystemTime::UNIX_EPOCH
- .duration_since(SystemTime::now())
- .unwrap_err();
- let err: Error = time_error.into();
- assert_eq!(err, Error::FailedToGetCurrentTime);
- }
-}
diff --git a/vendor/rustls/src/hash_hs.rs b/vendor/rustls/src/hash_hs.rs
deleted file mode 100644
index 8b4edc68..00000000
--- a/vendor/rustls/src/hash_hs.rs
+++ /dev/null
@@ -1,347 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec::Vec;
-use core::mem;
-
-use crate::crypto::hash;
-use crate::msgs::codec::Codec;
-use crate::msgs::enums::HashAlgorithm;
-use crate::msgs::handshake::HandshakeMessagePayload;
-use crate::msgs::message::{Message, MessagePayload};
-
-/// Early stage buffering of handshake payloads.
-///
-/// Before we know the hash algorithm to use to verify the handshake, we just buffer the messages.
-/// During the handshake, we may restart the transcript due to a HelloRetryRequest, reverting
-/// from the `HandshakeHash` to a `HandshakeHashBuffer` again.
-#[derive(Clone)]
-pub(crate) struct HandshakeHashBuffer {
- buffer: Vec<u8>,
- client_auth_enabled: bool,
-}
-
-impl HandshakeHashBuffer {
- pub(crate) fn new() -> Self {
- Self {
- buffer: Vec::new(),
- client_auth_enabled: false,
- }
- }
-
- /// We might be doing client auth, so need to keep a full
- /// log of the handshake.
- pub(crate) fn set_client_auth_enabled(&mut self) {
- self.client_auth_enabled = true;
- }
-
- /// Hash/buffer a handshake message.
- pub(crate) fn add_message(&mut self, m: &Message<'_>) {
- match &m.payload {
- MessagePayload::Handshake { encoded, .. } => self.add_raw(encoded.bytes()),
- MessagePayload::HandshakeFlight(payload) => self.add_raw(payload.bytes()),
- _ => {}
- };
- }
-
- /// Hash or buffer a byte slice.
- fn add_raw(&mut self, buf: &[u8]) {
- self.buffer.extend_from_slice(buf);
- }
-
- /// Get the hash value if we were to hash `extra` too.
- pub(crate) fn hash_given(
- &self,
- provider: &'static dyn hash::Hash,
- extra: &[u8],
- ) -> hash::Output {
- let mut ctx = provider.start();
- ctx.update(&self.buffer);
- ctx.update(extra);
- ctx.finish()
- }
-
- /// We now know what hash function the verify_data will use.
- pub(crate) fn start_hash(self, provider: &'static dyn hash::Hash) -> HandshakeHash {
- let mut ctx = provider.start();
- ctx.update(&self.buffer);
- HandshakeHash {
- provider,
- ctx,
- client_auth: match self.client_auth_enabled {
- true => Some(self.buffer),
- false => None,
- },
- }
- }
-}
-
-/// This deals with keeping a running hash of the handshake
-/// payloads. This is computed by buffering initially. Once
-/// we know what hash function we need to use we switch to
-/// incremental hashing.
-///
-/// For client auth, we also need to buffer all the messages.
-/// This is disabled in cases where client auth is not possible.
-pub(crate) struct HandshakeHash {
- provider: &'static dyn hash::Hash,
- ctx: Box<dyn hash::Context>,
-
- /// buffer for client-auth.
- client_auth: Option<Vec<u8>>,
-}
-
-impl HandshakeHash {
- /// We decided not to do client auth after all, so discard
- /// the transcript.
- pub(crate) fn abandon_client_auth(&mut self) {
- self.client_auth = None;
- }
-
- /// Hash/buffer a handshake message.
- pub(crate) fn add_message(&mut self, m: &Message<'_>) -> &mut Self {
- match &m.payload {
- MessagePayload::Handshake { encoded, .. } => self.add_raw(encoded.bytes()),
- MessagePayload::HandshakeFlight(payload) => self.add_raw(payload.bytes()),
- _ => self,
- }
- }
-
- /// Hash/buffer an encoded handshake message.
- pub(crate) fn add(&mut self, bytes: &[u8]) {
- self.add_raw(bytes);
- }
-
- /// Hash or buffer a byte slice.
- fn add_raw(&mut self, buf: &[u8]) -> &mut Self {
- self.ctx.update(buf);
-
- if let Some(buffer) = &mut self.client_auth {
- buffer.extend_from_slice(buf);
- }
-
- self
- }
-
- /// Get the hash value if we were to hash `extra` too,
- /// using hash function `hash`.
- pub(crate) fn hash_given(&self, extra: &[u8]) -> hash::Output {
- let mut ctx = self.ctx.fork();
- ctx.update(extra);
- ctx.finish()
- }
-
- pub(crate) fn into_hrr_buffer(self) -> HandshakeHashBuffer {
- let old_hash = self.ctx.finish();
- let old_handshake_hash_msg =
- HandshakeMessagePayload::build_handshake_hash(old_hash.as_ref());
-
- HandshakeHashBuffer {
- client_auth_enabled: self.client_auth.is_some(),
- buffer: old_handshake_hash_msg.get_encoding(),
- }
- }
-
- /// Take the current hash value, and encapsulate it in a
- /// 'handshake_hash' handshake message. Start this hash
- /// again, with that message at the front.
- pub(crate) fn rollup_for_hrr(&mut self) {
- let ctx = &mut self.ctx;
-
- let old_ctx = mem::replace(ctx, self.provider.start());
- let old_hash = old_ctx.finish();
- let old_handshake_hash_msg =
- HandshakeMessagePayload::build_handshake_hash(old_hash.as_ref());
-
- self.add_raw(&old_handshake_hash_msg.get_encoding());
- }
-
- /// Get the current hash value.
- pub(crate) fn current_hash(&self) -> hash::Output {
- self.ctx.fork_finish()
- }
-
- /// Takes this object's buffer containing all handshake messages
- /// so far. This method only works once; it resets the buffer
- /// to empty.
- #[cfg(feature = "tls12")]
- pub(crate) fn take_handshake_buf(&mut self) -> Option<Vec<u8>> {
- self.client_auth.take()
- }
-
- /// The hashing algorithm
- pub(crate) fn algorithm(&self) -> HashAlgorithm {
- self.provider.algorithm()
- }
-}
-
-impl Clone for HandshakeHash {
- fn clone(&self) -> Self {
- Self {
- provider: self.provider,
- ctx: self.ctx.fork(),
- client_auth: self.client_auth.clone(),
- }
- }
-}
-
-#[cfg(test)]
-#[macro_rules_attribute::apply(test_for_each_provider)]
-mod tests {
- use super::provider::hash::SHA256;
- use super::*;
- use crate::crypto::hash::Hash;
- use crate::enums::ProtocolVersion;
- use crate::msgs::base::Payload;
- use crate::msgs::handshake::{HandshakeMessagePayload, HandshakePayload};
-
- #[test]
- fn hashes_correctly() {
- let mut hhb = HandshakeHashBuffer::new();
- hhb.add_raw(b"hello");
- assert_eq!(hhb.buffer.len(), 5);
- let mut hh = hhb.start_hash(&SHA256);
- assert!(hh.client_auth.is_none());
- hh.add_raw(b"world");
- let h = hh.current_hash();
- let h = h.as_ref();
- assert_eq!(h[0], 0x93);
- assert_eq!(h[1], 0x6a);
- assert_eq!(h[2], 0x18);
- assert_eq!(h[3], 0x5c);
- }
-
- #[test]
- fn hashes_message_types() {
- // handshake protocol encoding of 0x0e 00 00 00
- let server_hello_done_message = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::ServerHelloDone,
- )),
- };
-
- let app_data_ignored = Message {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::ApplicationData(Payload::Borrowed(b"hello")),
- };
-
- let end_of_early_data_flight = Message {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::HandshakeFlight(Payload::Borrowed(b"\x05\x00\x00\x00")),
- };
-
- // buffered mode
- let mut hhb = HandshakeHashBuffer::new();
- hhb.add_message(&server_hello_done_message);
- hhb.add_message(&app_data_ignored);
- hhb.add_message(&end_of_early_data_flight);
- assert_eq!(
- hhb.start_hash(&SHA256)
- .current_hash()
- .as_ref(),
- SHA256
- .hash(b"\x0e\x00\x00\x00\x05\x00\x00\x00")
- .as_ref()
- );
-
- // non-buffered mode
- let mut hh = HandshakeHashBuffer::new().start_hash(&SHA256);
- hh.add_message(&server_hello_done_message);
- hh.add_message(&app_data_ignored);
- hh.add_message(&end_of_early_data_flight);
- assert_eq!(
- hh.current_hash().as_ref(),
- SHA256
- .hash(b"\x0e\x00\x00\x00\x05\x00\x00\x00")
- .as_ref()
- );
- }
-
- #[cfg(feature = "tls12")]
- #[test]
- fn buffers_correctly() {
- let mut hhb = HandshakeHashBuffer::new();
- hhb.set_client_auth_enabled();
- hhb.add_raw(b"hello");
- assert_eq!(hhb.buffer.len(), 5);
- let mut hh = hhb.start_hash(&SHA256);
- assert_eq!(
- hh.client_auth
- .as_ref()
- .map(|buf| buf.len()),
- Some(5)
- );
- hh.add_raw(b"world");
- assert_eq!(
- hh.client_auth
- .as_ref()
- .map(|buf| buf.len()),
- Some(10)
- );
- let h = hh.current_hash();
- let h = h.as_ref();
- assert_eq!(h[0], 0x93);
- assert_eq!(h[1], 0x6a);
- assert_eq!(h[2], 0x18);
- assert_eq!(h[3], 0x5c);
- let buf = hh.take_handshake_buf();
- assert_eq!(Some(b"helloworld".to_vec()), buf);
- }
-
- #[test]
- fn abandon() {
- let mut hhb = HandshakeHashBuffer::new();
- hhb.set_client_auth_enabled();
- hhb.add_raw(b"hello");
- assert_eq!(hhb.buffer.len(), 5);
- let mut hh = hhb.start_hash(&SHA256);
- assert_eq!(
- hh.client_auth
- .as_ref()
- .map(|buf| buf.len()),
- Some(5)
- );
- hh.abandon_client_auth();
- assert_eq!(hh.client_auth, None);
- hh.add_raw(b"world");
- assert_eq!(hh.client_auth, None);
- let h = hh.current_hash();
- let h = h.as_ref();
- assert_eq!(h[0], 0x93);
- assert_eq!(h[1], 0x6a);
- assert_eq!(h[2], 0x18);
- assert_eq!(h[3], 0x5c);
- }
-
- #[test]
- fn clones_correctly() {
- let mut hhb = HandshakeHashBuffer::new();
- hhb.set_client_auth_enabled();
- hhb.add_raw(b"hello");
- assert_eq!(hhb.buffer.len(), 5);
-
- // Cloning the HHB should result in the same buffer and client auth state.
- let mut hhb_prime = hhb.clone();
- assert_eq!(hhb_prime.buffer, hhb.buffer);
- assert!(hhb_prime.client_auth_enabled);
-
- // Updating the HHB clone shouldn't affect the original.
- hhb_prime.add_raw(b"world");
- assert_eq!(hhb_prime.buffer.len(), 10);
- assert_ne!(hhb.buffer, hhb_prime.buffer);
-
- let hh = hhb.start_hash(&SHA256);
- let hh_hash = hh.current_hash();
- let hh_hash = hh_hash.as_ref();
-
- // Cloning the HH should result in the same current hash.
- let mut hh_prime = hh.clone();
- let hh_prime_hash = hh_prime.current_hash();
- let hh_prime_hash = hh_prime_hash.as_ref();
- assert_eq!(hh_hash, hh_prime_hash);
-
- // Updating the HH clone shouldn't affect the original.
- hh_prime.add_raw(b"goodbye");
- assert_eq!(hh.current_hash().as_ref(), hh_hash);
- assert_ne!(hh_prime.current_hash().as_ref(), hh_hash);
- }
-}
diff --git a/vendor/rustls/src/key_log.rs b/vendor/rustls/src/key_log.rs
deleted file mode 100644
index 0ffcccfe..00000000
--- a/vendor/rustls/src/key_log.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-use core::fmt::Debug;
-
-#[cfg(all(doc, feature = "std"))]
-use crate::KeyLogFile;
-
-/// This trait represents the ability to do something useful
-/// with key material, such as logging it to a file for debugging.
-///
-/// Naturally, secrets passed over the interface are *extremely*
-/// sensitive and can break the security of past, present and
-/// future sessions.
-///
-/// You'll likely want some interior mutability in your
-/// implementation to make this useful.
-///
-/// See [`KeyLogFile`] that implements the standard
-/// `SSLKEYLOGFILE` environment variable behaviour.
-pub trait KeyLog: Debug + Send + Sync {
- /// Log the given `secret`. `client_random` is provided for
- /// session identification. `label` describes precisely what
- /// `secret` means:
- ///
- /// - `CLIENT_RANDOM`: `secret` is the master secret for a TLSv1.2 session.
- /// - `CLIENT_EARLY_TRAFFIC_SECRET`: `secret` encrypts early data
- /// transmitted by a client
- /// - `SERVER_HANDSHAKE_TRAFFIC_SECRET`: `secret` encrypts
- /// handshake messages from the server during a TLSv1.3 handshake.
- /// - `CLIENT_HANDSHAKE_TRAFFIC_SECRET`: `secret` encrypts
- /// handshake messages from the client during a TLSv1.3 handshake.
- /// - `SERVER_TRAFFIC_SECRET_0`: `secret` encrypts post-handshake data
- /// from the server in a TLSv1.3 session.
- /// - `CLIENT_TRAFFIC_SECRET_0`: `secret` encrypts post-handshake data
- /// from the client in a TLSv1.3 session.
- /// - `EXPORTER_SECRET`: `secret` is the post-handshake exporter secret
- /// in a TLSv1.3 session.
- ///
- /// These strings are selected to match the NSS key log format:
- /// <https://nss-crypto.org/reference/security/nss/legacy/key_log_format/index.html>
- fn log(&self, label: &str, client_random: &[u8], secret: &[u8]);
-
- /// Indicates whether the secret with label `label` will be logged.
- ///
- /// If `will_log` returns true then `log` will be called with the secret.
- /// Otherwise, `log` will not be called for the secret. This is a
- /// performance optimization.
- fn will_log(&self, _label: &str) -> bool {
- true
- }
-}
-
-/// KeyLog that does exactly nothing.
-#[derive(Debug)]
-pub struct NoKeyLog;
-
-impl KeyLog for NoKeyLog {
- fn log(&self, _: &str, _: &[u8], _: &[u8]) {}
- #[inline]
- fn will_log(&self, _label: &str) -> bool {
- false
- }
-}
diff --git a/vendor/rustls/src/key_log_file.rs b/vendor/rustls/src/key_log_file.rs
deleted file mode 100644
index 45f29da5..00000000
--- a/vendor/rustls/src/key_log_file.rs
+++ /dev/null
@@ -1,162 +0,0 @@
-use alloc::vec::Vec;
-use core::fmt::{Debug, Formatter};
-use std::env::var_os;
-use std::ffi::OsString;
-use std::fs::{File, OpenOptions};
-use std::io;
-use std::io::Write;
-use std::sync::Mutex;
-
-use crate::KeyLog;
-use crate::log::warn;
-
-// Internal mutable state for KeyLogFile
-struct KeyLogFileInner {
- file: Option<File>,
- buf: Vec<u8>,
-}
-
-impl KeyLogFileInner {
- fn new(var: Option<OsString>) -> Self {
- let Some(path) = &var else {
- return Self {
- file: None,
- buf: Vec::new(),
- };
- };
-
- #[cfg_attr(not(feature = "logging"), allow(unused_variables))]
- let file = match OpenOptions::new()
- .append(true)
- .create(true)
- .open(path)
- {
- Ok(f) => Some(f),
- Err(e) => {
- warn!("unable to create key log file {path:?}: {e}");
- None
- }
- };
-
- Self {
- file,
- buf: Vec::new(),
- }
- }
-
- fn try_write(&mut self, label: &str, client_random: &[u8], secret: &[u8]) -> io::Result<()> {
- let Some(file) = &mut self.file else {
- return Ok(());
- };
-
- self.buf.truncate(0);
- write!(self.buf, "{label} ")?;
- for b in client_random.iter() {
- write!(self.buf, "{b:02x}")?;
- }
- write!(self.buf, " ")?;
- for b in secret.iter() {
- write!(self.buf, "{b:02x}")?;
- }
- writeln!(self.buf)?;
- file.write_all(&self.buf)
- }
-}
-
-impl Debug for KeyLogFileInner {
- fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
- f.debug_struct("KeyLogFileInner")
- // Note: we omit self.buf deliberately as it may contain key data.
- .field("file", &self.file)
- .finish()
- }
-}
-
-/// [`KeyLog`] implementation that opens a file whose name is
-/// given by the `SSLKEYLOGFILE` environment variable, and writes
-/// keys into it.
-///
-/// If `SSLKEYLOGFILE` is not set, this does nothing.
-///
-/// If such a file cannot be opened, or cannot be written then
-/// this does nothing but logs errors at warning-level.
-pub struct KeyLogFile(Mutex<KeyLogFileInner>);
-
-impl KeyLogFile {
- /// Makes a new `KeyLogFile`. The environment variable is
- /// inspected and the named file is opened during this call.
- pub fn new() -> Self {
- let var = var_os("SSLKEYLOGFILE");
- Self(Mutex::new(KeyLogFileInner::new(var)))
- }
-}
-
-impl KeyLog for KeyLogFile {
- fn log(&self, label: &str, client_random: &[u8], secret: &[u8]) {
- #[cfg_attr(not(feature = "logging"), allow(unused_variables))]
- match self
- .0
- .lock()
- .unwrap()
- .try_write(label, client_random, secret)
- {
- Ok(()) => {}
- Err(e) => {
- warn!("error writing to key log file: {e}");
- }
- }
- }
-}
-
-impl Debug for KeyLogFile {
- fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
- match self.0.try_lock() {
- Ok(key_log_file) => write!(f, "{key_log_file:?}"),
- Err(_) => write!(f, "KeyLogFile {{ <locked> }}"),
- }
- }
-}
-
-#[cfg(all(test, target_os = "linux"))]
-mod tests {
- use super::*;
-
- fn init() {
- let _ = env_logger::builder()
- .is_test(true)
- .try_init();
- }
-
- #[test]
- fn test_env_var_is_not_set() {
- init();
- let mut inner = KeyLogFileInner::new(None);
- assert!(
- inner
- .try_write("label", b"random", b"secret")
- .is_ok()
- );
- }
-
- #[test]
- fn test_env_var_cannot_be_opened() {
- init();
- let mut inner = KeyLogFileInner::new(Some("/dev/does-not-exist".into()));
- assert!(
- inner
- .try_write("label", b"random", b"secret")
- .is_ok()
- );
- }
-
- #[test]
- fn test_env_var_cannot_be_written() {
- init();
- let mut inner = KeyLogFileInner::new(Some("/dev/full".into()));
- assert!(
- inner
- .try_write("label", b"random", b"secret")
- .is_err()
- );
- }
-}
diff --git a/vendor/rustls/src/lib.rs b/vendor/rustls/src/lib.rs
deleted file mode 100644
index 845f4e94..00000000
--- a/vendor/rustls/src/lib.rs
+++ /dev/null
@@ -1,715 +0,0 @@
-//! # Rustls - a modern TLS library
-//!
-//! Rustls is a TLS library that aims to provide a good level of cryptographic security,
-//! requires no configuration to achieve that security, and provides no unsafe features or
-//! obsolete cryptography by default.
-//!
-//! Rustls implements TLS1.2 and TLS1.3 for both clients and servers. See [the full
-//! list of protocol features](manual::_04_features).
-//!
-//! ### Platform support
-//!
-//! While Rustls itself is platform independent, by default it uses [`aws-lc-rs`] for implementing
-//! the cryptography in TLS. See [the aws-lc-rs FAQ][aws-lc-rs-platforms-faq] for more details of the
-//! platform/architecture support constraints in aws-lc-rs.
-//!
-//! [`ring`] is also available via the `ring` crate feature: see
-//! [the supported `ring` target platforms][ring-target-platforms].
-//!
-//! By providing a custom instance of the [`crypto::CryptoProvider`] struct, you
-//! can replace all cryptography dependencies of rustls. This is a route to being portable
-//! to a wider set of architectures and environments, or compliance requirements. See the
-//! [`crypto::CryptoProvider`] documentation for more details.
-//!
-//! Specifying `default-features = false` when depending on rustls will remove the implicit
-//! dependency on aws-lc-rs.
-//!
-//! Rustls requires Rust 1.71 or later. It has an optional dependency on zlib-rs which requires 1.75 or later.
-//!
-//! [ring-target-platforms]: https://github.com/briansmith/ring/blob/2e8363b433fa3b3962c877d9ed2e9145612f3160/include/ring-core/target.h#L18-L64
-//! [`crypto::CryptoProvider`]: crate::crypto::CryptoProvider
-//! [`ring`]: https://crates.io/crates/ring
-//! [aws-lc-rs-platforms-faq]: https://aws.github.io/aws-lc-rs/faq.html#can-i-run-aws-lc-rs-on-x-platform-or-architecture
-//! [`aws-lc-rs`]: https://crates.io/crates/aws-lc-rs
-//!
-//! ### Cryptography providers
-//!
-//! Since Rustls 0.22 it has been possible to choose the provider of the cryptographic primitives
-//! that Rustls uses. This may be appealing if you have specific platform, compliance or feature
-//! requirements that aren't met by the default provider, [`aws-lc-rs`].
-//!
-//! Users that wish to customize the provider in use can do so when constructing `ClientConfig`
-//! and `ServerConfig` instances using the `with_crypto_provider` method on the respective config
-//! builder types. See the [`crypto::CryptoProvider`] documentation for more details.
-//!
-//! #### Built-in providers
-//!
-//! Rustls ships with two built-in providers controlled by associated crate features:
-//!
-//! * [`aws-lc-rs`] - enabled by default, available with the `aws_lc_rs` crate feature enabled.
-//! * [`ring`] - available with the `ring` crate feature enabled.
-//!
-//! See the documentation for [`crypto::CryptoProvider`] for details on how providers are
-//! selected.
-//!
-//! #### Third-party providers
-//!
-//! The community has also started developing third-party providers for Rustls:
-//!
-//! * [`boring-rustls-provider`] - a work-in-progress provider that uses [`boringssl`] for
-//! cryptography.
-//! * [`rustls-graviola`] - a provider that uses [`graviola`] for cryptography.
-//! * [`rustls-mbedtls-provider`] - a provider that uses [`mbedtls`] for cryptography.
-//! * [`rustls-openssl`] - a provider that uses [OpenSSL] for cryptography.
-//! * [`rustls-rustcrypto`] - an experimental provider that uses the crypto primitives
-//! from [`RustCrypto`] for cryptography.
-//! * [`rustls-symcrypt`] - a provider that uses Microsoft's [SymCrypt] library.
-//! * [`rustls-wolfcrypt-provider`] - a work-in-progress provider that uses [`wolfCrypt`] for cryptography.
-//!
-//! [`rustls-graviola`]: https://crates.io/crates/rustls-graviola
-//! [`graviola`]: https://github.com/ctz/graviola
-//! [`rustls-mbedtls-provider`]: https://github.com/fortanix/rustls-mbedtls-provider
-//! [`mbedtls`]: https://github.com/Mbed-TLS/mbedtls
-//! [`rustls-openssl`]: https://github.com/tofay/rustls-openssl
-//! [OpenSSL]: https://openssl-library.org/
-//! [`rustls-symcrypt`]: https://github.com/microsoft/rustls-symcrypt
-//! [SymCrypt]: https://github.com/microsoft/SymCrypt
-//! [`boring-rustls-provider`]: https://github.com/janrueth/boring-rustls-provider
-//! [`boringssl`]: https://github.com/google/boringssl
-//! [`rustls-rustcrypto`]: https://github.com/RustCrypto/rustls-rustcrypto
-//! [`RustCrypto`]: https://github.com/RustCrypto
-//! [`rustls-wolfcrypt-provider`]: https://github.com/wolfSSL/rustls-wolfcrypt-provider
-//! [`wolfCrypt`]: https://www.wolfssl.com/products/wolfcrypt
-//!
-//! #### Custom provider
-//!
-//! We also provide a simple example of writing your own provider in the [custom provider example].
-//! This example implements a minimal provider using parts of the [`RustCrypto`] ecosystem.
-//!
-//! See the [Making a custom CryptoProvider] section of the documentation for more information
-//! on this topic.
-//!
-//! [custom provider example]: https://github.com/rustls/rustls/tree/main/provider-example/
-//! [`RustCrypto`]: https://github.com/RustCrypto
-//! [Making a custom CryptoProvider]: https://docs.rs/rustls/latest/rustls/crypto/struct.CryptoProvider.html#making-a-custom-cryptoprovider
-//!
-//! ## Design overview
-//!
-//! Rustls is a low-level library. If your goal is to make HTTPS connections you may prefer
-//! to use a library built on top of Rustls like [hyper] or [ureq].
-//!
-//! [hyper]: https://crates.io/crates/hyper
-//! [ureq]: https://crates.io/crates/ureq
-//!
-//! ### Rustls does not take care of network IO
-//! It doesn't make or accept TCP connections, or do DNS, or read or write files.
-//!
-//! Our [examples] directory contains demos that show how to handle I/O using the
-//! [`stream::Stream`] helper, as well as more complex asynchronous I/O using [`mio`].
-//! If you're already using Tokio for an async runtime you may prefer to use [`tokio-rustls`] instead
-//! of interacting with rustls directly.
-//!
-//! [examples]: https://github.com/rustls/rustls/tree/main/examples
-//! [`tokio-rustls`]: https://github.com/rustls/tokio-rustls
-//!
-//! ### Rustls provides encrypted pipes
-//! These are the [`ServerConnection`] and [`ClientConnection`] types. You supply raw TLS traffic
-//! on the left (via the [`read_tls()`] and [`write_tls()`] methods) and then read/write the
-//! plaintext on the right:
-//!
-//! [`read_tls()`]: Connection::read_tls
-//! [`write_tls()`]: Connection::read_tls
-//!
-//! ```text
-//! TLS Plaintext
-//! === =========
-//! read_tls() +-----------------------+ reader() as io::Read
-//! | |
-//! +---------> ClientConnection +--------->
-//! | or |
-//! <---------+ ServerConnection <---------+
-//! | |
-//! write_tls() +-----------------------+ writer() as io::Write
-//! ```
-//!
-//! ### Rustls takes care of server certificate verification
-//! You do not need to provide anything other than a set of root certificates to trust.
-//! Certificate verification cannot be turned off or disabled in the main API.
-//!
-//! ## Getting started
-//! This is the minimum you need to do to make a TLS client connection.
-//!
-//! First we load some root certificates. These are used to authenticate the server.
-//! The simplest way is to depend on the [`webpki_roots`] crate which contains
-//! the Mozilla set of root certificates.
-//!
-//! ```rust,no_run
-//! # #[cfg(feature = "aws-lc-rs")] {
-//! let root_store = rustls::RootCertStore::from_iter(
-//! webpki_roots::TLS_SERVER_ROOTS
-//! .iter()
-//! .cloned(),
-//! );
-//! # }
-//! ```
-//!
-//! [`webpki_roots`]: https://crates.io/crates/webpki-roots
-//!
-//! Next, we make a `ClientConfig`. You're likely to make one of these per process,
-//! and use it for all connections made by that process.
-//!
-//! ```rust,no_run
-//! # #[cfg(feature = "aws_lc_rs")] {
-//! # let root_store: rustls::RootCertStore = panic!();
-//! let config = rustls::ClientConfig::builder()
-//! .with_root_certificates(root_store)
-//! .with_no_client_auth();
-//! # }
-//! ```
-//!
-//! Now we can make a connection. You need to provide the server's hostname so we
-//! know what to expect to find in the server's certificate.
-//!
-//! ```rust
-//! # #[cfg(feature = "aws_lc_rs")] {
-//! # use rustls;
-//! # use webpki;
-//! # use std::sync::Arc;
-//! # rustls::crypto::aws_lc_rs::default_provider().install_default();
-//! # let root_store = rustls::RootCertStore::from_iter(
-//! # webpki_roots::TLS_SERVER_ROOTS
-//! # .iter()
-//! # .cloned(),
-//! # );
-//! # let config = rustls::ClientConfig::builder()
-//! # .with_root_certificates(root_store)
-//! # .with_no_client_auth();
-//! let rc_config = Arc::new(config);
-//! let example_com = "example.com".try_into().unwrap();
-//! let mut client = rustls::ClientConnection::new(rc_config, example_com);
-//! # }
-//! ```
-//!
-//! Now you should do appropriate IO for the `client` object. If `client.wants_read()` yields
-//! true, you should call `client.read_tls()` when the underlying connection has data.
-//! Likewise, if `client.wants_write()` yields true, you should call `client.write_tls()`
-//! when the underlying connection is able to send data. You should continue doing this
-//! as long as the connection is valid.
-//!
-//! The return types of `read_tls()` and `write_tls()` only tell you if the IO worked. No
-//! parsing or processing of the TLS messages is done. After each `read_tls()` you should
-//! therefore call `client.process_new_packets()` which parses and processes the messages.
-//! Any error returned from `process_new_packets` is fatal to the connection, and will tell you
-//! why. For example, if the server's certificate is expired `process_new_packets` will
-//! return `Err(InvalidCertificate(Expired))`. From this point on,
-//! `process_new_packets` will not do any new work and will return that error continually.
-//!
-//! You can extract newly received data by calling `client.reader()` (which implements the
-//! `io::Read` trait). You can send data to the peer by calling `client.writer()` (which
-//! implements `io::Write` trait). Note that `client.writer().write()` buffers data you
-//! send if the TLS connection is not yet established: this is useful for writing (say) a
-//! HTTP request, but this is buffered so avoid large amounts of data.
-//!
-//! The following code uses a fictional socket IO API for illustration, and does not handle
-//! errors.
-//!
-//! ```rust,no_run
-//! # #[cfg(feature = "aws_lc_rs")] {
-//! # let mut client = rustls::ClientConnection::new(panic!(), panic!()).unwrap();
-//! # struct Socket { }
-//! # impl Socket {
-//! # fn ready_for_write(&self) -> bool { false }
-//! # fn ready_for_read(&self) -> bool { false }
-//! # fn wait_for_something_to_happen(&self) { }
-//! # }
-//! #
-//! # use std::io::{Read, Write, Result};
-//! # impl Read for Socket {
-//! # fn read(&mut self, buf: &mut [u8]) -> Result<usize> { panic!() }
-//! # }
-//! # impl Write for Socket {
-//! # fn write(&mut self, buf: &[u8]) -> Result<usize> { panic!() }
-//! # fn flush(&mut self) -> Result<()> { panic!() }
-//! # }
-//! #
-//! # fn connect(_address: &str, _port: u16) -> Socket {
-//! # panic!();
-//! # }
-//! use std::io;
-//! use rustls::Connection;
-//!
-//! client.writer().write(b"GET / HTTP/1.0\r\n\r\n").unwrap();
-//! let mut socket = connect("example.com", 443);
-//! loop {
-//! if client.wants_read() && socket.ready_for_read() {
-//! client.read_tls(&mut socket).unwrap();
-//! client.process_new_packets().unwrap();
-//!
-//! let mut plaintext = Vec::new();
-//! client.reader().read_to_end(&mut plaintext).unwrap();
-//! io::stdout().write(&plaintext).unwrap();
-//! }
-//!
-//! if client.wants_write() && socket.ready_for_write() {
-//! client.write_tls(&mut socket).unwrap();
-//! }
-//!
-//! socket.wait_for_something_to_happen();
-//! }
-//! # }
-//! ```
-//!
-//! # Examples
-//!
-//! You can find several client and server examples of varying complexity in the [examples]
-//! directory, including [`tlsserver-mio`](https://github.com/rustls/rustls/blob/main/examples/src/bin/tlsserver-mio.rs)
-//! and [`tlsclient-mio`](https://github.com/rustls/rustls/blob/main/examples/src/bin/tlsclient-mio.rs)
-//! \- full worked examples using [`mio`].
-//!
-//! [`mio`]: https://docs.rs/mio/latest/mio/
-//!
-//! # Manual
-//!
-//! The [rustls manual](crate::manual) explains design decisions and includes how-to guidance.
-//!
-//! # Crate features
-//! Here's a list of what features are exposed by the rustls crate and what
-//! they mean.
-//!
-//! - `std` (enabled by default): enable the high-level (buffered) Connection API and other functionality
-//! which relies on the `std` library.
-//!
-//! - `aws_lc_rs` (enabled by default): makes the rustls crate depend on the [`aws-lc-rs`] crate.
-//! Use `rustls::crypto::aws_lc_rs::default_provider().install_default()` to
-//! use it as the default `CryptoProvider`, or provide it explicitly
-//! when making a `ClientConfig` or `ServerConfig`.
-//!
-//! Note that aws-lc-rs has additional build-time dependencies like cmake.
-//! See [the documentation](https://aws.github.io/aws-lc-rs/requirements/index.html) for details.
-//!
-//! - `ring`: makes the rustls crate depend on the *ring* crate for cryptography.
-//! Use `rustls::crypto::ring::default_provider().install_default()` to
-//! use it as the default `CryptoProvider`, or provide it explicitly
-//! when making a `ClientConfig` or `ServerConfig`.
-//!
-//! - `fips`: enable support for FIPS140-3-approved cryptography, via the [`aws-lc-rs`] crate.
-//! This feature enables the `aws_lc_rs` crate feature, which makes the rustls crate depend
-//! on [aws-lc-rs](https://github.com/aws/aws-lc-rs). It also changes the default
-//! for [`ServerConfig::require_ems`] and [`ClientConfig::require_ems`].
-//!
-//! See [manual::_06_fips] for more details.
-//!
-//! - `prefer-post-quantum` (enabled by default): for the [`aws-lc-rs`]-backed provider,
-//! prioritizes post-quantum secure key exchange by default (using X25519MLKEM768).
-//! This feature merely alters the order of `rustls::crypto::aws_lc_rs::DEFAULT_KX_GROUPS`.
-//! See [the manual][x25519mlkem768-manual] for more details.
-//!
-//! - `custom-provider`: disables implicit use of built-in providers (`aws-lc-rs` or `ring`). This forces
-//! applications to manually install one, for instance, when using a custom `CryptoProvider`.
-//!
-//! - `tls12` (enabled by default): enable support for TLS version 1.2. Note that, due to the
-//! additive nature of Cargo features and because it is enabled by default, other crates
-//! in your dependency graph could re-enable it for your application. If you want to disable
-//! TLS 1.2 for security reasons, consider explicitly enabling TLS 1.3 only in the config
-//! builder API.
-//!
-//! - `logging` (enabled by default): make the rustls crate depend on the `log` crate.
-//! rustls outputs interesting protocol-level messages at `trace!` and `debug!` level,
-//! and protocol-level errors at `warn!` and `error!` level. The log messages do not
-//! contain secret key data, and so are safe to archive without affecting session security.
-//!
-//! - `read_buf`: when building with Rust Nightly, adds support for the unstable
-//! `std::io::ReadBuf` and related APIs. This reduces costs from initializing
-//! buffers. Will do nothing on non-Nightly releases.
-//!
-//! - `brotli`: uses the `brotli` crate for RFC8879 certificate compression support.
-//!
-//! - `zlib`: uses the `zlib-rs` crate for RFC8879 certificate compression support.
-//!
-//! [x25519mlkem768-manual]: manual::_05_defaults#about-the-post-quantum-secure-key-exchange-x25519mlkem768
-
-// Require docs for public APIs, deny unsafe code, etc.
-#![forbid(unsafe_code, unused_must_use)]
-#![cfg_attr(not(any(read_buf, bench, coverage_nightly)), forbid(unstable_features))]
-#![warn(
- clippy::alloc_instead_of_core,
- clippy::manual_let_else,
- clippy::std_instead_of_core,
- clippy::use_self,
- clippy::upper_case_acronyms,
- elided_lifetimes_in_paths,
- missing_docs,
- trivial_casts,
- trivial_numeric_casts,
- unreachable_pub,
- unused_import_braces,
- unused_extern_crates,
- unused_qualifications
-)]
-// Relax these clippy lints:
-// - ptr_arg: this triggers on references to type aliases that are Vec
-// underneath.
-// - too_many_arguments: some things just need a lot of state, wrapping it
-// doesn't necessarily make it easier to follow what's going on
-// - new_ret_no_self: we sometimes return `Arc<Self>`, which seems fine
-// - single_component_path_imports: our top-level `use log` import causes
-// a false positive, https://github.com/rust-lang/rust-clippy/issues/5210
-// - new_without_default: for internal constructors, the indirection is not
-// helpful
-#![allow(
- clippy::too_many_arguments,
- clippy::new_ret_no_self,
- clippy::ptr_arg,
- clippy::single_component_path_imports,
- clippy::new_without_default
-)]
-// Enable documentation for all features on docs.rs
-#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
-// Enable coverage() attr for nightly coverage builds, see
-// <https://github.com/rust-lang/rust/issues/84605>
-// (`coverage_nightly` is a cfg set by `cargo-llvm-cov`)
-#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
-// XXX: Because of https://github.com/rust-lang/rust/issues/54726, we cannot
-// write `#![rustversion::attr(nightly, feature(read_buf))]` here. Instead,
-// build.rs set `read_buf` for (only) Rust Nightly to get the same effect.
-//
-// All the other conditional logic in the crate could use
-// `#[rustversion::nightly]` instead of `#[cfg(read_buf)]`; `#[cfg(read_buf)]`
-// is used to avoid needing `rustversion` to be compiled twice during
-// cross-compiling.
-#![cfg_attr(read_buf, feature(read_buf))]
-#![cfg_attr(read_buf, feature(core_io_borrowed_buf))]
-#![cfg_attr(bench, feature(test))]
-#![no_std]
-
-extern crate alloc;
-// This `extern crate` plus the `#![no_std]` attribute changes the default prelude from
-// `std::prelude` to `core::prelude`. That forces one to _explicitly_ import (`use`) everything that
-// is in `std::prelude` but not in `core::prelude`. This helps maintain no-std support as even
-// developers that are not interested in, or aware of, no-std support and / or that never run
-// `cargo build --no-default-features` locally will get errors when they rely on `std::prelude` API.
-#[cfg(any(feature = "std", test))]
-extern crate std;
-
-#[cfg(doc)]
-use crate::crypto::CryptoProvider;
-
-// Import `test` sysroot crate for `Bencher` definitions.
-#[cfg(bench)]
-#[allow(unused_extern_crates)]
-extern crate test;
-
-// log for logging (optional).
-#[cfg(feature = "logging")]
-use log;
-
-#[cfg(not(feature = "logging"))]
-mod log {
- macro_rules! trace ( ($($tt:tt)*) => {{}} );
- macro_rules! debug ( ($($tt:tt)*) => {{}} );
- macro_rules! error ( ($($tt:tt)*) => {{}} );
- macro_rules! _warn ( ($($tt:tt)*) => {{}} );
- pub(crate) use {_warn as warn, debug, error, trace};
-}
-
-#[cfg(test)]
-#[macro_use]
-mod test_macros;
-
-/// This internal `sync` module aliases the `Arc` implementation to allow downstream forks
-/// of rustls targeting architectures without atomic pointers to replace the implementation
-/// with another implementation such as `portable_atomic_util::Arc` in one central location.
-mod sync {
- #[allow(clippy::disallowed_types)]
- pub(crate) type Arc<T> = alloc::sync::Arc<T>;
- #[allow(clippy::disallowed_types)]
- pub(crate) type Weak<T> = alloc::sync::Weak<T>;
-}
-
-#[macro_use]
-mod msgs;
-mod common_state;
-pub mod compress;
-mod conn;
-/// Crypto provider interface.
-pub mod crypto;
-mod error;
-mod hash_hs;
-#[cfg(any(feature = "std", feature = "hashbrown"))]
-mod limited_cache;
-mod rand;
-mod record_layer;
-#[cfg(feature = "std")]
-mod stream;
-#[cfg(feature = "tls12")]
-mod tls12;
-mod tls13;
-mod vecbuf;
-mod verify;
-#[cfg(test)]
-mod verifybench;
-mod x509;
-#[macro_use]
-mod check;
-#[cfg(feature = "logging")]
-mod bs_debug;
-mod builder;
-mod enums;
-mod key_log;
-#[cfg(feature = "std")]
-mod key_log_file;
-mod suites;
-mod versions;
-mod webpki;
-
-/// Internal classes that are used in integration tests.
-/// The contents of this section DO NOT form part of the stable interface.
-#[allow(missing_docs)]
-#[doc(hidden)]
-pub mod internal {
- /// Low-level TLS message parsing and encoding functions.
- pub mod msgs {
- pub mod base {
- pub use crate::msgs::base::{Payload, PayloadU16};
- }
- pub mod codec {
- pub use crate::msgs::codec::{Codec, Reader};
- }
- pub mod enums {
- pub use crate::msgs::enums::{
- AlertLevel, EchVersion, ExtensionType, HpkeAead, HpkeKdf, HpkeKem,
- };
- }
- pub mod fragmenter {
- pub use crate::msgs::fragmenter::MessageFragmenter;
- }
- pub mod handshake {
- pub use crate::msgs::handshake::{
- EchConfigContents, EchConfigPayload, HpkeKeyConfig, HpkeSymmetricCipherSuite,
- };
- }
- pub mod message {
- pub use crate::msgs::message::{
- Message, MessagePayload, OutboundOpaqueMessage, PlainMessage,
- };
- }
- pub mod persist {
- pub use crate::msgs::persist::ServerSessionValue;
- }
- }
-
- pub use crate::tls13::key_schedule::{derive_traffic_iv, derive_traffic_key};
-
- pub mod fuzzing {
- pub use crate::msgs::deframer::fuzz_deframer;
- }
-}
-
-/// Unbuffered connection API
-///
-/// This is an alternative to the [`crate::ConnectionCommon`] API that does not internally buffer
-/// TLS nor plaintext data. Instead those buffers are managed by the API user so they have
-/// control over when and how to allocate, resize and dispose of them.
-///
-/// This API is lower level than the `ConnectionCommon` API and is built around a state machine
-/// interface where the API user must handle each state to advance and complete the
-/// handshake process.
-///
-/// Like the `ConnectionCommon` API, no IO happens internally so all IO must be handled by the API
-/// user. Unlike the `ConnectionCommon` API, this API does not make use of the [`std::io::Read`] and
-/// [`std::io::Write`] traits so it's usable in no-std context.
-///
-/// The entry points into this API are [`crate::client::UnbufferedClientConnection::new`],
-/// [`crate::server::UnbufferedServerConnection::new`] and
-/// [`unbuffered::UnbufferedConnectionCommon::process_tls_records`]. The state machine API is
-/// documented in [`unbuffered::ConnectionState`].
-///
-/// # Examples
-///
-/// [`unbuffered-client`] and [`unbuffered-server`] are examples that fully exercise the API in
-/// std, non-async context.
-///
-/// [`unbuffered-client`]: https://github.com/rustls/rustls/blob/main/examples/src/bin/unbuffered-client.rs
-/// [`unbuffered-server`]: https://github.com/rustls/rustls/blob/main/examples/src/bin/unbuffered-server.rs
-pub mod unbuffered {
- pub use crate::conn::UnbufferedConnectionCommon;
- pub use crate::conn::unbuffered::{
- AppDataRecord, ConnectionState, EncodeError, EncodeTlsData, EncryptError,
- InsufficientSizeError, ReadEarlyData, ReadTraffic, TransmitTlsData, UnbufferedStatus,
- WriteTraffic,
- };
-}
-
-// The public interface is:
-pub use crate::builder::{ConfigBuilder, ConfigSide, WantsVerifier, WantsVersions};
-pub use crate::common_state::{CommonState, HandshakeKind, IoState, Side};
-#[cfg(feature = "std")]
-pub use crate::conn::{Connection, Reader, Writer};
-pub use crate::conn::{ConnectionCommon, SideData, kernel};
-pub use crate::enums::{
- AlertDescription, CertificateCompressionAlgorithm, CipherSuite, ContentType, HandshakeType,
- ProtocolVersion, SignatureAlgorithm, SignatureScheme,
-};
-pub use crate::error::{
- CertRevocationListError, CertificateError, EncryptedClientHelloError, Error,
- ExtendedKeyPurpose, InconsistentKeys, InvalidMessage, OtherError, PeerIncompatible,
- PeerMisbehaved,
-};
-pub use crate::key_log::{KeyLog, NoKeyLog};
-#[cfg(feature = "std")]
-pub use crate::key_log_file::KeyLogFile;
-pub use crate::msgs::enums::NamedGroup;
-pub use crate::msgs::ffdhe_groups;
-pub use crate::msgs::handshake::DistinguishedName;
-#[cfg(feature = "std")]
-pub use crate::stream::{Stream, StreamOwned};
-pub use crate::suites::{
- CipherSuiteCommon, ConnectionTrafficSecrets, ExtractedSecrets, SupportedCipherSuite,
-};
-#[cfg(feature = "std")]
-pub use crate::ticketer::TicketRotator;
-#[cfg(any(feature = "std", feature = "hashbrown"))] // < XXX: incorrect feature gate
-pub use crate::ticketer::TicketSwitcher;
-#[cfg(feature = "tls12")]
-pub use crate::tls12::Tls12CipherSuite;
-pub use crate::tls13::Tls13CipherSuite;
-pub use crate::verify::DigitallySignedStruct;
-pub use crate::versions::{ALL_VERSIONS, DEFAULT_VERSIONS, SupportedProtocolVersion};
-pub use crate::webpki::RootCertStore;
-
-/// Items for use in a client.
-pub mod client {
- pub(super) mod builder;
- mod client_conn;
- mod common;
- mod ech;
- pub(super) mod handy;
- mod hs;
- #[cfg(test)]
- mod test;
- #[cfg(feature = "tls12")]
- mod tls12;
- mod tls13;
-
- pub use builder::WantsClientCert;
- pub use client_conn::{
- ClientConfig, ClientConnectionData, ClientSessionStore, EarlyDataError, ResolvesClientCert,
- Resumption, Tls12Resumption, UnbufferedClientConnection,
- };
- #[cfg(feature = "std")]
- pub use client_conn::{ClientConnection, WriteEarlyData};
- pub use ech::{EchConfig, EchGreaseConfig, EchMode, EchStatus};
- pub use handy::AlwaysResolvesClientRawPublicKeys;
- #[cfg(any(feature = "std", feature = "hashbrown"))]
- pub use handy::ClientSessionMemoryCache;
-
- /// Dangerous configuration that should be audited and used with extreme care.
- pub mod danger {
- pub use super::builder::danger::DangerousClientConfigBuilder;
- pub use super::client_conn::danger::DangerousClientConfig;
- pub use crate::verify::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
- }
-
- pub use crate::msgs::persist::{Tls12ClientSessionValue, Tls13ClientSessionValue};
- pub use crate::webpki::{
- ServerCertVerifierBuilder, VerifierBuilderError, WebPkiServerVerifier,
- verify_server_cert_signed_by_trust_anchor, verify_server_name,
- };
-}
-
-pub use client::ClientConfig;
-#[cfg(feature = "std")]
-pub use client::ClientConnection;
-
-/// Items for use in a server.
-pub mod server {
- pub(crate) mod builder;
- mod common;
- pub(crate) mod handy;
- mod hs;
- mod server_conn;
- #[cfg(test)]
- mod test;
- #[cfg(feature = "tls12")]
- mod tls12;
- mod tls13;
-
- pub use builder::WantsServerCert;
- #[cfg(any(feature = "std", feature = "hashbrown"))]
- pub use handy::ResolvesServerCertUsingSni;
- #[cfg(any(feature = "std", feature = "hashbrown"))]
- pub use handy::ServerSessionMemoryCache;
- pub use handy::{AlwaysResolvesServerRawPublicKeys, NoServerSessionStorage};
- pub use server_conn::{
- Accepted, ClientHello, ProducesTickets, ResolvesServerCert, ServerConfig,
- ServerConnectionData, StoresServerSessions, UnbufferedServerConnection,
- };
- #[cfg(feature = "std")]
- pub use server_conn::{AcceptedAlert, Acceptor, ReadEarlyData, ServerConnection};
-
- pub use crate::enums::CertificateType;
- pub use crate::verify::NoClientAuth;
- pub use crate::webpki::{
- ClientCertVerifierBuilder, ParsedCertificate, VerifierBuilderError, WebPkiClientVerifier,
- };
-
- /// Dangerous configuration that should be audited and used with extreme care.
- pub mod danger {
- pub use crate::verify::{ClientCertVerified, ClientCertVerifier};
- }
-}
-
-pub use server::ServerConfig;
-#[cfg(feature = "std")]
-pub use server::ServerConnection;
-
-/// All defined protocol versions appear in this module.
-///
-/// ALL_VERSIONS is a provided as an array of all of these values.
-pub mod version {
- #[cfg(feature = "tls12")]
- pub use crate::versions::TLS12;
- pub use crate::versions::TLS13;
-}
-
-/// Re-exports the contents of the [rustls-pki-types](https://docs.rs/rustls-pki-types) crate for easy access
-pub mod pki_types {
- #[doc(no_inline)]
- pub use pki_types::*;
-}
-
-/// Message signing interfaces.
-pub mod sign {
- pub use crate::crypto::signer::{CertifiedKey, Signer, SigningKey, SingleCertAndKey};
-}
-
-/// APIs for implementing QUIC TLS
-pub mod quic;
-
-#[cfg(any(feature = "std", feature = "hashbrown"))] // < XXX: incorrect feature gate
-/// APIs for implementing TLS tickets
-pub mod ticketer;
-
-/// This is the rustls manual.
-pub mod manual;
-
-pub mod time_provider;
-
-/// APIs abstracting over locking primitives.
-pub mod lock;
-
-/// Polyfills for features that are not yet stabilized or available with current MSRV.
-pub(crate) mod polyfill;
-
-#[cfg(any(feature = "std", feature = "hashbrown"))]
-mod hash_map {
- #[cfg(feature = "std")]
- pub(crate) use std::collections::HashMap;
- #[cfg(feature = "std")]
- pub(crate) use std::collections::hash_map::Entry;
-
- #[cfg(all(not(feature = "std"), feature = "hashbrown"))]
- pub(crate) use hashbrown::HashMap;
- #[cfg(all(not(feature = "std"), feature = "hashbrown"))]
- pub(crate) use hashbrown::hash_map::Entry;
-}
diff --git a/vendor/rustls/src/limited_cache.rs b/vendor/rustls/src/limited_cache.rs
deleted file mode 100644
index 6ae8bf94..00000000
--- a/vendor/rustls/src/limited_cache.rs
+++ /dev/null
@@ -1,250 +0,0 @@
-use alloc::collections::VecDeque;
-use core::borrow::Borrow;
-use core::hash::Hash;
-
-use crate::hash_map::{Entry, HashMap};
-
-/// A HashMap-alike, which never gets larger than a specified
-/// capacity, and evicts the oldest insertion to maintain this.
-///
-/// The requested capacity may be rounded up by the underlying
-/// collections. This implementation uses all the allocated
-/// storage.
-///
-/// This is inefficient: it stores keys twice.
-pub(crate) struct LimitedCache<K: Clone + Hash + Eq, V> {
- map: HashMap<K, V>,
-
- // first item is the oldest key
- oldest: VecDeque<K>,
-}
-
-impl<K, V> LimitedCache<K, V>
-where
- K: Eq + Hash + Clone + core::fmt::Debug,
- V: Default,
-{
- pub(crate) fn get_or_insert_default_and_edit(&mut self, k: K, edit: impl FnOnce(&mut V)) {
- let inserted_new_item = match self.map.entry(k) {
- Entry::Occupied(value) => {
- edit(value.into_mut());
- false
- }
- entry @ Entry::Vacant(_) => {
- self.oldest
- .push_back(entry.key().clone());
- edit(entry.or_insert_with(V::default));
- true
- }
- };
-
- // ensure next insertion does not require a realloc
- if inserted_new_item && self.oldest.capacity() == self.oldest.len() {
- if let Some(oldest_key) = self.oldest.pop_front() {
- self.map.remove(&oldest_key);
- }
- }
- }
-
- pub(crate) fn get_mut<Q: Hash + Eq + ?Sized>(&mut self, k: &Q) -> Option<&mut V>
- where
- K: Borrow<Q>,
- {
- self.map.get_mut(k)
- }
-}
-
-impl<K, V> LimitedCache<K, V>
-where
- K: Eq + Hash + Clone + core::fmt::Debug,
- V: Default,
-{
- /// Create a new LimitedCache with the given rough capacity.
- pub(crate) fn new(capacity_order_of_magnitude: usize) -> Self {
- Self {
- map: HashMap::with_capacity(capacity_order_of_magnitude),
- oldest: VecDeque::with_capacity(capacity_order_of_magnitude),
- }
- }
-
- pub(crate) fn insert(&mut self, k: K, v: V) {
- let inserted_new_item = match self.map.entry(k) {
- Entry::Occupied(mut old) => {
- // Note: does not freshen entry in `oldest`
- old.insert(v);
- false
- }
-
- entry @ Entry::Vacant(_) => {
- self.oldest
- .push_back(entry.key().clone());
- entry.or_insert(v);
- true
- }
- };
-
- // ensure next insertion does not require a realloc
- if inserted_new_item && self.oldest.capacity() == self.oldest.len() {
- if let Some(oldest_key) = self.oldest.pop_front() {
- self.map.remove(&oldest_key);
- }
- }
- }
-
- pub(crate) fn get<Q: Hash + Eq + ?Sized>(&self, k: &Q) -> Option<&V>
- where
- K: Borrow<Q>,
- {
- self.map.get(k)
- }
-
- pub(crate) fn remove<Q: Hash + Eq + ?Sized>(&mut self, k: &Q) -> Option<V>
- where
- K: Borrow<Q>,
- {
- let value = self.map.remove(k)?;
-
- // O(N) search, followed by O(N) removal
- if let Some(index) = self
- .oldest
- .iter()
- .position(|item| item.borrow() == k)
- {
- self.oldest.remove(index);
- }
-
- Some(value)
- }
-}
-
-#[cfg(test)]
-mod tests {
- use std::prelude::v1::*;
-
- type Test = super::LimitedCache<String, usize>;
-
- #[test]
- fn test_updates_existing_item() {
- let mut t = Test::new(3);
- t.insert("abc".into(), 1);
- t.insert("abc".into(), 2);
- assert_eq!(t.get("abc"), Some(&2));
- }
-
- #[test]
- fn test_evicts_oldest_item() {
- let mut t = Test::new(3);
- t.insert("abc".into(), 1);
- t.insert("def".into(), 2);
- t.insert("ghi".into(), 3);
-
- assert_eq!(t.get("abc"), None);
- assert_eq!(t.get("def"), Some(&2));
- assert_eq!(t.get("ghi"), Some(&3));
- }
-
- #[test]
- fn test_evicts_second_oldest_item_if_first_removed() {
- let mut t = Test::new(3);
- t.insert("abc".into(), 1);
- t.insert("def".into(), 2);
-
- assert_eq!(t.remove("abc"), Some(1));
-
- t.insert("ghi".into(), 3);
- t.insert("jkl".into(), 4);
-
- assert_eq!(t.get("abc"), None);
- assert_eq!(t.get("def"), None);
- assert_eq!(t.get("ghi"), Some(&3));
- assert_eq!(t.get("jkl"), Some(&4));
- }
-
- #[test]
- fn test_evicts_after_second_oldest_item_removed() {
- let mut t = Test::new(3);
- t.insert("abc".into(), 1);
- t.insert("def".into(), 2);
-
- assert_eq!(t.remove("def"), Some(2));
- assert_eq!(t.get("abc"), Some(&1));
-
- t.insert("ghi".into(), 3);
- t.insert("jkl".into(), 4);
-
- assert_eq!(t.get("abc"), None);
- assert_eq!(t.get("def"), None);
- assert_eq!(t.get("ghi"), Some(&3));
- assert_eq!(t.get("jkl"), Some(&4));
- }
-
- #[test]
- fn test_removes_all_items() {
- let mut t = Test::new(3);
- t.insert("abc".into(), 1);
- t.insert("def".into(), 2);
-
- assert_eq!(t.remove("def"), Some(2));
- assert_eq!(t.remove("abc"), Some(1));
-
- t.insert("ghi".into(), 3);
- t.insert("jkl".into(), 4);
- t.insert("mno".into(), 5);
-
- assert_eq!(t.get("abc"), None);
- assert_eq!(t.get("def"), None);
- assert_eq!(t.get("ghi"), None);
- assert_eq!(t.get("jkl"), Some(&4));
- assert_eq!(t.get("mno"), Some(&5));
- }
-
- #[test]
- fn test_inserts_many_items() {
- let mut t = Test::new(3);
-
- for _ in 0..10000 {
- t.insert("abc".into(), 1);
- t.insert("def".into(), 2);
- t.insert("ghi".into(), 3);
- }
- }
-
- #[test]
- fn test_get_or_insert_default_and_edit_evicts_old_items_to_meet_capacity() {
- let mut t = Test::new(3);
-
- t.get_or_insert_default_and_edit("abc".into(), |v| *v += 1);
- t.get_or_insert_default_and_edit("def".into(), |v| *v += 2);
-
- // evicts "abc"
- t.get_or_insert_default_and_edit("ghi".into(), |v| *v += 3);
- assert_eq!(t.get("abc"), None);
-
- // evicts "def"
- t.get_or_insert_default_and_edit("jkl".into(), |v| *v += 4);
- assert_eq!(t.get("def"), None);
-
- // evicts "ghi"
- t.get_or_insert_default_and_edit("abc".into(), |v| *v += 5);
- assert_eq!(t.get("ghi"), None);
-
- // evicts "jkl"
- t.get_or_insert_default_and_edit("def".into(), |v| *v += 6);
-
- assert_eq!(t.get("abc"), Some(&5));
- assert_eq!(t.get("def"), Some(&6));
- assert_eq!(t.get("ghi"), None);
- assert_eq!(t.get("jkl"), None);
- }
-
- #[test]
- fn test_get_or_insert_default_and_edit_edits_existing_item() {
- let mut t = Test::new(3);
-
- t.get_or_insert_default_and_edit("abc".into(), |v| *v += 1);
- t.get_or_insert_default_and_edit("abc".into(), |v| *v += 2);
- t.get_or_insert_default_and_edit("abc".into(), |v| *v += 3);
-
- assert_eq!(t.get("abc"), Some(&6));
- }
-}
diff --git a/vendor/rustls/src/lock.rs b/vendor/rustls/src/lock.rs
deleted file mode 100644
index b632b2c5..00000000
--- a/vendor/rustls/src/lock.rs
+++ /dev/null
@@ -1,89 +0,0 @@
-#[cfg(not(feature = "std"))]
-pub use no_std_lock::*;
-#[cfg(feature = "std")]
-pub use std_lock::*;
-
-#[cfg(feature = "std")]
-mod std_lock {
- use std::sync::Mutex as StdMutex;
- pub use std::sync::MutexGuard;
-
- /// A wrapper around [`std::sync::Mutex`].
- #[derive(Debug)]
- pub struct Mutex<T> {
- inner: StdMutex<T>,
- }
-
- impl<T> Mutex<T> {
- /// Creates a new mutex in an unlocked state ready for use.
- pub fn new(data: T) -> Self {
- Self {
- inner: StdMutex::new(data),
- }
- }
-
- /// Acquires the mutex, blocking the current thread until it is able to do so.
- ///
- /// This will return `None` in the case the mutex is poisoned.
- #[inline]
- pub fn lock(&self) -> Option<MutexGuard<'_, T>> {
- self.inner.lock().ok()
- }
- }
-}
-
-#[cfg(not(feature = "std"))]
-mod no_std_lock {
- use alloc::boxed::Box;
- use core::fmt::Debug;
- use core::ops::DerefMut;
-
- use crate::sync::Arc;
-
- /// A no-std compatible wrapper around [`Lock`].
- #[derive(Debug)]
- pub struct Mutex<T> {
- inner: Arc<dyn Lock<T>>,
- }
-
- impl<T: Send + 'static> Mutex<T> {
- /// Creates a new mutex in an unlocked state ready for use.
- pub fn new<M>(val: T) -> Self
- where
- M: MakeMutex,
- T: Send + 'static,
- {
- Self {
- inner: M::make_mutex(val),
- }
- }
-
- /// Acquires the mutex, blocking the current thread until it is able to do so.
- ///
- /// This will return `None` in the case the mutex is poisoned.
- #[inline]
- pub fn lock(&self) -> Option<MutexGuard<'_, T>> {
- self.inner.lock().ok()
- }
- }
-
- /// A lock protecting shared data.
- pub trait Lock<T>: Debug + Send + Sync {
- /// Acquire the lock.
- fn lock(&self) -> Result<MutexGuard<'_, T>, Poisoned>;
- }
-
- /// A lock builder.
- pub trait MakeMutex {
- /// Create a new mutex.
- fn make_mutex<T>(value: T) -> Arc<dyn Lock<T>>
- where
- T: Send + 'static;
- }
-
- /// A no-std compatible mutex guard.
- pub type MutexGuard<'a, T> = Box<dyn DerefMut<Target = T> + 'a>;
-
- /// A marker type used to indicate `Lock::lock` failed due to a poisoned lock.
- pub struct Poisoned;
-}
diff --git a/vendor/rustls/src/manual/defaults.rs b/vendor/rustls/src/manual/defaults.rs
deleted file mode 100644
index f6f70dc0..00000000
--- a/vendor/rustls/src/manual/defaults.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-/*!
-
-## Rationale for defaults
-
-### Why is AES-256 preferred over AES-128?
-
-This is a trade-off between:
-
-1. classical security level: searching a 2^128 key space is as implausible as 2^256.
-2. post-quantum security level: the difference is more meaningful, and AES-256 seems like the conservative choice.
-3. performance: AES-256 is around 40% slower than AES-128, though hardware acceleration typically narrows this gap.
-
-The choice is frankly quite marginal.
-
-### Why is AES-GCM preferred over chacha20-poly1305?
-
-Hardware support for accelerating AES-GCM is widespread, and hardware-accelerated AES-GCM
-is quicker than un-accelerated chacha20-poly1305.
-
-However, if you know your application will run on a platform without that, you should
-_definitely_ change the default order to prefer chacha20-poly1305: both the performance and
-the implementation security will be improved. We think this is an uncommon case.
-
-### Why is x25519 preferred for key exchange over nistp256?
-
-Both provide roughly the same classical security level, but x25519 has better performance and
-it's _much_ more likely that both peers will have good quality implementations.
-
-### About the post-quantum-secure key exchange `X25519MLKEM768`
-
-[`X25519MLKEM768`] -- a hybrid[^1], post-quantum-secure[^2] key exchange
-algorithm -- is available when using the aws-lc-rs provider.
-
-The `prefer-post-quantum` crate feature makes `X25519MLKEM768` the
-highest-priority key exchange algorithm. Otherwise, it is available but
-not highest-priority.
-
-[X25519MLKEM768] is pre-standardization, but is now widely deployed,
-for example, by [Chrome] and [Cloudflare].
-
-You may see unexpected connection failures (such as [tldr.fail])
--- [please report these to us][interop-bug].
-
-The two components of this key exchange are well regarded:
-X25519 alone is already used by default by rustls, and tends to have
-higher quality implementations than other elliptic curves.
-ML-KEM-768 was standardized by NIST in [FIPS203].
-
-[`MLKEM768`] is available separately, but is not currently enabled
-by default out of conservatism.
-
-[^1]: meaning: a construction that runs a classical and post-quantum
- key exchange, and uses the output of both together. This is a hedge
- against the post-quantum half being broken.
-
-[^2]: a "post-quantum-secure" algorithm is one posited to be invulnerable
- to attack using a cryptographically-relevant quantum computer. In contrast,
- classical algorithms would be broken by such a computer. Note that such computers
- do not currently exist, and may never exist, but current traffic could be captured
- now and attacked later.
-
-[X25519MLKEM768]: <https://datatracker.ietf.org/doc/draft-ietf-tls-ecdhe-mlkem/>
-[`X25519MLKEM768`]: crate::crypto::aws_lc_rs::kx_group::X25519MLKEM768
-[`MLKEM768`]: crate::crypto::aws_lc_rs::kx_group::MLKEM768
-[FIPS203]: <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf>
-[Chrome]: <https://security.googleblog.com/2024/09/a-new-path-for-kyber-on-web.html>
-[Cloudflare]: <https://blog.cloudflare.com/pq-2024/#ml-kem-768-and-x25519>
-[interop-bug]: <https://github.com/rustls/rustls/issues/new?assignees=&labels=&projects=&template=bug_report.md&title=>
-[tldr.fail]: <https://tldr.fail/>
-
-*/
diff --git a/vendor/rustls/src/manual/features.rs b/vendor/rustls/src/manual/features.rs
deleted file mode 100644
index 69daf48a..00000000
--- a/vendor/rustls/src/manual/features.rs
+++ /dev/null
@@ -1,100 +0,0 @@
-/*!
-
-The below list reflects the support provided with the default crate features.
-Items marked with an asterisk `*` can be extended or altered via public
-APIs ([`CryptoProvider`] for example).
-
-[`CryptoProvider`]: crate::crypto::CryptoProvider
-
-## Current features
-
-* TLS1.2 and TLS1.3
-* ECDSA, Ed25519 or RSA server authentication by clients `*`
-* ECDSA, Ed25519[^1] or RSA server authentication by servers `*`
-* Forward secrecy using ECDHE; with curve25519, nistp256 or nistp384 curves `*`
-* Post-quantum hybrid key exchange with [X25519MLKEM768](https://datatracker.ietf.org/doc/draft-ietf-tls-ecdhe-mlkem/) [^2] `*`
-* AES128-GCM and AES256-GCM bulk encryption, with safe nonces `*`
-* ChaCha20-Poly1305 bulk encryption ([RFC7905](https://tools.ietf.org/html/rfc7905)) `*`
-* ALPN support
-* SNI support
-* Tunable fragment size to make TLS messages match size of underlying transport
-* Optional use of vectored IO to minimise system calls
-* TLS1.2 session resumption
-* TLS1.2 resumption via tickets ([RFC5077](https://tools.ietf.org/html/rfc5077))
-* TLS1.3 resumption via tickets or session storage
-* TLS1.3 0-RTT data
-* Server and optional client authentication
-* Extended master secret support ([RFC7627](https://tools.ietf.org/html/rfc7627))
-* Exporters ([RFC5705](https://tools.ietf.org/html/rfc5705))
-* OCSP stapling by servers
-* [RFC7250](https://tools.ietf.org/html/rfc7250) raw public keys for TLS1.3
-* [RFC8879](https://tools.ietf.org/html/rfc8879) certificate compression by clients
- and servers `*`
-* Client-side Encrypted client hello (ECH)
- ([draft-ietf-tls-esni](https://datatracker.ietf.org/doc/draft-ietf-tls-esni/)).
-
-[^1]: Note that, at the time of writing, Ed25519 does not have wide support
- in browsers. It is also not supported by the WebPKI, because the
- CA/Browser Forum Baseline Requirements do not support it for publicly
- trusted certificates.
-[^2]: See [the documentation][crate::manual::_05_defaults#about-the-post-quantum-secure-key-exchange-x25519mlkem768]
-
-## Non-features
-
-For reasons explained in the other sections of this manual, rustls does not
-and will not support:
-
-* SSL1, SSL2, SSL3, TLS1 or TLS1.1
-* RC4
-* DES or triple DES
-* EXPORT ciphersuites
-* MAC-then-encrypt ciphersuites
-* Ciphersuites without forward secrecy
-* Renegotiation
-* Kerberos
-* TLS 1.2 protocol compression
-* Discrete-log Diffie-Hellman `*`
-* Automatic protocol version downgrade
-* Using CA certificates directly to authenticate a server/client (often called "self-signed
- certificates"). _Rustls' default certificate verifier does not support using a trust anchor as
- both a CA certificate and an end-entity certificate in order to limit complexity and risk in
- path building. While dangerous, all authentication can be turned off if required --
- see the [example code](https://github.com/rustls/rustls/blob/v/0.23.23/examples/src/bin/tlsclient-mio.rs#L338)_ `*`
-
-### About "custom extensions"
-
-OpenSSL allows an application to add arbitrary TLS extensions (via
-the `SSL_CTX_add_custom_ext` function and associated APIs). We don't
-support this, with the following rationale:
-
-Such an API is limited to extensions that are quite narrow in scope:
-they cannot change the meaning of standard messages, or introduce new
-messages, or make any changes to the connection's cryptography.
-
-However, there is no reasonable way to technically limit that API to
-that set of extensions. That makes the API pretty unsafe (in the
-TLS and cryptography sense, not memory safety sense). This could
-cause security or interop failures.
-
-Instead, we suggest that potential users of that API consider:
-
-- whether their use can fit in standard extensions such as ALPN,
- or [ALPS][alps][^3].
-- if not, whether they can fit in a more general extension, and define
- and standardize that in the [IETF TLSWG][tlswg].
-
-Note the above is not a guarantee or offer that rustls will implement
-any specific extensions that are standardized by the IETF TLSWG.
-It is a non-goal of this project to implement absolutely everything.
-
-For experimentation and pre-standardization testing, we suggest
-forking rustls.
-
-See also: [Go's position on such an API][golang].
-
-[alps]: https://datatracker.ietf.org/doc/html/draft-vvv-tls-alps
-[golang]: https://github.com/golang/go/issues/51497
-[tlswg]: https://datatracker.ietf.org/wg/tls/charter/
-[^3]: rustls does not currently implement ALPS, but it is something we
- would consider once standardised and deployed.
-*/
diff --git a/vendor/rustls/src/manual/fips.rs b/vendor/rustls/src/manual/fips.rs
deleted file mode 100644
index 203a759e..00000000
--- a/vendor/rustls/src/manual/fips.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-/*! # Using rustls with FIPS-approved cryptography
-
-To use FIPS-approved cryptography with rustls, you should take
-these actions:
-
-## 1. Enable the `fips` crate feature for rustls.
-
-Use:
-
-```toml
-rustls = { version = "0.23", features = [ "fips" ] }
-```
-
-## 2. Use the FIPS `CryptoProvider`
-
-This is [`default_fips_provider()`]:
-
-```rust,ignore
-rustls::crypto::default_fips_provider()
- .install_default()
- .expect("default provider already set elsewhere");
-```
-
-This snippet makes use of the process-default provider,
-and that assumes all your uses of rustls use that.
-See [`CryptoProvider`] documentation for other ways to
-specify which `CryptoProvider` to use.
-
-## 3. Validate the FIPS status of your `ClientConfig`/`ServerConfig` at run-time
-
-See [`ClientConfig::fips()`] or [`ServerConfig::fips()`].
-
-You could, for example:
-
-```rust,ignore
-# let client_config = unreachable!();
-assert!(client_config.fips());
-```
-
-But maybe your application has an error handling
-or health-check strategy better than panicking.
-
-# aws-lc-rs FIPS approval status
-
-This is covered by [FIPS 140-3 certificate #4816][cert-4816].
-See [the security policy][policy-4816] for precisely which
-environments and functions this certificate covers.
-
-Later releases of aws-lc-rs may be covered by later certificates,
-or be pending certification.
-
-For the most up-to-date details see the latest documentation
-for the [`aws-lc-fips-sys`] crate.
-
-[`aws-lc-fips-sys`]: https://crates.io/crates/aws-lc-fips-sys
-[`default_fips_provider()`]: crate::crypto::default_fips_provider
-[`CryptoProvider`]: crate::crypto::CryptoProvider
-[`ClientConfig::fips()`]: crate::client::ClientConfig::fips
-[`ServerConfig::fips()`]: crate::server::ServerConfig::fips
-[cert-4816]: https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/4816
-[policy-4816]: https://csrc.nist.gov/CSRC/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp4816.pdf
-*/
diff --git a/vendor/rustls/src/manual/howto.rs b/vendor/rustls/src/manual/howto.rs
deleted file mode 100644
index 6c00c695..00000000
--- a/vendor/rustls/src/manual/howto.rs
+++ /dev/null
@@ -1,124 +0,0 @@
-/*! # Customising private key usage
-
-By default rustls supports PKCS#8-format[^1] RSA or ECDSA keys, plus PKCS#1-format RSA keys.
-
-However, if your private key resides in a HSM, or in another process, or perhaps
-another machine, rustls has some extension points to support this:
-
-The main trait you must implement is [`sign::SigningKey`][signing_key]. The primary method here
-is [`choose_scheme()`][choose_scheme] where you are given a set of [`SignatureScheme`s][sig_scheme] the client says
-it supports: you must choose one (or return `None` -- this aborts the handshake). Having
-done that, you return an implementation of the [`sign::Signer`][signer] trait.
-The [`sign()`][sign_method] performs the signature and returns it.
-
-(Unfortunately this is currently designed for keys with low latency access, like in a
-PKCS#11 provider, Microsoft CryptoAPI, etc. so is blocking rather than asynchronous.
-It's a TODO to make these and other extension points async.)
-
-Once you have these two pieces, configuring a server to use them involves, briefly:
-
-- packaging your [`sign::SigningKey`][signing_key] with the matching certificate chain into a [`sign::CertifiedKey`][certified_key]
-- making a [`ResolvesServerCertUsingSni`][cert_using_sni] and feeding in your [`sign::CertifiedKey`][certified_key] for all SNI hostnames you want to use it for,
-- setting that as your `ServerConfig`'s [`cert_resolver`][cert_resolver]
-
-For a complete example of implementing a custom [`sign::SigningKey`][signing_key] and
-[`sign::Signer`][signer] see the [`signer` module in the `rustls-cng` crate][rustls-cng-signer].
-
-[signing_key]: crate::crypto::signer::SigningKey
-[choose_scheme]: crate::crypto::signer::SigningKey::choose_scheme
-[sig_scheme]: crate::SignatureScheme
-[signer]: crate::crypto::signer::Signer
-[sign_method]: crate::crypto::signer::Signer::sign
-[certified_key]: crate::crypto::signer::CertifiedKey
-[cert_using_sni]: crate::server::ResolvesServerCertUsingSni
-[cert_resolver]: crate::ServerConfig::cert_resolver
-[rustls-cng-signer]: https://github.com/rustls/rustls-cng/blob/dev/src/signer.rs
-
-[^1]: For PKCS#8 it does not support password encryption -- there's not a meaningful threat
- model addressed by this, and the encryption supported is typically extremely poor.
-
-# Unexpected EOF
-
-TLS has a `close_notify` mechanism to prevent truncation attacks[^2].
-According to the TLS RFCs, each party is required to send a `close_notify` message before
-closing the write side of the connection. However, some implementations don't send it.
-So long as the application layer protocol (for instance HTTP/2) has message length framing
-and can reject truncated messages, this is not a security problem.
-
-Rustls treats an EOF without `close_notify` as an error of type `std::io::Error` with
-`ErrorKind::UnexpectedEof`. In some situations it's appropriate for the application to handle
-this error the same way it would handle a normal EOF (a read returning `Ok(0)`). In particular
-if `UnexpectedEof` occurs on an idle connection it is appropriate to treat it the same way as a
-clean shutdown. And if an application always uses messages with length framing (in other words,
-messages are never delimited by the close of the TCP connection), it can unconditionally
-ignore `UnexpectedEof` errors from rustls.
-
-[^2]: <https://datatracker.ietf.org/doc/html/rfc8446#section-6.1>
-
-# Debugging
-
-If you encounter a bug with Rustls it can be helpful to collect up as much diagnostic
-information as possible.
-
-## Collecting logs
-
-If your bug reproduces with one of the [Rustls examples] you can use the
-[`RUST_LOG`] environment variable to increase the log verbosity. If you're using
-your own application, you may need to configure it with a logging backend
-like `env_logger`.
-
-Consider reproducing your bug with `RUST_LOG=rustls=trace` and sharing the result
-in a [GitHub gist].
-
-[Rustls examples]: https://github.com/rustls/rustls/tree/main/examples
-[`RUST_LOG`]: https://docs.rs/env_logger/latest/env_logger/#enabling-logging
-[`env_logger`]: https://docs.rs/env_logger/
-[GitHub gist]: https://docs.github.com/en/get-started/writing-on-github/editing-and-sharing-content-with-gists/creating-gists
-
-## Taking a packet capture
-
-When logs aren't enough taking a packet capture ("pcap") is another helpful tool.
-The details of how to accomplish this vary by operating system/context.
-
-### tcpdump
-
-As one example, on Linux using [`tcpdump`] is often easiest.
-
-If you know the IP address of the remote server your bug demonstrates with you
-could take a short packet capture with this command (after replacing
-`XX.XX.XX.XX` with the correct IP address):
-
-```bash
-sudo tcpdump -i any tcp and dst host XX.XX.XX.XX -C5 -w rustls.pcap
-```
-
-The `-i any` captures on any network interface. The `tcp and dst host XX.XX.XX.XX`
-portion target the capture to TCP traffic to the specified IP address. The `-C5`
-argument limits the capture to at most 5MB. Lastly the `-w` argument writes the
-capture to `rustls.pcap`.
-
-Another approach is to use `tcp and port XXXX` instead of `tcp and dst host XX.XX.XX.XX`
-to capture all traffic to a specific port instead of a specific host server.
-
-[`tcpdump`]: https://www.redhat.com/en/blog/introduction-using-tcpdump-linux-command-line
-
-### SSLKEYLOGFILE
-
-If the bug you are reporting happens after data is encrypted you may also wish to
-share the secret keys required to decrypt the post-handshake traffic.
-
-If you're using one of the [Rustls examples] you can set the `SSLKEYLOGFILE` environment
-variable to a path where secrets will be written. E.g. `SSLKEYLOGFILE=rustls.pcap.keys`.
-
-If you're using your own application you may need to customize the Rustls `ClientConfig`
-or `ServerConfig`'s `key_log` setting like the example applications do.
-
-With the file from `SSLKEYLOGFILE` it is possible to use [Wireshark] or another tool to
-decrypt the post-handshake messages, following [these instructions][curl-sslkeylogfile].
-
-Remember this allows plaintext decryption and should only be done in testing contexts
-where no sensitive data (API keys, etc) are being shared.
-
-[Wireshark]: https://www.wireshark.org/download.html
-[curl-sslkeylogfile]: https://everything.curl.dev/usingcurl/tls/sslkeylogfile.html
-*/
diff --git a/vendor/rustls/src/manual/implvulns.rs b/vendor/rustls/src/manual/implvulns.rs
deleted file mode 100644
index a073350c..00000000
--- a/vendor/rustls/src/manual/implvulns.rs
+++ /dev/null
@@ -1,104 +0,0 @@
-/*! # A review of TLS Implementation Vulnerabilities
-
-An important part of engineering involves studying and learning from the mistakes of the past.
-It would be tremendously unfortunate to spend effort re-discovering and re-fixing the same
-vulnerabilities that were discovered in the past.
-
-## Memory safety
-
-Being written entirely in the safe-subset of Rust immediately offers us freedom from the entire
-class of memory safety vulnerabilities. There are too many to exhaustively list, and there will
-certainly be more in the future.
-
-Examples:
-
-- Heartbleed [CVE-2014-0160](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-0160) (OpenSSL)
-- Memory corruption in ASN.1 decoder [CVE-2016-2108](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-2108) (OpenSSL)
-- Buffer overflow in read_server_hello [CVE-2014-3466](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3466) (GnuTLS)
-
-## `goto fail`
-
-This is the name of a vulnerability in Apple Secure Transport [CVE-2014-1266](https://nvd.nist.gov/vuln/detail/CVE-2014-1266).
-This boiled down to the following code, which validates the server's signature on the key exchange:
-
-```c
- if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0)
- goto fail;
- if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
- goto fail;
-> goto fail;
- if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0)
- goto fail;
-```
-
-The marked line was duplicated, likely accidentally during a merge. This meant
-the remaining part of the function (including the actual signature validation)
-was unconditionally skipped.
-
-Ultimately the one countermeasure to this type of bug is basic testing: that a
-valid signature returns success, and that an invalid one does not. rustls
-has such testing, but this is really table stakes for security code.
-
-Further than this, though, we could consider that the *lack* of an error from
-this function is a poor indicator that the signature was valid. rustls, instead,
-has zero-size and non-copyable types that indicate a particular signature validation
-has been performed. These types can be thought of as *capabilities* originated only
-by designated signature verification functions -- such functions can then be a focus
-of manual code review. Like capabilities, values of these types are otherwise unforgeable,
-and are communicable only by Rust's move semantics.
-
-Values of these types are threaded through the protocol state machine, leading to terminal
-states that look like:
-
-```ignore
-struct ExpectTraffic {
- (...)
- _cert_verified: verify::ServerCertVerified,
- _sig_verified: verify::HandshakeSignatureValid,
- _fin_verified: verify::FinishedMessageVerified,
-}
-```
-
-Since this state requires a value of these types, it will be a compile-time error to
-reach that state without performing the requisite security-critical operations.
-
-This approach is not infallible, but it has zero runtime cost.
-
-## State machine attacks: EarlyCCS and SMACK/SKIP/FREAK
-
-EarlyCCS [CVE-2014-0224](https://nvd.nist.gov/vuln/detail/CVE-2014-0224) was a vulnerability in OpenSSL
-found in 2014. The TLS `ChangeCipherSpec` message would be processed at inappropriate times, leading
-to data being encrypted with the wrong keys (specifically, keys which were not secret). This resulted
-from OpenSSL taking a *reactive* strategy to incoming messages ("when I get a message X, I should do Y")
-which allows it to diverge from the proper state machine under attacker control.
-
-[SMACK](https://mitls.org/pages/attacks/SMACK) is a similar suite of vulnerabilities found in JSSE,
-CyaSSL, OpenSSL, Mono and axTLS. "SKIP-TLS" demonstrated that some implementations allowed handshake
-messages (and in one case, the entire handshake!) to be skipped leading to breaks in security. "FREAK"
-found that some implementations incorrectly allowed export-only state transitions (i.e., transitions that
-were only valid when an export ciphersuite was in use).
-
-rustls represents its protocol state machine carefully to avoid these defects. We model the handshake,
-CCS and application data subprotocols in the same single state machine. Each state in this machine is
-represented with a single struct, and transitions are modelled as functions that consume the current state
-plus one TLS message[^1] and return a struct representing the next state. These functions fully validate
-the message type before further operations.
-
-A sample sequence for a full TLSv1.2 handshake by a client looks like:
-
-- `hs::ExpectServerHello` (Note: ClientHello is logically sent before this state); transition to `tls12::ExpectCertificate`
-- `tls12::ExpectCertificate`; transition to `tls12::ExpectServerKX`
-- `tls12::ExpectServerKX`; transition to `tls12::ExpectServerDoneOrCertReq`
-- `tls12::ExpectServerDoneOrCertReq`; delegates to `tls12::ExpectCertificateRequest` or `tls12::ExpectServerDone` depending on incoming message.
- - `tls12::ExpectServerDone`; transition to `tls12::ExpectCCS`
-- `tls12::ExpectCCS`; transition to `tls12::ExpectFinished`
-- `tls12::ExpectFinished`; transition to `tls12::ExpectTraffic`
-- `tls12::ExpectTraffic`; terminal state; transitions to `tls12::ExpectTraffic`
-
-In the future we plan to formally prove that all possible transitions modelled in this system of types
-are correct with respect to the standard(s). At the moment we rely merely on exhaustive testing.
-
-[^1]: a logical TLS message: post-decryption, post-fragmentation.
-
-
-*/
diff --git a/vendor/rustls/src/manual/mod.rs b/vendor/rustls/src/manual/mod.rs
deleted file mode 100644
index 0e4fddce..00000000
--- a/vendor/rustls/src/manual/mod.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-/*!
-
-This documentation primarily aims to explain design decisions taken in rustls.
-
-It does this from a few aspects: how rustls attempts to avoid construction errors
-that occurred in other TLS libraries, how rustls attempts to avoid past TLS
-protocol vulnerabilities, and assorted advice for achieving common tasks with rustls.
-*/
-#![allow(non_snake_case)]
-
-/// This section discusses vulnerabilities in other TLS implementations, theorising their
-/// root cause and how we aim to avoid them in rustls.
-#[path = "implvulns.rs"]
-pub mod _01_impl_vulnerabilities;
-
-/// This section discusses vulnerabilities and design errors in the TLS protocol.
-#[path = "tlsvulns.rs"]
-pub mod _02_tls_vulnerabilities;
-
-/// This section collects together goal-oriented documentation.
-#[path = "howto.rs"]
-pub mod _03_howto;
-
-/// This section documents rustls itself: what protocol features are and are not implemented.
-#[path = "features.rs"]
-pub mod _04_features;
-
-/// This section provides rationale for the defaults in rustls.
-#[path = "defaults.rs"]
-pub mod _05_defaults;
-
-/// This section provides guidance on using rustls with FIPS-approved cryptography.
-#[path = "fips.rs"]
-pub mod _06_fips;
diff --git a/vendor/rustls/src/manual/tlsvulns.rs b/vendor/rustls/src/manual/tlsvulns.rs
deleted file mode 100644
index 6d2220e3..00000000
--- a/vendor/rustls/src/manual/tlsvulns.rs
+++ /dev/null
@@ -1,175 +0,0 @@
-/*! # A review of protocol vulnerabilities
-
-## CBC MAC-then-encrypt ciphersuites
-
-Back in 2000 [Bellare and Namprempre](https://eprint.iacr.org/2000/025) discussed how to make authenticated
-encryption by composing separate encryption and authentication primitives. That paper included this table:
-
-| Composition Method | Privacy | | | Integrity | |
-|--------------------|---------|-|-|-----------|-|
-|| IND-CPA | IND-CCA | NM-CPA | INT-PTXT | INT-CTXT |
-| Encrypt-and-MAC | insecure | insecure | insecure | secure | insecure |
-| MAC-then-encrypt | secure | insecure | insecure | secure | insecure |
-| Encrypt-then-MAC | secure | secure | secure | secure | secure |
-
-One may assume from this fairly clear result that encrypt-and-MAC and MAC-then-encrypt compositions would be quickly abandoned
-in favour of the remaining proven-secure option. But that didn't happen, not in TLSv1.1 (2006) nor in TLSv1.2 (2008). Worse,
-both RFCs included incorrect advice on countermeasures for implementers, suggesting that the flaw was "not believed to be large
-enough to be exploitable".
-
-[Lucky 13](http://www.isg.rhul.ac.uk/tls/Lucky13.html) (2013) exploited this flaw and affected all implementations, including
-those written [after discovery](https://aws.amazon.com/blogs/security/s2n-and-lucky-13/). OpenSSL even had a
-[memory safety vulnerability in the fix for Lucky 13](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-2107), which
-gives a flavour of the kind of complexity required to remove the side channel.
-
-rustls does not implement CBC MAC-then-encrypt ciphersuites for these reasons. TLSv1.3 removed support for these
-ciphersuites in 2018.
-
-There are some further rejected options worth mentioning: [RFC7366](https://tools.ietf.org/html/rfc7366) defines
-Encrypt-then-MAC for TLS, but unfortunately cannot be negotiated without also supporting MAC-then-encrypt
-(clients cannot express "I offer CBC, but only EtM and not MtE").
-
-## RSA PKCS#1 encryption
-
-"RSA key exchange" in TLS involves the client choosing a large random value and encrypting it using the server's
-public key. This has two overall problems:
-
-1. It provides no _forward secrecy_: later compromise of the server's private key breaks confidentiality of
- *all* past sessions using that key. This is a crucial property in the presence of software that is often
- [poor at keeping a secret](http://heartbleed.com/).
-2. The padding used in practice in TLS ("PKCS#1", or fully "RSAES-PKCS1-v1_5") has been known to be broken since
- [1998](http://archiv.infsec.ethz.ch/education/fs08/secsem/bleichenbacher98.pdf).
-
-In a similar pattern to the MAC-then-encrypt problem discussed above, TLSv1.0 (1999), TLSv1.1 (2006) and TLSv1.2 (2008)
-continued to specify use of PKCS#1 encryption, again with incrementally more complex and incorrect advice on countermeasures.
-
-[ROBOT](https://robotattack.org/) (2018) showed that implementations were still vulnerable to these attacks twenty years later.
-[The Marvin Attack](https://people.redhat.com/~hkario/marvin/) (2023) demonstrated the same a further five years later.
-
-rustls does not support RSA key exchange. TLSv1.3 also removed support.
-
-## BEAST
-
-[BEAST](https://vnhacker.blogspot.com/2011/09/beast.html) ([CVE-2011-3389](https://nvd.nist.gov/vuln/detail/CVE-2011-3389))
-was demonstrated in 2011 by Thai Duong and Juliano Rizzo,
-and was another vulnerability in CBC-based ciphersuites in SSLv3.0 and TLSv1.0. CBC mode is vulnerable to adaptive
-chosen-plaintext attacks if the IV is predictable. In the case of these protocol versions, the IV was the previous
-block of ciphertext (as if the entire TLS session was one CBC ciphertext, albeit revealed incrementally). This was
-obviously predictable, since it was published on the wire.
-
-OpenSSL contained a countermeasure for this problem from 2002 onwards: it encrypts an empty message before each real
-one, so that the IV used in the real message is unpredictable. This was turned off by default due to bugs in IE6.
-
-TLSv1.1 fix this vulnerability, but not any of the other deficiencies of CBC mode (see above).
-
-rustls does not support these ciphersuites.
-
-## CRIME
-
-In 2002 [John Kelsey](https://www.iacr.org/cryptodb/archive/2002/FSE/3091/3091.pdf) discussed the length side channel
-as applied to compression of combined secret and attacker-chosen strings.
-
-Compression continued to be an option in TLSv1.1 (2006) and in TLSv1.2 (2008). Support in libraries was widespread.
-
-[CRIME](https://en.wikipedia.org/wiki/CRIME) ([CVE-2012-4929](https://nvd.nist.gov/vuln/detail/CVE-2012-4929))
-was demonstrated in 2012, again by Thai Duong and Juliano Rizzo. It attacked several protocols offering transparent
-compression of application data, allowing quick adaptive chosen-plaintext attacks against secret values like cookies.
-
-rustls does not implement compression. TLSv1.3 also removed support.
-
-## Logjam / FREAK
-
-Way back when SSL was first being born, circa 1995, the US government considered cryptography a munition requiring
-export control. SSL contained specific ciphersuites with dramatically small key sizes that were not subject
-to export control. These controls were dropped in 2000.
-
-Since the "export-grade" ciphersuites no longer fulfilled any purpose, and because they were actively harmful to users,
-one may have expected software support to disappear quickly. This did not happen.
-
-In 2015 [the FREAK attack](https://mitls.org/pages/attacks/SMACK#freak) ([CVE-2015-0204](https://nvd.nist.gov/vuln/detail/CVE-2015-0204))
-and [the Logjam attack](https://weakdh.org/) ([CVE-2015-4000](https://nvd.nist.gov/vuln/detail/CVE-2015-4000)) both
-demonstrated total breaks of security in the presence of servers that accepted export ciphersuites. FREAK factored
-512-bit RSA keys, while Logjam optimised solving discrete logs in the 512-bit group used by many different servers.
-
-Naturally, rustls does not implement any of these ciphersuites.
-
-## SWEET32
-
-Block ciphers are vulnerable to birthday attacks, where the probability of repeating a block increases dramatically
-once a particular key has been used for many blocks. For block ciphers with 64-bit blocks, this becomes probable
-once a given key encrypts the order of 32GB of data.
-
-[Sweet32](https://sweet32.info/) ([CVE-2016-2183](https://nvd.nist.gov/vuln/detail/CVE-2016-2183)) attacked this fact
-in the context of TLS support for 3DES, breaking confidentiality by analysing a large amount of attacker-induced traffic
-in one session.
-
-rustls does not support any 64-bit block ciphers.
-
-## DROWN
-
-[DROWN](https://drownattack.com/) ([CVE-2016-0800](https://nvd.nist.gov/vuln/detail/CVE-2016-0800)) is a cross-protocol
-attack that breaks the security of TLSv1.2 and earlier (when used with RSA key exchange) by using SSLv2. It is required
-that the server uses the same key for both protocol versions.
-
-rustls naturally does not support SSLv2, but most importantly does not support RSA key exchange for TLSv1.2.
-
-## Poodle
-
-[POODLE](https://cdn1.vox-cdn.com/uploads/chorus_asset/file/2354994/ssl-poodle.0.pdf) ([CVE-2014-3566](https://nvd.nist.gov/vuln/detail/CVE-2014-3566))
-is an attack against CBC mode ciphersuites in SSLv3. This was possible in most cases because some clients willingly
-downgraded to SSLv3 after failed handshakes for later versions.
-
-rustls does not support CBC mode ciphersuites, or SSLv3. Note that rustls does not need to implement `TLS_FALLBACK_SCSV`
-introduced as a countermeasure because it contains no ability to downgrade from TLS 1.2 to earlier protocol versions,
-and TLS 1.3 has protocol-level downgrade protection based on the [ServerHello server random value](https://www.rfc-editor.org/rfc/rfc8446#section-4.1.3).
-
-## GCM nonces
-
-[RFC5288](https://tools.ietf.org/html/rfc5288) introduced GCM-based ciphersuites for use in TLS. Unfortunately
-the design was poor; it reused design for an unrelated security setting proposed in RFC5116.
-
-GCM is a typical nonce-based AEAD: it requires a unique (but not necessarily unpredictable) 96-bit nonce for each encryption
-with a given key. The design specified by RFC5288 left two-thirds of the nonce construction up to implementations:
-
-- wasting 8 bytes per TLS ciphertext,
-- meaning correct operation cannot be tested for (e.g., in protocol-level test vectors).
-
-There were no trade-offs here: TLS has a 64-bit sequence number that is not allowed to wrap and would make an ideal nonce.
-
-As a result, a [2016 study](https://eprint.iacr.org/2016/475.pdf) found:
-
-- implementations from IBM, A10 and Citrix used randomly-chosen nonces, which are unlikely to be unique over long connections,
-- an implementation from Radware used the same nonce for the first two messages.
-
-rustls uses a counter from a random starting point for GCM nonces. TLSv1.3 and the Chacha20-Poly1305 TLSv1.2 ciphersuite
-standardise this method.
-
-## Renegotiation
-
-In 2009 Marsh Ray and Steve Dispensa [discovered](https://kryptera.se/Renegotiating%20TLS.pdf) that the renegotiation
-feature of all versions of TLS allows a MitM to splice a request of their choice onto the front of the client's real HTTP
-request. A countermeasure was proposed and widely implemented to bind renegotiations to their previous negotiations;
-unfortunately this was insufficient.
-
-rustls does not support renegotiation in TLSv1.2. TLSv1.3 also no longer supports renegotiation.
-
-## 3SHAKE
-
-[3SHAKE](https://www.mitls.org/pages/attacks/3SHAKE) (2014) described a complex attack that broke the "Secure Renegotiation" extension
-introduced as a countermeasure to the previous protocol flaw.
-
-rustls does not support renegotiation for TLSv1.2 connections, or RSA key exchange, and both are required for this attack
-to work. rustls implements the "Extended Master Secret" (RFC7627) extension for TLSv1.2 which was standardised as a countermeasure.
-
-TLSv1.3 no longer supports renegotiation and RSA key exchange. It also effectively incorporates the improvements made in RFC7627.
-
-## KCI
-
-[This vulnerability](https://kcitls.org/) makes use of TLS ciphersuites (those offering static DH) which were standardised
-yet not widely used. However, they were implemented by libraries, and as a result enabled for various clients. It coupled
-this with misconfigured certificates (on services including facebook.com) which allowed their misuse to MitM connections.
-
-rustls does not support static DH/EC-DH ciphersuites. We assert that it is misissuance to sign an EC certificate
-with the keyUsage extension allowing both signatures and key exchange. That it isn't is probably a failure
-of CAB Forum baseline requirements.
-*/
diff --git a/vendor/rustls/src/msgs/alert.rs b/vendor/rustls/src/msgs/alert.rs
deleted file mode 100644
index e66f64cf..00000000
--- a/vendor/rustls/src/msgs/alert.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-use alloc::vec::Vec;
-
-use crate::enums::AlertDescription;
-use crate::error::InvalidMessage;
-use crate::msgs::codec::{Codec, Reader};
-use crate::msgs::enums::AlertLevel;
-
-#[derive(Debug)]
-pub struct AlertMessagePayload {
- pub level: AlertLevel,
- pub description: AlertDescription,
-}
-
-impl Codec<'_> for AlertMessagePayload {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.level.encode(bytes);
- self.description.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let level = AlertLevel::read(r)?;
- let description = AlertDescription::read(r)?;
- r.expect_empty("AlertMessagePayload")
- .map(|_| Self { level, description })
- }
-}
diff --git a/vendor/rustls/src/msgs/base.rs b/vendor/rustls/src/msgs/base.rs
deleted file mode 100644
index 4204714d..00000000
--- a/vendor/rustls/src/msgs/base.rs
+++ /dev/null
@@ -1,238 +0,0 @@
-use alloc::vec::Vec;
-use core::fmt;
-use core::marker::PhantomData;
-
-use pki_types::CertificateDer;
-use zeroize::Zeroize;
-
-use crate::error::InvalidMessage;
-use crate::msgs::codec;
-use crate::msgs::codec::{Codec, Reader};
-
-/// An externally length'd payload
-#[derive(Clone, Eq, PartialEq)]
-pub enum Payload<'a> {
- Borrowed(&'a [u8]),
- Owned(Vec<u8>),
-}
-
-impl<'a> Codec<'a> for Payload<'a> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- bytes.extend_from_slice(self.bytes());
- }
-
- fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
- Ok(Self::read(r))
- }
-}
-
-impl<'a> Payload<'a> {
- pub fn bytes(&self) -> &[u8] {
- match self {
- Self::Borrowed(bytes) => bytes,
- Self::Owned(bytes) => bytes,
- }
- }
-
- pub fn into_owned(self) -> Payload<'static> {
- Payload::Owned(self.into_vec())
- }
-
- pub fn into_vec(self) -> Vec<u8> {
- match self {
- Self::Borrowed(bytes) => bytes.to_vec(),
- Self::Owned(bytes) => bytes,
- }
- }
-
- pub fn read(r: &mut Reader<'a>) -> Self {
- Self::Borrowed(r.rest())
- }
-}
-
-impl Payload<'static> {
- pub fn new(bytes: impl Into<Vec<u8>>) -> Self {
- Self::Owned(bytes.into())
- }
-
- pub fn empty() -> Self {
- Self::Borrowed(&[])
- }
-}
-
-impl<'a> Codec<'a> for CertificateDer<'a> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- codec::u24(self.as_ref().len() as u32).encode(bytes);
- bytes.extend(self.as_ref());
- }
-
- fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
- let len = codec::u24::read(r)?.0 as usize;
- let mut sub = r.sub(len)?;
- let body = sub.rest();
- Ok(Self::from(body))
- }
-}
-
-impl fmt::Debug for Payload<'_> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- hex(f, self.bytes())
- }
-}
-
-/// An arbitrary, unknown-content, u24-length-prefixed payload
-#[derive(Clone, Eq, PartialEq)]
-pub(crate) struct PayloadU24<'a>(pub(crate) Payload<'a>);
-
-impl PayloadU24<'_> {
- pub(crate) fn into_owned(self) -> PayloadU24<'static> {
- PayloadU24(self.0.into_owned())
- }
-}
-
-impl<'a> Codec<'a> for PayloadU24<'a> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- let inner = self.0.bytes();
- codec::u24(inner.len() as u32).encode(bytes);
- bytes.extend_from_slice(inner);
- }
-
- fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
- let len = codec::u24::read(r)?.0 as usize;
- let mut sub = r.sub(len)?;
- Ok(Self(Payload::read(&mut sub)))
- }
-}
-
-impl fmt::Debug for PayloadU24<'_> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.0.fmt(f)
- }
-}
-
-/// An arbitrary, unknown-content, u16-length-prefixed payload
-///
-/// The `C` type parameter controls whether decoded values may
-/// be empty.
-#[derive(Clone, Eq, PartialEq)]
-pub struct PayloadU16<C: Cardinality = MaybeEmpty>(pub(crate) Vec<u8>, PhantomData<C>);
-
-impl<C: Cardinality> PayloadU16<C> {
- pub fn new(bytes: Vec<u8>) -> Self {
- debug_assert!(bytes.len() >= C::MIN);
- Self(bytes, PhantomData)
- }
-}
-
-impl PayloadU16<MaybeEmpty> {
- pub(crate) fn empty() -> Self {
- Self::new(Vec::new())
- }
-}
-
-impl<C: Cardinality> Codec<'_> for PayloadU16<C> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- debug_assert!(self.0.len() >= C::MIN);
- (self.0.len() as u16).encode(bytes);
- bytes.extend_from_slice(&self.0);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let len = u16::read(r)? as usize;
- if len < C::MIN {
- return Err(InvalidMessage::IllegalEmptyValue);
- }
- let mut sub = r.sub(len)?;
- let body = sub.rest().to_vec();
- Ok(Self(body, PhantomData))
- }
-}
-
-impl<C: Cardinality> fmt::Debug for PayloadU16<C> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- hex(f, &self.0)
- }
-}
-
-/// An arbitrary, unknown-content, u8-length-prefixed payload
-///
-/// `C` controls the minimum length accepted when decoding.
-#[derive(Clone, Eq, PartialEq)]
-pub(crate) struct PayloadU8<C: Cardinality = MaybeEmpty>(pub(crate) Vec<u8>, PhantomData<C>);
-
-impl<C: Cardinality> PayloadU8<C> {
- pub(crate) fn encode_slice(slice: &[u8], bytes: &mut Vec<u8>) {
- (slice.len() as u8).encode(bytes);
- bytes.extend_from_slice(slice);
- }
-
- pub(crate) fn new(bytes: Vec<u8>) -> Self {
- debug_assert!(bytes.len() >= C::MIN);
- Self(bytes, PhantomData)
- }
-}
-
-impl PayloadU8<MaybeEmpty> {
- pub(crate) fn empty() -> Self {
- Self(Vec::new(), PhantomData)
- }
-}
-
-impl<C: Cardinality> Codec<'_> for PayloadU8<C> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- debug_assert!(self.0.len() >= C::MIN);
- (self.0.len() as u8).encode(bytes);
- bytes.extend_from_slice(&self.0);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let len = u8::read(r)? as usize;
- if len < C::MIN {
- return Err(InvalidMessage::IllegalEmptyValue);
- }
- let mut sub = r.sub(len)?;
- let body = sub.rest().to_vec();
- Ok(Self(body, PhantomData))
- }
-}
-
-impl<C: Cardinality> Zeroize for PayloadU8<C> {
- fn zeroize(&mut self) {
- self.0.zeroize();
- }
-}
-
-impl<C: Cardinality> fmt::Debug for PayloadU8<C> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- hex(f, &self.0)
- }
-}
-
-pub trait Cardinality: Clone + Eq + PartialEq {
- const MIN: usize;
-}
-
-#[derive(Clone, Eq, PartialEq)]
-pub struct MaybeEmpty;
-
-impl Cardinality for MaybeEmpty {
- const MIN: usize = 0;
-}
-
-#[derive(Clone, Eq, PartialEq)]
-pub struct NonEmpty;
-
-impl Cardinality for NonEmpty {
- const MIN: usize = 1;
-}
-
-// Format an iterator of u8 into a hex string
-pub(super) fn hex<'a>(
- f: &mut fmt::Formatter<'_>,
- payload: impl IntoIterator<Item = &'a u8>,
-) -> fmt::Result {
- for b in payload {
- write!(f, "{b:02x}")?;
- }
- Ok(())
-}
diff --git a/vendor/rustls/src/msgs/ccs.rs b/vendor/rustls/src/msgs/ccs.rs
deleted file mode 100644
index ac2c9e6a..00000000
--- a/vendor/rustls/src/msgs/ccs.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-use alloc::vec::Vec;
-
-use crate::error::InvalidMessage;
-use crate::msgs::codec::{Codec, Reader};
-
-#[derive(Debug)]
-pub struct ChangeCipherSpecPayload;
-
-impl Codec<'_> for ChangeCipherSpecPayload {
- fn encode(&self, bytes: &mut Vec<u8>) {
- 1u8.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let typ = u8::read(r)?;
- if typ != 1 {
- return Err(InvalidMessage::InvalidCcs);
- }
-
- r.expect_empty("ChangeCipherSpecPayload")
- .map(|_| Self {})
- }
-}
diff --git a/vendor/rustls/src/msgs/codec.rs b/vendor/rustls/src/msgs/codec.rs
deleted file mode 100644
index bd62cd3a..00000000
--- a/vendor/rustls/src/msgs/codec.rs
+++ /dev/null
@@ -1,404 +0,0 @@
-use alloc::vec::Vec;
-use core::fmt::Debug;
-use core::marker::PhantomData;
-
-use crate::error::InvalidMessage;
-
-/// Wrapper over a slice of bytes that allows reading chunks from
-/// with the current position state held using a cursor.
-///
-/// A new reader for a sub section of the buffer can be created
-/// using the `sub` function or a section of a certain length can
-/// be obtained using the `take` function
-pub struct Reader<'a> {
- /// The underlying buffer storing the readers content
- buffer: &'a [u8],
- /// Stores the current reading position for the buffer
- cursor: usize,
-}
-
-impl<'a> Reader<'a> {
- /// Creates a new Reader of the provided `bytes` slice with
- /// the initial cursor position of zero.
- pub fn init(bytes: &'a [u8]) -> Self {
- Reader {
- buffer: bytes,
- cursor: 0,
- }
- }
-
- /// Attempts to create a new Reader on a sub section of this
- /// readers bytes by taking a slice of the provided `length`
- /// will return None if there is not enough bytes
- pub fn sub(&mut self, length: usize) -> Result<Self, InvalidMessage> {
- match self.take(length) {
- Some(bytes) => Ok(Reader::init(bytes)),
- None => Err(InvalidMessage::MessageTooShort),
- }
- }
-
- /// Borrows a slice of all the remaining bytes
- /// that appear after the cursor position.
- ///
- /// Moves the cursor to the end of the buffer length.
- pub fn rest(&mut self) -> &'a [u8] {
- let rest = &self.buffer[self.cursor..];
- self.cursor = self.buffer.len();
- rest
- }
-
- /// Attempts to borrow a slice of bytes from the current
- /// cursor position of `length` if there is not enough
- /// bytes remaining after the cursor to take the length
- /// then None is returned instead.
- pub fn take(&mut self, length: usize) -> Option<&'a [u8]> {
- if self.left() < length {
- return None;
- }
- let current = self.cursor;
- self.cursor += length;
- Some(&self.buffer[current..current + length])
- }
-
- /// Used to check whether the reader has any content left
- /// after the cursor (cursor has not reached end of buffer)
- pub fn any_left(&self) -> bool {
- self.cursor < self.buffer.len()
- }
-
- pub fn expect_empty(&self, name: &'static str) -> Result<(), InvalidMessage> {
- match self.any_left() {
- true => Err(InvalidMessage::TrailingData(name)),
- false => Ok(()),
- }
- }
-
- /// Returns the cursor position which is also the number
- /// of bytes that have been read from the buffer.
- pub fn used(&self) -> usize {
- self.cursor
- }
-
- /// Returns the number of bytes that are still able to be
- /// read (The number of remaining takes)
- pub fn left(&self) -> usize {
- self.buffer.len() - self.cursor
- }
-}
-
-/// Trait for implementing encoding and decoding functionality
-/// on something.
-pub trait Codec<'a>: Debug + Sized {
- /// Function for encoding itself by appending itself to
- /// the provided vec of bytes.
- fn encode(&self, bytes: &mut Vec<u8>);
-
- /// Function for decoding itself from the provided reader
- /// will return Some if the decoding was successful or
- /// None if it was not.
- fn read(_: &mut Reader<'a>) -> Result<Self, InvalidMessage>;
-
- /// Convenience function for encoding the implementation
- /// into a vec and returning it
- fn get_encoding(&self) -> Vec<u8> {
- let mut bytes = Vec::new();
- self.encode(&mut bytes);
- bytes
- }
-
- /// Function for wrapping a call to the read function in
- /// a Reader for the slice of bytes provided
- ///
- /// Returns `Err(InvalidMessage::ExcessData(_))` if
- /// `Self::read` does not read the entirety of `bytes`.
- fn read_bytes(bytes: &'a [u8]) -> Result<Self, InvalidMessage> {
- let mut reader = Reader::init(bytes);
- Self::read(&mut reader).and_then(|r| {
- reader.expect_empty("read_bytes")?;
- Ok(r)
- })
- }
-}
-
-impl Codec<'_> for u8 {
- fn encode(&self, bytes: &mut Vec<u8>) {
- bytes.push(*self);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- match r.take(1) {
- Some(&[byte]) => Ok(byte),
- _ => Err(InvalidMessage::MissingData("u8")),
- }
- }
-}
-
-pub(crate) fn put_u16(v: u16, out: &mut [u8]) {
- let out: &mut [u8; 2] = (&mut out[..2]).try_into().unwrap();
- *out = u16::to_be_bytes(v);
-}
-
-impl Codec<'_> for u16 {
- fn encode(&self, bytes: &mut Vec<u8>) {
- let mut b16 = [0u8; 2];
- put_u16(*self, &mut b16);
- bytes.extend_from_slice(&b16);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- match r.take(2) {
- Some(&[b1, b2]) => Ok(Self::from_be_bytes([b1, b2])),
- _ => Err(InvalidMessage::MissingData("u16")),
- }
- }
-}
-
-// Make a distinct type for u24, even though it's a u32 underneath
-#[allow(non_camel_case_types)]
-#[derive(Debug, Copy, Clone)]
-pub struct u24(pub u32);
-
-#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
-impl From<u24> for usize {
- #[inline]
- fn from(v: u24) -> Self {
- v.0 as Self
- }
-}
-
-impl Codec<'_> for u24 {
- fn encode(&self, bytes: &mut Vec<u8>) {
- let be_bytes = u32::to_be_bytes(self.0);
- bytes.extend_from_slice(&be_bytes[1..]);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- match r.take(3) {
- Some(&[a, b, c]) => Ok(Self(u32::from_be_bytes([0, a, b, c]))),
- _ => Err(InvalidMessage::MissingData("u24")),
- }
- }
-}
-
-impl Codec<'_> for u32 {
- fn encode(&self, bytes: &mut Vec<u8>) {
- bytes.extend(Self::to_be_bytes(*self));
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- match r.take(4) {
- Some(&[a, b, c, d]) => Ok(Self::from_be_bytes([a, b, c, d])),
- _ => Err(InvalidMessage::MissingData("u32")),
- }
- }
-}
-
-pub(crate) fn put_u64(v: u64, bytes: &mut [u8]) {
- let bytes: &mut [u8; 8] = (&mut bytes[..8]).try_into().unwrap();
- *bytes = u64::to_be_bytes(v);
-}
-
-impl Codec<'_> for u64 {
- fn encode(&self, bytes: &mut Vec<u8>) {
- let mut b64 = [0u8; 8];
- put_u64(*self, &mut b64);
- bytes.extend_from_slice(&b64);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- match r.take(8) {
- Some(&[a, b, c, d, e, f, g, h]) => Ok(Self::from_be_bytes([a, b, c, d, e, f, g, h])),
- _ => Err(InvalidMessage::MissingData("u64")),
- }
- }
-}
-
-/// Implement `Codec` for lists of elements that implement `TlsListElement`.
-///
-/// `TlsListElement` provides the size of the length prefix for the list.
-impl<'a, T: Codec<'a> + TlsListElement + Debug> Codec<'a> for Vec<T> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- let nest = LengthPrefixedBuffer::new(T::SIZE_LEN, bytes);
-
- for i in self {
- i.encode(nest.buf);
- }
- }
-
- fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
- let mut ret = Self::new();
- for item in TlsListIter::<T>::new(r)? {
- ret.push(item?);
- }
-
- Ok(ret)
- }
-}
-
-/// An iterator over a vector of `TlsListElements`.
-///
-/// All uses _MUST_ exhaust the iterator, as errors may be delayed
-/// until the last element.
-pub(crate) struct TlsListIter<'a, T: Codec<'a> + TlsListElement + Debug> {
- sub: Reader<'a>,
- _t: PhantomData<T>,
-}
-
-impl<'a, T: Codec<'a> + TlsListElement + Debug> TlsListIter<'a, T> {
- pub(crate) fn new(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
- let len = T::SIZE_LEN.read(r)?;
- let sub = r.sub(len)?;
- Ok(Self {
- sub,
- _t: PhantomData,
- })
- }
-}
-
-impl<'a, T: Codec<'a> + TlsListElement + Debug> Iterator for TlsListIter<'a, T> {
- type Item = Result<T, InvalidMessage>;
-
- fn next(&mut self) -> Option<Self::Item> {
- match self.sub.any_left() {
- true => Some(T::read(&mut self.sub)),
- false => None,
- }
- }
-}
-
-impl Codec<'_> for () {
- fn encode(&self, _: &mut Vec<u8>) {}
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- r.expect_empty("Empty")
- }
-}
-
-/// A trait for types that can be encoded and decoded in a list.
-///
-/// This trait is used to implement `Codec` for `Vec<T>`. Lists in the TLS wire format are
-/// prefixed with a length, the size of which depends on the type of the list elements.
-/// As such, the `Codec` implementation for `Vec<T>` requires an implementation of this trait
-/// for its element type `T`.
-pub(crate) trait TlsListElement {
- const SIZE_LEN: ListLength;
-}
-
-/// The length of the length prefix for a list.
-///
-/// The types that appear in lists are limited to three kinds of length prefixes:
-/// 1, 2, and 3 bytes. For the latter kind, we require a `TlsListElement` implementer
-/// to specify a maximum length and error if the actual length is larger.
-pub(crate) enum ListLength {
- /// U8 but non-empty
- NonZeroU8 { empty_error: InvalidMessage },
-
- /// U16, perhaps empty
- U16,
-
- /// U16 but non-empty
- NonZeroU16 { empty_error: InvalidMessage },
-
- /// U24 with imposed upper bound
- U24 { max: usize, error: InvalidMessage },
-}
-
-impl ListLength {
- pub(crate) fn read(&self, r: &mut Reader<'_>) -> Result<usize, InvalidMessage> {
- Ok(match self {
- Self::NonZeroU8 { empty_error } => match usize::from(u8::read(r)?) {
- 0 => return Err(*empty_error),
- len => len,
- },
- Self::U16 => usize::from(u16::read(r)?),
- Self::NonZeroU16 { empty_error } => match usize::from(u16::read(r)?) {
- 0 => return Err(*empty_error),
- len => len,
- },
- Self::U24 { max, error } => match usize::from(u24::read(r)?) {
- len if len > *max => return Err(*error),
- len => len,
- },
- })
- }
-}
-
-/// Tracks encoding a length-delimited structure in a single pass.
-pub(crate) struct LengthPrefixedBuffer<'a> {
- pub(crate) buf: &'a mut Vec<u8>,
- len_offset: usize,
- size_len: ListLength,
-}
-
-impl<'a> LengthPrefixedBuffer<'a> {
- /// Inserts a dummy length into `buf`, and remembers where it went.
- ///
- /// After this, the body of the length-delimited structure should be appended to `LengthPrefixedBuffer::buf`.
- /// The length header is corrected in `LengthPrefixedBuffer::drop`.
- pub(crate) fn new(size_len: ListLength, buf: &'a mut Vec<u8>) -> Self {
- let len_offset = buf.len();
- buf.extend(match size_len {
- ListLength::NonZeroU8 { .. } => &[0xff][..],
- ListLength::U16 | ListLength::NonZeroU16 { .. } => &[0xff, 0xff],
- ListLength::U24 { .. } => &[0xff, 0xff, 0xff],
- });
-
- Self {
- buf,
- len_offset,
- size_len,
- }
- }
-}
-
-impl Drop for LengthPrefixedBuffer<'_> {
- /// Goes back and corrects the length previously inserted at the start of the structure.
- fn drop(&mut self) {
- match self.size_len {
- ListLength::NonZeroU8 { .. } => {
- let len = self.buf.len() - self.len_offset - 1;
- debug_assert!(len <= 0xff);
- self.buf[self.len_offset] = len as u8;
- }
- ListLength::U16 | ListLength::NonZeroU16 { .. } => {
- let len = self.buf.len() - self.len_offset - 2;
- debug_assert!(len <= 0xffff);
- let out: &mut [u8; 2] = (&mut self.buf[self.len_offset..self.len_offset + 2])
- .try_into()
- .unwrap();
- *out = u16::to_be_bytes(len as u16);
- }
- ListLength::U24 { .. } => {
- let len = self.buf.len() - self.len_offset - 3;
- debug_assert!(len <= 0xff_ffff);
- let len_bytes = u32::to_be_bytes(len as u32);
- let out: &mut [u8; 3] = (&mut self.buf[self.len_offset..self.len_offset + 3])
- .try_into()
- .unwrap();
- out.copy_from_slice(&len_bytes[1..]);
- }
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use std::prelude::v1::*;
- use std::vec;
-
- use super::*;
-
- #[test]
- fn interrupted_length_prefixed_buffer_leaves_maximum_length() {
- let mut buf = Vec::new();
- let nested = LengthPrefixedBuffer::new(ListLength::U16, &mut buf);
- nested.buf.push(0xaa);
- assert_eq!(nested.buf, &vec![0xff, 0xff, 0xaa]);
- // <- if the buffer is accidentally read here, there is no possibility
- // that the contents of the length-prefixed buffer are interpreted
- // as a subsequent encoding (perhaps allowing injection of a different
- // extension)
- drop(nested);
- assert_eq!(buf, vec![0x00, 0x01, 0xaa]);
- }
-}
diff --git a/vendor/rustls/src/msgs/deframer/buffers.rs b/vendor/rustls/src/msgs/deframer/buffers.rs
deleted file mode 100644
index bf098740..00000000
--- a/vendor/rustls/src/msgs/deframer/buffers.rs
+++ /dev/null
@@ -1,296 +0,0 @@
-use alloc::vec::Vec;
-use core::mem;
-use core::ops::Range;
-#[cfg(feature = "std")]
-use std::io;
-
-#[cfg(feature = "std")]
-use crate::msgs::message::MAX_WIRE_SIZE;
-
-/// Conversion from a slice within a larger buffer into
-/// a `Range` offset within.
-#[derive(Debug)]
-pub(crate) struct Locator {
- bounds: Range<*const u8>,
-}
-
-impl Locator {
- #[inline]
- pub(crate) fn new(slice: &[u8]) -> Self {
- Self {
- bounds: slice.as_ptr_range(),
- }
- }
-
- #[inline]
- pub(crate) fn locate(&self, slice: &[u8]) -> Range<usize> {
- let bounds = slice.as_ptr_range();
- debug_assert!(self.fully_contains(slice));
- let start = bounds.start as usize - self.bounds.start as usize;
- let len = bounds.end as usize - bounds.start as usize;
- Range {
- start,
- end: start + len,
- }
- }
-
- #[inline]
- pub(crate) fn fully_contains(&self, slice: &[u8]) -> bool {
- let bounds = slice.as_ptr_range();
- bounds.start >= self.bounds.start && bounds.end <= self.bounds.end
- }
-}
-
-/// Conversion from a `Range` offset to the original slice.
-pub(crate) struct Delocator<'b> {
- slice: &'b [u8],
-}
-
-impl<'b> Delocator<'b> {
- #[inline]
- pub(crate) fn new(slice: &'b [u8]) -> Self {
- Self { slice }
- }
-
- #[inline]
- pub(crate) fn slice_from_range(&'_ self, range: &Range<usize>) -> &'b [u8] {
- // safety: this unwrap is safe so long as `range` came from `locate()`
- // for the same buffer
- self.slice.get(range.clone()).unwrap()
- }
-
- #[inline]
- pub(crate) fn locator(self) -> Locator {
- Locator::new(self.slice)
- }
-}
-
-/// Reordering the underlying buffer based on ranges.
-pub(crate) struct Coalescer<'b> {
- slice: &'b mut [u8],
-}
-
-impl<'b> Coalescer<'b> {
- #[inline]
- pub(crate) fn new(slice: &'b mut [u8]) -> Self {
- Self { slice }
- }
-
- #[inline]
- pub(crate) fn copy_within(&mut self, from: Range<usize>, to: Range<usize>) {
- debug_assert!(from.len() == to.len());
- debug_assert!(self.slice.get(from.clone()).is_some());
- debug_assert!(self.slice.get(to.clone()).is_some());
- self.slice.copy_within(from, to.start);
- }
-
- #[inline]
- pub(crate) fn delocator(self) -> Delocator<'b> {
- Delocator::new(self.slice)
- }
-}
-
-/// Accounting structure tracking progress in parsing a single buffer.
-#[derive(Clone, Debug)]
-pub(crate) struct BufferProgress {
- /// Prefix of the buffer that has been processed so far.
- ///
- /// `processed` may exceed `discard`, that means we have parsed
- /// some buffer, but are still using it. This happens due to
- /// in-place decryption of incoming records, and in-place
- /// reassembly of handshake messages.
- ///
- /// 0 <= processed <= len
- processed: usize,
-
- /// Prefix of the buffer that can be removed.
- ///
- /// If `discard` exceeds `processed`, that means we are ignoring
- /// data without processing it.
- ///
- /// 0 <= discard <= len
- discard: usize,
-}
-
-impl BufferProgress {
- pub(super) fn new(processed: usize) -> Self {
- Self {
- processed,
- discard: 0,
- }
- }
-
- #[inline]
- pub(crate) fn add_discard(&mut self, discard: usize) {
- self.discard += discard;
- }
-
- #[inline]
- pub(crate) fn add_processed(&mut self, processed: usize) {
- self.processed += processed;
- }
-
- #[inline]
- pub(crate) fn take_discard(&mut self) -> usize {
- // the caller is about to discard `discard` bytes
- // from the front of the buffer. adjust `processed`
- // down by the same amount.
- self.processed = self
- .processed
- .saturating_sub(self.discard);
- mem::take(&mut self.discard)
- }
-
- #[inline]
- pub(crate) fn processed(&self) -> usize {
- self.processed
- }
-}
-
-#[derive(Default, Debug)]
-pub(crate) struct DeframerVecBuffer {
- /// Buffer of data read from the socket, in the process of being parsed into messages.
- ///
- /// For buffer size management, checkout out the [`DeframerVecBuffer::prepare_read()`] method.
- buf: Vec<u8>,
-
- /// What size prefix of `buf` is used.
- used: usize,
-}
-
-impl DeframerVecBuffer {
- /// Discard `taken` bytes from the start of our buffer.
- pub(crate) fn discard(&mut self, taken: usize) {
- #[allow(clippy::comparison_chain)]
- if taken < self.used {
- /* Before:
- * +----------+----------+----------+
- * | taken | pending |xxxxxxxxxx|
- * +----------+----------+----------+
- * 0 ^ taken ^ self.used
- *
- * After:
- * +----------+----------+----------+
- * | pending |xxxxxxxxxxxxxxxxxxxxx|
- * +----------+----------+----------+
- * 0 ^ self.used
- */
-
- self.buf
- .copy_within(taken..self.used, 0);
- self.used -= taken;
- } else if taken >= self.used {
- self.used = 0;
- }
- }
-
- pub(crate) fn filled_mut(&mut self) -> &mut [u8] {
- &mut self.buf[..self.used]
- }
-
- pub(crate) fn filled(&self) -> &[u8] {
- &self.buf[..self.used]
- }
-}
-
-#[cfg(feature = "std")]
-impl DeframerVecBuffer {
- /// Read some bytes from `rd`, and add them to the buffer.
- pub(crate) fn read(&mut self, rd: &mut dyn io::Read, in_handshake: bool) -> io::Result<usize> {
- if let Err(err) = self.prepare_read(in_handshake) {
- return Err(io::Error::new(io::ErrorKind::InvalidData, err));
- }
-
- // Try to do the largest reads possible. Note that if
- // we get a message with a length field out of range here,
- // we do a zero length read. That looks like an EOF to
- // the next layer up, which is fine.
- let new_bytes = rd.read(&mut self.buf[self.used..])?;
- self.used += new_bytes;
- Ok(new_bytes)
- }
-
- /// Resize the internal `buf` if necessary for reading more bytes.
- fn prepare_read(&mut self, is_joining_hs: bool) -> Result<(), &'static str> {
- /// TLS allows for handshake messages of up to 16MB. We
- /// restrict that to 64KB to limit potential for denial-of-
- /// service.
- const MAX_HANDSHAKE_SIZE: u32 = 0xffff;
-
- const READ_SIZE: usize = 4096;
-
- // We allow a maximum of 64k of buffered data for handshake messages only. Enforce this
- // by varying the maximum allowed buffer size here based on whether a prefix of a
- // handshake payload is currently being buffered. Given that the first read of such a
- // payload will only ever be 4k bytes, the next time we come around here we allow a
- // larger buffer size. Once the large message and any following handshake messages in
- // the same flight have been consumed, `pop()` will call `discard()` to reset `used`.
- // At this point, the buffer resizing logic below should reduce the buffer size.
- let allow_max = match is_joining_hs {
- true => MAX_HANDSHAKE_SIZE as usize,
- false => MAX_WIRE_SIZE,
- };
-
- if self.used >= allow_max {
- return Err("message buffer full");
- }
-
- // If we can and need to increase the buffer size to allow a 4k read, do so. After
- // dealing with a large handshake message (exceeding `OutboundOpaqueMessage::MAX_WIRE_SIZE`),
- // make sure to reduce the buffer size again (large messages should be rare).
- // Also, reduce the buffer size if there are neither full nor partial messages in it,
- // which usually means that the other side suspended sending data.
- let need_capacity = Ord::min(allow_max, self.used + READ_SIZE);
- if need_capacity > self.buf.len() {
- self.buf.resize(need_capacity, 0);
- } else if self.used == 0 || self.buf.len() > allow_max {
- self.buf.resize(need_capacity, 0);
- self.buf.shrink_to(need_capacity);
- }
-
- Ok(())
- }
-
- /// Append `bytes` to the end of this buffer.
- ///
- /// Return a `Range` saying where it went.
- pub(crate) fn extend(&mut self, bytes: &[u8]) -> Range<usize> {
- let len = bytes.len();
- let start = self.used;
- let end = start + len;
- if self.buf.len() < end {
- self.buf.resize(end, 0);
- }
- self.buf[start..end].copy_from_slice(bytes);
- self.used += len;
- Range { start, end }
- }
-}
-
-/// A borrowed version of [`DeframerVecBuffer`] that tracks discard operations
-#[derive(Debug)]
-pub(crate) struct DeframerSliceBuffer<'a> {
- // a fully initialized buffer that will be deframed
- buf: &'a mut [u8],
- // number of bytes to discard from the front of `buf` at a later time
- discard: usize,
-}
-
-impl<'a> DeframerSliceBuffer<'a> {
- pub(crate) fn new(buf: &'a mut [u8]) -> Self {
- Self { buf, discard: 0 }
- }
-
- /// Tracks a pending discard operation of `num_bytes`
- pub(crate) fn queue_discard(&mut self, num_bytes: usize) {
- self.discard += num_bytes;
- }
-
- pub(crate) fn pending_discard(&self) -> usize {
- self.discard
- }
-
- pub(crate) fn filled_mut(&mut self) -> &mut [u8] {
- &mut self.buf[self.discard..]
- }
-}
diff --git a/vendor/rustls/src/msgs/deframer/handshake.rs b/vendor/rustls/src/msgs/deframer/handshake.rs
deleted file mode 100644
index 0d91f0ea..00000000
--- a/vendor/rustls/src/msgs/deframer/handshake.rs
+++ /dev/null
@@ -1,525 +0,0 @@
-use alloc::vec::Vec;
-use core::mem;
-use core::ops::Range;
-
-use super::buffers::{BufferProgress, Coalescer, Delocator, Locator};
-use crate::error::InvalidMessage;
-use crate::msgs::codec::{Codec, u24};
-use crate::msgs::message::InboundPlainMessage;
-use crate::{ContentType, ProtocolVersion};
-
-#[derive(Debug)]
-pub(crate) struct HandshakeDeframer {
- /// Spans covering individual handshake payloads, in order of receipt.
- spans: Vec<FragmentSpan>,
-
- /// Discard value, tracking the rightmost extent of the last message
- /// in `spans`.
- outer_discard: usize,
-}
-
-impl HandshakeDeframer {
- /// Accepts a message into the deframer.
- ///
- /// `containing_buffer` allows mapping the message payload to its position
- /// in the input buffer, and thereby avoid retaining a borrow on the input
- /// buffer.
- ///
- /// That is required because our processing of handshake messages requires
- /// them to be contiguous (and avoiding that would mean supporting gather-based
- /// parsing in a large number of places, including `core`, `webpki`, and the
- /// `CryptoProvider` interface). `coalesce()` arranges for that to happen, but
- /// to do so it needs to move the fragments together in the original buffer.
- /// This would not be possible if the messages were borrowing from that buffer.
- ///
- /// `outer_discard` is the rightmost extent of the original message.
- pub(crate) fn input_message(
- &mut self,
- msg: InboundPlainMessage<'_>,
- containing_buffer: &Locator,
- outer_discard: usize,
- ) {
- debug_assert_eq!(msg.typ, ContentType::Handshake);
- debug_assert!(containing_buffer.fully_contains(msg.payload));
- debug_assert!(self.outer_discard <= outer_discard);
-
- self.outer_discard = outer_discard;
-
- // if our last span is incomplete, we can blindly add this as a new span --
- // no need to attempt parsing it with `DissectHandshakeIter`.
- //
- // `coalesce()` will later move this new message to be contiguous with
- // `_last_incomplete`, and reparse the result.
- //
- // we cannot merge these processes, because `coalesce` mutates the underlying
- // buffer, and `msg` borrows it.
- if let Some(_last_incomplete) = self
- .spans
- .last()
- .filter(|span| !span.is_complete())
- {
- self.spans.push(FragmentSpan {
- version: msg.version,
- size: None,
- bounds: containing_buffer.locate(msg.payload),
- });
- return;
- }
-
- // otherwise, we can expect `msg` to contain a handshake header introducing
- // a new message (and perhaps several of them.)
- for span in DissectHandshakeIter::new(msg, containing_buffer) {
- self.spans.push(span);
- }
- }
-
- /// Returns a `BufferProgress` that skips over unprocessed handshake data.
- pub(crate) fn progress(&self) -> BufferProgress {
- BufferProgress::new(self.outer_discard)
- }
-
- /// Do we have a message ready? ie, would `iter().next()` return `Some`?
- pub(crate) fn has_message_ready(&self) -> bool {
- match self.spans.first() {
- Some(span) => span.is_complete(),
- None => false,
- }
- }
-
- /// Do we have any message data, partial or otherwise?
- pub(crate) fn is_active(&self) -> bool {
- !self.spans.is_empty()
- }
-
- /// We are "aligned" if there is no partial fragment of a handshake
- /// message.
- pub(crate) fn is_aligned(&self) -> bool {
- self.spans
- .iter()
- .all(|span| span.is_complete())
- }
-
- /// Iterate over the complete messages.
- pub(crate) fn iter<'a, 'b>(&'a mut self, containing_buffer: &'b [u8]) -> HandshakeIter<'a, 'b> {
- HandshakeIter {
- deframer: self,
- containing_buffer: Delocator::new(containing_buffer),
- index: 0,
- }
- }
-
- /// Coalesce the handshake portions of the given buffer,
- /// if needed.
- ///
- /// This does nothing if there is nothing to do.
- ///
- /// In a normal TLS stream, handshake messages need not be contiguous.
- /// For example, each handshake message could be delivered in its own
- /// outer TLS message. This would mean the handshake messages are
- /// separated by the outer TLS message headers, and likely also
- /// separated by encryption overhead (any explicit nonce in front,
- /// any padding and authentication tag afterwards).
- ///
- /// For a toy example of one handshake message in two fragments, and:
- ///
- /// - the letter `h` for handshake header octets
- /// - the letter `H` for handshake payload octets
- /// - the letter `x` for octets in the buffer ignored by this code,
- ///
- /// the buffer and `spans` data structure could look like:
- ///
- /// ```text
- /// 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9
- /// x x x x x h h h h H H H x x x x x H H H H H H x x x
- /// '------------' '----------'
- /// | |
- /// spans = [ { bounds = (5, 12), |
- /// size = Some(9), .. }, |
- /// { bounds = (17, 23), .. } ]
- /// ```
- ///
- /// In this case, `requires_coalesce` returns `Some(0)`. Then
- /// `coalesce_one` moves the second range leftwards:
- ///
- /// ```text
- /// 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9
- /// x x x x x h h h h H H H x x x x x H H H H H H x x x
- /// '----------'
- /// ^ '----------'
- /// | v
- /// '--<---<--'
- /// copy_within(from = (17, 23),
- /// to = (12, 18))
- /// ```
- ///
- /// Leaving the buffer and spans:
- ///
- /// ```text
- /// 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9
- /// x x x x x h h h h H H H H H H H H H x x x x x x x x
- /// '------------------------'
- /// |
- /// spans = [ { bounds = (5, 18), size = Some(9), .. } ]
- /// ```
- pub(crate) fn coalesce(&mut self, containing_buffer: &mut [u8]) -> Result<(), InvalidMessage> {
- // Strategy: while there is work to do, scan `spans`
- // for a pair where the first is not complete. move
- // the second down towards the first, then reparse the contents.
- while let Some(i) = self.requires_coalesce() {
- self.coalesce_one(i, Coalescer::new(containing_buffer));
- }
-
- // check resulting spans pass our imposed length limit
- match self
- .spans
- .iter()
- .any(|span| span.size.unwrap_or_default() > MAX_HANDSHAKE_SIZE)
- {
- true => Err(InvalidMessage::HandshakePayloadTooLarge),
- false => Ok(()),
- }
- }
-
- /// Within `containing_buffer`, move `span[index+1]` to be contiguous
- /// with `span[index]`.
- fn coalesce_one(&mut self, index: usize, mut containing_buffer: Coalescer<'_>) {
- let second = self.spans.remove(index + 1);
- let mut first = self.spans.remove(index);
-
- // move the entirety of `second` to be contiguous with `first`
- let len = second.bounds.len();
- let target = Range {
- start: first.bounds.end,
- end: first.bounds.end + len,
- };
-
- containing_buffer.copy_within(second.bounds, target);
- let delocator = containing_buffer.delocator();
-
- // now adjust `first` to cover both
- first.bounds.end += len;
-
- // finally, attempt to re-dissect `first`
- let msg = InboundPlainMessage {
- typ: ContentType::Handshake,
- version: first.version,
- payload: delocator.slice_from_range(&first.bounds),
- };
-
- for (i, span) in DissectHandshakeIter::new(msg, &delocator.locator()).enumerate() {
- self.spans.insert(index + i, span);
- }
- }
-
- /// We require coalescing if any span except the last is not complete.
- ///
- /// Returns an index into `spans` for the first non-complete span:
- /// this will never be the last item.
- fn requires_coalesce(&self) -> Option<usize> {
- self.spans
- .split_last()
- .and_then(|(_last, elements)| {
- elements
- .iter()
- .enumerate()
- .find_map(|(i, span)| (!span.is_complete()).then_some(i))
- })
- }
-}
-
-impl Default for HandshakeDeframer {
- fn default() -> Self {
- Self {
- // capacity: a typical upper limit on handshake messages in
- // a single flight
- spans: Vec::with_capacity(16),
- outer_discard: 0,
- }
- }
-}
-
-struct DissectHandshakeIter<'a, 'b> {
- version: ProtocolVersion,
- payload: &'b [u8],
- containing_buffer: &'a Locator,
-}
-
-impl<'a, 'b> DissectHandshakeIter<'a, 'b> {
- fn new(msg: InboundPlainMessage<'b>, containing_buffer: &'a Locator) -> Self {
- Self {
- version: msg.version,
- payload: msg.payload,
- containing_buffer,
- }
- }
-}
-
-impl Iterator for DissectHandshakeIter<'_, '_> {
- type Item = FragmentSpan;
-
- fn next(&mut self) -> Option<Self::Item> {
- if self.payload.is_empty() {
- return None;
- }
-
- // If there is not enough data to have a header the length is unknown
- if self.payload.len() < HANDSHAKE_HEADER_LEN {
- let buf = mem::take(&mut self.payload);
- let bounds = self.containing_buffer.locate(buf);
- return Some(FragmentSpan {
- version: self.version,
- size: None,
- bounds: bounds.clone(),
- });
- }
-
- let (header, rest) = mem::take(&mut self.payload).split_at(HANDSHAKE_HEADER_LEN);
-
- // safety: header[1..] is exactly 3 bytes, so `u24::read_bytes` cannot fail
- let size = u24::read_bytes(&header[1..])
- .unwrap()
- .into();
-
- let available = if size < rest.len() {
- self.payload = &rest[size..];
- size
- } else {
- rest.len()
- };
-
- let mut bounds = self.containing_buffer.locate(header);
- bounds.end += available;
- Some(FragmentSpan {
- version: self.version,
- size: Some(size),
- bounds: bounds.clone(),
- })
- }
-}
-
-pub(crate) struct HandshakeIter<'a, 'b> {
- deframer: &'a mut HandshakeDeframer,
- containing_buffer: Delocator<'b>,
- index: usize,
-}
-
-impl<'b> Iterator for HandshakeIter<'_, 'b> {
- type Item = (InboundPlainMessage<'b>, usize);
-
- fn next(&mut self) -> Option<Self::Item> {
- let next_span = self.deframer.spans.get(self.index)?;
-
- if !next_span.is_complete() {
- return None;
- }
-
- // if this is the last handshake message, then we'll end
- // up with an empty `spans` and can discard the remainder
- // of the input buffer.
- let discard = if self.deframer.spans.len() - 1 == self.index {
- mem::take(&mut self.deframer.outer_discard)
- } else {
- 0
- };
-
- self.index += 1;
- Some((
- InboundPlainMessage {
- typ: ContentType::Handshake,
- version: next_span.version,
- payload: self
- .containing_buffer
- .slice_from_range(&next_span.bounds),
- },
- discard,
- ))
- }
-}
-
-impl Drop for HandshakeIter<'_, '_> {
- fn drop(&mut self) {
- self.deframer.spans.drain(..self.index);
- }
-}
-
-#[derive(Debug)]
-struct FragmentSpan {
- /// version taken from containing message.
- version: ProtocolVersion,
-
- /// size of the handshake message body (excluding header)
- ///
- /// `None` means the size is unknown, because `bounds` is not
- /// large enough to encompass a whole header.
- size: Option<usize>,
-
- /// bounds of the handshake message, including header
- bounds: Range<usize>,
-}
-
-impl FragmentSpan {
- /// A `FragmentSpan` is "complete" if its size is known, and its
- /// bounds exactly encompasses one handshake message.
- fn is_complete(&self) -> bool {
- match self.size {
- Some(sz) => sz + HANDSHAKE_HEADER_LEN == self.bounds.len(),
- None => false,
- }
- }
-}
-
-const HANDSHAKE_HEADER_LEN: usize = 1 + 3;
-
-/// TLS allows for handshake messages of up to 16MB. We
-/// restrict that to 64KB to limit potential for denial-of-
-/// service.
-const MAX_HANDSHAKE_SIZE: usize = 0xffff;
-
-#[cfg(test)]
-mod tests {
- use std::vec;
-
- use super::*;
- use crate::msgs::deframer::DeframerIter;
-
- fn add_bytes(hs: &mut HandshakeDeframer, slice: &[u8], within: &[u8]) {
- let msg = InboundPlainMessage {
- typ: ContentType::Handshake,
- version: ProtocolVersion::TLSv1_3,
- payload: slice,
- };
- let locator = Locator::new(within);
- let discard = locator.locate(slice).end;
- hs.input_message(msg, &locator, discard);
- }
-
- #[test]
- fn coalesce() {
- let mut input = vec![0, 0, 0, 0x21, 0, 0, 0, 0, 0x01, 0xff, 0x00, 0x01];
- let mut hs = HandshakeDeframer::default();
-
- add_bytes(&mut hs, &input[3..4], &input);
- assert_eq!(hs.requires_coalesce(), None);
- add_bytes(&mut hs, &input[4..6], &input);
- assert_eq!(hs.requires_coalesce(), Some(0));
- add_bytes(&mut hs, &input[8..10], &input);
- assert_eq!(hs.requires_coalesce(), Some(0));
-
- std::println!("before: {hs:?}");
- hs.coalesce(&mut input).unwrap();
- std::println!("after: {hs:?}");
-
- let (msg, discard) = hs.iter(&input).next().unwrap();
- std::println!("msg {msg:?} discard {discard:?}");
- assert_eq!(msg.typ, ContentType::Handshake);
- assert_eq!(msg.version, ProtocolVersion::TLSv1_3);
- assert_eq!(msg.payload, &[0x21, 0x00, 0x00, 0x01, 0xff]);
-
- input.drain(..discard);
- assert_eq!(input, &[0, 1]);
- }
-
- #[test]
- fn append() {
- let mut input = vec![0, 0, 0, 0x21, 0, 0, 5, 0, 0, 1, 2, 3, 4, 5, 0];
- let mut hs = HandshakeDeframer::default();
-
- add_bytes(&mut hs, &input[3..7], &input);
- add_bytes(&mut hs, &input[9..14], &input);
- assert_eq!(hs.spans.len(), 2);
-
- hs.coalesce(&mut input).unwrap();
- assert_eq!(hs.spans.len(), 1);
-
- let (msg, discard) = std::dbg!(hs.iter(&input).next().unwrap());
- assert_eq!(msg.typ, ContentType::Handshake);
- assert_eq!(msg.version, ProtocolVersion::TLSv1_3);
- assert_eq!(msg.payload, &[0x21, 0x00, 0x00, 0x05, 1, 2, 3, 4, 5]);
-
- input.drain(..discard);
- assert_eq!(input, &[0]);
- }
-
- #[test]
- fn coalesce_rejects_excess_size_message() {
- const X: u8 = 0xff;
- let mut input = vec![0x21, 0x01, 0x00, X, 0x00, 0xab, X];
- let mut hs = HandshakeDeframer::default();
-
- // split header over multiple messages, which motivates doing
- // this check in `coalesce()`
- add_bytes(&mut hs, &input[0..3], &input);
- add_bytes(&mut hs, &input[4..6], &input);
-
- assert_eq!(
- hs.coalesce(&mut input),
- Err(InvalidMessage::HandshakePayloadTooLarge)
- );
- }
-
- #[test]
- fn iter_only_returns_full_messages() {
- let input = [0, 0, 0, 0x21, 0, 0, 1, 0xab, 0x21, 0, 0, 1];
-
- let mut hs = HandshakeDeframer::default();
-
- add_bytes(&mut hs, &input[3..8], &input);
- add_bytes(&mut hs, &input[8..12], &input);
-
- let mut iter = hs.iter(&input);
- let (msg, discard) = iter.next().unwrap();
- assert!(iter.next().is_none());
-
- assert_eq!(msg.typ, ContentType::Handshake);
- assert_eq!(msg.version, ProtocolVersion::TLSv1_3);
- assert_eq!(msg.payload, &[0x21, 0x00, 0x00, 0x01, 0xab]);
- assert_eq!(discard, 0);
- }
-
- #[test]
- fn handshake_flight() {
- // intended to be a realistic example
- let mut input = include_bytes!("../../testdata/handshake-test.1.bin").to_vec();
- let locator = Locator::new(&input);
-
- let mut hs = HandshakeDeframer::default();
-
- let mut iter = DeframerIter::new(&mut input[..]);
-
- while let Some(message) = iter.next() {
- let plain = message.unwrap().into_plain_message();
- std::println!("message {plain:?}");
-
- hs.input_message(plain, &locator, iter.bytes_consumed());
- }
-
- hs.coalesce(&mut input[..]).unwrap();
-
- let mut iter = hs.iter(&input[..]);
- for _ in 0..4 {
- let (msg, discard) = iter.next().unwrap();
- assert!(matches!(
- msg,
- InboundPlainMessage {
- typ: ContentType::Handshake,
- ..
- }
- ));
- assert_eq!(discard, 0);
- }
-
- let (msg, discard) = iter.next().unwrap();
- assert!(matches!(
- msg,
- InboundPlainMessage {
- typ: ContentType::Handshake,
- ..
- }
- ));
- assert_eq!(discard, 4280);
- drop(iter);
-
- input.drain(0..discard);
- assert!(input.is_empty());
- }
-}
diff --git a/vendor/rustls/src/msgs/deframer/mod.rs b/vendor/rustls/src/msgs/deframer/mod.rs
deleted file mode 100644
index 4122b525..00000000
--- a/vendor/rustls/src/msgs/deframer/mod.rs
+++ /dev/null
@@ -1,238 +0,0 @@
-use core::mem;
-
-use crate::error::{Error, InvalidMessage};
-use crate::msgs::codec::Reader;
-use crate::msgs::message::{
- HEADER_SIZE, InboundOpaqueMessage, MessageError, read_opaque_message_header,
-};
-
-pub(crate) mod buffers;
-pub(crate) mod handshake;
-
-/// A deframer of TLS wire messages.
-///
-/// Returns `Some(Ok(_))` containing each `InboundOpaqueMessage` deframed
-/// from the buffer.
-///
-/// Returns `None` if no further messages can be deframed from the
-/// buffer. More data is required for further progress.
-///
-/// Returns `Some(Err(_))` if the peer is not talking TLS, but some
-/// other protocol. The caller should abort the connection, because
-/// the deframer cannot recover.
-///
-/// Call `bytes_consumed()` to learn how many bytes the iterator has
-/// processed from the front of the original buffer. This is only updated
-/// when a message is successfully deframed (ie. `Some(Ok(_))` is returned).
-pub(crate) struct DeframerIter<'a> {
- buf: &'a mut [u8],
- consumed: usize,
-}
-
-impl<'a> DeframerIter<'a> {
- /// Make a new `DeframerIter`
- pub(crate) fn new(buf: &'a mut [u8]) -> Self {
- Self { buf, consumed: 0 }
- }
-
- /// How many bytes were processed successfully from the front
- /// of the buffer passed to `new()`?
- pub(crate) fn bytes_consumed(&self) -> usize {
- self.consumed
- }
-}
-
-impl<'a> Iterator for DeframerIter<'a> {
- type Item = Result<InboundOpaqueMessage<'a>, Error>;
-
- fn next(&mut self) -> Option<Self::Item> {
- let mut reader = Reader::init(self.buf);
-
- let (typ, version, len) = match read_opaque_message_header(&mut reader) {
- Ok(header) => header,
- Err(err) => {
- let err = match err {
- MessageError::TooShortForHeader | MessageError::TooShortForLength => {
- return None;
- }
- MessageError::InvalidEmptyPayload => InvalidMessage::InvalidEmptyPayload,
- MessageError::MessageTooLarge => InvalidMessage::MessageTooLarge,
- MessageError::InvalidContentType => InvalidMessage::InvalidContentType,
- MessageError::UnknownProtocolVersion => InvalidMessage::UnknownProtocolVersion,
- };
- return Some(Err(err.into()));
- }
- };
-
- let end = HEADER_SIZE + len as usize;
-
- self.buf.get(HEADER_SIZE..end)?;
-
- // we now have a TLS header and body on the front of `self.buf`. remove
- // it from the front.
- let (consumed, remainder) = mem::take(&mut self.buf).split_at_mut(end);
- self.buf = remainder;
- self.consumed += end;
-
- Some(Ok(InboundOpaqueMessage::new(
- typ,
- version,
- &mut consumed[HEADER_SIZE..],
- )))
- }
-}
-
-pub fn fuzz_deframer(data: &[u8]) {
- let mut buf = data.to_vec();
- let mut iter = DeframerIter::new(&mut buf);
-
- for message in iter.by_ref() {
- if message.is_err() {
- break;
- }
- }
-
- assert!(iter.bytes_consumed() <= buf.len());
-}
-
-#[cfg(feature = "std")]
-#[cfg(test)]
-mod tests {
- use alloc::vec::Vec;
- use std::prelude::v1::*;
-
- use super::*;
- use crate::ContentType;
-
- #[test]
- fn iterator_empty_before_header_received() {
- assert!(
- DeframerIter::new(&mut [])
- .next()
- .is_none()
- );
- assert!(
- DeframerIter::new(&mut [0x16])
- .next()
- .is_none()
- );
- assert!(
- DeframerIter::new(&mut [0x16, 0x03])
- .next()
- .is_none()
- );
- assert!(
- DeframerIter::new(&mut [0x16, 0x03, 0x03])
- .next()
- .is_none()
- );
- assert!(
- DeframerIter::new(&mut [0x16, 0x03, 0x03, 0x00])
- .next()
- .is_none()
- );
- assert!(
- DeframerIter::new(&mut [0x16, 0x03, 0x03, 0x00, 0x01])
- .next()
- .is_none()
- );
- }
-
- #[test]
- fn iterate_one_message() {
- let mut buffer = [0x17, 0x03, 0x03, 0x00, 0x01, 0x00];
- let mut iter = DeframerIter::new(&mut buffer);
- assert_eq!(
- iter.next().unwrap().unwrap().typ,
- ContentType::ApplicationData
- );
- assert_eq!(iter.bytes_consumed(), 6);
- assert!(iter.next().is_none());
- }
-
- #[test]
- fn iterate_two_messages() {
- let mut buffer = [
- 0x16, 0x03, 0x03, 0x00, 0x01, 0x00, 0x17, 0x03, 0x03, 0x00, 0x01, 0x00,
- ];
- let mut iter = DeframerIter::new(&mut buffer);
- assert_eq!(iter.next().unwrap().unwrap().typ, ContentType::Handshake);
- assert_eq!(iter.bytes_consumed(), 6);
- assert_eq!(
- iter.next().unwrap().unwrap().typ,
- ContentType::ApplicationData
- );
- assert_eq!(iter.bytes_consumed(), 12);
- assert!(iter.next().is_none());
- }
-
- #[test]
- fn iterator_invalid_protocol_version_rejected() {
- let mut buffer = include_bytes!("../../testdata/deframer-invalid-version.bin").to_vec();
- let mut iter = DeframerIter::new(&mut buffer);
- assert_eq!(
- iter.next().unwrap().err(),
- Some(Error::InvalidMessage(
- InvalidMessage::UnknownProtocolVersion
- ))
- );
- }
-
- #[test]
- fn iterator_invalid_content_type_rejected() {
- let mut buffer = include_bytes!("../../testdata/deframer-invalid-contenttype.bin").to_vec();
- let mut iter = DeframerIter::new(&mut buffer);
- assert_eq!(
- iter.next().unwrap().err(),
- Some(Error::InvalidMessage(InvalidMessage::InvalidContentType))
- );
- }
-
- #[test]
- fn iterator_excess_message_length_rejected() {
- let mut buffer = include_bytes!("../../testdata/deframer-invalid-length.bin").to_vec();
- let mut iter = DeframerIter::new(&mut buffer);
- assert_eq!(
- iter.next().unwrap().err(),
- Some(Error::InvalidMessage(InvalidMessage::MessageTooLarge))
- );
- }
-
- #[test]
- fn iterator_zero_message_length_rejected() {
- let mut buffer = include_bytes!("../../testdata/deframer-invalid-empty.bin").to_vec();
- let mut iter = DeframerIter::new(&mut buffer);
- assert_eq!(
- iter.next().unwrap().err(),
- Some(Error::InvalidMessage(InvalidMessage::InvalidEmptyPayload))
- );
- }
-
- #[test]
- fn iterator_over_many_messages() {
- let client_hello = include_bytes!("../../testdata/deframer-test.1.bin");
- let mut buffer = Vec::with_capacity(3 * client_hello.len());
- buffer.extend(client_hello);
- buffer.extend(client_hello);
- buffer.extend(client_hello);
- let mut iter = DeframerIter::new(&mut buffer);
- let mut count = 0;
-
- for message in iter.by_ref() {
- let message = message.unwrap();
- assert_eq!(ContentType::Handshake, message.typ);
- count += 1;
- }
-
- assert_eq!(count, 3);
- assert_eq!(client_hello.len() * 3, iter.bytes_consumed());
- }
-
- #[test]
- fn exercise_fuzz_deframer() {
- fuzz_deframer(&[0xff, 0xff, 0xff, 0xff, 0xff]);
- for prefix in 0..7 {
- fuzz_deframer(&[0x16, 0x03, 0x03, 0x00, 0x01, 0xff][..prefix]);
- }
- }
-}
diff --git a/vendor/rustls/src/msgs/enums.rs b/vendor/rustls/src/msgs/enums.rs
deleted file mode 100644
index 6eaa2b32..00000000
--- a/vendor/rustls/src/msgs/enums.rs
+++ /dev/null
@@ -1,510 +0,0 @@
-#![allow(clippy::upper_case_acronyms)]
-#![allow(non_camel_case_types)]
-use crate::crypto::{KeyExchangeAlgorithm, hash};
-use crate::msgs::codec::{Codec, Reader};
-
-enum_builder! {
- /// The `HashAlgorithm` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u8)]
- pub enum HashAlgorithm {
- NONE => 0x00,
- MD5 => 0x01,
- SHA1 => 0x02,
- SHA224 => 0x03,
- SHA256 => 0x04,
- SHA384 => 0x05,
- SHA512 => 0x06,
- }
-}
-
-impl HashAlgorithm {
- /// Returns the hash of the empty input.
- ///
- /// This returns `None` for some hash algorithms, so the caller
- /// should be prepared to do the computation themselves in this case.
- pub(crate) fn hash_for_empty_input(&self) -> Option<hash::Output> {
- match self {
- Self::SHA256 => Some(hash::Output::new(
- b"\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\
- \x9a\xfb\xf4\xc8\x99\x6f\xb9\x24\
- \x27\xae\x41\xe4\x64\x9b\x93\x4c\
- \xa4\x95\x99\x1b\x78\x52\xb8\x55",
- )),
- Self::SHA384 => Some(hash::Output::new(
- b"\x38\xb0\x60\xa7\x51\xac\x96\x38\
- \x4c\xd9\x32\x7e\xb1\xb1\xe3\x6a\
- \x21\xfd\xb7\x11\x14\xbe\x07\x43\
- \x4c\x0c\xc7\xbf\x63\xf6\xe1\xda\
- \x27\x4e\xde\xbf\xe7\x6f\x65\xfb\
- \xd5\x1a\xd2\xf1\x48\x98\xb9\x5b",
- )),
- _ => None,
- }
- }
-}
-
-enum_builder! {
- /// The `ClientCertificateType` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u8)]
- pub(crate) enum ClientCertificateType {
- RSASign => 0x01,
- DSSSign => 0x02,
- RSAFixedDH => 0x03,
- DSSFixedDH => 0x04,
- RSAEphemeralDH => 0x05,
- DSSEphemeralDH => 0x06,
- FortezzaDMS => 0x14,
- ECDSASign => 0x40,
- RSAFixedECDH => 0x41,
- ECDSAFixedECDH => 0x42,
- }
-}
-
-enum_builder! {
- /// The `Compression` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u8)]
- pub enum Compression {
- Null => 0x00,
- Deflate => 0x01,
- LSZ => 0x40,
- }
-}
-
-enum_builder! {
- /// The `AlertLevel` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u8)]
- pub enum AlertLevel {
- Warning => 0x01,
- Fatal => 0x02,
- }
-}
-
-enum_builder! {
- /// The `HeartbeatMessageType` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u8)]
- pub(crate) enum HeartbeatMessageType {
- Request => 0x01,
- Response => 0x02,
- }
-}
-
-enum_builder! {
- /// The `ExtensionType` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u16)]
- pub enum ExtensionType {
- ServerName => 0x0000,
- MaxFragmentLength => 0x0001,
- ClientCertificateUrl => 0x0002,
- TrustedCAKeys => 0x0003,
- TruncatedHMAC => 0x0004,
- StatusRequest => 0x0005,
- UserMapping => 0x0006,
- ClientAuthz => 0x0007,
- ServerAuthz => 0x0008,
- CertificateType => 0x0009,
- EllipticCurves => 0x000a,
- ECPointFormats => 0x000b,
- SRP => 0x000c,
- SignatureAlgorithms => 0x000d,
- UseSRTP => 0x000e,
- Heartbeat => 0x000f,
- ALProtocolNegotiation => 0x0010,
- SCT => 0x0012,
- ClientCertificateType => 0x0013,
- ServerCertificateType => 0x0014,
- Padding => 0x0015,
- ExtendedMasterSecret => 0x0017,
- CompressCertificate => 0x001b,
- SessionTicket => 0x0023,
- PreSharedKey => 0x0029,
- EarlyData => 0x002a,
- SupportedVersions => 0x002b,
- Cookie => 0x002c,
- PSKKeyExchangeModes => 0x002d,
- TicketEarlyDataInfo => 0x002e,
- CertificateAuthorities => 0x002f,
- OIDFilters => 0x0030,
- PostHandshakeAuth => 0x0031,
- SignatureAlgorithmsCert => 0x0032,
- KeyShare => 0x0033,
- TransportParameters => 0x0039,
- NextProtocolNegotiation => 0x3374,
- ChannelId => 0x754f,
- RenegotiationInfo => 0xff01,
- TransportParametersDraft => 0xffa5,
- EncryptedClientHello => 0xfe0d, // https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#section-11.1
- EncryptedClientHelloOuterExtensions => 0xfd00, // https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#section-5.1
- }
-}
-
-impl ExtensionType {
- /// Returns true if the extension type can be compressed in an "inner" client hello for ECH.
- ///
- /// This function should only return true for extension types where the inner hello and outer
- /// hello extensions values will always be identical. Extensions that may be identical
- /// sometimes (e.g. server name, cert compression methods), but not always, SHOULD NOT be
- /// compressed.
- ///
- /// See [draft-ietf-esni-18 §5](https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#section-5)
- /// and [draft-ietf-esni-18 §10.5](https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#section-10.5)
- /// for more information.
- pub(crate) fn ech_compress(&self) -> bool {
- // We match which extensions we will compress with BoringSSL and Go's stdlib.
- matches!(
- self,
- Self::StatusRequest
- | Self::EllipticCurves
- | Self::SignatureAlgorithms
- | Self::SignatureAlgorithmsCert
- | Self::ALProtocolNegotiation
- | Self::SupportedVersions
- | Self::Cookie
- | Self::KeyShare
- | Self::PSKKeyExchangeModes
- )
- }
-}
-
-enum_builder! {
- /// The `ServerNameType` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u8)]
- pub(crate) enum ServerNameType {
- HostName => 0x00,
- }
-}
-
-enum_builder! {
- /// The `NamedCurve` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- ///
- /// This enum is used for recognizing elliptic curve parameters advertised
- /// by a peer during a TLS handshake. It is **not** a list of curves that
- /// Rustls supports. See [`crate::crypto::ring::kx_group`] for the list of supported
- /// elliptic curve groups.
- #[repr(u16)]
- pub(crate) enum NamedCurve {
- sect163k1 => 0x0001,
- sect163r1 => 0x0002,
- sect163r2 => 0x0003,
- sect193r1 => 0x0004,
- sect193r2 => 0x0005,
- sect233k1 => 0x0006,
- sect233r1 => 0x0007,
- sect239k1 => 0x0008,
- sect283k1 => 0x0009,
- sect283r1 => 0x000a,
- sect409k1 => 0x000b,
- sect409r1 => 0x000c,
- sect571k1 => 0x000d,
- sect571r1 => 0x000e,
- secp160k1 => 0x000f,
- secp160r1 => 0x0010,
- secp160r2 => 0x0011,
- secp192k1 => 0x0012,
- secp192r1 => 0x0013,
- secp224k1 => 0x0014,
- secp224r1 => 0x0015,
- secp256k1 => 0x0016,
- secp256r1 => 0x0017,
- secp384r1 => 0x0018,
- secp521r1 => 0x0019,
- brainpoolp256r1 => 0x001a,
- brainpoolp384r1 => 0x001b,
- brainpoolp512r1 => 0x001c,
- X25519 => 0x001d,
- X448 => 0x001e,
- arbitrary_explicit_prime_curves => 0xff01,
- arbitrary_explicit_char2_curves => 0xff02,
- }
-}
-
-enum_builder! {
- /// The `NamedGroup` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u16)]
- pub enum NamedGroup {
- secp256r1 => 0x0017,
- secp384r1 => 0x0018,
- secp521r1 => 0x0019,
- X25519 => 0x001d,
- X448 => 0x001e,
- FFDHE2048 => 0x0100,
- FFDHE3072 => 0x0101,
- FFDHE4096 => 0x0102,
- FFDHE6144 => 0x0103,
- FFDHE8192 => 0x0104,
- MLKEM512 => 0x0200,
- MLKEM768 => 0x0201,
- MLKEM1024 => 0x0202,
- secp256r1MLKEM768 => 0x11eb,
- X25519MLKEM768 => 0x11ec,
- }
-}
-
-impl NamedGroup {
- /// Return the key exchange algorithm associated with this `NamedGroup`
- pub fn key_exchange_algorithm(self) -> KeyExchangeAlgorithm {
- match u16::from(self) {
- x if (0x100..0x200).contains(&x) => KeyExchangeAlgorithm::DHE,
- _ => KeyExchangeAlgorithm::ECDHE,
- }
- }
-}
-
-enum_builder! {
- /// The `ECPointFormat` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u8)]
- pub enum ECPointFormat {
- Uncompressed => 0x00,
- ANSIX962CompressedPrime => 0x01,
- ANSIX962CompressedChar2 => 0x02,
- }
-}
-
-enum_builder! {
- /// The `HeartbeatMode` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u8)]
- pub(crate) enum HeartbeatMode {
- PeerAllowedToSend => 0x01,
- PeerNotAllowedToSend => 0x02,
- }
-}
-
-enum_builder! {
- /// The `ECCurveType` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u8)]
- pub(crate) enum ECCurveType {
- ExplicitPrime => 0x01,
- ExplicitChar2 => 0x02,
- NamedCurve => 0x03,
- }
-}
-
-enum_builder! {
- /// The `PskKeyExchangeMode` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u8)]
- pub enum PskKeyExchangeMode {
- PSK_KE => 0x00,
- PSK_DHE_KE => 0x01,
- }
-}
-
-enum_builder! {
- /// The `KeyUpdateRequest` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u8)]
- pub enum KeyUpdateRequest {
- UpdateNotRequested => 0x00,
- UpdateRequested => 0x01,
- }
-}
-
-enum_builder! {
- /// The `CertificateStatusType` TLS protocol enum. Values in this enum are taken
- /// from the various RFCs covering TLS, and are listed by IANA.
- /// The `Unknown` item is used when processing unrecognised ordinals.
- #[repr(u8)]
- pub enum CertificateStatusType {
- OCSP => 0x01,
- }
-}
-
-enum_builder! {
- /// The Key Encapsulation Mechanism (`Kem`) type for HPKE operations.
- /// Listed by IANA, as specified in [RFC 9180 Section 7.1]
- ///
- /// [RFC 9180 Section 7.1]: <https://datatracker.ietf.org/doc/html/rfc9180#kemid-values>
- #[repr(u16)]
- pub enum HpkeKem {
- DHKEM_P256_HKDF_SHA256 => 0x0010,
- DHKEM_P384_HKDF_SHA384 => 0x0011,
- DHKEM_P521_HKDF_SHA512 => 0x0012,
- DHKEM_X25519_HKDF_SHA256 => 0x0020,
- DHKEM_X448_HKDF_SHA512 => 0x0021,
- }
-}
-
-enum_builder! {
- /// The Key Derivation Function (`Kdf`) type for HPKE operations.
- /// Listed by IANA, as specified in [RFC 9180 Section 7.2]
- ///
- /// [RFC 9180 Section 7.2]: <https://datatracker.ietf.org/doc/html/rfc9180#name-key-derivation-functions-kd>
- #[repr(u16)]
- pub enum HpkeKdf {
- HKDF_SHA256 => 0x0001,
- HKDF_SHA384 => 0x0002,
- HKDF_SHA512 => 0x0003,
- }
-}
-
-impl Default for HpkeKdf {
- // TODO(XXX): revisit the default configuration. This is just what Cloudflare ships right now.
- fn default() -> Self {
- Self::HKDF_SHA256
- }
-}
-
-enum_builder! {
- /// The Authenticated Encryption with Associated Data (`Aead`) type for HPKE operations.
- /// Listed by IANA, as specified in [RFC 9180 Section 7.3]
- ///
- /// [RFC 9180 Section 7.3]: <https://datatracker.ietf.org/doc/html/rfc9180#name-authenticated-encryption-wi>
- #[repr(u16)]
- pub enum HpkeAead {
- AES_128_GCM => 0x0001,
- AES_256_GCM => 0x0002,
- CHACHA20_POLY_1305 => 0x0003,
- EXPORT_ONLY => 0xFFFF,
- }
-}
-
-impl HpkeAead {
- /// Returns the length of the tag for the AEAD algorithm, or none if the AEAD is EXPORT_ONLY.
- pub(crate) fn tag_len(&self) -> Option<usize> {
- match self {
- // See RFC 9180 Section 7.3, column `Nt`, the length in bytes of the authentication tag
- // for the algorithm.
- // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.3
- Self::AES_128_GCM | Self::AES_256_GCM | Self::CHACHA20_POLY_1305 => Some(16),
- _ => None,
- }
- }
-}
-
-impl Default for HpkeAead {
- // TODO(XXX): revisit the default configuration. This is just what Cloudflare ships right now.
- fn default() -> Self {
- Self::AES_128_GCM
- }
-}
-
-enum_builder! {
- /// The Encrypted Client Hello protocol version (`EchVersion`).
- ///
- /// Specified in [draft-ietf-tls-esni Section 4].
- /// TODO(XXX): Update reference once RFC is published.
- ///
- /// [draft-ietf-tls-esni Section 4]: <https://www.ietf.org/archive/id/draft-ietf-tls-esni-17.html#section-4>
- #[repr(u16)]
- pub enum EchVersion {
- V18 => 0xfe0d,
- }
-}
-
-#[cfg(test)]
-pub(crate) mod tests {
- // These tests are intended to provide coverage and
- // check panic-safety of relatively unused values.
-
- use std::prelude::v1::*;
-
- use super::*;
-
- #[test]
- fn test_enums() {
- test_enum8::<HashAlgorithm>(HashAlgorithm::NONE, HashAlgorithm::SHA512);
- test_enum8::<ClientCertificateType>(
- ClientCertificateType::RSASign,
- ClientCertificateType::ECDSAFixedECDH,
- );
- test_enum8::<Compression>(Compression::Null, Compression::LSZ);
- test_enum8::<AlertLevel>(AlertLevel::Warning, AlertLevel::Fatal);
- test_enum8::<HeartbeatMessageType>(
- HeartbeatMessageType::Request,
- HeartbeatMessageType::Response,
- );
- test_enum16::<ExtensionType>(ExtensionType::ServerName, ExtensionType::RenegotiationInfo);
- test_enum8::<ServerNameType>(ServerNameType::HostName, ServerNameType::HostName);
- test_enum16::<NamedCurve>(
- NamedCurve::sect163k1,
- NamedCurve::arbitrary_explicit_char2_curves,
- );
- test_enum16::<NamedGroup>(NamedGroup::secp256r1, NamedGroup::FFDHE8192);
- test_enum8::<ECPointFormat>(
- ECPointFormat::Uncompressed,
- ECPointFormat::ANSIX962CompressedChar2,
- );
- test_enum8::<HeartbeatMode>(
- HeartbeatMode::PeerAllowedToSend,
- HeartbeatMode::PeerNotAllowedToSend,
- );
- test_enum8::<ECCurveType>(ECCurveType::ExplicitPrime, ECCurveType::NamedCurve);
- test_enum8::<PskKeyExchangeMode>(
- PskKeyExchangeMode::PSK_KE,
- PskKeyExchangeMode::PSK_DHE_KE,
- );
- test_enum8::<KeyUpdateRequest>(
- KeyUpdateRequest::UpdateNotRequested,
- KeyUpdateRequest::UpdateRequested,
- );
- test_enum8::<CertificateStatusType>(
- CertificateStatusType::OCSP,
- CertificateStatusType::OCSP,
- );
- }
-
- pub(crate) fn test_enum8<T: for<'a> Codec<'a>>(first: T, last: T) {
- let first_v = get8(&first);
- let last_v = get8(&last);
-
- for val in first_v..last_v + 1 {
- let mut buf = Vec::new();
- val.encode(&mut buf);
- assert_eq!(buf.len(), 1);
-
- let t = T::read_bytes(&buf).unwrap();
- assert_eq!(val, get8(&t));
- }
- }
-
- pub(crate) fn test_enum16<T: for<'a> Codec<'a>>(first: T, last: T) {
- let first_v = get16(&first);
- let last_v = get16(&last);
-
- for val in first_v..last_v + 1 {
- let mut buf = Vec::new();
- val.encode(&mut buf);
- assert_eq!(buf.len(), 2);
-
- let t = T::read_bytes(&buf).unwrap();
- assert_eq!(val, get16(&t));
- }
- }
-
- fn get8<T: for<'a> Codec<'a>>(enum_value: &T) -> u8 {
- let enc = enum_value.get_encoding();
- assert_eq!(enc.len(), 1);
- enc[0]
- }
-
- fn get16<T: for<'a> Codec<'a>>(enum_value: &T) -> u16 {
- let enc = enum_value.get_encoding();
- assert_eq!(enc.len(), 2);
- (enc[0] as u16 >> 8) | (enc[1] as u16)
- }
-}
diff --git a/vendor/rustls/src/msgs/ffdhe_groups.rs b/vendor/rustls/src/msgs/ffdhe_groups.rs
deleted file mode 100644
index ac105b59..00000000
--- a/vendor/rustls/src/msgs/ffdhe_groups.rs
+++ /dev/null
@@ -1,323 +0,0 @@
-//! This module contains parameters for FFDHE named groups as defined
-//! in [RFC 7919 Appendix A](https://datatracker.ietf.org/doc/html/rfc7919#appendix-A).
-
-use crate::NamedGroup;
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-/// Parameters of an FFDHE group, with Big-endian byte order
-pub struct FfdheGroup<'a> {
- pub p: &'a [u8],
- pub g: &'a [u8],
-}
-
-impl FfdheGroup<'static> {
- /// Return the `FfdheGroup` corresponding to the provided `NamedGroup`
- /// if it is indeed an FFDHE group
- #[deprecated(
- since = "0.23.13",
- note = "This function is linker-unfriendly. Use `SupportedKxGroup::ffdhe_group()` instead"
- )]
- pub fn from_named_group(named_group: NamedGroup) -> Option<Self> {
- match named_group {
- NamedGroup::FFDHE2048 => Some(FFDHE2048),
- NamedGroup::FFDHE3072 => Some(FFDHE3072),
- NamedGroup::FFDHE4096 => Some(FFDHE4096),
- NamedGroup::FFDHE6144 => Some(FFDHE6144),
- NamedGroup::FFDHE8192 => Some(FFDHE8192),
- _ => None,
- }
- }
-}
-
-impl<'a> FfdheGroup<'a> {
- /// Return the `NamedGroup` for the `FfdheGroup` if it represents one.
- #[deprecated(
- since = "0.23.13",
- note = "This function is linker-unfriendly. Use `SupportedKxGroup::name()` instead"
- )]
- pub fn named_group(&self) -> Option<NamedGroup> {
- match *self {
- FFDHE2048 => Some(NamedGroup::FFDHE2048),
- FFDHE3072 => Some(NamedGroup::FFDHE3072),
- FFDHE4096 => Some(NamedGroup::FFDHE4096),
- FFDHE6144 => Some(NamedGroup::FFDHE6144),
- FFDHE8192 => Some(NamedGroup::FFDHE8192),
- _ => None,
- }
- }
-
- /// Construct an `FfdheGroup` from the given `p` and `g`, trimming any potential leading zeros.
- pub fn from_params_trimming_leading_zeros(p: &'a [u8], g: &'a [u8]) -> Self {
- fn trim_leading_zeros(buf: &[u8]) -> &[u8] {
- for start in 0..buf.len() {
- if buf[start] != 0 {
- return &buf[start..];
- }
- }
- &[]
- }
-
- FfdheGroup {
- p: trim_leading_zeros(p),
- g: trim_leading_zeros(g),
- }
- }
-}
-
-/// FFDHE2048 group defined in [RFC 7919 Appendix A.1]
-///
-/// [RFC 7919 Appendix A.1]: https://datatracker.ietf.org/doc/html/rfc7919#appendix-A.1
-pub const FFDHE2048: FfdheGroup<'static> = FfdheGroup {
- p: &[
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0xf8, 0x54, 0x58, 0xa2, 0xbb, 0x4a,
- 0x9a, 0xaf, 0xdc, 0x56, 0x20, 0x27, 0x3d, 0x3c, 0xf1, 0xd8, 0xb9, 0xc5, 0x83, 0xce, 0x2d,
- 0x36, 0x95, 0xa9, 0xe1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xfb, 0xcc, 0x93, 0x9d, 0xce, 0x24,
- 0x9b, 0x3e, 0xf9, 0x7d, 0x2f, 0xe3, 0x63, 0x63, 0x0c, 0x75, 0xd8, 0xf6, 0x81, 0xb2, 0x02,
- 0xae, 0xc4, 0x61, 0x7a, 0xd3, 0xdf, 0x1e, 0xd5, 0xd5, 0xfd, 0x65, 0x61, 0x24, 0x33, 0xf5,
- 0x1f, 0x5f, 0x06, 0x6e, 0xd0, 0x85, 0x63, 0x65, 0x55, 0x3d, 0xed, 0x1a, 0xf3, 0xb5, 0x57,
- 0x13, 0x5e, 0x7f, 0x57, 0xc9, 0x35, 0x98, 0x4f, 0x0c, 0x70, 0xe0, 0xe6, 0x8b, 0x77, 0xe2,
- 0xa6, 0x89, 0xda, 0xf3, 0xef, 0xe8, 0x72, 0x1d, 0xf1, 0x58, 0xa1, 0x36, 0xad, 0xe7, 0x35,
- 0x30, 0xac, 0xca, 0x4f, 0x48, 0x3a, 0x79, 0x7a, 0xbc, 0x0a, 0xb1, 0x82, 0xb3, 0x24, 0xfb,
- 0x61, 0xd1, 0x08, 0xa9, 0x4b, 0xb2, 0xc8, 0xe3, 0xfb, 0xb9, 0x6a, 0xda, 0xb7, 0x60, 0xd7,
- 0xf4, 0x68, 0x1d, 0x4f, 0x42, 0xa3, 0xde, 0x39, 0x4d, 0xf4, 0xae, 0x56, 0xed, 0xe7, 0x63,
- 0x72, 0xbb, 0x19, 0x0b, 0x07, 0xa7, 0xc8, 0xee, 0x0a, 0x6d, 0x70, 0x9e, 0x02, 0xfc, 0xe1,
- 0xcd, 0xf7, 0xe2, 0xec, 0xc0, 0x34, 0x04, 0xcd, 0x28, 0x34, 0x2f, 0x61, 0x91, 0x72, 0xfe,
- 0x9c, 0xe9, 0x85, 0x83, 0xff, 0x8e, 0x4f, 0x12, 0x32, 0xee, 0xf2, 0x81, 0x83, 0xc3, 0xfe,
- 0x3b, 0x1b, 0x4c, 0x6f, 0xad, 0x73, 0x3b, 0xb5, 0xfc, 0xbc, 0x2e, 0xc2, 0x20, 0x05, 0xc5,
- 0x8e, 0xf1, 0x83, 0x7d, 0x16, 0x83, 0xb2, 0xc6, 0xf3, 0x4a, 0x26, 0xc1, 0xb2, 0xef, 0xfa,
- 0x88, 0x6b, 0x42, 0x38, 0x61, 0x28, 0x5c, 0x97, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff,
- ],
- g: &[2],
-};
-
-/// FFDHE3072 group defined in [RFC 7919 Appendix A.2]
-///
-/// [RFC 7919 Appendix A.2]: https://datatracker.ietf.org/doc/html/rfc7919#appendix-A.2
-pub const FFDHE3072: FfdheGroup<'static> = FfdheGroup {
- p: &[
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0xf8, 0x54, 0x58, 0xa2, 0xbb, 0x4a,
- 0x9a, 0xaf, 0xdc, 0x56, 0x20, 0x27, 0x3d, 0x3c, 0xf1, 0xd8, 0xb9, 0xc5, 0x83, 0xce, 0x2d,
- 0x36, 0x95, 0xa9, 0xe1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xfb, 0xcc, 0x93, 0x9d, 0xce, 0x24,
- 0x9b, 0x3e, 0xf9, 0x7d, 0x2f, 0xe3, 0x63, 0x63, 0x0c, 0x75, 0xd8, 0xf6, 0x81, 0xb2, 0x02,
- 0xae, 0xc4, 0x61, 0x7a, 0xd3, 0xdf, 0x1e, 0xd5, 0xd5, 0xfd, 0x65, 0x61, 0x24, 0x33, 0xf5,
- 0x1f, 0x5f, 0x06, 0x6e, 0xd0, 0x85, 0x63, 0x65, 0x55, 0x3d, 0xed, 0x1a, 0xf3, 0xb5, 0x57,
- 0x13, 0x5e, 0x7f, 0x57, 0xc9, 0x35, 0x98, 0x4f, 0x0c, 0x70, 0xe0, 0xe6, 0x8b, 0x77, 0xe2,
- 0xa6, 0x89, 0xda, 0xf3, 0xef, 0xe8, 0x72, 0x1d, 0xf1, 0x58, 0xa1, 0x36, 0xad, 0xe7, 0x35,
- 0x30, 0xac, 0xca, 0x4f, 0x48, 0x3a, 0x79, 0x7a, 0xbc, 0x0a, 0xb1, 0x82, 0xb3, 0x24, 0xfb,
- 0x61, 0xd1, 0x08, 0xa9, 0x4b, 0xb2, 0xc8, 0xe3, 0xfb, 0xb9, 0x6a, 0xda, 0xb7, 0x60, 0xd7,
- 0xf4, 0x68, 0x1d, 0x4f, 0x42, 0xa3, 0xde, 0x39, 0x4d, 0xf4, 0xae, 0x56, 0xed, 0xe7, 0x63,
- 0x72, 0xbb, 0x19, 0x0b, 0x07, 0xa7, 0xc8, 0xee, 0x0a, 0x6d, 0x70, 0x9e, 0x02, 0xfc, 0xe1,
- 0xcd, 0xf7, 0xe2, 0xec, 0xc0, 0x34, 0x04, 0xcd, 0x28, 0x34, 0x2f, 0x61, 0x91, 0x72, 0xfe,
- 0x9c, 0xe9, 0x85, 0x83, 0xff, 0x8e, 0x4f, 0x12, 0x32, 0xee, 0xf2, 0x81, 0x83, 0xc3, 0xfe,
- 0x3b, 0x1b, 0x4c, 0x6f, 0xad, 0x73, 0x3b, 0xb5, 0xfc, 0xbc, 0x2e, 0xc2, 0x20, 0x05, 0xc5,
- 0x8e, 0xf1, 0x83, 0x7d, 0x16, 0x83, 0xb2, 0xc6, 0xf3, 0x4a, 0x26, 0xc1, 0xb2, 0xef, 0xfa,
- 0x88, 0x6b, 0x42, 0x38, 0x61, 0x1f, 0xcf, 0xdc, 0xde, 0x35, 0x5b, 0x3b, 0x65, 0x19, 0x03,
- 0x5b, 0xbc, 0x34, 0xf4, 0xde, 0xf9, 0x9c, 0x02, 0x38, 0x61, 0xb4, 0x6f, 0xc9, 0xd6, 0xe6,
- 0xc9, 0x07, 0x7a, 0xd9, 0x1d, 0x26, 0x91, 0xf7, 0xf7, 0xee, 0x59, 0x8c, 0xb0, 0xfa, 0xc1,
- 0x86, 0xd9, 0x1c, 0xae, 0xfe, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, 0xb4, 0x13, 0x0c, 0x93,
- 0xbc, 0x43, 0x79, 0x44, 0xf4, 0xfd, 0x44, 0x52, 0xe2, 0xd7, 0x4d, 0xd3, 0x64, 0xf2, 0xe2,
- 0x1e, 0x71, 0xf5, 0x4b, 0xff, 0x5c, 0xae, 0x82, 0xab, 0x9c, 0x9d, 0xf6, 0x9e, 0xe8, 0x6d,
- 0x2b, 0xc5, 0x22, 0x36, 0x3a, 0x0d, 0xab, 0xc5, 0x21, 0x97, 0x9b, 0x0d, 0xea, 0xda, 0x1d,
- 0xbf, 0x9a, 0x42, 0xd5, 0xc4, 0x48, 0x4e, 0x0a, 0xbc, 0xd0, 0x6b, 0xfa, 0x53, 0xdd, 0xef,
- 0x3c, 0x1b, 0x20, 0xee, 0x3f, 0xd5, 0x9d, 0x7c, 0x25, 0xe4, 0x1d, 0x2b, 0x66, 0xc6, 0x2e,
- 0x37, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- ],
- g: &[2],
-};
-
-/// FFDHE4096 group defined in [RFC 7919 Appendix A.3]
-///
-/// [RFC 7919 Appendix A.3]: https://datatracker.ietf.org/doc/html/rfc7919#appendix-A.3
-pub const FFDHE4096: FfdheGroup<'static> = FfdheGroup {
- p: &[
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0xf8, 0x54, 0x58, 0xa2, 0xbb, 0x4a,
- 0x9a, 0xaf, 0xdc, 0x56, 0x20, 0x27, 0x3d, 0x3c, 0xf1, 0xd8, 0xb9, 0xc5, 0x83, 0xce, 0x2d,
- 0x36, 0x95, 0xa9, 0xe1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xfb, 0xcc, 0x93, 0x9d, 0xce, 0x24,
- 0x9b, 0x3e, 0xf9, 0x7d, 0x2f, 0xe3, 0x63, 0x63, 0x0c, 0x75, 0xd8, 0xf6, 0x81, 0xb2, 0x02,
- 0xae, 0xc4, 0x61, 0x7a, 0xd3, 0xdf, 0x1e, 0xd5, 0xd5, 0xfd, 0x65, 0x61, 0x24, 0x33, 0xf5,
- 0x1f, 0x5f, 0x06, 0x6e, 0xd0, 0x85, 0x63, 0x65, 0x55, 0x3d, 0xed, 0x1a, 0xf3, 0xb5, 0x57,
- 0x13, 0x5e, 0x7f, 0x57, 0xc9, 0x35, 0x98, 0x4f, 0x0c, 0x70, 0xe0, 0xe6, 0x8b, 0x77, 0xe2,
- 0xa6, 0x89, 0xda, 0xf3, 0xef, 0xe8, 0x72, 0x1d, 0xf1, 0x58, 0xa1, 0x36, 0xad, 0xe7, 0x35,
- 0x30, 0xac, 0xca, 0x4f, 0x48, 0x3a, 0x79, 0x7a, 0xbc, 0x0a, 0xb1, 0x82, 0xb3, 0x24, 0xfb,
- 0x61, 0xd1, 0x08, 0xa9, 0x4b, 0xb2, 0xc8, 0xe3, 0xfb, 0xb9, 0x6a, 0xda, 0xb7, 0x60, 0xd7,
- 0xf4, 0x68, 0x1d, 0x4f, 0x42, 0xa3, 0xde, 0x39, 0x4d, 0xf4, 0xae, 0x56, 0xed, 0xe7, 0x63,
- 0x72, 0xbb, 0x19, 0x0b, 0x07, 0xa7, 0xc8, 0xee, 0x0a, 0x6d, 0x70, 0x9e, 0x02, 0xfc, 0xe1,
- 0xcd, 0xf7, 0xe2, 0xec, 0xc0, 0x34, 0x04, 0xcd, 0x28, 0x34, 0x2f, 0x61, 0x91, 0x72, 0xfe,
- 0x9c, 0xe9, 0x85, 0x83, 0xff, 0x8e, 0x4f, 0x12, 0x32, 0xee, 0xf2, 0x81, 0x83, 0xc3, 0xfe,
- 0x3b, 0x1b, 0x4c, 0x6f, 0xad, 0x73, 0x3b, 0xb5, 0xfc, 0xbc, 0x2e, 0xc2, 0x20, 0x05, 0xc5,
- 0x8e, 0xf1, 0x83, 0x7d, 0x16, 0x83, 0xb2, 0xc6, 0xf3, 0x4a, 0x26, 0xc1, 0xb2, 0xef, 0xfa,
- 0x88, 0x6b, 0x42, 0x38, 0x61, 0x1f, 0xcf, 0xdc, 0xde, 0x35, 0x5b, 0x3b, 0x65, 0x19, 0x03,
- 0x5b, 0xbc, 0x34, 0xf4, 0xde, 0xf9, 0x9c, 0x02, 0x38, 0x61, 0xb4, 0x6f, 0xc9, 0xd6, 0xe6,
- 0xc9, 0x07, 0x7a, 0xd9, 0x1d, 0x26, 0x91, 0xf7, 0xf7, 0xee, 0x59, 0x8c, 0xb0, 0xfa, 0xc1,
- 0x86, 0xd9, 0x1c, 0xae, 0xfe, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, 0xb4, 0x13, 0x0c, 0x93,
- 0xbc, 0x43, 0x79, 0x44, 0xf4, 0xfd, 0x44, 0x52, 0xe2, 0xd7, 0x4d, 0xd3, 0x64, 0xf2, 0xe2,
- 0x1e, 0x71, 0xf5, 0x4b, 0xff, 0x5c, 0xae, 0x82, 0xab, 0x9c, 0x9d, 0xf6, 0x9e, 0xe8, 0x6d,
- 0x2b, 0xc5, 0x22, 0x36, 0x3a, 0x0d, 0xab, 0xc5, 0x21, 0x97, 0x9b, 0x0d, 0xea, 0xda, 0x1d,
- 0xbf, 0x9a, 0x42, 0xd5, 0xc4, 0x48, 0x4e, 0x0a, 0xbc, 0xd0, 0x6b, 0xfa, 0x53, 0xdd, 0xef,
- 0x3c, 0x1b, 0x20, 0xee, 0x3f, 0xd5, 0x9d, 0x7c, 0x25, 0xe4, 0x1d, 0x2b, 0x66, 0x9e, 0x1e,
- 0xf1, 0x6e, 0x6f, 0x52, 0xc3, 0x16, 0x4d, 0xf4, 0xfb, 0x79, 0x30, 0xe9, 0xe4, 0xe5, 0x88,
- 0x57, 0xb6, 0xac, 0x7d, 0x5f, 0x42, 0xd6, 0x9f, 0x6d, 0x18, 0x77, 0x63, 0xcf, 0x1d, 0x55,
- 0x03, 0x40, 0x04, 0x87, 0xf5, 0x5b, 0xa5, 0x7e, 0x31, 0xcc, 0x7a, 0x71, 0x35, 0xc8, 0x86,
- 0xef, 0xb4, 0x31, 0x8a, 0xed, 0x6a, 0x1e, 0x01, 0x2d, 0x9e, 0x68, 0x32, 0xa9, 0x07, 0x60,
- 0x0a, 0x91, 0x81, 0x30, 0xc4, 0x6d, 0xc7, 0x78, 0xf9, 0x71, 0xad, 0x00, 0x38, 0x09, 0x29,
- 0x99, 0xa3, 0x33, 0xcb, 0x8b, 0x7a, 0x1a, 0x1d, 0xb9, 0x3d, 0x71, 0x40, 0x00, 0x3c, 0x2a,
- 0x4e, 0xce, 0xa9, 0xf9, 0x8d, 0x0a, 0xcc, 0x0a, 0x82, 0x91, 0xcd, 0xce, 0xc9, 0x7d, 0xcf,
- 0x8e, 0xc9, 0xb5, 0x5a, 0x7f, 0x88, 0xa4, 0x6b, 0x4d, 0xb5, 0xa8, 0x51, 0xf4, 0x41, 0x82,
- 0xe1, 0xc6, 0x8a, 0x00, 0x7e, 0x5e, 0x65, 0x5f, 0x6a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff,
- ],
- g: &[2],
-};
-
-/// FFDHE6144 group defined in [RFC 7919 Appendix A.4]
-///
-/// [RFC 7919 Appendix A.4]: https://datatracker.ietf.org/doc/html/rfc7919#appendix-A.4
-pub const FFDHE6144: FfdheGroup<'static> = FfdheGroup {
- p: &[
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0xf8, 0x54, 0x58, 0xa2, 0xbb, 0x4a,
- 0x9a, 0xaf, 0xdc, 0x56, 0x20, 0x27, 0x3d, 0x3c, 0xf1, 0xd8, 0xb9, 0xc5, 0x83, 0xce, 0x2d,
- 0x36, 0x95, 0xa9, 0xe1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xfb, 0xcc, 0x93, 0x9d, 0xce, 0x24,
- 0x9b, 0x3e, 0xf9, 0x7d, 0x2f, 0xe3, 0x63, 0x63, 0x0c, 0x75, 0xd8, 0xf6, 0x81, 0xb2, 0x02,
- 0xae, 0xc4, 0x61, 0x7a, 0xd3, 0xdf, 0x1e, 0xd5, 0xd5, 0xfd, 0x65, 0x61, 0x24, 0x33, 0xf5,
- 0x1f, 0x5f, 0x06, 0x6e, 0xd0, 0x85, 0x63, 0x65, 0x55, 0x3d, 0xed, 0x1a, 0xf3, 0xb5, 0x57,
- 0x13, 0x5e, 0x7f, 0x57, 0xc9, 0x35, 0x98, 0x4f, 0x0c, 0x70, 0xe0, 0xe6, 0x8b, 0x77, 0xe2,
- 0xa6, 0x89, 0xda, 0xf3, 0xef, 0xe8, 0x72, 0x1d, 0xf1, 0x58, 0xa1, 0x36, 0xad, 0xe7, 0x35,
- 0x30, 0xac, 0xca, 0x4f, 0x48, 0x3a, 0x79, 0x7a, 0xbc, 0x0a, 0xb1, 0x82, 0xb3, 0x24, 0xfb,
- 0x61, 0xd1, 0x08, 0xa9, 0x4b, 0xb2, 0xc8, 0xe3, 0xfb, 0xb9, 0x6a, 0xda, 0xb7, 0x60, 0xd7,
- 0xf4, 0x68, 0x1d, 0x4f, 0x42, 0xa3, 0xde, 0x39, 0x4d, 0xf4, 0xae, 0x56, 0xed, 0xe7, 0x63,
- 0x72, 0xbb, 0x19, 0x0b, 0x07, 0xa7, 0xc8, 0xee, 0x0a, 0x6d, 0x70, 0x9e, 0x02, 0xfc, 0xe1,
- 0xcd, 0xf7, 0xe2, 0xec, 0xc0, 0x34, 0x04, 0xcd, 0x28, 0x34, 0x2f, 0x61, 0x91, 0x72, 0xfe,
- 0x9c, 0xe9, 0x85, 0x83, 0xff, 0x8e, 0x4f, 0x12, 0x32, 0xee, 0xf2, 0x81, 0x83, 0xc3, 0xfe,
- 0x3b, 0x1b, 0x4c, 0x6f, 0xad, 0x73, 0x3b, 0xb5, 0xfc, 0xbc, 0x2e, 0xc2, 0x20, 0x05, 0xc5,
- 0x8e, 0xf1, 0x83, 0x7d, 0x16, 0x83, 0xb2, 0xc6, 0xf3, 0x4a, 0x26, 0xc1, 0xb2, 0xef, 0xfa,
- 0x88, 0x6b, 0x42, 0x38, 0x61, 0x1f, 0xcf, 0xdc, 0xde, 0x35, 0x5b, 0x3b, 0x65, 0x19, 0x03,
- 0x5b, 0xbc, 0x34, 0xf4, 0xde, 0xf9, 0x9c, 0x02, 0x38, 0x61, 0xb4, 0x6f, 0xc9, 0xd6, 0xe6,
- 0xc9, 0x07, 0x7a, 0xd9, 0x1d, 0x26, 0x91, 0xf7, 0xf7, 0xee, 0x59, 0x8c, 0xb0, 0xfa, 0xc1,
- 0x86, 0xd9, 0x1c, 0xae, 0xfe, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, 0xb4, 0x13, 0x0c, 0x93,
- 0xbc, 0x43, 0x79, 0x44, 0xf4, 0xfd, 0x44, 0x52, 0xe2, 0xd7, 0x4d, 0xd3, 0x64, 0xf2, 0xe2,
- 0x1e, 0x71, 0xf5, 0x4b, 0xff, 0x5c, 0xae, 0x82, 0xab, 0x9c, 0x9d, 0xf6, 0x9e, 0xe8, 0x6d,
- 0x2b, 0xc5, 0x22, 0x36, 0x3a, 0x0d, 0xab, 0xc5, 0x21, 0x97, 0x9b, 0x0d, 0xea, 0xda, 0x1d,
- 0xbf, 0x9a, 0x42, 0xd5, 0xc4, 0x48, 0x4e, 0x0a, 0xbc, 0xd0, 0x6b, 0xfa, 0x53, 0xdd, 0xef,
- 0x3c, 0x1b, 0x20, 0xee, 0x3f, 0xd5, 0x9d, 0x7c, 0x25, 0xe4, 0x1d, 0x2b, 0x66, 0x9e, 0x1e,
- 0xf1, 0x6e, 0x6f, 0x52, 0xc3, 0x16, 0x4d, 0xf4, 0xfb, 0x79, 0x30, 0xe9, 0xe4, 0xe5, 0x88,
- 0x57, 0xb6, 0xac, 0x7d, 0x5f, 0x42, 0xd6, 0x9f, 0x6d, 0x18, 0x77, 0x63, 0xcf, 0x1d, 0x55,
- 0x03, 0x40, 0x04, 0x87, 0xf5, 0x5b, 0xa5, 0x7e, 0x31, 0xcc, 0x7a, 0x71, 0x35, 0xc8, 0x86,
- 0xef, 0xb4, 0x31, 0x8a, 0xed, 0x6a, 0x1e, 0x01, 0x2d, 0x9e, 0x68, 0x32, 0xa9, 0x07, 0x60,
- 0x0a, 0x91, 0x81, 0x30, 0xc4, 0x6d, 0xc7, 0x78, 0xf9, 0x71, 0xad, 0x00, 0x38, 0x09, 0x29,
- 0x99, 0xa3, 0x33, 0xcb, 0x8b, 0x7a, 0x1a, 0x1d, 0xb9, 0x3d, 0x71, 0x40, 0x00, 0x3c, 0x2a,
- 0x4e, 0xce, 0xa9, 0xf9, 0x8d, 0x0a, 0xcc, 0x0a, 0x82, 0x91, 0xcd, 0xce, 0xc9, 0x7d, 0xcf,
- 0x8e, 0xc9, 0xb5, 0x5a, 0x7f, 0x88, 0xa4, 0x6b, 0x4d, 0xb5, 0xa8, 0x51, 0xf4, 0x41, 0x82,
- 0xe1, 0xc6, 0x8a, 0x00, 0x7e, 0x5e, 0x0d, 0xd9, 0x02, 0x0b, 0xfd, 0x64, 0xb6, 0x45, 0x03,
- 0x6c, 0x7a, 0x4e, 0x67, 0x7d, 0x2c, 0x38, 0x53, 0x2a, 0x3a, 0x23, 0xba, 0x44, 0x42, 0xca,
- 0xf5, 0x3e, 0xa6, 0x3b, 0xb4, 0x54, 0x32, 0x9b, 0x76, 0x24, 0xc8, 0x91, 0x7b, 0xdd, 0x64,
- 0xb1, 0xc0, 0xfd, 0x4c, 0xb3, 0x8e, 0x8c, 0x33, 0x4c, 0x70, 0x1c, 0x3a, 0xcd, 0xad, 0x06,
- 0x57, 0xfc, 0xcf, 0xec, 0x71, 0x9b, 0x1f, 0x5c, 0x3e, 0x4e, 0x46, 0x04, 0x1f, 0x38, 0x81,
- 0x47, 0xfb, 0x4c, 0xfd, 0xb4, 0x77, 0xa5, 0x24, 0x71, 0xf7, 0xa9, 0xa9, 0x69, 0x10, 0xb8,
- 0x55, 0x32, 0x2e, 0xdb, 0x63, 0x40, 0xd8, 0xa0, 0x0e, 0xf0, 0x92, 0x35, 0x05, 0x11, 0xe3,
- 0x0a, 0xbe, 0xc1, 0xff, 0xf9, 0xe3, 0xa2, 0x6e, 0x7f, 0xb2, 0x9f, 0x8c, 0x18, 0x30, 0x23,
- 0xc3, 0x58, 0x7e, 0x38, 0xda, 0x00, 0x77, 0xd9, 0xb4, 0x76, 0x3e, 0x4e, 0x4b, 0x94, 0xb2,
- 0xbb, 0xc1, 0x94, 0xc6, 0x65, 0x1e, 0x77, 0xca, 0xf9, 0x92, 0xee, 0xaa, 0xc0, 0x23, 0x2a,
- 0x28, 0x1b, 0xf6, 0xb3, 0xa7, 0x39, 0xc1, 0x22, 0x61, 0x16, 0x82, 0x0a, 0xe8, 0xdb, 0x58,
- 0x47, 0xa6, 0x7c, 0xbe, 0xf9, 0xc9, 0x09, 0x1b, 0x46, 0x2d, 0x53, 0x8c, 0xd7, 0x2b, 0x03,
- 0x74, 0x6a, 0xe7, 0x7f, 0x5e, 0x62, 0x29, 0x2c, 0x31, 0x15, 0x62, 0xa8, 0x46, 0x50, 0x5d,
- 0xc8, 0x2d, 0xb8, 0x54, 0x33, 0x8a, 0xe4, 0x9f, 0x52, 0x35, 0xc9, 0x5b, 0x91, 0x17, 0x8c,
- 0xcf, 0x2d, 0xd5, 0xca, 0xce, 0xf4, 0x03, 0xec, 0x9d, 0x18, 0x10, 0xc6, 0x27, 0x2b, 0x04,
- 0x5b, 0x3b, 0x71, 0xf9, 0xdc, 0x6b, 0x80, 0xd6, 0x3f, 0xdd, 0x4a, 0x8e, 0x9a, 0xdb, 0x1e,
- 0x69, 0x62, 0xa6, 0x95, 0x26, 0xd4, 0x31, 0x61, 0xc1, 0xa4, 0x1d, 0x57, 0x0d, 0x79, 0x38,
- 0xda, 0xd4, 0xa4, 0x0e, 0x32, 0x9c, 0xd0, 0xe4, 0x0e, 0x65, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff,
- ],
- g: &[2],
-};
-
-/// FFDHE8192 group defined in [RFC 7919 Appendix A.5]
-///
-/// [RFC 7919 Appendix A.5]: https://datatracker.ietf.org/doc/html/rfc7919#appendix-A.5
-pub const FFDHE8192: FfdheGroup<'static> = FfdheGroup {
- p: &[
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0xf8, 0x54, 0x58, 0xa2, 0xbb, 0x4a,
- 0x9a, 0xaf, 0xdc, 0x56, 0x20, 0x27, 0x3d, 0x3c, 0xf1, 0xd8, 0xb9, 0xc5, 0x83, 0xce, 0x2d,
- 0x36, 0x95, 0xa9, 0xe1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xfb, 0xcc, 0x93, 0x9d, 0xce, 0x24,
- 0x9b, 0x3e, 0xf9, 0x7d, 0x2f, 0xe3, 0x63, 0x63, 0x0c, 0x75, 0xd8, 0xf6, 0x81, 0xb2, 0x02,
- 0xae, 0xc4, 0x61, 0x7a, 0xd3, 0xdf, 0x1e, 0xd5, 0xd5, 0xfd, 0x65, 0x61, 0x24, 0x33, 0xf5,
- 0x1f, 0x5f, 0x06, 0x6e, 0xd0, 0x85, 0x63, 0x65, 0x55, 0x3d, 0xed, 0x1a, 0xf3, 0xb5, 0x57,
- 0x13, 0x5e, 0x7f, 0x57, 0xc9, 0x35, 0x98, 0x4f, 0x0c, 0x70, 0xe0, 0xe6, 0x8b, 0x77, 0xe2,
- 0xa6, 0x89, 0xda, 0xf3, 0xef, 0xe8, 0x72, 0x1d, 0xf1, 0x58, 0xa1, 0x36, 0xad, 0xe7, 0x35,
- 0x30, 0xac, 0xca, 0x4f, 0x48, 0x3a, 0x79, 0x7a, 0xbc, 0x0a, 0xb1, 0x82, 0xb3, 0x24, 0xfb,
- 0x61, 0xd1, 0x08, 0xa9, 0x4b, 0xb2, 0xc8, 0xe3, 0xfb, 0xb9, 0x6a, 0xda, 0xb7, 0x60, 0xd7,
- 0xf4, 0x68, 0x1d, 0x4f, 0x42, 0xa3, 0xde, 0x39, 0x4d, 0xf4, 0xae, 0x56, 0xed, 0xe7, 0x63,
- 0x72, 0xbb, 0x19, 0x0b, 0x07, 0xa7, 0xc8, 0xee, 0x0a, 0x6d, 0x70, 0x9e, 0x02, 0xfc, 0xe1,
- 0xcd, 0xf7, 0xe2, 0xec, 0xc0, 0x34, 0x04, 0xcd, 0x28, 0x34, 0x2f, 0x61, 0x91, 0x72, 0xfe,
- 0x9c, 0xe9, 0x85, 0x83, 0xff, 0x8e, 0x4f, 0x12, 0x32, 0xee, 0xf2, 0x81, 0x83, 0xc3, 0xfe,
- 0x3b, 0x1b, 0x4c, 0x6f, 0xad, 0x73, 0x3b, 0xb5, 0xfc, 0xbc, 0x2e, 0xc2, 0x20, 0x05, 0xc5,
- 0x8e, 0xf1, 0x83, 0x7d, 0x16, 0x83, 0xb2, 0xc6, 0xf3, 0x4a, 0x26, 0xc1, 0xb2, 0xef, 0xfa,
- 0x88, 0x6b, 0x42, 0x38, 0x61, 0x1f, 0xcf, 0xdc, 0xde, 0x35, 0x5b, 0x3b, 0x65, 0x19, 0x03,
- 0x5b, 0xbc, 0x34, 0xf4, 0xde, 0xf9, 0x9c, 0x02, 0x38, 0x61, 0xb4, 0x6f, 0xc9, 0xd6, 0xe6,
- 0xc9, 0x07, 0x7a, 0xd9, 0x1d, 0x26, 0x91, 0xf7, 0xf7, 0xee, 0x59, 0x8c, 0xb0, 0xfa, 0xc1,
- 0x86, 0xd9, 0x1c, 0xae, 0xfe, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, 0xb4, 0x13, 0x0c, 0x93,
- 0xbc, 0x43, 0x79, 0x44, 0xf4, 0xfd, 0x44, 0x52, 0xe2, 0xd7, 0x4d, 0xd3, 0x64, 0xf2, 0xe2,
- 0x1e, 0x71, 0xf5, 0x4b, 0xff, 0x5c, 0xae, 0x82, 0xab, 0x9c, 0x9d, 0xf6, 0x9e, 0xe8, 0x6d,
- 0x2b, 0xc5, 0x22, 0x36, 0x3a, 0x0d, 0xab, 0xc5, 0x21, 0x97, 0x9b, 0x0d, 0xea, 0xda, 0x1d,
- 0xbf, 0x9a, 0x42, 0xd5, 0xc4, 0x48, 0x4e, 0x0a, 0xbc, 0xd0, 0x6b, 0xfa, 0x53, 0xdd, 0xef,
- 0x3c, 0x1b, 0x20, 0xee, 0x3f, 0xd5, 0x9d, 0x7c, 0x25, 0xe4, 0x1d, 0x2b, 0x66, 0x9e, 0x1e,
- 0xf1, 0x6e, 0x6f, 0x52, 0xc3, 0x16, 0x4d, 0xf4, 0xfb, 0x79, 0x30, 0xe9, 0xe4, 0xe5, 0x88,
- 0x57, 0xb6, 0xac, 0x7d, 0x5f, 0x42, 0xd6, 0x9f, 0x6d, 0x18, 0x77, 0x63, 0xcf, 0x1d, 0x55,
- 0x03, 0x40, 0x04, 0x87, 0xf5, 0x5b, 0xa5, 0x7e, 0x31, 0xcc, 0x7a, 0x71, 0x35, 0xc8, 0x86,
- 0xef, 0xb4, 0x31, 0x8a, 0xed, 0x6a, 0x1e, 0x01, 0x2d, 0x9e, 0x68, 0x32, 0xa9, 0x07, 0x60,
- 0x0a, 0x91, 0x81, 0x30, 0xc4, 0x6d, 0xc7, 0x78, 0xf9, 0x71, 0xad, 0x00, 0x38, 0x09, 0x29,
- 0x99, 0xa3, 0x33, 0xcb, 0x8b, 0x7a, 0x1a, 0x1d, 0xb9, 0x3d, 0x71, 0x40, 0x00, 0x3c, 0x2a,
- 0x4e, 0xce, 0xa9, 0xf9, 0x8d, 0x0a, 0xcc, 0x0a, 0x82, 0x91, 0xcd, 0xce, 0xc9, 0x7d, 0xcf,
- 0x8e, 0xc9, 0xb5, 0x5a, 0x7f, 0x88, 0xa4, 0x6b, 0x4d, 0xb5, 0xa8, 0x51, 0xf4, 0x41, 0x82,
- 0xe1, 0xc6, 0x8a, 0x00, 0x7e, 0x5e, 0x0d, 0xd9, 0x02, 0x0b, 0xfd, 0x64, 0xb6, 0x45, 0x03,
- 0x6c, 0x7a, 0x4e, 0x67, 0x7d, 0x2c, 0x38, 0x53, 0x2a, 0x3a, 0x23, 0xba, 0x44, 0x42, 0xca,
- 0xf5, 0x3e, 0xa6, 0x3b, 0xb4, 0x54, 0x32, 0x9b, 0x76, 0x24, 0xc8, 0x91, 0x7b, 0xdd, 0x64,
- 0xb1, 0xc0, 0xfd, 0x4c, 0xb3, 0x8e, 0x8c, 0x33, 0x4c, 0x70, 0x1c, 0x3a, 0xcd, 0xad, 0x06,
- 0x57, 0xfc, 0xcf, 0xec, 0x71, 0x9b, 0x1f, 0x5c, 0x3e, 0x4e, 0x46, 0x04, 0x1f, 0x38, 0x81,
- 0x47, 0xfb, 0x4c, 0xfd, 0xb4, 0x77, 0xa5, 0x24, 0x71, 0xf7, 0xa9, 0xa9, 0x69, 0x10, 0xb8,
- 0x55, 0x32, 0x2e, 0xdb, 0x63, 0x40, 0xd8, 0xa0, 0x0e, 0xf0, 0x92, 0x35, 0x05, 0x11, 0xe3,
- 0x0a, 0xbe, 0xc1, 0xff, 0xf9, 0xe3, 0xa2, 0x6e, 0x7f, 0xb2, 0x9f, 0x8c, 0x18, 0x30, 0x23,
- 0xc3, 0x58, 0x7e, 0x38, 0xda, 0x00, 0x77, 0xd9, 0xb4, 0x76, 0x3e, 0x4e, 0x4b, 0x94, 0xb2,
- 0xbb, 0xc1, 0x94, 0xc6, 0x65, 0x1e, 0x77, 0xca, 0xf9, 0x92, 0xee, 0xaa, 0xc0, 0x23, 0x2a,
- 0x28, 0x1b, 0xf6, 0xb3, 0xa7, 0x39, 0xc1, 0x22, 0x61, 0x16, 0x82, 0x0a, 0xe8, 0xdb, 0x58,
- 0x47, 0xa6, 0x7c, 0xbe, 0xf9, 0xc9, 0x09, 0x1b, 0x46, 0x2d, 0x53, 0x8c, 0xd7, 0x2b, 0x03,
- 0x74, 0x6a, 0xe7, 0x7f, 0x5e, 0x62, 0x29, 0x2c, 0x31, 0x15, 0x62, 0xa8, 0x46, 0x50, 0x5d,
- 0xc8, 0x2d, 0xb8, 0x54, 0x33, 0x8a, 0xe4, 0x9f, 0x52, 0x35, 0xc9, 0x5b, 0x91, 0x17, 0x8c,
- 0xcf, 0x2d, 0xd5, 0xca, 0xce, 0xf4, 0x03, 0xec, 0x9d, 0x18, 0x10, 0xc6, 0x27, 0x2b, 0x04,
- 0x5b, 0x3b, 0x71, 0xf9, 0xdc, 0x6b, 0x80, 0xd6, 0x3f, 0xdd, 0x4a, 0x8e, 0x9a, 0xdb, 0x1e,
- 0x69, 0x62, 0xa6, 0x95, 0x26, 0xd4, 0x31, 0x61, 0xc1, 0xa4, 0x1d, 0x57, 0x0d, 0x79, 0x38,
- 0xda, 0xd4, 0xa4, 0x0e, 0x32, 0x9c, 0xcf, 0xf4, 0x6a, 0xaa, 0x36, 0xad, 0x00, 0x4c, 0xf6,
- 0x00, 0xc8, 0x38, 0x1e, 0x42, 0x5a, 0x31, 0xd9, 0x51, 0xae, 0x64, 0xfd, 0xb2, 0x3f, 0xce,
- 0xc9, 0x50, 0x9d, 0x43, 0x68, 0x7f, 0xeb, 0x69, 0xed, 0xd1, 0xcc, 0x5e, 0x0b, 0x8c, 0xc3,
- 0xbd, 0xf6, 0x4b, 0x10, 0xef, 0x86, 0xb6, 0x31, 0x42, 0xa3, 0xab, 0x88, 0x29, 0x55, 0x5b,
- 0x2f, 0x74, 0x7c, 0x93, 0x26, 0x65, 0xcb, 0x2c, 0x0f, 0x1c, 0xc0, 0x1b, 0xd7, 0x02, 0x29,
- 0x38, 0x88, 0x39, 0xd2, 0xaf, 0x05, 0xe4, 0x54, 0x50, 0x4a, 0xc7, 0x8b, 0x75, 0x82, 0x82,
- 0x28, 0x46, 0xc0, 0xba, 0x35, 0xc3, 0x5f, 0x5c, 0x59, 0x16, 0x0c, 0xc0, 0x46, 0xfd, 0x82,
- 0x51, 0x54, 0x1f, 0xc6, 0x8c, 0x9c, 0x86, 0xb0, 0x22, 0xbb, 0x70, 0x99, 0x87, 0x6a, 0x46,
- 0x0e, 0x74, 0x51, 0xa8, 0xa9, 0x31, 0x09, 0x70, 0x3f, 0xee, 0x1c, 0x21, 0x7e, 0x6c, 0x38,
- 0x26, 0xe5, 0x2c, 0x51, 0xaa, 0x69, 0x1e, 0x0e, 0x42, 0x3c, 0xfc, 0x99, 0xe9, 0xe3, 0x16,
- 0x50, 0xc1, 0x21, 0x7b, 0x62, 0x48, 0x16, 0xcd, 0xad, 0x9a, 0x95, 0xf9, 0xd5, 0xb8, 0x01,
- 0x94, 0x88, 0xd9, 0xc0, 0xa0, 0xa1, 0xfe, 0x30, 0x75, 0xa5, 0x77, 0xe2, 0x31, 0x83, 0xf8,
- 0x1d, 0x4a, 0x3f, 0x2f, 0xa4, 0x57, 0x1e, 0xfc, 0x8c, 0xe0, 0xba, 0x8a, 0x4f, 0xe8, 0xb6,
- 0x85, 0x5d, 0xfe, 0x72, 0xb0, 0xa6, 0x6e, 0xde, 0xd2, 0xfb, 0xab, 0xfb, 0xe5, 0x8a, 0x30,
- 0xfa, 0xfa, 0xbe, 0x1c, 0x5d, 0x71, 0xa8, 0x7e, 0x2f, 0x74, 0x1e, 0xf8, 0xc1, 0xfe, 0x86,
- 0xfe, 0xa6, 0xbb, 0xfd, 0xe5, 0x30, 0x67, 0x7f, 0x0d, 0x97, 0xd1, 0x1d, 0x49, 0xf7, 0xa8,
- 0x44, 0x3d, 0x08, 0x22, 0xe5, 0x06, 0xa9, 0xf4, 0x61, 0x4e, 0x01, 0x1e, 0x2a, 0x94, 0x83,
- 0x8f, 0xf8, 0x8c, 0xd6, 0x8c, 0x8b, 0xb7, 0xc5, 0xc6, 0x42, 0x4c, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff,
- ],
- g: &[2],
-};
-
-#[test]
-fn named_group_ffdhe_group_roundtrip() {
- use NamedGroup::*;
- let ffdhe_groups = [FFDHE2048, FFDHE3072, FFDHE4096, FFDHE6144, FFDHE8192];
- for g in ffdhe_groups {
- #[allow(deprecated)]
- let roundtrip = FfdheGroup::from_named_group(g)
- .unwrap()
- .named_group();
- assert_eq!(roundtrip, Some(g));
- }
-}
diff --git a/vendor/rustls/src/msgs/fragmenter.rs b/vendor/rustls/src/msgs/fragmenter.rs
deleted file mode 100644
index 48636777..00000000
--- a/vendor/rustls/src/msgs/fragmenter.rs
+++ /dev/null
@@ -1,232 +0,0 @@
-use crate::Error;
-use crate::enums::{ContentType, ProtocolVersion};
-use crate::msgs::message::{OutboundChunks, OutboundPlainMessage, PlainMessage};
-pub(crate) const MAX_FRAGMENT_LEN: usize = 16384;
-pub(crate) const PACKET_OVERHEAD: usize = 1 + 2 + 2;
-pub(crate) const MAX_FRAGMENT_SIZE: usize = MAX_FRAGMENT_LEN + PACKET_OVERHEAD;
-
-pub struct MessageFragmenter {
- max_frag: usize,
-}
-
-impl Default for MessageFragmenter {
- fn default() -> Self {
- Self {
- max_frag: MAX_FRAGMENT_LEN,
- }
- }
-}
-
-impl MessageFragmenter {
- /// Take `msg` and fragment it into new messages with the same type and version.
- ///
- /// Each returned message size is no more than `max_frag`.
- ///
- /// Return an iterator across those messages.
- ///
- /// Payloads are borrowed from `msg`.
- pub fn fragment_message<'a>(
- &self,
- msg: &'a PlainMessage,
- ) -> impl Iterator<Item = OutboundPlainMessage<'a>> + 'a {
- self.fragment_payload(msg.typ, msg.version, msg.payload.bytes().into())
- }
-
- /// Take `payload` and fragment it into new messages with given type and version.
- ///
- /// Each returned message size is no more than `max_frag`.
- ///
- /// Return an iterator across those messages.
- ///
- /// Payloads are borrowed from `payload`.
- pub(crate) fn fragment_payload<'a>(
- &self,
- typ: ContentType,
- version: ProtocolVersion,
- payload: OutboundChunks<'a>,
- ) -> impl ExactSizeIterator<Item = OutboundPlainMessage<'a>> {
- Chunker::new(payload, self.max_frag).map(move |payload| OutboundPlainMessage {
- typ,
- version,
- payload,
- })
- }
-
- /// Set the maximum fragment size that will be produced.
- ///
- /// This includes overhead. A `max_fragment_size` of 10 will produce TLS fragments
- /// up to 10 bytes long.
- ///
- /// A `max_fragment_size` of `None` sets the highest allowable fragment size.
- ///
- /// Returns BadMaxFragmentSize if the size is smaller than 32 or larger than 16389.
- pub fn set_max_fragment_size(&mut self, max_fragment_size: Option<usize>) -> Result<(), Error> {
- self.max_frag = match max_fragment_size {
- Some(sz @ 32..=MAX_FRAGMENT_SIZE) => sz - PACKET_OVERHEAD,
- None => MAX_FRAGMENT_LEN,
- _ => return Err(Error::BadMaxFragmentSize),
- };
- Ok(())
- }
-}
-
-/// An iterator over borrowed fragments of a payload
-struct Chunker<'a> {
- payload: OutboundChunks<'a>,
- limit: usize,
-}
-
-impl<'a> Chunker<'a> {
- fn new(payload: OutboundChunks<'a>, limit: usize) -> Self {
- Self { payload, limit }
- }
-}
-
-impl<'a> Iterator for Chunker<'a> {
- type Item = OutboundChunks<'a>;
-
- fn next(&mut self) -> Option<Self::Item> {
- if self.payload.is_empty() {
- return None;
- }
-
- let (before, after) = self.payload.split_at(self.limit);
- self.payload = after;
- Some(before)
- }
-}
-
-impl ExactSizeIterator for Chunker<'_> {
- fn len(&self) -> usize {
- (self.payload.len() + self.limit - 1) / self.limit
- }
-}
-
-#[cfg(test)]
-mod tests {
- use std::prelude::v1::*;
- use std::vec;
-
- use super::{MessageFragmenter, PACKET_OVERHEAD};
- use crate::enums::{ContentType, ProtocolVersion};
- use crate::msgs::base::Payload;
- use crate::msgs::message::{OutboundChunks, OutboundPlainMessage, PlainMessage};
-
- fn msg_eq(
- m: &OutboundPlainMessage<'_>,
- total_len: usize,
- typ: &ContentType,
- version: &ProtocolVersion,
- bytes: &[u8],
- ) {
- assert_eq!(&m.typ, typ);
- assert_eq!(&m.version, version);
- assert_eq!(m.payload.to_vec(), bytes);
-
- let buf = m.to_unencrypted_opaque().encode();
-
- assert_eq!(total_len, buf.len());
- }
-
- #[test]
- fn smoke() {
- let typ = ContentType::Handshake;
- let version = ProtocolVersion::TLSv1_2;
- let data: Vec<u8> = (1..70u8).collect();
- let m = PlainMessage {
- typ,
- version,
- payload: Payload::new(data),
- };
-
- let mut frag = MessageFragmenter::default();
- frag.set_max_fragment_size(Some(32))
- .unwrap();
- let q = frag
- .fragment_message(&m)
- .collect::<Vec<_>>();
- assert_eq!(q.len(), 3);
- msg_eq(
- &q[0],
- 32,
- &typ,
- &version,
- &[
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27,
- ],
- );
- msg_eq(
- &q[1],
- 32,
- &typ,
- &version,
- &[
- 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
- 49, 50, 51, 52, 53, 54,
- ],
- );
- msg_eq(
- &q[2],
- 20,
- &typ,
- &version,
- &[55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
- );
- }
-
- #[test]
- fn non_fragment() {
- let m = PlainMessage {
- typ: ContentType::Handshake,
- version: ProtocolVersion::TLSv1_2,
- payload: Payload::new(b"\x01\x02\x03\x04\x05\x06\x07\x08".to_vec()),
- };
-
- let mut frag = MessageFragmenter::default();
- frag.set_max_fragment_size(Some(32))
- .unwrap();
- let q = frag
- .fragment_message(&m)
- .collect::<Vec<_>>();
- assert_eq!(q.len(), 1);
- msg_eq(
- &q[0],
- PACKET_OVERHEAD + 8,
- &ContentType::Handshake,
- &ProtocolVersion::TLSv1_2,
- b"\x01\x02\x03\x04\x05\x06\x07\x08",
- );
- }
-
- #[test]
- fn fragment_multiple_slices() {
- let typ = ContentType::Handshake;
- let version = ProtocolVersion::TLSv1_2;
- let payload_owner: Vec<&[u8]> = vec![&[b'a'; 8], &[b'b'; 12], &[b'c'; 32], &[b'd'; 20]];
- let borrowed_payload = OutboundChunks::new(&payload_owner);
- let mut frag = MessageFragmenter::default();
- frag.set_max_fragment_size(Some(37)) // 32 + packet overhead
- .unwrap();
-
- let fragments = frag
- .fragment_payload(typ, version, borrowed_payload)
- .collect::<Vec<_>>();
- assert_eq!(fragments.len(), 3);
- msg_eq(
- &fragments[0],
- 37,
- &typ,
- &version,
- b"aaaaaaaabbbbbbbbbbbbcccccccccccc",
- );
- msg_eq(
- &fragments[1],
- 37,
- &typ,
- &version,
- b"ccccccccccccccccccccdddddddddddd",
- );
- msg_eq(&fragments[2], 13, &typ, &version, b"dddddddd");
- }
-}
diff --git a/vendor/rustls/src/msgs/handshake.rs b/vendor/rustls/src/msgs/handshake.rs
deleted file mode 100644
index 093f2d12..00000000
--- a/vendor/rustls/src/msgs/handshake.rs
+++ /dev/null
@@ -1,3210 +0,0 @@
-use alloc::boxed::Box;
-use alloc::collections::BTreeSet;
-#[cfg(feature = "logging")]
-use alloc::string::String;
-use alloc::vec;
-use alloc::vec::Vec;
-use core::ops::{Deref, DerefMut};
-use core::{fmt, iter};
-
-use pki_types::{CertificateDer, DnsName};
-
-#[cfg(feature = "tls12")]
-use crate::crypto::ActiveKeyExchange;
-use crate::crypto::SecureRandom;
-use crate::enums::{
- CertificateCompressionAlgorithm, CertificateType, CipherSuite, EchClientHelloType,
- HandshakeType, ProtocolVersion, SignatureScheme,
-};
-use crate::error::InvalidMessage;
-#[cfg(feature = "tls12")]
-use crate::ffdhe_groups::FfdheGroup;
-use crate::log::warn;
-use crate::msgs::base::{MaybeEmpty, NonEmpty, Payload, PayloadU8, PayloadU16, PayloadU24};
-use crate::msgs::codec::{
- self, Codec, LengthPrefixedBuffer, ListLength, Reader, TlsListElement, TlsListIter,
-};
-use crate::msgs::enums::{
- CertificateStatusType, ClientCertificateType, Compression, ECCurveType, ECPointFormat,
- EchVersion, ExtensionType, HpkeAead, HpkeKdf, HpkeKem, KeyUpdateRequest, NamedGroup,
- PskKeyExchangeMode, ServerNameType,
-};
-use crate::rand;
-use crate::sync::Arc;
-use crate::verify::DigitallySignedStruct;
-use crate::x509::wrap_in_sequence;
-
-/// Create a newtype wrapper around a given type.
-///
-/// This is used to create newtypes for the various TLS message types which is used to wrap
-/// the `PayloadU8` or `PayloadU16` types. This is typically used for types where we don't need
-/// anything other than access to the underlying bytes.
-macro_rules! wrapped_payload(
- ($(#[$comment:meta])* $vis:vis struct $name:ident, $inner:ident$(<$inner_ty:ty>)?,) => {
- $(#[$comment])*
- #[derive(Clone, Debug)]
- $vis struct $name($inner$(<$inner_ty>)?);
-
- impl From<Vec<u8>> for $name {
- fn from(v: Vec<u8>) -> Self {
- Self($inner::new(v))
- }
- }
-
- impl AsRef<[u8]> for $name {
- fn as_ref(&self) -> &[u8] {
- self.0.0.as_slice()
- }
- }
-
- impl Codec<'_> for $name {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.0.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- Ok(Self($inner::read(r)?))
- }
- }
- }
-);
-
-#[derive(Clone, Copy, Eq, PartialEq)]
-pub(crate) struct Random(pub(crate) [u8; 32]);
-
-impl fmt::Debug for Random {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- super::base::hex(f, &self.0)
- }
-}
-
-static HELLO_RETRY_REQUEST_RANDOM: Random = Random([
- 0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, 0x02, 0x1e, 0x65, 0xb8, 0x91,
- 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e, 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c,
-]);
-
-static ZERO_RANDOM: Random = Random([0u8; 32]);
-
-impl Codec<'_> for Random {
- fn encode(&self, bytes: &mut Vec<u8>) {
- bytes.extend_from_slice(&self.0);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let Some(bytes) = r.take(32) else {
- return Err(InvalidMessage::MissingData("Random"));
- };
-
- let mut opaque = [0; 32];
- opaque.clone_from_slice(bytes);
- Ok(Self(opaque))
- }
-}
-
-impl Random {
- pub(crate) fn new(secure_random: &dyn SecureRandom) -> Result<Self, rand::GetRandomFailed> {
- let mut data = [0u8; 32];
- secure_random.fill(&mut data)?;
- Ok(Self(data))
- }
-}
-
-impl From<[u8; 32]> for Random {
- #[inline]
- fn from(bytes: [u8; 32]) -> Self {
- Self(bytes)
- }
-}
-
-#[derive(Copy, Clone)]
-pub(crate) struct SessionId {
- len: usize,
- data: [u8; 32],
-}
-
-impl fmt::Debug for SessionId {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- super::base::hex(f, &self.data[..self.len])
- }
-}
-
-impl PartialEq for SessionId {
- fn eq(&self, other: &Self) -> bool {
- if self.len != other.len {
- return false;
- }
-
- let mut diff = 0u8;
- for i in 0..self.len {
- diff |= self.data[i] ^ other.data[i];
- }
-
- diff == 0u8
- }
-}
-
-impl Codec<'_> for SessionId {
- fn encode(&self, bytes: &mut Vec<u8>) {
- debug_assert!(self.len <= 32);
- bytes.push(self.len as u8);
- bytes.extend_from_slice(self.as_ref());
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let len = u8::read(r)? as usize;
- if len > 32 {
- return Err(InvalidMessage::TrailingData("SessionID"));
- }
-
- let Some(bytes) = r.take(len) else {
- return Err(InvalidMessage::MissingData("SessionID"));
- };
-
- let mut out = [0u8; 32];
- out[..len].clone_from_slice(&bytes[..len]);
- Ok(Self { data: out, len })
- }
-}
-
-impl SessionId {
- pub(crate) fn random(secure_random: &dyn SecureRandom) -> Result<Self, rand::GetRandomFailed> {
- let mut data = [0u8; 32];
- secure_random.fill(&mut data)?;
- Ok(Self { data, len: 32 })
- }
-
- pub(crate) fn empty() -> Self {
- Self {
- data: [0u8; 32],
- len: 0,
- }
- }
-
- #[cfg(feature = "tls12")]
- pub(crate) fn is_empty(&self) -> bool {
- self.len == 0
- }
-}
-
-impl AsRef<[u8]> for SessionId {
- fn as_ref(&self) -> &[u8] {
- &self.data[..self.len]
- }
-}
-
-#[derive(Clone, Debug, PartialEq)]
-pub struct UnknownExtension {
- pub(crate) typ: ExtensionType,
- pub(crate) payload: Payload<'static>,
-}
-
-impl UnknownExtension {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.payload.encode(bytes);
- }
-
- fn read(typ: ExtensionType, r: &mut Reader<'_>) -> Self {
- let payload = Payload::read(r).into_owned();
- Self { typ, payload }
- }
-}
-
-#[derive(Clone, Copy, Debug)]
-pub(crate) struct SupportedEcPointFormats {
- pub(crate) uncompressed: bool,
-}
-
-impl Codec<'_> for SupportedEcPointFormats {
- fn encode(&self, bytes: &mut Vec<u8>) {
- let inner = LengthPrefixedBuffer::new(ECPointFormat::SIZE_LEN, bytes);
-
- if self.uncompressed {
- ECPointFormat::Uncompressed.encode(inner.buf);
- }
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let mut uncompressed = false;
-
- for pf in TlsListIter::<ECPointFormat>::new(r)? {
- if let ECPointFormat::Uncompressed = pf? {
- uncompressed = true;
- }
- }
-
- Ok(Self { uncompressed })
- }
-}
-
-impl Default for SupportedEcPointFormats {
- fn default() -> Self {
- Self { uncompressed: true }
- }
-}
-
-/// RFC8422: `ECPointFormat ec_point_format_list<1..2^8-1>`
-impl TlsListElement for ECPointFormat {
- const SIZE_LEN: ListLength = ListLength::NonZeroU8 {
- empty_error: InvalidMessage::IllegalEmptyList("ECPointFormats"),
- };
-}
-
-/// RFC8422: `NamedCurve named_curve_list<2..2^16-1>`
-impl TlsListElement for NamedGroup {
- const SIZE_LEN: ListLength = ListLength::NonZeroU16 {
- empty_error: InvalidMessage::IllegalEmptyList("NamedGroups"),
- };
-}
-
-/// RFC8446: `SignatureScheme supported_signature_algorithms<2..2^16-2>;`
-impl TlsListElement for SignatureScheme {
- const SIZE_LEN: ListLength = ListLength::NonZeroU16 {
- empty_error: InvalidMessage::NoSignatureSchemes,
- };
-}
-
-#[derive(Clone, Debug)]
-pub(crate) enum ServerNamePayload<'a> {
- /// A successfully decoded value:
- SingleDnsName(DnsName<'a>),
-
- /// A DNS name which was actually an IP address
- IpAddress,
-
- /// A successfully decoded, but syntactically-invalid value.
- Invalid,
-}
-
-impl ServerNamePayload<'_> {
- fn into_owned(self) -> ServerNamePayload<'static> {
- match self {
- Self::SingleDnsName(d) => ServerNamePayload::SingleDnsName(d.to_owned()),
- Self::IpAddress => ServerNamePayload::IpAddress,
- Self::Invalid => ServerNamePayload::Invalid,
- }
- }
-
- /// RFC6066: `ServerName server_name_list<1..2^16-1>`
- const SIZE_LEN: ListLength = ListLength::NonZeroU16 {
- empty_error: InvalidMessage::IllegalEmptyList("ServerNames"),
- };
-}
-
-/// Simplified encoding/decoding for a `ServerName` extension payload to/from `DnsName`
-///
-/// This is possible because:
-///
-/// - the spec (RFC6066) disallows multiple names for a given name type
-/// - name types other than ServerNameType::HostName are not defined, and they and
-/// any data that follows them cannot be skipped over.
-impl<'a> Codec<'a> for ServerNamePayload<'a> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- let server_name_list = LengthPrefixedBuffer::new(Self::SIZE_LEN, bytes);
-
- let ServerNamePayload::SingleDnsName(dns_name) = self else {
- return;
- };
-
- ServerNameType::HostName.encode(server_name_list.buf);
- let name_slice = dns_name.as_ref().as_bytes();
- (name_slice.len() as u16).encode(server_name_list.buf);
- server_name_list
- .buf
- .extend_from_slice(name_slice);
- }
-
- fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
- let mut found = None;
-
- let len = Self::SIZE_LEN.read(r)?;
- let mut sub = r.sub(len)?;
-
- while sub.any_left() {
- let typ = ServerNameType::read(&mut sub)?;
-
- let payload = match typ {
- ServerNameType::HostName => HostNamePayload::read(&mut sub)?,
- _ => {
- // Consume remainder of extension bytes. Since the length of the item
- // is an unknown encoding, we cannot continue.
- sub.rest();
- break;
- }
- };
-
- // "The ServerNameList MUST NOT contain more than one name of
- // the same name_type." - RFC6066
- if found.is_some() {
- warn!("Illegal SNI extension: duplicate host_name received");
- return Err(InvalidMessage::InvalidServerName);
- }
-
- found = match payload {
- HostNamePayload::HostName(dns_name) => {
- Some(Self::SingleDnsName(dns_name.to_owned()))
- }
-
- HostNamePayload::IpAddress(_invalid) => {
- warn!(
- "Illegal SNI extension: ignoring IP address presented as hostname ({_invalid:?})"
- );
- Some(Self::IpAddress)
- }
-
- HostNamePayload::Invalid(_invalid) => {
- warn!(
- "Illegal SNI hostname received {:?}",
- String::from_utf8_lossy(&_invalid.0)
- );
- Some(Self::Invalid)
- }
- };
- }
-
- Ok(found.unwrap_or(Self::Invalid))
- }
-}
-
-impl<'a> From<&DnsName<'a>> for ServerNamePayload<'static> {
- fn from(value: &DnsName<'a>) -> Self {
- Self::SingleDnsName(trim_hostname_trailing_dot_for_sni(value))
- }
-}
-
-#[derive(Clone, Debug)]
-pub(crate) enum HostNamePayload {
- HostName(DnsName<'static>),
- IpAddress(PayloadU16<NonEmpty>),
- Invalid(PayloadU16<NonEmpty>),
-}
-
-impl HostNamePayload {
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- use pki_types::ServerName;
- let raw = PayloadU16::<NonEmpty>::read(r)?;
-
- match ServerName::try_from(raw.0.as_slice()) {
- Ok(ServerName::DnsName(d)) => Ok(Self::HostName(d.to_owned())),
- Ok(ServerName::IpAddress(_)) => Ok(Self::IpAddress(raw)),
- Ok(_) | Err(_) => Ok(Self::Invalid(raw)),
- }
- }
-}
-
-wrapped_payload!(
- /// RFC7301: `opaque ProtocolName<1..2^8-1>;`
- pub(crate) struct ProtocolName, PayloadU8<NonEmpty>,
-);
-
-impl PartialEq for ProtocolName {
- fn eq(&self, other: &Self) -> bool {
- self.0 == other.0
- }
-}
-
-impl Deref for ProtocolName {
- type Target = [u8];
-
- fn deref(&self) -> &Self::Target {
- self.as_ref()
- }
-}
-
-/// RFC7301: `ProtocolName protocol_name_list<2..2^16-1>`
-impl TlsListElement for ProtocolName {
- const SIZE_LEN: ListLength = ListLength::NonZeroU16 {
- empty_error: InvalidMessage::IllegalEmptyList("ProtocolNames"),
- };
-}
-
-/// RFC7301 encodes a single protocol name as `Vec<ProtocolName>`
-#[derive(Clone, Debug)]
-pub(crate) struct SingleProtocolName(ProtocolName);
-
-impl SingleProtocolName {
- pub(crate) fn new(single: ProtocolName) -> Self {
- Self(single)
- }
-
- const SIZE_LEN: ListLength = ListLength::NonZeroU16 {
- empty_error: InvalidMessage::IllegalEmptyList("ProtocolNames"),
- };
-}
-
-impl Codec<'_> for SingleProtocolName {
- fn encode(&self, bytes: &mut Vec<u8>) {
- let body = LengthPrefixedBuffer::new(Self::SIZE_LEN, bytes);
- self.0.encode(body.buf);
- }
-
- fn read(reader: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let len = Self::SIZE_LEN.read(reader)?;
- let mut sub = reader.sub(len)?;
-
- let item = ProtocolName::read(&mut sub)?;
-
- if sub.any_left() {
- Err(InvalidMessage::TrailingData("SingleProtocolName"))
- } else {
- Ok(Self(item))
- }
- }
-}
-
-impl AsRef<ProtocolName> for SingleProtocolName {
- fn as_ref(&self) -> &ProtocolName {
- &self.0
- }
-}
-
-// --- TLS 1.3 Key shares ---
-#[derive(Clone, Debug)]
-pub(crate) struct KeyShareEntry {
- pub(crate) group: NamedGroup,
- /// RFC8446: `opaque key_exchange<1..2^16-1>;`
- pub(crate) payload: PayloadU16<NonEmpty>,
-}
-
-impl KeyShareEntry {
- pub(crate) fn new(group: NamedGroup, payload: impl Into<Vec<u8>>) -> Self {
- Self {
- group,
- payload: PayloadU16::new(payload.into()),
- }
- }
-}
-
-impl Codec<'_> for KeyShareEntry {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.group.encode(bytes);
- self.payload.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let group = NamedGroup::read(r)?;
- let payload = PayloadU16::read(r)?;
-
- Ok(Self { group, payload })
- }
-}
-
-// --- TLS 1.3 PresharedKey offers ---
-#[derive(Clone, Debug)]
-pub(crate) struct PresharedKeyIdentity {
- /// RFC8446: `opaque identity<1..2^16-1>;`
- pub(crate) identity: PayloadU16<NonEmpty>,
- pub(crate) obfuscated_ticket_age: u32,
-}
-
-impl PresharedKeyIdentity {
- pub(crate) fn new(id: Vec<u8>, age: u32) -> Self {
- Self {
- identity: PayloadU16::new(id),
- obfuscated_ticket_age: age,
- }
- }
-}
-
-impl Codec<'_> for PresharedKeyIdentity {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.identity.encode(bytes);
- self.obfuscated_ticket_age.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- Ok(Self {
- identity: PayloadU16::read(r)?,
- obfuscated_ticket_age: u32::read(r)?,
- })
- }
-}
-
-/// RFC8446: `PskIdentity identities<7..2^16-1>;`
-impl TlsListElement for PresharedKeyIdentity {
- const SIZE_LEN: ListLength = ListLength::NonZeroU16 {
- empty_error: InvalidMessage::IllegalEmptyList("PskIdentities"),
- };
-}
-
-wrapped_payload!(
- /// RFC8446: `opaque PskBinderEntry<32..255>;`
- pub(crate) struct PresharedKeyBinder, PayloadU8<NonEmpty>,
-);
-
-/// RFC8446: `PskBinderEntry binders<33..2^16-1>;`
-impl TlsListElement for PresharedKeyBinder {
- const SIZE_LEN: ListLength = ListLength::NonZeroU16 {
- empty_error: InvalidMessage::IllegalEmptyList("PskBinders"),
- };
-}
-
-#[derive(Clone, Debug)]
-pub(crate) struct PresharedKeyOffer {
- pub(crate) identities: Vec<PresharedKeyIdentity>,
- pub(crate) binders: Vec<PresharedKeyBinder>,
-}
-
-impl PresharedKeyOffer {
- /// Make a new one with one entry.
- pub(crate) fn new(id: PresharedKeyIdentity, binder: Vec<u8>) -> Self {
- Self {
- identities: vec![id],
- binders: vec![PresharedKeyBinder::from(binder)],
- }
- }
-}
-
-impl Codec<'_> for PresharedKeyOffer {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.identities.encode(bytes);
- self.binders.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- Ok(Self {
- identities: Vec::read(r)?,
- binders: Vec::read(r)?,
- })
- }
-}
-
-// --- RFC6066 certificate status request ---
-wrapped_payload!(pub(crate) struct ResponderId, PayloadU16,);
-
-/// RFC6066: `ResponderID responder_id_list<0..2^16-1>;`
-impl TlsListElement for ResponderId {
- const SIZE_LEN: ListLength = ListLength::U16;
-}
-
-#[derive(Clone, Debug)]
-pub(crate) struct OcspCertificateStatusRequest {
- pub(crate) responder_ids: Vec<ResponderId>,
- pub(crate) extensions: PayloadU16,
-}
-
-impl Codec<'_> for OcspCertificateStatusRequest {
- fn encode(&self, bytes: &mut Vec<u8>) {
- CertificateStatusType::OCSP.encode(bytes);
- self.responder_ids.encode(bytes);
- self.extensions.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- Ok(Self {
- responder_ids: Vec::read(r)?,
- extensions: PayloadU16::read(r)?,
- })
- }
-}
-
-#[derive(Clone, Debug)]
-pub(crate) enum CertificateStatusRequest {
- Ocsp(OcspCertificateStatusRequest),
- Unknown((CertificateStatusType, Payload<'static>)),
-}
-
-impl Codec<'_> for CertificateStatusRequest {
- fn encode(&self, bytes: &mut Vec<u8>) {
- match self {
- Self::Ocsp(r) => r.encode(bytes),
- Self::Unknown((typ, payload)) => {
- typ.encode(bytes);
- payload.encode(bytes);
- }
- }
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let typ = CertificateStatusType::read(r)?;
-
- match typ {
- CertificateStatusType::OCSP => {
- let ocsp_req = OcspCertificateStatusRequest::read(r)?;
- Ok(Self::Ocsp(ocsp_req))
- }
- _ => {
- let data = Payload::read(r).into_owned();
- Ok(Self::Unknown((typ, data)))
- }
- }
- }
-}
-
-impl CertificateStatusRequest {
- pub(crate) fn build_ocsp() -> Self {
- let ocsp = OcspCertificateStatusRequest {
- responder_ids: Vec::new(),
- extensions: PayloadU16::empty(),
- };
- Self::Ocsp(ocsp)
- }
-}
-
-// ---
-
-/// RFC8446: `PskKeyExchangeMode ke_modes<1..255>;`
-#[derive(Clone, Copy, Debug, Default)]
-pub(crate) struct PskKeyExchangeModes {
- pub(crate) psk_dhe: bool,
- pub(crate) psk: bool,
-}
-
-impl Codec<'_> for PskKeyExchangeModes {
- fn encode(&self, bytes: &mut Vec<u8>) {
- let inner = LengthPrefixedBuffer::new(PskKeyExchangeMode::SIZE_LEN, bytes);
- if self.psk_dhe {
- PskKeyExchangeMode::PSK_DHE_KE.encode(inner.buf);
- }
- if self.psk {
- PskKeyExchangeMode::PSK_KE.encode(inner.buf);
- }
- }
-
- fn read(reader: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let mut psk_dhe = false;
- let mut psk = false;
-
- for ke in TlsListIter::<PskKeyExchangeMode>::new(reader)? {
- match ke? {
- PskKeyExchangeMode::PSK_DHE_KE => psk_dhe = true,
- PskKeyExchangeMode::PSK_KE => psk = true,
- _ => continue,
- };
- }
-
- Ok(Self { psk_dhe, psk })
- }
-}
-
-impl TlsListElement for PskKeyExchangeMode {
- const SIZE_LEN: ListLength = ListLength::NonZeroU8 {
- empty_error: InvalidMessage::IllegalEmptyList("PskKeyExchangeModes"),
- };
-}
-
-/// RFC8446: `KeyShareEntry client_shares<0..2^16-1>;`
-impl TlsListElement for KeyShareEntry {
- const SIZE_LEN: ListLength = ListLength::U16;
-}
-
-/// The body of the `SupportedVersions` extension when it appears in a
-/// `ClientHello`
-///
-/// This is documented as a preference-order vector, but we (as a server)
-/// ignore the preference of the client.
-///
-/// RFC8446: `ProtocolVersion versions<2..254>;`
-#[derive(Clone, Copy, Debug, Default)]
-pub(crate) struct SupportedProtocolVersions {
- pub(crate) tls13: bool,
- pub(crate) tls12: bool,
-}
-
-impl SupportedProtocolVersions {
- /// Return true if `filter` returns true for any enabled version.
- pub(crate) fn any(&self, filter: impl Fn(ProtocolVersion) -> bool) -> bool {
- if self.tls13 && filter(ProtocolVersion::TLSv1_3) {
- return true;
- }
- if self.tls12 && filter(ProtocolVersion::TLSv1_2) {
- return true;
- }
- false
- }
-
- const LIST_LENGTH: ListLength = ListLength::NonZeroU8 {
- empty_error: InvalidMessage::IllegalEmptyList("ProtocolVersions"),
- };
-}
-
-impl Codec<'_> for SupportedProtocolVersions {
- fn encode(&self, bytes: &mut Vec<u8>) {
- let inner = LengthPrefixedBuffer::new(Self::LIST_LENGTH, bytes);
- if self.tls13 {
- ProtocolVersion::TLSv1_3.encode(inner.buf);
- }
- if self.tls12 {
- ProtocolVersion::TLSv1_2.encode(inner.buf);
- }
- }
-
- fn read(reader: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let mut tls12 = false;
- let mut tls13 = false;
-
- for pv in TlsListIter::<ProtocolVersion>::new(reader)? {
- match pv? {
- ProtocolVersion::TLSv1_3 => tls13 = true,
- ProtocolVersion::TLSv1_2 => tls12 = true,
- _ => continue,
- };
- }
-
- Ok(Self { tls13, tls12 })
- }
-}
-
-impl TlsListElement for ProtocolVersion {
- const SIZE_LEN: ListLength = ListLength::NonZeroU8 {
- empty_error: InvalidMessage::IllegalEmptyList("ProtocolVersions"),
- };
-}
-
-/// RFC7250: `CertificateType client_certificate_types<1..2^8-1>;`
-///
-/// Ditto `CertificateType server_certificate_types<1..2^8-1>;`
-impl TlsListElement for CertificateType {
- const SIZE_LEN: ListLength = ListLength::NonZeroU8 {
- empty_error: InvalidMessage::IllegalEmptyList("CertificateTypes"),
- };
-}
-
-/// RFC8879: `CertificateCompressionAlgorithm algorithms<2..2^8-2>;`
-impl TlsListElement for CertificateCompressionAlgorithm {
- const SIZE_LEN: ListLength = ListLength::NonZeroU8 {
- empty_error: InvalidMessage::IllegalEmptyList("CertificateCompressionAlgorithms"),
- };
-}
-
-/// A precursor to `ClientExtensions`, allowing customisation.
-///
-/// This is smaller than `ClientExtensions`, as it only contains the extensions
-/// we need to vary between different protocols (eg, TCP-TLS versus QUIC).
-#[derive(Clone, Default)]
-pub(crate) struct ClientExtensionsInput<'a> {
- /// QUIC transport parameters
- pub(crate) transport_parameters: Option<TransportParameters<'a>>,
-
- /// ALPN protocols
- pub(crate) protocols: Option<Vec<ProtocolName>>,
-}
-
-impl ClientExtensionsInput<'_> {
- pub(crate) fn from_alpn(alpn_protocols: Vec<Vec<u8>>) -> ClientExtensionsInput<'static> {
- let protocols = match alpn_protocols.is_empty() {
- true => None,
- false => Some(
- alpn_protocols
- .into_iter()
- .map(ProtocolName::from)
- .collect::<Vec<_>>(),
- ),
- };
-
- ClientExtensionsInput {
- transport_parameters: None,
- protocols,
- }
- }
-
- pub(crate) fn into_owned(self) -> ClientExtensionsInput<'static> {
- let Self {
- transport_parameters,
- protocols,
- } = self;
- ClientExtensionsInput {
- transport_parameters: transport_parameters.map(|x| x.into_owned()),
- protocols,
- }
- }
-}
-
-#[derive(Clone)]
-pub(crate) enum TransportParameters<'a> {
- /// QUIC transport parameters (RFC9001 prior to draft 33)
- QuicDraft(Payload<'a>),
-
- /// QUIC transport parameters (RFC9001)
- Quic(Payload<'a>),
-}
-
-impl TransportParameters<'_> {
- pub(crate) fn into_owned(self) -> TransportParameters<'static> {
- match self {
- Self::QuicDraft(v) => TransportParameters::QuicDraft(v.into_owned()),
- Self::Quic(v) => TransportParameters::Quic(v.into_owned()),
- }
- }
-}
-
-extension_struct! {
- /// A representation of extensions present in a `ClientHello` message
- ///
- /// All extensions are optional (by definition) so are represented with `Option<T>`.
- ///
- /// Some extensions have an empty value and are represented with Option<()>.
- ///
- /// Unknown extensions are dropped during parsing.
- pub(crate) struct ClientExtensions<'a> {
- /// Requested server name indication (RFC6066)
- ExtensionType::ServerName =>
- pub(crate) server_name: Option<ServerNamePayload<'a>>,
-
- /// Certificate status is requested (RFC6066)
- ExtensionType::StatusRequest =>
- pub(crate) certificate_status_request: Option<CertificateStatusRequest>,
-
- /// Supported groups (RFC4492/RFC8446)
- ExtensionType::EllipticCurves =>
- pub(crate) named_groups: Option<Vec<NamedGroup>>,
-
- /// Supported EC point formats (RFC4492)
- ExtensionType::ECPointFormats =>
- pub(crate) ec_point_formats: Option<SupportedEcPointFormats>,
-
- /// Supported signature schemes (RFC5246/RFC8446)
- ExtensionType::SignatureAlgorithms =>
- pub(crate) signature_schemes: Option<Vec<SignatureScheme>>,
-
- /// Offered ALPN protocols (RFC6066)
- ExtensionType::ALProtocolNegotiation =>
- pub(crate) protocols: Option<Vec<ProtocolName>>,
-
- /// Available client certificate types (RFC7250)
- ExtensionType::ClientCertificateType =>
- pub(crate) client_certificate_types: Option<Vec<CertificateType>>,
-
- /// Acceptable server certificate types (RFC7250)
- ExtensionType::ServerCertificateType =>
- pub(crate) server_certificate_types: Option<Vec<CertificateType>>,
-
- /// Extended master secret is requested (RFC7627)
- ExtensionType::ExtendedMasterSecret =>
- pub(crate) extended_master_secret_request: Option<()>,
-
- /// Offered certificate compression methods (RFC8879)
- ExtensionType::CompressCertificate =>
- pub(crate) certificate_compression_algorithms: Option<Vec<CertificateCompressionAlgorithm>>,
-
- /// Session ticket offer or request (RFC5077/RFC8446)
- ExtensionType::SessionTicket =>
- pub(crate) session_ticket: Option<ClientSessionTicket>,
-
- /// Offered preshared keys (RFC8446)
- ExtensionType::PreSharedKey =>
- pub(crate) preshared_key_offer: Option<PresharedKeyOffer>,
-
- /// Early data is requested (RFC8446)
- ExtensionType::EarlyData =>
- pub(crate) early_data_request: Option<()>,
-
- /// Supported TLS versions (RFC8446)
- ExtensionType::SupportedVersions =>
- pub(crate) supported_versions: Option<SupportedProtocolVersions>,
-
- /// Stateless HelloRetryRequest cookie (RFC8446)
- ExtensionType::Cookie =>
- pub(crate) cookie: Option<PayloadU16<NonEmpty>>,
-
- /// Offered preshared key modes (RFC8446)
- ExtensionType::PSKKeyExchangeModes =>
- pub(crate) preshared_key_modes: Option<PskKeyExchangeModes>,
-
- /// Certificate authority names (RFC8446)
- ExtensionType::CertificateAuthorities =>
- pub(crate) certificate_authority_names: Option<Vec<DistinguishedName>>,
-
- /// Offered key exchange shares (RFC8446)
- ExtensionType::KeyShare =>
- pub(crate) key_shares: Option<Vec<KeyShareEntry>>,
-
- /// QUIC transport parameters (RFC9001)
- ExtensionType::TransportParameters =>
- pub(crate) transport_parameters: Option<Payload<'a>>,
-
- /// Secure renegotiation (RFC5746)
- ExtensionType::RenegotiationInfo =>
- pub(crate) renegotiation_info: Option<PayloadU8>,
-
- /// QUIC transport parameters (RFC9001 prior to draft 33)
- ExtensionType::TransportParametersDraft =>
- pub(crate) transport_parameters_draft: Option<Payload<'a>>,
-
- /// Encrypted inner client hello (draft-ietf-tls-esni)
- ExtensionType::EncryptedClientHello =>
- pub(crate) encrypted_client_hello: Option<EncryptedClientHello>,
-
- /// Encrypted client hello outer extensions (draft-ietf-tls-esni)
- ExtensionType::EncryptedClientHelloOuterExtensions =>
- pub(crate) encrypted_client_hello_outer: Option<Vec<ExtensionType>>,
- } + {
- /// Order randomization seed.
- pub(crate) order_seed: u16,
-
- /// Extensions that must appear contiguously.
- pub(crate) contiguous_extensions: Vec<ExtensionType>,
- }
-}
-
-impl ClientExtensions<'_> {
- pub(crate) fn into_owned(self) -> ClientExtensions<'static> {
- let Self {
- server_name,
- certificate_status_request,
- named_groups,
- ec_point_formats,
- signature_schemes,
- protocols,
- client_certificate_types,
- server_certificate_types,
- extended_master_secret_request,
- certificate_compression_algorithms,
- session_ticket,
- preshared_key_offer,
- early_data_request,
- supported_versions,
- cookie,
- preshared_key_modes,
- certificate_authority_names,
- key_shares,
- transport_parameters,
- renegotiation_info,
- transport_parameters_draft,
- encrypted_client_hello,
- encrypted_client_hello_outer,
- order_seed,
- contiguous_extensions,
- } = self;
- ClientExtensions {
- server_name: server_name.map(|x| x.into_owned()),
- certificate_status_request,
- named_groups,
- ec_point_formats,
- signature_schemes,
- protocols,
- client_certificate_types,
- server_certificate_types,
- extended_master_secret_request,
- certificate_compression_algorithms,
- session_ticket,
- preshared_key_offer,
- early_data_request,
- supported_versions,
- cookie,
- preshared_key_modes,
- certificate_authority_names,
- key_shares,
- transport_parameters: transport_parameters.map(|x| x.into_owned()),
- renegotiation_info,
- transport_parameters_draft: transport_parameters_draft.map(|x| x.into_owned()),
- encrypted_client_hello,
- encrypted_client_hello_outer,
- order_seed,
- contiguous_extensions,
- }
- }
-
- pub(crate) fn used_extensions_in_encoding_order(&self) -> Vec<ExtensionType> {
- let mut exts = self.order_insensitive_extensions_in_random_order();
- exts.extend(&self.contiguous_extensions);
-
- if self
- .encrypted_client_hello_outer
- .is_some()
- {
- exts.push(ExtensionType::EncryptedClientHelloOuterExtensions);
- }
- if self.encrypted_client_hello.is_some() {
- exts.push(ExtensionType::EncryptedClientHello);
- }
- if self.preshared_key_offer.is_some() {
- exts.push(ExtensionType::PreSharedKey);
- }
- exts
- }
-
- /// Returns extensions which don't need a specific order, in randomized order.
- ///
- /// Extensions are encoded in three portions:
- ///
- /// - First, extensions not otherwise dealt with by other cases.
- /// These are encoded in random order, controlled by `self.order_seed`,
- /// and this is the set of extensions returned by this function.
- ///
- /// - Second, extensions named in `self.contiguous_extensions`, in the order
- /// given by that field.
- ///
- /// - Lastly, any ECH and PSK extensions (in that order). These
- /// are required to be last by the standard.
- fn order_insensitive_extensions_in_random_order(&self) -> Vec<ExtensionType> {
- let mut order = self.collect_used();
-
- // Remove extensions which have specific order requirements.
- order.retain(|ext| {
- !(matches!(
- ext,
- ExtensionType::PreSharedKey
- | ExtensionType::EncryptedClientHello
- | ExtensionType::EncryptedClientHelloOuterExtensions
- ) || self.contiguous_extensions.contains(ext))
- });
-
- order.sort_by_cached_key(|new_ext| {
- let seed = ((self.order_seed as u32) << 16) | (u16::from(*new_ext) as u32);
- low_quality_integer_hash(seed)
- });
-
- order
- }
-}
-
-impl<'a> Codec<'a> for ClientExtensions<'a> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- let order = self.used_extensions_in_encoding_order();
-
- if order.is_empty() {
- return;
- }
-
- let body = LengthPrefixedBuffer::new(ListLength::U16, bytes);
- for item in order {
- self.encode_one(item, body.buf);
- }
- }
-
- fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
- let mut out = Self::default();
-
- // extensions length can be absent if no extensions
- if !r.any_left() {
- return Ok(out);
- }
-
- let mut checker = DuplicateExtensionChecker::new();
-
- let len = usize::from(u16::read(r)?);
- let mut sub = r.sub(len)?;
-
- while sub.any_left() {
- let typ = out.read_one(&mut sub, |unknown| checker.check(unknown))?;
-
- // PreSharedKey offer must come last
- if typ == ExtensionType::PreSharedKey && sub.any_left() {
- return Err(InvalidMessage::PreSharedKeyIsNotFinalExtension);
- }
- }
-
- Ok(out)
- }
-}
-
-fn trim_hostname_trailing_dot_for_sni(dns_name: &DnsName<'_>) -> DnsName<'static> {
- let dns_name_str = dns_name.as_ref();
-
- // RFC6066: "The hostname is represented as a byte string using
- // ASCII encoding without a trailing dot"
- if dns_name_str.ends_with('.') {
- let trimmed = &dns_name_str[0..dns_name_str.len() - 1];
- DnsName::try_from(trimmed)
- .unwrap()
- .to_owned()
- } else {
- dns_name.to_owned()
- }
-}
-
-#[derive(Clone, Debug)]
-pub(crate) enum ClientSessionTicket {
- Request,
- Offer(Payload<'static>),
-}
-
-impl<'a> Codec<'a> for ClientSessionTicket {
- fn encode(&self, bytes: &mut Vec<u8>) {
- match self {
- Self::Request => (),
- Self::Offer(p) => p.encode(bytes),
- }
- }
-
- fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
- Ok(match r.left() {
- 0 => Self::Request,
- _ => Self::Offer(Payload::read(r).into_owned()),
- })
- }
-}
-
-#[derive(Default)]
-pub(crate) struct ServerExtensionsInput<'a> {
- /// QUIC transport parameters
- pub(crate) transport_parameters: Option<TransportParameters<'a>>,
-}
-
-extension_struct! {
- pub(crate) struct ServerExtensions<'a> {
- /// Supported EC point formats (RFC4492)
- ExtensionType::ECPointFormats =>
- pub(crate) ec_point_formats: Option<SupportedEcPointFormats>,
-
- /// Server name indication acknowledgement (RFC6066)
- ExtensionType::ServerName =>
- pub(crate) server_name_ack: Option<()>,
-
- /// Session ticket acknowledgement (RFC5077)
- ExtensionType::SessionTicket =>
- pub(crate) session_ticket_ack: Option<()>,
-
- ExtensionType::RenegotiationInfo =>
- pub(crate) renegotiation_info: Option<PayloadU8>,
-
- /// Selected ALPN protocol (RFC7301)
- ExtensionType::ALProtocolNegotiation =>
- pub(crate) selected_protocol: Option<SingleProtocolName>,
-
- /// Key exchange server share (RFC8446)
- ExtensionType::KeyShare =>
- pub(crate) key_share: Option<KeyShareEntry>,
-
- /// Selected preshared key index (RFC8446)
- ExtensionType::PreSharedKey =>
- pub(crate) preshared_key: Option<u16>,
-
- /// Required client certificate type (RFC7250)
- ExtensionType::ClientCertificateType =>
- pub(crate) client_certificate_type: Option<CertificateType>,
-
- /// Selected server certificate type (RFC7250)
- ExtensionType::ServerCertificateType =>
- pub(crate) server_certificate_type: Option<CertificateType>,
-
- /// Extended master secret is in use (RFC7627)
- ExtensionType::ExtendedMasterSecret =>
- pub(crate) extended_master_secret_ack: Option<()>,
-
- /// Certificate status acknowledgement (RFC6066)
- ExtensionType::StatusRequest =>
- pub(crate) certificate_status_request_ack: Option<()>,
-
- /// Selected TLS version (RFC8446)
- ExtensionType::SupportedVersions =>
- pub(crate) selected_version: Option<ProtocolVersion>,
-
- /// QUIC transport parameters (RFC9001)
- ExtensionType::TransportParameters =>
- pub(crate) transport_parameters: Option<Payload<'a>>,
-
- /// QUIC transport parameters (RFC9001 prior to draft 33)
- ExtensionType::TransportParametersDraft =>
- pub(crate) transport_parameters_draft: Option<Payload<'a>>,
-
- /// Early data is accepted (RFC8446)
- ExtensionType::EarlyData =>
- pub(crate) early_data_ack: Option<()>,
-
- /// Encrypted inner client hello response (draft-ietf-tls-esni)
- ExtensionType::EncryptedClientHello =>
- pub(crate) encrypted_client_hello_ack: Option<ServerEncryptedClientHello>,
- } + {
- pub(crate) unknown_extensions: BTreeSet<u16>,
- }
-}
-
-impl ServerExtensions<'_> {
- fn into_owned(self) -> ServerExtensions<'static> {
- let Self {
- ec_point_formats,
- server_name_ack,
- session_ticket_ack,
- renegotiation_info,
- selected_protocol,
- key_share,
- preshared_key,
- client_certificate_type,
- server_certificate_type,
- extended_master_secret_ack,
- certificate_status_request_ack,
- selected_version,
- transport_parameters,
- transport_parameters_draft,
- early_data_ack,
- encrypted_client_hello_ack,
- unknown_extensions,
- } = self;
- ServerExtensions {
- ec_point_formats,
- server_name_ack,
- session_ticket_ack,
- renegotiation_info,
- selected_protocol,
- key_share,
- preshared_key,
- client_certificate_type,
- server_certificate_type,
- extended_master_secret_ack,
- certificate_status_request_ack,
- selected_version,
- transport_parameters: transport_parameters.map(|x| x.into_owned()),
- transport_parameters_draft: transport_parameters_draft.map(|x| x.into_owned()),
- early_data_ack,
- encrypted_client_hello_ack,
- unknown_extensions,
- }
- }
-}
-
-impl<'a> Codec<'a> for ServerExtensions<'a> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- let extensions = LengthPrefixedBuffer::new(ListLength::U16, bytes);
-
- for ext in Self::ALL_EXTENSIONS {
- self.encode_one(*ext, extensions.buf);
- }
- }
-
- fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
- let mut out = Self::default();
- let mut checker = DuplicateExtensionChecker::new();
-
- let len = usize::from(u16::read(r)?);
- let mut sub = r.sub(len)?;
-
- while sub.any_left() {
- out.read_one(&mut sub, |unknown| checker.check(unknown))?;
- }
-
- out.unknown_extensions = checker.0;
- Ok(out)
- }
-}
-
-#[derive(Clone, Debug)]
-pub(crate) struct ClientHelloPayload {
- pub(crate) client_version: ProtocolVersion,
- pub(crate) random: Random,
- pub(crate) session_id: SessionId,
- pub(crate) cipher_suites: Vec<CipherSuite>,
- pub(crate) compression_methods: Vec<Compression>,
- pub(crate) extensions: Box<ClientExtensions<'static>>,
-}
-
-impl ClientHelloPayload {
- pub(crate) fn ech_inner_encoding(&self, to_compress: Vec<ExtensionType>) -> Vec<u8> {
- let mut bytes = Vec::new();
- self.payload_encode(&mut bytes, Encoding::EchInnerHello { to_compress });
- bytes
- }
-
- pub(crate) fn payload_encode(&self, bytes: &mut Vec<u8>, purpose: Encoding) {
- self.client_version.encode(bytes);
- self.random.encode(bytes);
-
- match purpose {
- // SessionID is required to be empty in the encoded inner client hello.
- Encoding::EchInnerHello { .. } => SessionId::empty().encode(bytes),
- _ => self.session_id.encode(bytes),
- }
-
- self.cipher_suites.encode(bytes);
- self.compression_methods.encode(bytes);
-
- let to_compress = match purpose {
- Encoding::EchInnerHello { to_compress } if !to_compress.is_empty() => to_compress,
- _ => {
- self.extensions.encode(bytes);
- return;
- }
- };
-
- let mut compressed = self.extensions.clone();
-
- // First, eliminate the full-fat versions of the extensions
- for e in &to_compress {
- compressed.clear(*e);
- }
-
- // Replace with the marker noting which extensions were elided.
- compressed.encrypted_client_hello_outer = Some(to_compress);
-
- // And encode as normal.
- compressed.encode(bytes);
- }
-
- pub(crate) fn has_keyshare_extension_with_duplicates(&self) -> bool {
- self.key_shares
- .as_ref()
- .map(|entries| {
- has_duplicates::<_, _, u16>(
- entries
- .iter()
- .map(|kse| u16::from(kse.group)),
- )
- })
- .unwrap_or_default()
- }
-
- pub(crate) fn has_certificate_compression_extension_with_duplicates(&self) -> bool {
- if let Some(algs) = &self.certificate_compression_algorithms {
- has_duplicates::<_, _, u16>(algs.iter().cloned())
- } else {
- false
- }
- }
-}
-
-impl Codec<'_> for ClientHelloPayload {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.payload_encode(bytes, Encoding::Standard)
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let ret = Self {
- client_version: ProtocolVersion::read(r)?,
- random: Random::read(r)?,
- session_id: SessionId::read(r)?,
- cipher_suites: Vec::read(r)?,
- compression_methods: Vec::read(r)?,
- extensions: Box::new(ClientExtensions::read(r)?.into_owned()),
- };
-
- match r.any_left() {
- true => Err(InvalidMessage::TrailingData("ClientHelloPayload")),
- false => Ok(ret),
- }
- }
-}
-
-impl Deref for ClientHelloPayload {
- type Target = ClientExtensions<'static>;
- fn deref(&self) -> &Self::Target {
- &self.extensions
- }
-}
-
-impl DerefMut for ClientHelloPayload {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.extensions
- }
-}
-
-/// RFC8446: `CipherSuite cipher_suites<2..2^16-2>;`
-impl TlsListElement for CipherSuite {
- const SIZE_LEN: ListLength = ListLength::NonZeroU16 {
- empty_error: InvalidMessage::IllegalEmptyList("CipherSuites"),
- };
-}
-
-/// RFC5246: `CompressionMethod compression_methods<1..2^8-1>;`
-impl TlsListElement for Compression {
- const SIZE_LEN: ListLength = ListLength::NonZeroU8 {
- empty_error: InvalidMessage::IllegalEmptyList("Compressions"),
- };
-}
-
-/// draft-ietf-tls-esni-17: `ExtensionType OuterExtensions<2..254>;`
-impl TlsListElement for ExtensionType {
- const SIZE_LEN: ListLength = ListLength::NonZeroU8 {
- empty_error: InvalidMessage::IllegalEmptyList("ExtensionTypes"),
- };
-}
-
-extension_struct! {
- /// A representation of extensions present in a `HelloRetryRequest` message
- pub(crate) struct HelloRetryRequestExtensions<'a> {
- ExtensionType::KeyShare =>
- pub(crate) key_share: Option<NamedGroup>,
-
- ExtensionType::Cookie =>
- pub(crate) cookie: Option<PayloadU16<NonEmpty>>,
-
- ExtensionType::SupportedVersions =>
- pub(crate) supported_versions: Option<ProtocolVersion>,
-
- ExtensionType::EncryptedClientHello =>
- pub(crate) encrypted_client_hello: Option<Payload<'a>>,
- } + {
- /// Records decoding order of records, and controls encoding order.
- pub(crate) order: Option<Vec<ExtensionType>>,
- }
-}
-
-impl HelloRetryRequestExtensions<'_> {
- fn into_owned(self) -> HelloRetryRequestExtensions<'static> {
- let Self {
- key_share,
- cookie,
- supported_versions,
- encrypted_client_hello,
- order,
- } = self;
- HelloRetryRequestExtensions {
- key_share,
- cookie,
- supported_versions,
- encrypted_client_hello: encrypted_client_hello.map(|x| x.into_owned()),
- order,
- }
- }
-}
-
-impl<'a> Codec<'a> for HelloRetryRequestExtensions<'a> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- let extensions = LengthPrefixedBuffer::new(ListLength::U16, bytes);
-
- for ext in self
- .order
- .as_deref()
- .unwrap_or(Self::ALL_EXTENSIONS)
- {
- self.encode_one(*ext, extensions.buf);
- }
- }
-
- fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
- let mut out = Self::default();
-
- // we must record order, so re-encoding round trips. this is needed,
- // unfortunately, for ECH HRR confirmation
- let mut order = vec![];
-
- let len = usize::from(u16::read(r)?);
- let mut sub = r.sub(len)?;
-
- while sub.any_left() {
- let typ = out.read_one(&mut sub, |_unk| {
- Err(InvalidMessage::UnknownHelloRetryRequestExtension)
- })?;
-
- order.push(typ);
- }
-
- out.order = Some(order);
- Ok(out)
- }
-}
-
-#[derive(Clone, Debug)]
-pub(crate) struct HelloRetryRequest {
- pub(crate) legacy_version: ProtocolVersion,
- pub(crate) session_id: SessionId,
- pub(crate) cipher_suite: CipherSuite,
- pub(crate) extensions: HelloRetryRequestExtensions<'static>,
-}
-
-impl Codec<'_> for HelloRetryRequest {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.payload_encode(bytes, Encoding::Standard)
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let session_id = SessionId::read(r)?;
- let cipher_suite = CipherSuite::read(r)?;
- let compression = Compression::read(r)?;
-
- if compression != Compression::Null {
- return Err(InvalidMessage::UnsupportedCompression);
- }
-
- Ok(Self {
- legacy_version: ProtocolVersion::Unknown(0),
- session_id,
- cipher_suite,
- extensions: HelloRetryRequestExtensions::read(r)?.into_owned(),
- })
- }
-}
-
-impl HelloRetryRequest {
- fn payload_encode(&self, bytes: &mut Vec<u8>, purpose: Encoding) {
- self.legacy_version.encode(bytes);
- HELLO_RETRY_REQUEST_RANDOM.encode(bytes);
- self.session_id.encode(bytes);
- self.cipher_suite.encode(bytes);
- Compression::Null.encode(bytes);
-
- match purpose {
- // For the purpose of ECH confirmation, the Encrypted Client Hello extension
- // must have its payload replaced by 8 zero bytes.
- //
- // See draft-ietf-tls-esni-18 7.2.1:
- // <https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#name-sending-helloretryrequest-2>
- Encoding::EchConfirmation
- if self
- .extensions
- .encrypted_client_hello
- .is_some() =>
- {
- let hrr_confirmation = [0u8; 8];
- HelloRetryRequestExtensions {
- encrypted_client_hello: Some(Payload::Borrowed(&hrr_confirmation)),
- ..self.extensions.clone()
- }
- .encode(bytes);
- }
- _ => self.extensions.encode(bytes),
- }
- }
-}
-
-impl Deref for HelloRetryRequest {
- type Target = HelloRetryRequestExtensions<'static>;
- fn deref(&self) -> &Self::Target {
- &self.extensions
- }
-}
-
-impl DerefMut for HelloRetryRequest {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.extensions
- }
-}
-
-#[derive(Clone, Debug)]
-pub(crate) struct ServerHelloPayload {
- pub(crate) legacy_version: ProtocolVersion,
- pub(crate) random: Random,
- pub(crate) session_id: SessionId,
- pub(crate) cipher_suite: CipherSuite,
- pub(crate) compression_method: Compression,
- pub(crate) extensions: Box<ServerExtensions<'static>>,
-}
-
-impl Codec<'_> for ServerHelloPayload {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.payload_encode(bytes, Encoding::Standard)
- }
-
- // minus version and random, which have already been read.
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let session_id = SessionId::read(r)?;
- let suite = CipherSuite::read(r)?;
- let compression = Compression::read(r)?;
-
- // RFC5246:
- // "The presence of extensions can be detected by determining whether
- // there are bytes following the compression_method field at the end of
- // the ServerHello."
- let extensions = Box::new(
- if r.any_left() {
- ServerExtensions::read(r)?
- } else {
- ServerExtensions::default()
- }
- .into_owned(),
- );
-
- let ret = Self {
- legacy_version: ProtocolVersion::Unknown(0),
- random: ZERO_RANDOM,
- session_id,
- cipher_suite: suite,
- compression_method: compression,
- extensions,
- };
-
- r.expect_empty("ServerHelloPayload")
- .map(|_| ret)
- }
-}
-
-impl ServerHelloPayload {
- fn payload_encode(&self, bytes: &mut Vec<u8>, encoding: Encoding) {
- debug_assert!(
- !matches!(encoding, Encoding::EchConfirmation),
- "we cannot compute an ECH confirmation on a received ServerHello"
- );
-
- self.legacy_version.encode(bytes);
- self.random.encode(bytes);
- self.session_id.encode(bytes);
- self.cipher_suite.encode(bytes);
- self.compression_method.encode(bytes);
- self.extensions.encode(bytes);
- }
-}
-
-impl Deref for ServerHelloPayload {
- type Target = ServerExtensions<'static>;
- fn deref(&self) -> &Self::Target {
- &self.extensions
- }
-}
-
-impl DerefMut for ServerHelloPayload {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.extensions
- }
-}
-
-#[derive(Clone, Default, Debug)]
-pub(crate) struct CertificateChain<'a>(pub(crate) Vec<CertificateDer<'a>>);
-
-impl CertificateChain<'_> {
- pub(crate) fn into_owned(self) -> CertificateChain<'static> {
- CertificateChain(
- self.0
- .into_iter()
- .map(|c| c.into_owned())
- .collect(),
- )
- }
-}
-
-impl<'a> Codec<'a> for CertificateChain<'a> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- Vec::encode(&self.0, bytes)
- }
-
- fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
- Vec::read(r).map(Self)
- }
-}
-
-impl<'a> Deref for CertificateChain<'a> {
- type Target = [CertificateDer<'a>];
-
- fn deref(&self) -> &[CertificateDer<'a>] {
- &self.0
- }
-}
-
-impl TlsListElement for CertificateDer<'_> {
- const SIZE_LEN: ListLength = ListLength::U24 {
- max: CERTIFICATE_MAX_SIZE_LIMIT,
- error: InvalidMessage::CertificatePayloadTooLarge,
- };
-}
-
-/// TLS has a 16MB size limit on any handshake message,
-/// plus a 16MB limit on any given certificate.
-///
-/// We contract that to 64KB to limit the amount of memory allocation
-/// that is directly controllable by the peer.
-pub(crate) const CERTIFICATE_MAX_SIZE_LIMIT: usize = 0x1_0000;
-
-extension_struct! {
- pub(crate) struct CertificateExtensions<'a> {
- ExtensionType::StatusRequest =>
- pub(crate) status: Option<CertificateStatus<'a>>,
- }
-}
-
-impl CertificateExtensions<'_> {
- fn into_owned(self) -> CertificateExtensions<'static> {
- CertificateExtensions {
- status: self.status.map(|s| s.into_owned()),
- }
- }
-}
-
-impl<'a> Codec<'a> for CertificateExtensions<'a> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- let extensions = LengthPrefixedBuffer::new(ListLength::U16, bytes);
-
- for ext in Self::ALL_EXTENSIONS {
- self.encode_one(*ext, extensions.buf);
- }
- }
-
- fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
- let mut out = Self::default();
-
- let len = usize::from(u16::read(r)?);
- let mut sub = r.sub(len)?;
-
- while sub.any_left() {
- out.read_one(&mut sub, |_unk| {
- Err(InvalidMessage::UnknownCertificateExtension)
- })?;
- }
-
- Ok(out)
- }
-}
-
-#[derive(Debug)]
-pub(crate) struct CertificateEntry<'a> {
- pub(crate) cert: CertificateDer<'a>,
- pub(crate) extensions: CertificateExtensions<'a>,
-}
-
-impl<'a> Codec<'a> for CertificateEntry<'a> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.cert.encode(bytes);
- self.extensions.encode(bytes);
- }
-
- fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
- Ok(Self {
- cert: CertificateDer::read(r)?,
- extensions: CertificateExtensions::read(r)?.into_owned(),
- })
- }
-}
-
-impl<'a> CertificateEntry<'a> {
- pub(crate) fn new(cert: CertificateDer<'a>) -> Self {
- Self {
- cert,
- extensions: CertificateExtensions::default(),
- }
- }
-
- pub(crate) fn into_owned(self) -> CertificateEntry<'static> {
- CertificateEntry {
- cert: self.cert.into_owned(),
- extensions: self.extensions.into_owned(),
- }
- }
-}
-
-impl TlsListElement for CertificateEntry<'_> {
- const SIZE_LEN: ListLength = ListLength::U24 {
- max: CERTIFICATE_MAX_SIZE_LIMIT,
- error: InvalidMessage::CertificatePayloadTooLarge,
- };
-}
-
-#[derive(Debug)]
-pub(crate) struct CertificatePayloadTls13<'a> {
- pub(crate) context: PayloadU8,
- pub(crate) entries: Vec<CertificateEntry<'a>>,
-}
-
-impl<'a> Codec<'a> for CertificatePayloadTls13<'a> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.context.encode(bytes);
- self.entries.encode(bytes);
- }
-
- fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
- Ok(Self {
- context: PayloadU8::read(r)?,
- entries: Vec::read(r)?,
- })
- }
-}
-
-impl<'a> CertificatePayloadTls13<'a> {
- pub(crate) fn new(
- certs: impl Iterator<Item = &'a CertificateDer<'a>>,
- ocsp_response: Option<&'a [u8]>,
- ) -> Self {
- Self {
- context: PayloadU8::empty(),
- entries: certs
- // zip certificate iterator with `ocsp_response` followed by
- // an infinite-length iterator of `None`.
- .zip(
- ocsp_response
- .into_iter()
- .map(Some)
- .chain(iter::repeat(None)),
- )
- .map(|(cert, ocsp)| {
- let mut e = CertificateEntry::new(cert.clone());
- if let Some(ocsp) = ocsp {
- e.extensions.status = Some(CertificateStatus::new(ocsp));
- }
- e
- })
- .collect(),
- }
- }
-
- pub(crate) fn into_owned(self) -> CertificatePayloadTls13<'static> {
- CertificatePayloadTls13 {
- context: self.context,
- entries: self
- .entries
- .into_iter()
- .map(CertificateEntry::into_owned)
- .collect(),
- }
- }
-
- pub(crate) fn end_entity_ocsp(&self) -> Vec<u8> {
- let Some(entry) = self.entries.first() else {
- return vec![];
- };
- entry
- .extensions
- .status
- .as_ref()
- .map(|status| {
- status
- .ocsp_response
- .0
- .clone()
- .into_vec()
- })
- .unwrap_or_default()
- }
-
- pub(crate) fn into_certificate_chain(self) -> CertificateChain<'a> {
- CertificateChain(
- self.entries
- .into_iter()
- .map(|e| e.cert)
- .collect(),
- )
- }
-}
-
-/// Describes supported key exchange mechanisms.
-#[derive(Clone, Copy, Debug, PartialEq)]
-#[non_exhaustive]
-pub enum KeyExchangeAlgorithm {
- /// Diffie-Hellman Key exchange (with only known parameters as defined in [RFC 7919]).
- ///
- /// [RFC 7919]: https://datatracker.ietf.org/doc/html/rfc7919
- DHE,
- /// Key exchange performed via elliptic curve Diffie-Hellman.
- ECDHE,
-}
-
-pub(crate) static ALL_KEY_EXCHANGE_ALGORITHMS: &[KeyExchangeAlgorithm] =
- &[KeyExchangeAlgorithm::ECDHE, KeyExchangeAlgorithm::DHE];
-
-// We don't support arbitrary curves. It's a terrible
-// idea and unnecessary attack surface. Please,
-// get a grip.
-#[derive(Debug)]
-pub(crate) struct EcParameters {
- pub(crate) curve_type: ECCurveType,
- pub(crate) named_group: NamedGroup,
-}
-
-impl Codec<'_> for EcParameters {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.curve_type.encode(bytes);
- self.named_group.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let ct = ECCurveType::read(r)?;
- if ct != ECCurveType::NamedCurve {
- return Err(InvalidMessage::UnsupportedCurveType);
- }
-
- let grp = NamedGroup::read(r)?;
-
- Ok(Self {
- curve_type: ct,
- named_group: grp,
- })
- }
-}
-
-#[cfg(feature = "tls12")]
-pub(crate) trait KxDecode<'a>: fmt::Debug + Sized {
- /// Decode a key exchange message given the key_exchange `algo`
- fn decode(r: &mut Reader<'a>, algo: KeyExchangeAlgorithm) -> Result<Self, InvalidMessage>;
-}
-
-#[cfg(feature = "tls12")]
-#[derive(Debug)]
-pub(crate) enum ClientKeyExchangeParams {
- Ecdh(ClientEcdhParams),
- Dh(ClientDhParams),
-}
-
-#[cfg(feature = "tls12")]
-impl ClientKeyExchangeParams {
- pub(crate) fn pub_key(&self) -> &[u8] {
- match self {
- Self::Ecdh(ecdh) => &ecdh.public.0,
- Self::Dh(dh) => &dh.public.0,
- }
- }
-
- pub(crate) fn encode(&self, buf: &mut Vec<u8>) {
- match self {
- Self::Ecdh(ecdh) => ecdh.encode(buf),
- Self::Dh(dh) => dh.encode(buf),
- }
- }
-}
-
-#[cfg(feature = "tls12")]
-impl KxDecode<'_> for ClientKeyExchangeParams {
- fn decode(r: &mut Reader<'_>, algo: KeyExchangeAlgorithm) -> Result<Self, InvalidMessage> {
- use KeyExchangeAlgorithm::*;
- Ok(match algo {
- ECDHE => Self::Ecdh(ClientEcdhParams::read(r)?),
- DHE => Self::Dh(ClientDhParams::read(r)?),
- })
- }
-}
-
-#[cfg(feature = "tls12")]
-#[derive(Debug)]
-pub(crate) struct ClientEcdhParams {
- /// RFC4492: `opaque point <1..2^8-1>;`
- pub(crate) public: PayloadU8<NonEmpty>,
-}
-
-#[cfg(feature = "tls12")]
-impl Codec<'_> for ClientEcdhParams {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.public.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let pb = PayloadU8::read(r)?;
- Ok(Self { public: pb })
- }
-}
-
-#[cfg(feature = "tls12")]
-#[derive(Debug)]
-pub(crate) struct ClientDhParams {
- /// RFC5246: `opaque dh_Yc<1..2^16-1>;`
- pub(crate) public: PayloadU16<NonEmpty>,
-}
-
-#[cfg(feature = "tls12")]
-impl Codec<'_> for ClientDhParams {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.public.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- Ok(Self {
- public: PayloadU16::read(r)?,
- })
- }
-}
-
-#[derive(Debug)]
-pub(crate) struct ServerEcdhParams {
- pub(crate) curve_params: EcParameters,
- /// RFC4492: `opaque point <1..2^8-1>;`
- pub(crate) public: PayloadU8<NonEmpty>,
-}
-
-impl ServerEcdhParams {
- #[cfg(feature = "tls12")]
- pub(crate) fn new(kx: &dyn ActiveKeyExchange) -> Self {
- Self {
- curve_params: EcParameters {
- curve_type: ECCurveType::NamedCurve,
- named_group: kx.group(),
- },
- public: PayloadU8::new(kx.pub_key().to_vec()),
- }
- }
-}
-
-impl Codec<'_> for ServerEcdhParams {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.curve_params.encode(bytes);
- self.public.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let cp = EcParameters::read(r)?;
- let pb = PayloadU8::read(r)?;
-
- Ok(Self {
- curve_params: cp,
- public: pb,
- })
- }
-}
-
-#[derive(Debug)]
-#[allow(non_snake_case)]
-pub(crate) struct ServerDhParams {
- /// RFC5246: `opaque dh_p<1..2^16-1>;`
- pub(crate) dh_p: PayloadU16<NonEmpty>,
- /// RFC5246: `opaque dh_g<1..2^16-1>;`
- pub(crate) dh_g: PayloadU16<NonEmpty>,
- /// RFC5246: `opaque dh_Ys<1..2^16-1>;`
- pub(crate) dh_Ys: PayloadU16<NonEmpty>,
-}
-
-impl ServerDhParams {
- #[cfg(feature = "tls12")]
- pub(crate) fn new(kx: &dyn ActiveKeyExchange) -> Self {
- let Some(params) = kx.ffdhe_group() else {
- panic!("invalid NamedGroup for DHE key exchange: {:?}", kx.group());
- };
-
- Self {
- dh_p: PayloadU16::new(params.p.to_vec()),
- dh_g: PayloadU16::new(params.g.to_vec()),
- dh_Ys: PayloadU16::new(kx.pub_key().to_vec()),
- }
- }
-
- #[cfg(feature = "tls12")]
- pub(crate) fn as_ffdhe_group(&self) -> FfdheGroup<'_> {
- FfdheGroup::from_params_trimming_leading_zeros(&self.dh_p.0, &self.dh_g.0)
- }
-}
-
-impl Codec<'_> for ServerDhParams {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.dh_p.encode(bytes);
- self.dh_g.encode(bytes);
- self.dh_Ys.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- Ok(Self {
- dh_p: PayloadU16::read(r)?,
- dh_g: PayloadU16::read(r)?,
- dh_Ys: PayloadU16::read(r)?,
- })
- }
-}
-
-#[allow(dead_code)]
-#[derive(Debug)]
-pub(crate) enum ServerKeyExchangeParams {
- Ecdh(ServerEcdhParams),
- Dh(ServerDhParams),
-}
-
-impl ServerKeyExchangeParams {
- #[cfg(feature = "tls12")]
- pub(crate) fn new(kx: &dyn ActiveKeyExchange) -> Self {
- match kx.group().key_exchange_algorithm() {
- KeyExchangeAlgorithm::DHE => Self::Dh(ServerDhParams::new(kx)),
- KeyExchangeAlgorithm::ECDHE => Self::Ecdh(ServerEcdhParams::new(kx)),
- }
- }
-
- #[cfg(feature = "tls12")]
- pub(crate) fn pub_key(&self) -> &[u8] {
- match self {
- Self::Ecdh(ecdh) => &ecdh.public.0,
- Self::Dh(dh) => &dh.dh_Ys.0,
- }
- }
-
- pub(crate) fn encode(&self, buf: &mut Vec<u8>) {
- match self {
- Self::Ecdh(ecdh) => ecdh.encode(buf),
- Self::Dh(dh) => dh.encode(buf),
- }
- }
-}
-
-#[cfg(feature = "tls12")]
-impl KxDecode<'_> for ServerKeyExchangeParams {
- fn decode(r: &mut Reader<'_>, algo: KeyExchangeAlgorithm) -> Result<Self, InvalidMessage> {
- use KeyExchangeAlgorithm::*;
- Ok(match algo {
- ECDHE => Self::Ecdh(ServerEcdhParams::read(r)?),
- DHE => Self::Dh(ServerDhParams::read(r)?),
- })
- }
-}
-
-#[derive(Debug)]
-pub(crate) struct ServerKeyExchange {
- pub(crate) params: ServerKeyExchangeParams,
- pub(crate) dss: DigitallySignedStruct,
-}
-
-impl ServerKeyExchange {
- pub(crate) fn encode(&self, buf: &mut Vec<u8>) {
- self.params.encode(buf);
- self.dss.encode(buf);
- }
-}
-
-#[derive(Debug)]
-pub(crate) enum ServerKeyExchangePayload {
- Known(ServerKeyExchange),
- Unknown(Payload<'static>),
-}
-
-impl From<ServerKeyExchange> for ServerKeyExchangePayload {
- fn from(value: ServerKeyExchange) -> Self {
- Self::Known(value)
- }
-}
-
-impl Codec<'_> for ServerKeyExchangePayload {
- fn encode(&self, bytes: &mut Vec<u8>) {
- match self {
- Self::Known(x) => x.encode(bytes),
- Self::Unknown(x) => x.encode(bytes),
- }
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- // read as Unknown, fully parse when we know the
- // KeyExchangeAlgorithm
- Ok(Self::Unknown(Payload::read(r).into_owned()))
- }
-}
-
-impl ServerKeyExchangePayload {
- #[cfg(feature = "tls12")]
- pub(crate) fn unwrap_given_kxa(&self, kxa: KeyExchangeAlgorithm) -> Option<ServerKeyExchange> {
- if let Self::Unknown(unk) = self {
- let mut rd = Reader::init(unk.bytes());
-
- let result = ServerKeyExchange {
- params: ServerKeyExchangeParams::decode(&mut rd, kxa).ok()?,
- dss: DigitallySignedStruct::read(&mut rd).ok()?,
- };
-
- if !rd.any_left() {
- return Some(result);
- };
- }
-
- None
- }
-}
-
-/// RFC5246: `ClientCertificateType certificate_types<1..2^8-1>;`
-impl TlsListElement for ClientCertificateType {
- const SIZE_LEN: ListLength = ListLength::NonZeroU8 {
- empty_error: InvalidMessage::IllegalEmptyList("ClientCertificateTypes"),
- };
-}
-
-wrapped_payload!(
- /// A `DistinguishedName` is a `Vec<u8>` wrapped in internal types.
- ///
- /// It contains the DER or BER encoded [`Subject` field from RFC 5280](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6)
- /// for a single certificate. The Subject field is [encoded as an RFC 5280 `Name`](https://datatracker.ietf.org/doc/html/rfc5280#page-116).
- /// It can be decoded using [x509-parser's FromDer trait](https://docs.rs/x509-parser/latest/x509_parser/prelude/trait.FromDer.html).
- ///
- /// ```ignore
- /// for name in distinguished_names {
- /// use x509_parser::prelude::FromDer;
- /// println!("{}", x509_parser::x509::X509Name::from_der(&name.0)?.1);
- /// }
- /// ```
- ///
- /// The TLS encoding is defined in RFC5246: `opaque DistinguishedName<1..2^16-1>;`
- pub struct DistinguishedName,
- PayloadU16<NonEmpty>,
-);
-
-impl DistinguishedName {
- /// Create a [`DistinguishedName`] after prepending its outer SEQUENCE encoding.
- ///
- /// This can be decoded using [x509-parser's FromDer trait](https://docs.rs/x509-parser/latest/x509_parser/prelude/trait.FromDer.html).
- ///
- /// ```ignore
- /// use x509_parser::prelude::FromDer;
- /// println!("{}", x509_parser::x509::X509Name::from_der(dn.as_ref())?.1);
- /// ```
- pub fn in_sequence(bytes: &[u8]) -> Self {
- Self(PayloadU16::new(wrap_in_sequence(bytes)))
- }
-}
-
-/// RFC8446: `DistinguishedName authorities<3..2^16-1>;` however,
-/// RFC5246: `DistinguishedName certificate_authorities<0..2^16-1>;`
-impl TlsListElement for DistinguishedName {
- const SIZE_LEN: ListLength = ListLength::U16;
-}
-
-#[derive(Debug)]
-pub(crate) struct CertificateRequestPayload {
- pub(crate) certtypes: Vec<ClientCertificateType>,
- pub(crate) sigschemes: Vec<SignatureScheme>,
- pub(crate) canames: Vec<DistinguishedName>,
-}
-
-impl Codec<'_> for CertificateRequestPayload {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.certtypes.encode(bytes);
- self.sigschemes.encode(bytes);
- self.canames.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let certtypes = Vec::read(r)?;
- let sigschemes = Vec::read(r)?;
- let canames = Vec::read(r)?;
-
- if sigschemes.is_empty() {
- warn!("meaningless CertificateRequest message");
- Err(InvalidMessage::NoSignatureSchemes)
- } else {
- Ok(Self {
- certtypes,
- sigschemes,
- canames,
- })
- }
- }
-}
-
-extension_struct! {
- pub(crate) struct CertificateRequestExtensions {
- ExtensionType::SignatureAlgorithms =>
- pub(crate) signature_algorithms: Option<Vec<SignatureScheme>>,
-
- ExtensionType::CertificateAuthorities =>
- pub(crate) authority_names: Option<Vec<DistinguishedName>>,
-
- ExtensionType::CompressCertificate =>
- pub(crate) certificate_compression_algorithms: Option<Vec<CertificateCompressionAlgorithm>>,
- }
-}
-
-impl Codec<'_> for CertificateRequestExtensions {
- fn encode(&self, bytes: &mut Vec<u8>) {
- let extensions = LengthPrefixedBuffer::new(ListLength::U16, bytes);
-
- for ext in Self::ALL_EXTENSIONS {
- self.encode_one(*ext, extensions.buf);
- }
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let mut out = Self::default();
-
- let mut checker = DuplicateExtensionChecker::new();
-
- let len = usize::from(u16::read(r)?);
- let mut sub = r.sub(len)?;
-
- while sub.any_left() {
- out.read_one(&mut sub, |unknown| checker.check(unknown))?;
- }
-
- if out
- .signature_algorithms
- .as_ref()
- .map(|algs| algs.is_empty())
- .unwrap_or_default()
- {
- return Err(InvalidMessage::NoSignatureSchemes);
- }
-
- Ok(out)
- }
-}
-
-#[derive(Debug)]
-pub(crate) struct CertificateRequestPayloadTls13 {
- pub(crate) context: PayloadU8,
- pub(crate) extensions: CertificateRequestExtensions,
-}
-
-impl Codec<'_> for CertificateRequestPayloadTls13 {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.context.encode(bytes);
- self.extensions.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let context = PayloadU8::read(r)?;
- let extensions = CertificateRequestExtensions::read(r)?;
-
- Ok(Self {
- context,
- extensions,
- })
- }
-}
-
-// -- NewSessionTicket --
-#[derive(Debug)]
-pub(crate) struct NewSessionTicketPayload {
- pub(crate) lifetime_hint: u32,
- // Tickets can be large (KB), so we deserialise this straight
- // into an Arc, so it can be passed directly into the client's
- // session object without copying.
- pub(crate) ticket: Arc<PayloadU16>,
-}
-
-impl NewSessionTicketPayload {
- #[cfg(feature = "tls12")]
- pub(crate) fn new(lifetime_hint: u32, ticket: Vec<u8>) -> Self {
- Self {
- lifetime_hint,
- ticket: Arc::new(PayloadU16::new(ticket)),
- }
- }
-}
-
-impl Codec<'_> for NewSessionTicketPayload {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.lifetime_hint.encode(bytes);
- self.ticket.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let lifetime = u32::read(r)?;
- let ticket = Arc::new(PayloadU16::read(r)?);
-
- Ok(Self {
- lifetime_hint: lifetime,
- ticket,
- })
- }
-}
-
-// -- NewSessionTicket electric boogaloo --
-extension_struct! {
- pub(crate) struct NewSessionTicketExtensions {
- ExtensionType::EarlyData =>
- pub(crate) max_early_data_size: Option<u32>,
- }
-}
-
-impl Codec<'_> for NewSessionTicketExtensions {
- fn encode(&self, bytes: &mut Vec<u8>) {
- let extensions = LengthPrefixedBuffer::new(ListLength::U16, bytes);
-
- for ext in Self::ALL_EXTENSIONS {
- self.encode_one(*ext, extensions.buf);
- }
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let mut out = Self::default();
-
- let mut checker = DuplicateExtensionChecker::new();
-
- let len = usize::from(u16::read(r)?);
- let mut sub = r.sub(len)?;
-
- while sub.any_left() {
- out.read_one(&mut sub, |unknown| checker.check(unknown))?;
- }
-
- Ok(out)
- }
-}
-
-#[derive(Debug)]
-pub(crate) struct NewSessionTicketPayloadTls13 {
- pub(crate) lifetime: u32,
- pub(crate) age_add: u32,
- pub(crate) nonce: PayloadU8,
- pub(crate) ticket: Arc<PayloadU16>,
- pub(crate) extensions: NewSessionTicketExtensions,
-}
-
-impl NewSessionTicketPayloadTls13 {
- pub(crate) fn new(lifetime: u32, age_add: u32, nonce: Vec<u8>, ticket: Vec<u8>) -> Self {
- Self {
- lifetime,
- age_add,
- nonce: PayloadU8::new(nonce),
- ticket: Arc::new(PayloadU16::new(ticket)),
- extensions: NewSessionTicketExtensions::default(),
- }
- }
-}
-
-impl Codec<'_> for NewSessionTicketPayloadTls13 {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.lifetime.encode(bytes);
- self.age_add.encode(bytes);
- self.nonce.encode(bytes);
- self.ticket.encode(bytes);
- self.extensions.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let lifetime = u32::read(r)?;
- let age_add = u32::read(r)?;
- let nonce = PayloadU8::read(r)?;
- // nb. RFC8446: `opaque ticket<1..2^16-1>;`
- let ticket = Arc::new(match PayloadU16::<NonEmpty>::read(r) {
- Err(InvalidMessage::IllegalEmptyValue) => Err(InvalidMessage::EmptyTicketValue),
- Err(err) => Err(err),
- Ok(pl) => Ok(PayloadU16::new(pl.0)),
- }?);
- let extensions = NewSessionTicketExtensions::read(r)?;
-
- Ok(Self {
- lifetime,
- age_add,
- nonce,
- ticket,
- extensions,
- })
- }
-}
-
-// -- RFC6066 certificate status types
-
-/// Only supports OCSP
-#[derive(Clone, Debug)]
-pub(crate) struct CertificateStatus<'a> {
- pub(crate) ocsp_response: PayloadU24<'a>,
-}
-
-impl<'a> Codec<'a> for CertificateStatus<'a> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- CertificateStatusType::OCSP.encode(bytes);
- self.ocsp_response.encode(bytes);
- }
-
- fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
- let typ = CertificateStatusType::read(r)?;
-
- match typ {
- CertificateStatusType::OCSP => Ok(Self {
- ocsp_response: PayloadU24::read(r)?,
- }),
- _ => Err(InvalidMessage::InvalidCertificateStatusType),
- }
- }
-}
-
-impl<'a> CertificateStatus<'a> {
- pub(crate) fn new(ocsp: &'a [u8]) -> Self {
- CertificateStatus {
- ocsp_response: PayloadU24(Payload::Borrowed(ocsp)),
- }
- }
-
- #[cfg(feature = "tls12")]
- pub(crate) fn into_inner(self) -> Vec<u8> {
- self.ocsp_response.0.into_vec()
- }
-
- pub(crate) fn into_owned(self) -> CertificateStatus<'static> {
- CertificateStatus {
- ocsp_response: self.ocsp_response.into_owned(),
- }
- }
-}
-
-// -- RFC8879 compressed certificates
-
-#[derive(Debug)]
-pub(crate) struct CompressedCertificatePayload<'a> {
- pub(crate) alg: CertificateCompressionAlgorithm,
- pub(crate) uncompressed_len: u32,
- pub(crate) compressed: PayloadU24<'a>,
-}
-
-impl<'a> Codec<'a> for CompressedCertificatePayload<'a> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.alg.encode(bytes);
- codec::u24(self.uncompressed_len).encode(bytes);
- self.compressed.encode(bytes);
- }
-
- fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
- Ok(Self {
- alg: CertificateCompressionAlgorithm::read(r)?,
- uncompressed_len: codec::u24::read(r)?.0,
- compressed: PayloadU24::read(r)?,
- })
- }
-}
-
-impl CompressedCertificatePayload<'_> {
- fn into_owned(self) -> CompressedCertificatePayload<'static> {
- CompressedCertificatePayload {
- compressed: self.compressed.into_owned(),
- ..self
- }
- }
-
- pub(crate) fn as_borrowed(&self) -> CompressedCertificatePayload<'_> {
- CompressedCertificatePayload {
- alg: self.alg,
- uncompressed_len: self.uncompressed_len,
- compressed: PayloadU24(Payload::Borrowed(self.compressed.0.bytes())),
- }
- }
-}
-
-#[derive(Debug)]
-pub(crate) enum HandshakePayload<'a> {
- HelloRequest,
- ClientHello(ClientHelloPayload),
- ServerHello(ServerHelloPayload),
- HelloRetryRequest(HelloRetryRequest),
- Certificate(CertificateChain<'a>),
- CertificateTls13(CertificatePayloadTls13<'a>),
- CompressedCertificate(CompressedCertificatePayload<'a>),
- ServerKeyExchange(ServerKeyExchangePayload),
- CertificateRequest(CertificateRequestPayload),
- CertificateRequestTls13(CertificateRequestPayloadTls13),
- CertificateVerify(DigitallySignedStruct),
- ServerHelloDone,
- EndOfEarlyData,
- ClientKeyExchange(Payload<'a>),
- NewSessionTicket(NewSessionTicketPayload),
- NewSessionTicketTls13(NewSessionTicketPayloadTls13),
- EncryptedExtensions(Box<ServerExtensions<'a>>),
- KeyUpdate(KeyUpdateRequest),
- Finished(Payload<'a>),
- CertificateStatus(CertificateStatus<'a>),
- MessageHash(Payload<'a>),
- Unknown((HandshakeType, Payload<'a>)),
-}
-
-impl HandshakePayload<'_> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- use self::HandshakePayload::*;
- match self {
- HelloRequest | ServerHelloDone | EndOfEarlyData => {}
- ClientHello(x) => x.encode(bytes),
- ServerHello(x) => x.encode(bytes),
- HelloRetryRequest(x) => x.encode(bytes),
- Certificate(x) => x.encode(bytes),
- CertificateTls13(x) => x.encode(bytes),
- CompressedCertificate(x) => x.encode(bytes),
- ServerKeyExchange(x) => x.encode(bytes),
- ClientKeyExchange(x) => x.encode(bytes),
- CertificateRequest(x) => x.encode(bytes),
- CertificateRequestTls13(x) => x.encode(bytes),
- CertificateVerify(x) => x.encode(bytes),
- NewSessionTicket(x) => x.encode(bytes),
- NewSessionTicketTls13(x) => x.encode(bytes),
- EncryptedExtensions(x) => x.encode(bytes),
- KeyUpdate(x) => x.encode(bytes),
- Finished(x) => x.encode(bytes),
- CertificateStatus(x) => x.encode(bytes),
- MessageHash(x) => x.encode(bytes),
- Unknown((_, x)) => x.encode(bytes),
- }
- }
-
- pub(crate) fn handshake_type(&self) -> HandshakeType {
- use self::HandshakePayload::*;
- match self {
- HelloRequest => HandshakeType::HelloRequest,
- ClientHello(_) => HandshakeType::ClientHello,
- ServerHello(_) => HandshakeType::ServerHello,
- HelloRetryRequest(_) => HandshakeType::HelloRetryRequest,
- Certificate(_) | CertificateTls13(_) => HandshakeType::Certificate,
- CompressedCertificate(_) => HandshakeType::CompressedCertificate,
- ServerKeyExchange(_) => HandshakeType::ServerKeyExchange,
- CertificateRequest(_) | CertificateRequestTls13(_) => HandshakeType::CertificateRequest,
- CertificateVerify(_) => HandshakeType::CertificateVerify,
- ServerHelloDone => HandshakeType::ServerHelloDone,
- EndOfEarlyData => HandshakeType::EndOfEarlyData,
- ClientKeyExchange(_) => HandshakeType::ClientKeyExchange,
- NewSessionTicket(_) | NewSessionTicketTls13(_) => HandshakeType::NewSessionTicket,
- EncryptedExtensions(_) => HandshakeType::EncryptedExtensions,
- KeyUpdate(_) => HandshakeType::KeyUpdate,
- Finished(_) => HandshakeType::Finished,
- CertificateStatus(_) => HandshakeType::CertificateStatus,
- MessageHash(_) => HandshakeType::MessageHash,
- Unknown((t, _)) => *t,
- }
- }
-
- fn wire_handshake_type(&self) -> HandshakeType {
- match self.handshake_type() {
- // A `HelloRetryRequest` appears on the wire as a `ServerHello` with a magic `random` value.
- HandshakeType::HelloRetryRequest => HandshakeType::ServerHello,
- other => other,
- }
- }
-
- fn into_owned(self) -> HandshakePayload<'static> {
- use HandshakePayload::*;
-
- match self {
- HelloRequest => HelloRequest,
- ClientHello(x) => ClientHello(x),
- ServerHello(x) => ServerHello(x),
- HelloRetryRequest(x) => HelloRetryRequest(x),
- Certificate(x) => Certificate(x.into_owned()),
- CertificateTls13(x) => CertificateTls13(x.into_owned()),
- CompressedCertificate(x) => CompressedCertificate(x.into_owned()),
- ServerKeyExchange(x) => ServerKeyExchange(x),
- CertificateRequest(x) => CertificateRequest(x),
- CertificateRequestTls13(x) => CertificateRequestTls13(x),
- CertificateVerify(x) => CertificateVerify(x),
- ServerHelloDone => ServerHelloDone,
- EndOfEarlyData => EndOfEarlyData,
- ClientKeyExchange(x) => ClientKeyExchange(x.into_owned()),
- NewSessionTicket(x) => NewSessionTicket(x),
- NewSessionTicketTls13(x) => NewSessionTicketTls13(x),
- EncryptedExtensions(x) => EncryptedExtensions(Box::new(x.into_owned())),
- KeyUpdate(x) => KeyUpdate(x),
- Finished(x) => Finished(x.into_owned()),
- CertificateStatus(x) => CertificateStatus(x.into_owned()),
- MessageHash(x) => MessageHash(x.into_owned()),
- Unknown((t, x)) => Unknown((t, x.into_owned())),
- }
- }
-}
-
-#[derive(Debug)]
-pub struct HandshakeMessagePayload<'a>(pub(crate) HandshakePayload<'a>);
-
-impl<'a> Codec<'a> for HandshakeMessagePayload<'a> {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.payload_encode(bytes, Encoding::Standard);
- }
-
- fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
- Self::read_version(r, ProtocolVersion::TLSv1_2)
- }
-}
-
-impl<'a> HandshakeMessagePayload<'a> {
- pub(crate) fn read_version(
- r: &mut Reader<'a>,
- vers: ProtocolVersion,
- ) -> Result<Self, InvalidMessage> {
- let typ = HandshakeType::read(r)?;
- let len = codec::u24::read(r)?.0 as usize;
- let mut sub = r.sub(len)?;
-
- let payload = match typ {
- HandshakeType::HelloRequest if sub.left() == 0 => HandshakePayload::HelloRequest,
- HandshakeType::ClientHello => {
- HandshakePayload::ClientHello(ClientHelloPayload::read(&mut sub)?)
- }
- HandshakeType::ServerHello => {
- let version = ProtocolVersion::read(&mut sub)?;
- let random = Random::read(&mut sub)?;
-
- if random == HELLO_RETRY_REQUEST_RANDOM {
- let mut hrr = HelloRetryRequest::read(&mut sub)?;
- hrr.legacy_version = version;
- HandshakePayload::HelloRetryRequest(hrr)
- } else {
- let mut shp = ServerHelloPayload::read(&mut sub)?;
- shp.legacy_version = version;
- shp.random = random;
- HandshakePayload::ServerHello(shp)
- }
- }
- HandshakeType::Certificate if vers == ProtocolVersion::TLSv1_3 => {
- let p = CertificatePayloadTls13::read(&mut sub)?;
- HandshakePayload::CertificateTls13(p)
- }
- HandshakeType::Certificate => {
- HandshakePayload::Certificate(CertificateChain::read(&mut sub)?)
- }
- HandshakeType::ServerKeyExchange => {
- let p = ServerKeyExchangePayload::read(&mut sub)?;
- HandshakePayload::ServerKeyExchange(p)
- }
- HandshakeType::ServerHelloDone => {
- sub.expect_empty("ServerHelloDone")?;
- HandshakePayload::ServerHelloDone
- }
- HandshakeType::ClientKeyExchange => {
- HandshakePayload::ClientKeyExchange(Payload::read(&mut sub))
- }
- HandshakeType::CertificateRequest if vers == ProtocolVersion::TLSv1_3 => {
- let p = CertificateRequestPayloadTls13::read(&mut sub)?;
- HandshakePayload::CertificateRequestTls13(p)
- }
- HandshakeType::CertificateRequest => {
- let p = CertificateRequestPayload::read(&mut sub)?;
- HandshakePayload::CertificateRequest(p)
- }
- HandshakeType::CompressedCertificate => HandshakePayload::CompressedCertificate(
- CompressedCertificatePayload::read(&mut sub)?,
- ),
- HandshakeType::CertificateVerify => {
- HandshakePayload::CertificateVerify(DigitallySignedStruct::read(&mut sub)?)
- }
- HandshakeType::NewSessionTicket if vers == ProtocolVersion::TLSv1_3 => {
- let p = NewSessionTicketPayloadTls13::read(&mut sub)?;
- HandshakePayload::NewSessionTicketTls13(p)
- }
- HandshakeType::NewSessionTicket => {
- let p = NewSessionTicketPayload::read(&mut sub)?;
- HandshakePayload::NewSessionTicket(p)
- }
- HandshakeType::EncryptedExtensions => {
- HandshakePayload::EncryptedExtensions(Box::new(ServerExtensions::read(&mut sub)?))
- }
- HandshakeType::KeyUpdate => {
- HandshakePayload::KeyUpdate(KeyUpdateRequest::read(&mut sub)?)
- }
- HandshakeType::EndOfEarlyData => {
- sub.expect_empty("EndOfEarlyData")?;
- HandshakePayload::EndOfEarlyData
- }
- HandshakeType::Finished => HandshakePayload::Finished(Payload::read(&mut sub)),
- HandshakeType::CertificateStatus => {
- HandshakePayload::CertificateStatus(CertificateStatus::read(&mut sub)?)
- }
- HandshakeType::MessageHash => {
- // does not appear on the wire
- return Err(InvalidMessage::UnexpectedMessage("MessageHash"));
- }
- HandshakeType::HelloRetryRequest => {
- // not legal on wire
- return Err(InvalidMessage::UnexpectedMessage("HelloRetryRequest"));
- }
- _ => HandshakePayload::Unknown((typ, Payload::read(&mut sub))),
- };
-
- sub.expect_empty("HandshakeMessagePayload")
- .map(|_| Self(payload))
- }
-
- pub(crate) fn encoding_for_binder_signing(&self) -> Vec<u8> {
- let mut ret = self.get_encoding();
- let ret_len = ret.len() - self.total_binder_length();
- ret.truncate(ret_len);
- ret
- }
-
- pub(crate) fn total_binder_length(&self) -> usize {
- match &self.0 {
- HandshakePayload::ClientHello(ch) => match &ch.preshared_key_offer {
- Some(offer) => {
- let mut binders_encoding = Vec::new();
- offer
- .binders
- .encode(&mut binders_encoding);
- binders_encoding.len()
- }
- _ => 0,
- },
- _ => 0,
- }
- }
-
- pub(crate) fn payload_encode(&self, bytes: &mut Vec<u8>, encoding: Encoding) {
- // output type, length, and encoded payload
- self.0
- .wire_handshake_type()
- .encode(bytes);
-
- let nested = LengthPrefixedBuffer::new(
- ListLength::U24 {
- max: usize::MAX,
- error: InvalidMessage::MessageTooLarge,
- },
- bytes,
- );
-
- match &self.0 {
- // for Server Hello and HelloRetryRequest payloads we need to encode the payload
- // differently based on the purpose of the encoding.
- HandshakePayload::ServerHello(payload) => payload.payload_encode(nested.buf, encoding),
- HandshakePayload::HelloRetryRequest(payload) => {
- payload.payload_encode(nested.buf, encoding)
- }
-
- // All other payload types are encoded the same regardless of purpose.
- _ => self.0.encode(nested.buf),
- }
- }
-
- pub(crate) fn build_handshake_hash(hash: &[u8]) -> Self {
- Self(HandshakePayload::MessageHash(Payload::new(hash.to_vec())))
- }
-
- pub(crate) fn into_owned(self) -> HandshakeMessagePayload<'static> {
- HandshakeMessagePayload(self.0.into_owned())
- }
-}
-
-#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
-pub struct HpkeSymmetricCipherSuite {
- pub kdf_id: HpkeKdf,
- pub aead_id: HpkeAead,
-}
-
-impl Codec<'_> for HpkeSymmetricCipherSuite {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.kdf_id.encode(bytes);
- self.aead_id.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- Ok(Self {
- kdf_id: HpkeKdf::read(r)?,
- aead_id: HpkeAead::read(r)?,
- })
- }
-}
-
-/// draft-ietf-tls-esni-24: `HpkeSymmetricCipherSuite cipher_suites<4..2^16-4>;`
-impl TlsListElement for HpkeSymmetricCipherSuite {
- const SIZE_LEN: ListLength = ListLength::NonZeroU16 {
- empty_error: InvalidMessage::IllegalEmptyList("HpkeSymmetricCipherSuites"),
- };
-}
-
-#[derive(Clone, Debug, PartialEq)]
-pub struct HpkeKeyConfig {
- pub config_id: u8,
- pub kem_id: HpkeKem,
- /// draft-ietf-tls-esni-24: `opaque HpkePublicKey<1..2^16-1>;`
- pub public_key: PayloadU16<NonEmpty>,
- pub symmetric_cipher_suites: Vec<HpkeSymmetricCipherSuite>,
-}
-
-impl Codec<'_> for HpkeKeyConfig {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.config_id.encode(bytes);
- self.kem_id.encode(bytes);
- self.public_key.encode(bytes);
- self.symmetric_cipher_suites
- .encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- Ok(Self {
- config_id: u8::read(r)?,
- kem_id: HpkeKem::read(r)?,
- public_key: PayloadU16::read(r)?,
- symmetric_cipher_suites: Vec::<HpkeSymmetricCipherSuite>::read(r)?,
- })
- }
-}
-
-#[derive(Clone, Debug, PartialEq)]
-pub struct EchConfigContents {
- pub key_config: HpkeKeyConfig,
- pub maximum_name_length: u8,
- pub public_name: DnsName<'static>,
- pub extensions: Vec<EchConfigExtension>,
-}
-
-impl EchConfigContents {
- /// Returns true if there is more than one extension of a given
- /// type.
- pub(crate) fn has_duplicate_extension(&self) -> bool {
- has_duplicates::<_, _, u16>(
- self.extensions
- .iter()
- .map(|ext| ext.ext_type()),
- )
- }
-
- /// Returns true if there is at least one mandatory unsupported extension.
- pub(crate) fn has_unknown_mandatory_extension(&self) -> bool {
- self.extensions
- .iter()
- // An extension is considered mandatory if the high bit of its type is set.
- .any(|ext| {
- matches!(ext.ext_type(), ExtensionType::Unknown(_))
- && u16::from(ext.ext_type()) & 0x8000 != 0
- })
- }
-}
-
-impl Codec<'_> for EchConfigContents {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.key_config.encode(bytes);
- self.maximum_name_length.encode(bytes);
- let dns_name = &self.public_name.borrow();
- PayloadU8::<MaybeEmpty>::encode_slice(dns_name.as_ref().as_ref(), bytes);
- self.extensions.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- Ok(Self {
- key_config: HpkeKeyConfig::read(r)?,
- maximum_name_length: u8::read(r)?,
- public_name: {
- DnsName::try_from(
- PayloadU8::<MaybeEmpty>::read(r)?
- .0
- .as_slice(),
- )
- .map_err(|_| InvalidMessage::InvalidServerName)?
- .to_owned()
- },
- extensions: Vec::read(r)?,
- })
- }
-}
-
-/// An encrypted client hello (ECH) config.
-#[derive(Clone, Debug, PartialEq)]
-pub enum EchConfigPayload {
- /// A recognized V18 ECH configuration.
- V18(EchConfigContents),
- /// An unknown version ECH configuration.
- Unknown {
- version: EchVersion,
- contents: PayloadU16,
- },
-}
-
-impl TlsListElement for EchConfigPayload {
- const SIZE_LEN: ListLength = ListLength::U16;
-}
-
-impl Codec<'_> for EchConfigPayload {
- fn encode(&self, bytes: &mut Vec<u8>) {
- match self {
- Self::V18(c) => {
- // Write the version, the length, and the contents.
- EchVersion::V18.encode(bytes);
- let inner = LengthPrefixedBuffer::new(ListLength::U16, bytes);
- c.encode(inner.buf);
- }
- Self::Unknown { version, contents } => {
- // Unknown configuration versions are opaque.
- version.encode(bytes);
- contents.encode(bytes);
- }
- }
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let version = EchVersion::read(r)?;
- let length = u16::read(r)?;
- let mut contents = r.sub(length as usize)?;
-
- Ok(match version {
- EchVersion::V18 => Self::V18(EchConfigContents::read(&mut contents)?),
- _ => {
- // Note: we don't PayloadU16::read() here because we've already read the length prefix.
- let data = PayloadU16::new(contents.rest().into());
- Self::Unknown {
- version,
- contents: data,
- }
- }
- })
- }
-}
-
-#[derive(Clone, Debug, PartialEq)]
-pub enum EchConfigExtension {
- Unknown(UnknownExtension),
-}
-
-impl EchConfigExtension {
- pub(crate) fn ext_type(&self) -> ExtensionType {
- match self {
- Self::Unknown(r) => r.typ,
- }
- }
-}
-
-impl Codec<'_> for EchConfigExtension {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.ext_type().encode(bytes);
-
- let nested = LengthPrefixedBuffer::new(ListLength::U16, bytes);
- match self {
- Self::Unknown(r) => r.encode(nested.buf),
- }
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let typ = ExtensionType::read(r)?;
- let len = u16::read(r)? as usize;
- let mut sub = r.sub(len)?;
-
- #[allow(clippy::match_single_binding)] // Future-proofing.
- let ext = match typ {
- _ => Self::Unknown(UnknownExtension::read(typ, &mut sub)),
- };
-
- sub.expect_empty("EchConfigExtension")
- .map(|_| ext)
- }
-}
-
-impl TlsListElement for EchConfigExtension {
- const SIZE_LEN: ListLength = ListLength::U16;
-}
-
-/// Representation of the `ECHClientHello` client extension specified in
-/// [draft-ietf-tls-esni Section 5].
-///
-/// [draft-ietf-tls-esni Section 5]: <https://www.ietf.org/archive/id/draft-ietf-tls-esni-18.html#section-5>
-#[derive(Clone, Debug)]
-pub(crate) enum EncryptedClientHello {
- /// A `ECHClientHello` with type [EchClientHelloType::ClientHelloOuter].
- Outer(EncryptedClientHelloOuter),
- /// An empty `ECHClientHello` with type [EchClientHelloType::ClientHelloInner].
- ///
- /// This variant has no payload.
- Inner,
-}
-
-impl Codec<'_> for EncryptedClientHello {
- fn encode(&self, bytes: &mut Vec<u8>) {
- match self {
- Self::Outer(payload) => {
- EchClientHelloType::ClientHelloOuter.encode(bytes);
- payload.encode(bytes);
- }
- Self::Inner => {
- EchClientHelloType::ClientHelloInner.encode(bytes);
- // Empty payload.
- }
- }
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- match EchClientHelloType::read(r)? {
- EchClientHelloType::ClientHelloOuter => {
- Ok(Self::Outer(EncryptedClientHelloOuter::read(r)?))
- }
- EchClientHelloType::ClientHelloInner => Ok(Self::Inner),
- _ => Err(InvalidMessage::InvalidContentType),
- }
- }
-}
-
-/// Representation of the ECHClientHello extension with type outer specified in
-/// [draft-ietf-tls-esni Section 5].
-///
-/// [draft-ietf-tls-esni Section 5]: <https://www.ietf.org/archive/id/draft-ietf-tls-esni-18.html#section-5>
-#[derive(Clone, Debug)]
-pub(crate) struct EncryptedClientHelloOuter {
- /// The cipher suite used to encrypt ClientHelloInner. Must match a value from
- /// ECHConfigContents.cipher_suites list.
- pub cipher_suite: HpkeSymmetricCipherSuite,
- /// The ECHConfigContents.key_config.config_id for the chosen ECHConfig.
- pub config_id: u8,
- /// The HPKE encapsulated key, used by servers to decrypt the corresponding payload field.
- /// This field is empty in a ClientHelloOuter sent in response to a HelloRetryRequest.
- pub enc: PayloadU16,
- /// The serialized and encrypted ClientHelloInner structure, encrypted using HPKE.
- pub payload: PayloadU16<NonEmpty>,
-}
-
-impl Codec<'_> for EncryptedClientHelloOuter {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.cipher_suite.encode(bytes);
- self.config_id.encode(bytes);
- self.enc.encode(bytes);
- self.payload.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- Ok(Self {
- cipher_suite: HpkeSymmetricCipherSuite::read(r)?,
- config_id: u8::read(r)?,
- enc: PayloadU16::read(r)?,
- payload: PayloadU16::read(r)?,
- })
- }
-}
-
-/// Representation of the ECHEncryptedExtensions extension specified in
-/// [draft-ietf-tls-esni Section 5].
-///
-/// [draft-ietf-tls-esni Section 5]: <https://www.ietf.org/archive/id/draft-ietf-tls-esni-18.html#section-5>
-#[derive(Clone, Debug)]
-pub(crate) struct ServerEncryptedClientHello {
- pub(crate) retry_configs: Vec<EchConfigPayload>,
-}
-
-impl Codec<'_> for ServerEncryptedClientHello {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.retry_configs.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- Ok(Self {
- retry_configs: Vec::<EchConfigPayload>::read(r)?,
- })
- }
-}
-
-/// The method of encoding to use for a handshake message.
-///
-/// In some cases a handshake message may be encoded differently depending on the purpose
-/// the encoded message is being used for.
-pub(crate) enum Encoding {
- /// Standard RFC 8446 encoding.
- Standard,
- /// Encoding for ECH confirmation for HRR.
- EchConfirmation,
- /// Encoding for ECH inner client hello.
- EchInnerHello { to_compress: Vec<ExtensionType> },
-}
-
-fn has_duplicates<I: IntoIterator<Item = E>, E: Into<T>, T: Eq + Ord>(iter: I) -> bool {
- let mut seen = BTreeSet::new();
-
- for x in iter {
- if !seen.insert(x.into()) {
- return true;
- }
- }
-
- false
-}
-
-struct DuplicateExtensionChecker(BTreeSet<u16>);
-
-impl DuplicateExtensionChecker {
- fn new() -> Self {
- Self(BTreeSet::new())
- }
-
- fn check(&mut self, typ: ExtensionType) -> Result<(), InvalidMessage> {
- let u = u16::from(typ);
- match self.0.insert(u) {
- true => Ok(()),
- false => Err(InvalidMessage::DuplicateExtension(u)),
- }
- }
-}
-
-fn low_quality_integer_hash(mut x: u32) -> u32 {
- x = x
- .wrapping_add(0x7ed55d16)
- .wrapping_add(x << 12);
- x = (x ^ 0xc761c23c) ^ (x >> 19);
- x = x
- .wrapping_add(0x165667b1)
- .wrapping_add(x << 5);
- x = x.wrapping_add(0xd3a2646c) ^ (x << 9);
- x = x
- .wrapping_add(0xfd7046c5)
- .wrapping_add(x << 3);
- x = (x ^ 0xb55a4f09) ^ (x >> 16);
- x
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn test_ech_config_dupe_exts() {
- let unknown_ext = EchConfigExtension::Unknown(UnknownExtension {
- typ: ExtensionType::Unknown(0x42),
- payload: Payload::new(vec![0x42]),
- });
- let mut config = config_template();
- config
- .extensions
- .push(unknown_ext.clone());
- config.extensions.push(unknown_ext);
-
- assert!(config.has_duplicate_extension());
- assert!(!config.has_unknown_mandatory_extension());
- }
-
- #[test]
- fn test_ech_config_mandatory_exts() {
- let mandatory_unknown_ext = EchConfigExtension::Unknown(UnknownExtension {
- typ: ExtensionType::Unknown(0x42 | 0x8000), // Note: high bit set.
- payload: Payload::new(vec![0x42]),
- });
- let mut config = config_template();
- config
- .extensions
- .push(mandatory_unknown_ext);
-
- assert!(!config.has_duplicate_extension());
- assert!(config.has_unknown_mandatory_extension());
- }
-
- fn config_template() -> EchConfigContents {
- EchConfigContents {
- key_config: HpkeKeyConfig {
- config_id: 0,
- kem_id: HpkeKem::DHKEM_P256_HKDF_SHA256,
- public_key: PayloadU16::new(b"xxx".into()),
- symmetric_cipher_suites: vec![HpkeSymmetricCipherSuite {
- kdf_id: HpkeKdf::HKDF_SHA256,
- aead_id: HpkeAead::AES_128_GCM,
- }],
- },
- maximum_name_length: 0,
- public_name: DnsName::try_from("example.com").unwrap(),
- extensions: vec![],
- }
- }
-}
diff --git a/vendor/rustls/src/msgs/handshake_test.rs b/vendor/rustls/src/msgs/handshake_test.rs
deleted file mode 100644
index 53cf88fa..00000000
--- a/vendor/rustls/src/msgs/handshake_test.rs
+++ /dev/null
@@ -1,1051 +0,0 @@
-use std::prelude::v1::*;
-use std::{format, println, vec};
-
-use pki_types::{CertificateDer, DnsName};
-
-use super::base::{Payload, PayloadU8, PayloadU16, PayloadU24};
-use super::codec::{Codec, Reader, put_u16};
-use super::enums::{
- ClientCertificateType, Compression, ECCurveType, ExtensionType, KeyUpdateRequest, NamedGroup,
-};
-use super::handshake::{
- CertificateChain, CertificateEntry, CertificateExtensions, CertificatePayloadTls13,
- CertificateRequestExtensions, CertificateRequestPayload, CertificateRequestPayloadTls13,
- CertificateStatus, CertificateStatusRequest, ClientExtensions, ClientHelloPayload,
- ClientSessionTicket, CompressedCertificatePayload, DistinguishedName, EcParameters,
- EncryptedClientHello, HandshakeMessagePayload, HandshakePayload, HelloRetryRequest,
- HelloRetryRequestExtensions, KeyShareEntry, NewSessionTicketExtensions,
- NewSessionTicketPayload, NewSessionTicketPayloadTls13, PresharedKeyBinder,
- PresharedKeyIdentity, PresharedKeyOffer, ProtocolName, PskKeyExchangeModes, Random,
- ServerDhParams, ServerEcdhParams, ServerEncryptedClientHello, ServerExtensions,
- ServerHelloPayload, ServerKeyExchange, ServerKeyExchangeParams, ServerKeyExchangePayload,
- ServerNamePayload, SessionId, SingleProtocolName, SupportedEcPointFormats,
- SupportedProtocolVersions,
-};
-use crate::enums::{
- CertificateCompressionAlgorithm, CertificateType, CipherSuite, HandshakeType, ProtocolVersion,
- SignatureScheme,
-};
-use crate::error::InvalidMessage;
-use crate::sync::Arc;
-use crate::verify::DigitallySignedStruct;
-
-#[test]
-fn rejects_short_random() {
- let bytes = [0x01; 31];
- let mut rd = Reader::init(&bytes);
- assert!(Random::read(&mut rd).is_err());
-}
-
-#[test]
-fn reads_random() {
- let bytes = [0x01; 32];
- let mut rd = Reader::init(&bytes);
- let rnd = Random::read(&mut rd).unwrap();
- println!("{rnd:?}");
-
- assert!(!rd.any_left());
-}
-
-#[test]
-fn debug_random() {
- assert_eq!(
- "0101010101010101010101010101010101010101010101010101010101010101",
- format!("{:?}", Random::from([1; 32]))
- );
-}
-
-#[test]
-fn rejects_truncated_session_id() {
- let bytes = [32; 32];
- let mut rd = Reader::init(&bytes);
- assert!(SessionId::read(&mut rd).is_err());
-}
-
-#[test]
-fn rejects_session_id_with_bad_length() {
- let bytes = [33; 33];
- let mut rd = Reader::init(&bytes);
- assert!(SessionId::read(&mut rd).is_err());
-}
-
-#[test]
-fn session_id_with_different_lengths_are_unequal() {
- let a = SessionId::read(&mut Reader::init(&[1u8, 1])).unwrap();
- let b = SessionId::read(&mut Reader::init(&[2u8, 1, 2])).unwrap();
- assert_ne!(a, b);
-}
-
-#[test]
-fn accepts_short_session_id() {
- let bytes = [1; 2];
- let mut rd = Reader::init(&bytes);
- let sess = SessionId::read(&mut rd).unwrap();
- println!("{sess:?}");
-
- #[cfg(feature = "tls12")]
- assert!(!sess.is_empty());
- assert_ne!(sess, SessionId::empty());
- assert!(!rd.any_left());
-}
-
-#[test]
-fn accepts_empty_session_id() {
- let bytes = [0; 1];
- let mut rd = Reader::init(&bytes);
- let sess = SessionId::read(&mut rd).unwrap();
- println!("{sess:?}");
-
- #[cfg(feature = "tls12")]
- assert!(sess.is_empty());
- assert_eq!(sess, SessionId::empty());
- assert!(!rd.any_left());
-}
-
-#[test]
-fn debug_session_id() {
- let bytes = [
- 32, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1,
- ];
- let mut rd = Reader::init(&bytes);
- let sess = SessionId::read(&mut rd).unwrap();
- assert_eq!(
- "0101010101010101010101010101010101010101010101010101010101010101",
- format!("{sess:?}")
- );
-}
-
-#[test]
-fn refuses_client_exts_with_unparsed_bytes() {
- let bytes = [0x00u8, 0x08, 0x00, 0x0b, 0x00, 0x04, 0x02, 0xf8, 0x01, 0x02];
- assert_eq!(
- ClientExtensions::read_bytes(&bytes).unwrap_err(),
- InvalidMessage::TrailingData("ClientExtensions")
- );
-}
-
-#[test]
-fn refuses_server_ext_with_unparsed_bytes() {
- let bytes = [0x00u8, 0x08, 0x00, 0x0b, 0x00, 0x04, 0x02, 0xf8, 0x01, 0x02];
- assert_eq!(
- ServerExtensions::read_bytes(&bytes).unwrap_err(),
- InvalidMessage::TrailingData("ServerExtensions")
- );
-}
-
-#[test]
-fn refuses_certificate_ext_with_unparsed_bytes() {
- let bytes = [
- 0x00u8, 0x09, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x01,
- ];
- assert_eq!(
- CertificateExtensions::read_bytes(&bytes).unwrap_err(),
- InvalidMessage::TrailingData("CertificateExtensions")
- );
-}
-
-#[test]
-fn refuses_certificate_ext_with_unknown_type() {
- let bytes = [0x00u8, 0x08, 0x00, 0x05, 0x00, 0x03, 0x99, 0x00, 0x00, 0x00];
- assert_eq!(
- CertificateExtensions::read_bytes(&bytes).unwrap_err(),
- InvalidMessage::InvalidCertificateStatusType
- );
-}
-
-#[test]
-fn refuses_certificate_req_ext_with_unparsed_bytes() {
- let bytes = [
- 0x00u8, 0x09, 0x00, 0x0d, 0x00, 0x05, 0x00, 0x02, 0x01, 0x02, 0xff,
- ];
- assert_eq!(
- CertificateRequestExtensions::read_bytes(&bytes).unwrap_err(),
- InvalidMessage::TrailingData("CertificateRequestExtensions")
- );
-}
-
-#[test]
-fn refuses_certificate_req_ext_with_duplicate() {
- let bytes = [0x00u8, 0x08, 0x00, 0x99, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00];
- assert_eq!(
- CertificateRequestExtensions::read_bytes(&bytes).unwrap_err(),
- InvalidMessage::DuplicateExtension(0x0099)
- );
-}
-
-#[test]
-fn refuses_new_session_ticket_ext_with_unparsed_bytes() {
- let bytes = [
- 0x00u8, 0x09, 0x00, 0x2a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x01,
- ];
- assert_eq!(
- NewSessionTicketExtensions::read_bytes(&bytes).unwrap_err(),
- InvalidMessage::TrailingData("NewSessionTicketExtensions")
- );
-}
-
-#[test]
-fn refuses_new_session_ticket_ext_with_duplicate_extension() {
- let bytes = [0x00u8, 0x08, 0x00, 0x99, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00];
- assert_eq!(
- NewSessionTicketExtensions::read_bytes(&bytes).unwrap_err(),
- InvalidMessage::DuplicateExtension(0x0099)
- );
-}
-
-#[test]
-fn rejects_truncated_sni() {
- let bytes = [0, 1, 0];
- assert!(ServerNamePayload::read(&mut Reader::init(&bytes)).is_err());
-
- let bytes = [0, 2, 0, 1];
- assert!(ServerNamePayload::read(&mut Reader::init(&bytes)).is_err());
-
- let bytes = [0, 3, 0, 1, 0];
- assert!(ServerNamePayload::read(&mut Reader::init(&bytes)).is_err());
-
- let bytes = [0, 4, 0, 2, 0, 0];
- assert!(ServerNamePayload::read(&mut Reader::init(&bytes)).is_err());
-
- let bytes = [0, 5, 0, 3, 0, 0, 0];
- assert!(ServerNamePayload::read(&mut Reader::init(&bytes)).is_err());
-
- let bytes = [0, 5, 0, 3, 0, 0, 1];
- assert!(ServerNamePayload::read(&mut Reader::init(&bytes)).is_err());
-
- let bytes = [0, 6, 0, 4, 0, 0, 2, 0x68];
- assert!(ServerNamePayload::read(&mut Reader::init(&bytes)).is_err());
-}
-
-#[test]
-fn rejects_empty_sni_extension() {
- assert_eq!(
- ClientExtensions::read_bytes(&[0, 6, 0, 0, 0, 2, 0, 0]).unwrap_err(),
- InvalidMessage::IllegalEmptyList("ServerNames")
- );
-}
-
-#[test]
-fn rejects_duplicate_names_in_sni_extension() {
- assert_eq!(
- ClientExtensions::read_bytes(&[0, 14, 0, 0, 0, 10, 0, 8, 0, 0, 1, b'a', 0, 0, 1, b'b',])
- .unwrap_err(),
- InvalidMessage::InvalidServerName
- );
-}
-
-#[test]
-fn can_round_trip_psk_identity() {
- let bytes = [0, 1, 0x99, 0x11, 0x22, 0x33, 0x44];
- let psk_id = PresharedKeyIdentity::read(&mut Reader::init(&bytes)).unwrap();
- println!("{psk_id:?}");
- assert_eq!(psk_id.obfuscated_ticket_age, 0x11223344);
- assert_eq!(psk_id.get_encoding(), bytes.to_vec());
-
- let bytes = [0, 5, 0x1, 0x2, 0x3, 0x4, 0x5, 0x11, 0x22, 0x33, 0x44];
- let psk_id = PresharedKeyIdentity::read(&mut Reader::init(&bytes)).unwrap();
- println!("{psk_id:?}");
- assert_eq!(psk_id.identity.0, vec![0x1, 0x2, 0x3, 0x4, 0x5]);
- assert_eq!(psk_id.obfuscated_ticket_age, 0x11223344);
- assert_eq!(psk_id.get_encoding(), bytes.to_vec());
-}
-
-#[test]
-fn can_round_trip_psk_offer() {
- let bytes = [
- 0, 7, 0, 1, 0x99, 0x11, 0x22, 0x33, 0x44, 0, 4, 3, 0x01, 0x02, 0x3,
- ];
- let psko = PresharedKeyOffer::read(&mut Reader::init(&bytes)).unwrap();
- println!("{psko:?}");
-
- assert_eq!(psko.identities.len(), 1);
- assert_eq!(psko.identities[0].identity.0, vec![0x99]);
- assert_eq!(psko.identities[0].obfuscated_ticket_age, 0x11223344);
- assert_eq!(psko.binders.len(), 1);
- assert_eq!(psko.binders[0].as_ref(), &[1, 2, 3]);
- assert_eq!(psko.get_encoding(), bytes.to_vec());
-}
-
-#[test]
-fn can_round_trip_cert_status_req_for_ocsp() {
- let ext = CertificateStatusRequest::build_ocsp();
- println!("{ext:?}");
-
- let bytes = [
- 0, 11, 1, // OCSP
- 0, 5, 0, 3, 0, 1, 1, 0, 1, 2,
- ];
-
- let csr = CertificateStatusRequest::read(&mut Reader::init(&bytes)).unwrap();
- println!("{csr:?}");
- assert_eq!(csr.get_encoding(), bytes.to_vec());
-}
-
-#[test]
-fn can_round_trip_cert_status_req_for_other() {
- let bytes = [
- 0, 5, 2, // !OCSP
- 1, 2, 3, 4,
- ];
-
- let csr = CertificateStatusRequest::read(&mut Reader::init(&bytes)).unwrap();
- println!("{csr:?}");
- assert_eq!(csr.get_encoding(), bytes.to_vec());
-}
-
-#[test]
-fn can_print_all_client_extensions() {
- println!("client hello {:?}", sample_client_hello_payload());
-}
-
-#[test]
-fn can_clone_all_client_extensions() {
- let exts = sample_client_hello_payload().extensions;
- let exts2 = exts.clone();
- println!("{exts:?}, {exts2:?}");
-}
-
-#[test]
-fn client_extensions_basics() {
- let src = ClientExtensions {
- early_data_request: Some(()),
- ..Default::default()
- };
- let mut target = ClientExtensions::default();
-
- assert_eq!(src.collect_used(), vec![ExtensionType::EarlyData]);
- assert_eq!(target.collect_used(), vec![]);
-
- target.clone_one(&src, ExtensionType::EarlyData);
- assert_eq!(target.collect_used(), vec![ExtensionType::EarlyData]);
-}
-
-#[test]
-fn client_extensions_empty() {
- // both sides of empty-encoding branch
- assert_eq!(ClientExtensions::default().get_encoding(), Vec::<u8>::new());
- assert_eq!(
- ClientExtensions::read_bytes(&[])
- .unwrap()
- .collect_used(),
- vec![]
- );
-
- let early_data = b"\x00\x04\x00\x2a\x00\x00";
- assert_eq!(
- ClientExtensions {
- early_data_request: Some(()),
- ..Default::default()
- }
- .get_encoding(),
- early_data
- );
- assert_eq!(
- ClientExtensions::read_bytes(early_data)
- .unwrap()
- .collect_used(),
- vec![ExtensionType::EarlyData]
- );
-}
-
-#[test]
-fn client_extensions_decode_checks_duplicates() {
- // base
- ClientExtensions::read_bytes(b"\x00\x04\x00\x2a\x00\x00").unwrap();
-
- // duplicate known
- assert_eq!(
- ClientExtensions::read_bytes(b"\x00\x08\x00\x2a\x00\x00\x00\x2a\x00\x00").unwrap_err(),
- InvalidMessage::DuplicateExtension(0x002a)
- );
-
- // duplicate unknown
- assert_eq!(
- ClientExtensions::read_bytes(b"\x00\x08\xff\xff\x00\x00\xff\xff\x00\x00").unwrap_err(),
- InvalidMessage::DuplicateExtension(0xffff)
- );
-}
-
-#[test]
-fn client_extensions_ordering() {
- // the important thing here is that PSK requests come last,
- // ECH requests come second to last, and order of other extensions
- // do vary.
-
- let psk_offer = PresharedKeyOffer {
- identities: vec![],
- binders: vec![],
- };
-
- let psk_and_ech = ClientExtensions {
- early_data_request: Some(()),
- extended_master_secret_request: Some(()),
- preshared_key_offer: Some(psk_offer.clone()),
- encrypted_client_hello: Some(EncryptedClientHello::Inner),
- ..Default::default()
- };
-
- let psk_and_ech_with_contiguous = ClientExtensions {
- contiguous_extensions: vec![ExtensionType::ExtendedMasterSecret],
- ..psk_and_ech.clone()
- };
-
- let ech = ClientExtensions {
- early_data_request: Some(()),
- extended_master_secret_request: Some(()),
- encrypted_client_hello: Some(EncryptedClientHello::Inner),
- ..Default::default()
- };
-
- let psk = ClientExtensions {
- early_data_request: Some(()),
- extended_master_secret_request: Some(()),
- preshared_key_offer: Some(psk_offer),
- ..Default::default()
- };
-
- let neither = ClientExtensions {
- early_data_request: Some(()),
- extended_master_secret_request: Some(()),
- ..Default::default()
- };
-
- fn encoding_with_order(order_seed: u16, exts: &ClientExtensions<'_>) -> Vec<u8> {
- let mut e = exts.clone();
- e.order_seed = order_seed;
- e.get_encoding()
- }
-
- assert_ne!(
- encoding_with_order(0, &psk_and_ech),
- encoding_with_order(1, &psk_and_ech)
- );
- assert_eq!(
- encoding_with_order(0, &psk_and_ech_with_contiguous),
- encoding_with_order(1, &psk_and_ech_with_contiguous)
- );
- assert_ne!(encoding_with_order(0, &ech), encoding_with_order(1, &ech));
- assert_ne!(encoding_with_order(0, &psk), encoding_with_order(1, &psk));
- assert_ne!(
- encoding_with_order(0, &neither),
- encoding_with_order(1, &neither)
- );
-
- // check order invariants hold for all seeds
- for seed in 0..=0xffff {
- // must end with ECH and then PSK
- assert!(encoding_with_order(seed, &psk_and_ech).ends_with(
- b"\xfe\x0d\x00\x01\x01\
- \x00\x29\x00\x04\x00\x00\x00\x00"
- ));
-
- // must end with EMS, then ECH and then PSK
- assert!(
- encoding_with_order(seed, &psk_and_ech_with_contiguous).ends_with(
- b"\x00\x17\x00\x00\
- \xfe\x0d\x00\x01\x01\
- \x00\x29\x00\x04\x00\x00\x00\x00"
- )
- );
-
- // just PSK
- assert!(encoding_with_order(seed, &psk).ends_with(b"\x00\x29\x00\x04\x00\x00\x00\x00"));
-
- // just ECH
- assert!(encoding_with_order(seed, &ech).ends_with(b"\xfe\x0d\x00\x01\x01"));
- }
-}
-
-#[test]
-fn test_truncated_psk_offer() {
- let ext = PresharedKeyOffer {
- identities: vec![PresharedKeyIdentity::new(vec![3, 4, 5], 123456)],
- binders: vec![PresharedKeyBinder::from(vec![1, 2, 3])],
- };
-
- let mut enc = ext.get_encoding();
- println!("testing {ext:?} enc {enc:?}");
- for l in 0..enc.len() {
- if l == 9 {
- continue;
- }
- put_u16(l as u16, &mut enc);
- let rc = PresharedKeyOffer::read_bytes(&enc);
- assert!(rc.is_err());
- }
-}
-
-#[test]
-fn test_truncated_client_hello_is_detected() {
- let ch = sample_client_hello_payload();
- let enc = ch.get_encoding();
- println!("testing {ch:?} enc {enc:?}");
-
- for l in 0..enc.len() {
- println!("len {:?} enc {:?}", l, &enc[..l]);
- if l == 41 {
- continue; // where extensions are empty
- }
- assert!(ClientHelloPayload::read_bytes(&enc[..l]).is_err());
- }
-}
-
-#[test]
-fn test_truncated_client_extension_is_detected() {
- let chp = sample_client_hello_payload();
-
- let enc = chp.extensions.get_encoding();
- println!("testing enc {enc:?}");
-
- // "outer" truncation, i.e., where the extension-level length is longer than
- // the input
- for l in 1..enc.len() {
- assert!(ClientExtensions::read_bytes(&enc[..l]).is_err());
- }
-}
-
-#[test]
-fn test_truncated_hello_retry_extension_is_detected() {
- let hrr = sample_hello_retry_request();
-
- let mut enc = hrr.extensions.get_encoding();
- println!("testing enc {enc:?}");
-
- // "outer" truncation, i.e., where the extension-level length is longer than
- // the input
- for l in 0..enc.len() {
- assert!(HelloRetryRequestExtensions::read_bytes(&enc[..l]).is_err());
- }
-
- // "inner" truncation, where the extension-level length agrees with the input
- // length, but isn't long enough for the type of extension
- for l in 0..(enc.len() - 4) {
- put_u16(l as u16, &mut enc);
- println!(" encoding {enc:?} len {l:?}");
- assert!(HelloRetryRequestExtensions::read_bytes(&enc).is_err());
- }
-}
-
-#[test]
-fn test_truncated_server_extension_is_detected() {
- let shp = sample_server_hello_payload();
-
- let mut enc = shp.extensions.get_encoding();
- println!("testing enc {enc:?}");
-
- // "outer" truncation, i.e., where the extension-level length is longer than
- // the input
- for l in 0..enc.len() {
- assert!(ServerExtensions::read_bytes(&enc[..l]).is_err());
- }
-
- // "inner" truncation, where the extension-level length agrees with the input
- // length, but isn't long enough for the type of extension
- for l in 0..(enc.len() - 4) {
- put_u16(l as u16, &mut enc[..2]);
- println!(" encoding {enc:?} len {l:?}");
- assert!(ServerExtensions::read_bytes(&enc).is_err());
- }
-}
-
-#[test]
-fn can_print_all_server_extensions() {
- println!("server hello {:?}", sample_server_hello_payload());
-}
-
-#[test]
-fn can_clone_all_server_extensions() {
- let exts = sample_server_hello_payload().extensions;
- let exts2 = exts.clone();
- println!("{exts:?}, {exts2:?}");
-}
-
-#[test]
-fn can_round_trip_all_tls12_handshake_payloads() {
- for hm in all_tls12_handshake_payloads().iter() {
- println!("{:?}", hm.0.handshake_type());
- let bytes = hm.get_encoding();
- let mut rd = Reader::init(&bytes);
- let other = HandshakeMessagePayload::read(&mut rd).unwrap();
- assert!(!rd.any_left());
- assert_eq!(hm.get_encoding(), other.get_encoding());
-
- println!("{hm:?}");
- println!("{other:?}");
- }
-}
-
-#[test]
-fn can_into_owned_all_tls12_handshake_payloads() {
- for hm in all_tls12_handshake_payloads().drain(..) {
- let enc = hm.get_encoding();
- let debug = format!("{hm:?}");
- let other = hm.into_owned();
- assert_eq!(enc, other.get_encoding());
- assert_eq!(debug, format!("{other:?}"));
- }
-}
-
-#[test]
-fn can_detect_truncation_of_all_tls12_handshake_payloads() {
- for hm in all_tls12_handshake_payloads().iter() {
- let mut enc = hm.get_encoding();
- println!("test {hm:?} enc {enc:?}");
-
- // outer truncation
- for l in 0..enc.len() {
- assert!(HandshakeMessagePayload::read_bytes(&enc[..l]).is_err())
- }
-
- // inner truncation
- for l in 0..enc.len() - 4 {
- put_u24(l as u32, &mut enc[1..]);
- println!(" check len {l:?} enc {enc:?}");
-
- match (hm.0.handshake_type(), l) {
- (HandshakeType::ClientHello, 41)
- | (HandshakeType::ServerHello, 38)
- | (HandshakeType::ServerKeyExchange, _)
- | (HandshakeType::ClientKeyExchange, _)
- | (HandshakeType::Finished, _)
- | (HandshakeType::Unknown(_), _) => continue,
- _ => {}
- };
-
- assert!(
- HandshakeMessagePayload::read_version(
- &mut Reader::init(&enc),
- ProtocolVersion::TLSv1_2
- )
- .is_err()
- );
- assert!(HandshakeMessagePayload::read_bytes(&enc).is_err());
- }
- }
-}
-
-#[test]
-fn can_round_trip_all_tls13_handshake_payloads() {
- for hm in all_tls13_handshake_payloads().iter() {
- println!("{:?}", hm.0.handshake_type());
- let bytes = hm.get_encoding();
- let mut rd = Reader::init(&bytes);
-
- let other =
- HandshakeMessagePayload::read_version(&mut rd, ProtocolVersion::TLSv1_3).unwrap();
- assert!(!rd.any_left());
- assert_eq!(hm.get_encoding(), other.get_encoding());
-
- println!("{hm:?}");
- println!("{other:?}");
- }
-}
-
-#[test]
-fn can_into_owned_all_tls13_handshake_payloads() {
- for hm in all_tls13_handshake_payloads().drain(..) {
- let enc = hm.get_encoding();
- let debug = format!("{hm:?}");
- let other = hm.into_owned();
- assert_eq!(enc, other.get_encoding());
- assert_eq!(debug, format!("{other:?}"));
- }
-}
-
-#[test]
-fn can_detect_truncation_of_all_tls13_handshake_payloads() {
- for hm in all_tls13_handshake_payloads().iter() {
- let mut enc = hm.get_encoding();
- println!("test {hm:?} enc {enc:?}");
-
- // outer truncation
- for l in 0..enc.len() {
- assert!(HandshakeMessagePayload::read_bytes(&enc[..l]).is_err())
- }
-
- // inner truncation
- for l in 0..enc.len() - 4 {
- put_u24(l as u32, &mut enc[1..]);
- println!(" check len {l:?} enc {enc:?}");
-
- match (hm.0.handshake_type(), l) {
- (HandshakeType::ClientHello, 41)
- | (HandshakeType::ServerHello, 38)
- | (HandshakeType::ServerKeyExchange, _)
- | (HandshakeType::ClientKeyExchange, _)
- | (HandshakeType::Finished, _)
- | (HandshakeType::Unknown(_), _) => continue,
- _ => {}
- };
-
- assert!(
- HandshakeMessagePayload::read_version(
- &mut Reader::init(&enc),
- ProtocolVersion::TLSv1_3
- )
- .is_err()
- );
- }
- }
-}
-
-fn put_u24(u: u32, b: &mut [u8]) {
- b[0] = (u >> 16) as u8;
- b[1] = (u >> 8) as u8;
- b[2] = u as u8;
-}
-
-#[test]
-fn cannot_read_message_hash_from_network() {
- let mh = HandshakeMessagePayload(HandshakePayload::MessageHash(Payload::new(vec![1, 2, 3])));
- println!("mh {mh:?}");
- let enc = mh.get_encoding();
- assert!(HandshakeMessagePayload::read_bytes(&enc).is_err());
-}
-
-#[test]
-fn cannot_decode_huge_certificate() {
- let mut buf = [0u8; 65 * 1024];
- // exactly 64KB decodes fine
- buf[0] = 0x0b;
- buf[1] = 0x01;
- buf[2] = 0x00;
- buf[3] = 0x03;
- buf[4] = 0x01;
- buf[5] = 0x00;
- buf[6] = 0x00;
- buf[7] = 0x00;
- buf[8] = 0xff;
- buf[9] = 0xfd;
- HandshakeMessagePayload::read_bytes(&buf[..0x10000 + 7]).unwrap();
-
- // however 64KB + 1 byte does not
- buf[1] = 0x01;
- buf[2] = 0x00;
- buf[3] = 0x04;
- buf[4] = 0x01;
- buf[5] = 0x00;
- buf[6] = 0x01;
- assert_eq!(
- HandshakeMessagePayload::read_bytes(&buf[..0x10001 + 7]).unwrap_err(),
- InvalidMessage::CertificatePayloadTooLarge
- );
-}
-
-#[test]
-fn can_decode_server_hello_from_api_devicecheck_apple_com() {
- let data = include_bytes!("../testdata/hello-api.devicecheck.apple.com.bin");
- let mut r = Reader::init(data);
- let hm = HandshakeMessagePayload::read(&mut r).unwrap();
- println!("msg: {hm:?}");
-}
-
-#[test]
-fn wrapped_dn_encoding() {
- let subject = b"subject";
- let dn = DistinguishedName::in_sequence(&subject[..]);
- const DER_SEQUENCE_TAG: u8 = 0x30;
- let expected_prefix = vec![DER_SEQUENCE_TAG, subject.len() as u8];
- assert_eq!(dn.as_ref(), [expected_prefix, subject.to_vec()].concat());
-}
-
-fn sample_hello_retry_request() -> HelloRetryRequest {
- HelloRetryRequest {
- legacy_version: ProtocolVersion::TLSv1_2,
- session_id: SessionId::empty(),
- cipher_suite: CipherSuite::TLS_NULL_WITH_NULL_NULL,
- extensions: HelloRetryRequestExtensions {
- key_share: Some(NamedGroup::X25519),
- cookie: Some(PayloadU16::new(vec![0])),
- supported_versions: Some(ProtocolVersion::TLSv1_2),
- encrypted_client_hello: Some(Payload::new(vec![1, 2, 3])),
- order: None,
- },
- }
-}
-
-fn sample_client_hello_payload() -> ClientHelloPayload {
- ClientHelloPayload {
- client_version: ProtocolVersion::TLSv1_2,
- random: Random::from([0; 32]),
- session_id: SessionId::empty(),
- cipher_suites: vec![CipherSuite::TLS_NULL_WITH_NULL_NULL],
- compression_methods: vec![Compression::Null],
- extensions: Box::new(ClientExtensions {
- server_name: Some(ServerNamePayload::from(
- &DnsName::try_from("hello").unwrap(),
- )),
- cookie: Some(PayloadU16::new(vec![1, 2, 3])),
- signature_schemes: Some(vec![SignatureScheme::ECDSA_NISTP256_SHA256]),
- session_ticket: Some(ClientSessionTicket::Request),
- ec_point_formats: Some(SupportedEcPointFormats::default()),
- named_groups: Some(vec![NamedGroup::X25519]),
- protocols: Some(vec![ProtocolName::from(vec![0])]),
- supported_versions: Some(SupportedProtocolVersions {
- tls13: true,
- ..Default::default()
- }),
- key_shares: Some(vec![KeyShareEntry::new(NamedGroup::X25519, &[1, 2, 3][..])]),
- preshared_key_modes: Some(PskKeyExchangeModes {
- psk_dhe: true,
- psk: false,
- }),
- preshared_key_offer: Some(PresharedKeyOffer {
- identities: vec![
- PresharedKeyIdentity::new(vec![3, 4, 5], 123456),
- PresharedKeyIdentity::new(vec![6, 7, 8], 7891011),
- ],
- binders: vec![
- PresharedKeyBinder::from(vec![1, 2, 3]),
- PresharedKeyBinder::from(vec![3, 4, 5]),
- ],
- }),
- extended_master_secret_request: Some(()),
- certificate_status_request: Some(CertificateStatusRequest::build_ocsp()),
- server_certificate_types: Some(vec![CertificateType::RawPublicKey]),
- client_certificate_types: Some(vec![CertificateType::RawPublicKey]),
- transport_parameters: Some(Payload::new(vec![1, 2, 3])),
- early_data_request: Some(()),
- certificate_compression_algorithms: Some(vec![CertificateCompressionAlgorithm::Brotli]),
- encrypted_client_hello: Some(EncryptedClientHello::Inner),
- encrypted_client_hello_outer: Some(vec![ExtensionType::SCT]),
- ..Default::default()
- }),
- }
-}
-
-fn sample_server_hello_payload() -> ServerHelloPayload {
- ServerHelloPayload {
- legacy_version: ProtocolVersion::TLSv1_2,
- random: Random::from([0; 32]),
- session_id: SessionId::empty(),
- cipher_suite: CipherSuite::TLS_NULL_WITH_NULL_NULL,
- compression_method: Compression::Null,
- extensions: Box::new(ServerExtensions {
- ec_point_formats: Some(SupportedEcPointFormats::default()),
- server_name_ack: Some(()),
- session_ticket_ack: Some(()),
- renegotiation_info: Some(PayloadU8::new(vec![0])),
- selected_protocol: Some(SingleProtocolName::new(ProtocolName::from(vec![0]))),
- key_share: Some(KeyShareEntry::new(NamedGroup::X25519, &[1, 2, 3][..])),
- preshared_key: Some(3),
- early_data_ack: Some(()),
- encrypted_client_hello_ack: Some(ServerEncryptedClientHello {
- retry_configs: vec![],
- }),
- extended_master_secret_ack: Some(()),
- certificate_status_request_ack: Some(()),
- selected_version: Some(ProtocolVersion::TLSv1_2),
- transport_parameters: Some(Payload::new(vec![1, 2, 3])),
- transport_parameters_draft: None,
- client_certificate_type: Some(CertificateType::RawPublicKey),
- server_certificate_type: Some(CertificateType::RawPublicKey),
- unknown_extensions: Default::default(),
- }),
- }
-}
-
-fn all_tls12_handshake_payloads() -> Vec<HandshakeMessagePayload<'static>> {
- vec![
- HandshakeMessagePayload(HandshakePayload::HelloRequest),
- HandshakeMessagePayload(HandshakePayload::ClientHello(sample_client_hello_payload())),
- HandshakeMessagePayload(HandshakePayload::ServerHello(sample_server_hello_payload())),
- HandshakeMessagePayload(HandshakePayload::HelloRetryRequest(
- sample_hello_retry_request(),
- )),
- HandshakeMessagePayload(HandshakePayload::Certificate(CertificateChain(vec![
- CertificateDer::from(vec![1, 2, 3]),
- ]))),
- HandshakeMessagePayload(HandshakePayload::ServerKeyExchange(
- sample_ecdhe_server_key_exchange_payload(),
- )),
- HandshakeMessagePayload(HandshakePayload::ServerKeyExchange(
- sample_dhe_server_key_exchange_payload(),
- )),
- HandshakeMessagePayload(HandshakePayload::ServerKeyExchange(
- sample_unknown_server_key_exchange_payload(),
- )),
- HandshakeMessagePayload(HandshakePayload::CertificateRequest(
- sample_certificate_request_payload(),
- )),
- HandshakeMessagePayload(HandshakePayload::ServerHelloDone),
- HandshakeMessagePayload(HandshakePayload::ClientKeyExchange(Payload::Borrowed(&[
- 1, 2, 3,
- ]))),
- HandshakeMessagePayload(HandshakePayload::NewSessionTicket(
- sample_new_session_ticket_payload(),
- )),
- HandshakeMessagePayload(HandshakePayload::EncryptedExtensions(
- sample_encrypted_extensions(),
- )),
- HandshakeMessagePayload(HandshakePayload::KeyUpdate(
- KeyUpdateRequest::UpdateRequested,
- )),
- HandshakeMessagePayload(HandshakePayload::KeyUpdate(
- KeyUpdateRequest::UpdateNotRequested,
- )),
- HandshakeMessagePayload(HandshakePayload::Finished(Payload::Borrowed(&[1, 2, 3]))),
- HandshakeMessagePayload(HandshakePayload::CertificateStatus(
- sample_certificate_status(),
- )),
- HandshakeMessagePayload(HandshakePayload::Unknown((
- HandshakeType::Unknown(99),
- Payload::Borrowed(&[1, 2, 3]),
- ))),
- ]
-}
-
-fn all_tls13_handshake_payloads() -> Vec<HandshakeMessagePayload<'static>> {
- vec![
- HandshakeMessagePayload(HandshakePayload::HelloRequest),
- HandshakeMessagePayload(HandshakePayload::ClientHello(sample_client_hello_payload())),
- HandshakeMessagePayload(HandshakePayload::ServerHello(sample_server_hello_payload())),
- HandshakeMessagePayload(HandshakePayload::HelloRetryRequest(
- sample_hello_retry_request(),
- )),
- HandshakeMessagePayload(HandshakePayload::CertificateTls13(
- sample_certificate_payload_tls13(),
- )),
- HandshakeMessagePayload(HandshakePayload::CompressedCertificate(
- sample_compressed_certificate(),
- )),
- HandshakeMessagePayload(HandshakePayload::ServerKeyExchange(
- sample_ecdhe_server_key_exchange_payload(),
- )),
- HandshakeMessagePayload(HandshakePayload::ServerKeyExchange(
- sample_dhe_server_key_exchange_payload(),
- )),
- HandshakeMessagePayload(HandshakePayload::ServerKeyExchange(
- sample_unknown_server_key_exchange_payload(),
- )),
- HandshakeMessagePayload(HandshakePayload::CertificateRequestTls13(
- sample_certificate_request_payload_tls13(),
- )),
- HandshakeMessagePayload(HandshakePayload::CertificateVerify(
- DigitallySignedStruct::new(SignatureScheme::ECDSA_NISTP256_SHA256, vec![1, 2, 3]),
- )),
- HandshakeMessagePayload(HandshakePayload::ServerHelloDone),
- HandshakeMessagePayload(HandshakePayload::ClientKeyExchange(Payload::Borrowed(&[
- 1, 2, 3,
- ]))),
- HandshakeMessagePayload(HandshakePayload::NewSessionTicketTls13(
- sample_new_session_ticket_payload_tls13(),
- )),
- HandshakeMessagePayload(HandshakePayload::EncryptedExtensions(
- sample_encrypted_extensions(),
- )),
- HandshakeMessagePayload(HandshakePayload::KeyUpdate(
- KeyUpdateRequest::UpdateRequested,
- )),
- HandshakeMessagePayload(HandshakePayload::KeyUpdate(
- KeyUpdateRequest::UpdateNotRequested,
- )),
- HandshakeMessagePayload(HandshakePayload::Finished(Payload::Borrowed(&[1, 2, 3]))),
- HandshakeMessagePayload(HandshakePayload::CertificateStatus(
- sample_certificate_status(),
- )),
- HandshakeMessagePayload(HandshakePayload::Unknown((
- HandshakeType::Unknown(99),
- Payload::Borrowed(&[1, 2, 3]),
- ))),
- ]
-}
-
-fn sample_certificate_payload_tls13() -> CertificatePayloadTls13<'static> {
- CertificatePayloadTls13 {
- context: PayloadU8::new(vec![1, 2, 3]),
- entries: vec![CertificateEntry {
- cert: CertificateDer::from(vec![3, 4, 5]),
- extensions: CertificateExtensions {
- status: Some(CertificateStatus {
- ocsp_response: PayloadU24(Payload::new(vec![1, 2, 3])),
- }),
- },
- }],
- }
-}
-
-fn sample_compressed_certificate() -> CompressedCertificatePayload<'static> {
- CompressedCertificatePayload {
- alg: CertificateCompressionAlgorithm::Brotli,
- uncompressed_len: 123,
- compressed: PayloadU24(Payload::new(vec![1, 2, 3])),
- }
-}
-
-fn sample_ecdhe_server_key_exchange_payload() -> ServerKeyExchangePayload {
- ServerKeyExchangePayload::Known(ServerKeyExchange {
- params: ServerKeyExchangeParams::Ecdh(ServerEcdhParams {
- curve_params: EcParameters {
- curve_type: ECCurveType::NamedCurve,
- named_group: NamedGroup::X25519,
- },
- public: PayloadU8::new(vec![1, 2, 3]),
- }),
- dss: DigitallySignedStruct::new(SignatureScheme::RSA_PSS_SHA256, vec![1, 2, 3]),
- })
-}
-
-fn sample_dhe_server_key_exchange_payload() -> ServerKeyExchangePayload {
- ServerKeyExchangePayload::Known(ServerKeyExchange {
- params: ServerKeyExchangeParams::Dh(ServerDhParams {
- dh_p: PayloadU16::new(vec![1, 2, 3]),
- dh_g: PayloadU16::new(vec![2]),
- dh_Ys: PayloadU16::new(vec![1, 2]),
- }),
- dss: DigitallySignedStruct::new(SignatureScheme::RSA_PSS_SHA256, vec![1, 2, 3]),
- })
-}
-
-fn sample_unknown_server_key_exchange_payload() -> ServerKeyExchangePayload {
- ServerKeyExchangePayload::Unknown(Payload::Borrowed(&[1, 2, 3]))
-}
-
-fn sample_certificate_request_payload() -> CertificateRequestPayload {
- CertificateRequestPayload {
- certtypes: vec![ClientCertificateType::RSASign],
- sigschemes: vec![SignatureScheme::ECDSA_NISTP256_SHA256],
- canames: vec![DistinguishedName::from(vec![1, 2, 3])],
- }
-}
-
-fn sample_certificate_request_payload_tls13() -> CertificateRequestPayloadTls13 {
- CertificateRequestPayloadTls13 {
- context: PayloadU8::new(vec![1, 2, 3]),
- extensions: CertificateRequestExtensions {
- signature_algorithms: Some(vec![SignatureScheme::ECDSA_NISTP256_SHA256]),
- authority_names: Some(vec![DistinguishedName::from(vec![1, 2, 3])]),
- certificate_compression_algorithms: Some(vec![CertificateCompressionAlgorithm::Zlib]),
- },
- }
-}
-
-fn sample_new_session_ticket_payload() -> NewSessionTicketPayload {
- NewSessionTicketPayload {
- lifetime_hint: 1234,
- ticket: Arc::new(PayloadU16::new(vec![1, 2, 3])),
- }
-}
-
-fn sample_new_session_ticket_payload_tls13() -> NewSessionTicketPayloadTls13 {
- NewSessionTicketPayloadTls13 {
- lifetime: 123,
- age_add: 1234,
- nonce: PayloadU8::new(vec![1, 2, 3]),
- ticket: Arc::new(PayloadU16::new(vec![4, 5, 6])),
- extensions: NewSessionTicketExtensions {
- max_early_data_size: Some(1234),
- },
- }
-}
-
-fn sample_encrypted_extensions() -> Box<ServerExtensions<'static>> {
- sample_server_hello_payload().extensions
-}
-
-fn sample_certificate_status() -> CertificateStatus<'static> {
- CertificateStatus {
- ocsp_response: PayloadU24(Payload::new(vec![1, 2, 3])),
- }
-}
diff --git a/vendor/rustls/src/msgs/macros.rs b/vendor/rustls/src/msgs/macros.rs
deleted file mode 100644
index 53252a20..00000000
--- a/vendor/rustls/src/msgs/macros.rs
+++ /dev/null
@@ -1,313 +0,0 @@
-/// A macro which defines an enum type.
-macro_rules! enum_builder {
- (
- $(#[doc = $comment:literal])*
- #[repr($uint:ty)]
- $enum_vis:vis enum $enum_name:ident
- {
- $( $enum_var:ident => $enum_val:literal),* $(,)?
- $( !Debug:
- $( $enum_var_nd:ident => $enum_val_nd:literal),* $(,)?
- )?
- }
- ) => {
- $(#[doc = $comment])*
- #[non_exhaustive]
- #[derive(PartialEq, Eq, Clone, Copy)]
- $enum_vis enum $enum_name {
- $( $enum_var),*
- $(, $($enum_var_nd),* )?
- ,Unknown($uint)
- }
-
- impl $enum_name {
- // NOTE(allow) generated irrespective if there are callers
- #[allow(dead_code)]
- $enum_vis fn to_array(self) -> [u8; core::mem::size_of::<$uint>()] {
- <$uint>::from(self).to_be_bytes()
- }
-
- // NOTE(allow) generated irrespective if there are callers
- #[allow(dead_code)]
- $enum_vis fn as_str(&self) -> Option<&'static str> {
- match self {
- $( $enum_name::$enum_var => Some(stringify!($enum_var))),*
- $(, $( $enum_name::$enum_var_nd => Some(stringify!($enum_var_nd))),* )?
- ,$enum_name::Unknown(_) => None,
- }
- }
- }
-
- impl Codec<'_> for $enum_name {
- // NOTE(allow) fully qualified Vec is only needed in no-std mode
- #[allow(unused_qualifications)]
- fn encode(&self, bytes: &mut alloc::vec::Vec<u8>) {
- <$uint>::from(*self).encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, crate::error::InvalidMessage> {
- match <$uint>::read(r) {
- Ok(x) => Ok($enum_name::from(x)),
- Err(_) => Err(crate::error::InvalidMessage::MissingData(stringify!($enum_name))),
- }
- }
- }
-
- impl From<$uint> for $enum_name {
- fn from(x: $uint) -> Self {
- match x {
- $($enum_val => $enum_name::$enum_var),*
- $(, $($enum_val_nd => $enum_name::$enum_var_nd),* )?
- , x => $enum_name::Unknown(x),
- }
- }
- }
-
- impl From<$enum_name> for $uint {
- fn from(value: $enum_name) -> Self {
- match value {
- $( $enum_name::$enum_var => $enum_val),*
- $(, $( $enum_name::$enum_var_nd => $enum_val_nd),* )?
- ,$enum_name::Unknown(x) => x
- }
- }
- }
-
- impl core::fmt::Debug for $enum_name {
- fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
- match self {
- $( $enum_name::$enum_var => f.write_str(stringify!($enum_var)), )*
- _ => write!(f, "{}(0x{:x?})", stringify!($enum_name), <$uint>::from(*self)),
- }
- }
- }
- };
-}
-
-/// A macro which defines a structure containing TLS extensions
-///
-/// The contents are defined by two blocks, which are merged to
-/// give the struct's items. The second block is optional.
-///
-/// The first block defines the items read-into by decoding,
-/// and used for encoding.
-///
-/// The type of each item in the first block _must_ be an `Option`.
-/// This records the presence of that extension.
-///
-/// Each item in the first block is prefixed with a match arm,
-/// which must match an `ExtensionType` variant. This maps
-/// the item to its extension type.
-///
-/// Items in the second block are not encoded or decoded-to.
-/// They therefore must have a reasonable `Default` value.
-///
-/// All items must have a `Default`, `Debug` and `Clone`.
-macro_rules! extension_struct {
- (
- $(#[doc = $comment:literal])*
- $struct_vis:vis struct $struct_name:ident$(<$struct_lt:lifetime>)*
- {
- $(
- $(#[$item_attr:meta])*
- $item_id:path => $item_vis:vis $item_slot:ident : Option<$item_ty:ty>,
- )+
- } $( + {
- $(
- $(#[$meta_attr:meta])*
- $meta_vis:vis $meta_slot:ident : $meta_ty:ty,
- )+
- })*
- ) => {
- $(#[doc = $comment])*
- #[non_exhaustive]
- #[derive(Clone, Default)]
- $struct_vis struct $struct_name$(<$struct_lt>)* {
- $(
- $(#[$item_attr])*
- $item_vis $item_slot: Option<$item_ty>,
- )+
- $($(
- $(#[$meta_attr])*
- $meta_vis $meta_slot: $meta_ty,
- )+)*
- }
-
- impl<'a> $struct_name$(<$struct_lt>)* {
- /// Reads one extension typ, length and body from `r`.
- ///
- /// Unhandled extensions (according to `read_extension_body()` are inserted into `unknown_extensions`)
- fn read_one(
- &mut self,
- r: &mut Reader<'a>,
- mut unknown: impl FnMut(ExtensionType) -> Result<(), InvalidMessage>,
- ) -> Result<ExtensionType, InvalidMessage> {
- let typ = ExtensionType::read(r)?;
- let len = usize::from(u16::read(r)?);
- let mut ext_body = r.sub(len)?;
- match self.read_extension_body(typ, &mut ext_body)? {
- true => ext_body.expect_empty(stringify!($struct_name))?,
- false => unknown(typ)?,
-
- };
- Ok(typ)
- }
-
- /// Reads one extension body for an extension named by `typ`.
- ///
- /// Returns `true` if handled, `false` otherwise.
- ///
- /// `r` is fully consumed if `typ` is unhandled.
- fn read_extension_body(
- &mut self,
- typ: ExtensionType,
- r: &mut Reader<'a>,
- ) -> Result<bool, InvalidMessage> {
- match typ {
- $(
- $item_id => Self::read_once(r, $item_id, &mut self.$item_slot)?,
- )*
-
- // read and ignore unhandled extensions
- _ => {
- r.rest();
- return Ok(false);
- }
- }
-
- Ok(true)
- }
-
- /// Decode `r` as `T` into `out`, only if `out` is `None`.
- fn read_once<T>(r: &mut Reader<'a>, id: ExtensionType, out: &mut Option<T>) -> Result<(), InvalidMessage>
- where T: Codec<'a>,
- {
- if let Some(_) = out {
- return Err(InvalidMessage::DuplicateExtension(u16::from(id)));
- }
-
- *out = Some(T::read(r)?);
- Ok(())
- }
-
- /// Encode one extension body for `typ` into `output`.
- ///
- /// Adds nothing to `output` if `typ` is absent from this
- /// struct, either because it is `None` or unhandled by
- /// this struct.
- fn encode_one(
- &self,
- typ: ExtensionType,
- output: &mut Vec<u8>,
- ) {
- match typ {
- $(
- $item_id => if let Some(item) = &self.$item_slot {
- typ.encode(output);
- item.encode(LengthPrefixedBuffer::new(ListLength::U16, output).buf);
- },
-
- )*
- _ => {},
- }
- }
-
- /// Return a list of extensions whose items are `Some`
- #[allow(dead_code)]
- pub(crate) fn collect_used(&self) -> Vec<ExtensionType> {
- let mut r = Vec::with_capacity(Self::ALL_EXTENSIONS.len());
-
- $(
- if let Some(_) = &self.$item_slot {
- r.push($item_id);
- }
- )*
-
- r
- }
-
- /// Clone the value of the extension identified by `typ` from `source` to `self`.
- ///
- /// Does nothing if `typ` is not an extension handled by this object.
- #[allow(dead_code)]
- pub(crate) fn clone_one(
- &mut self,
- source: &Self,
- typ: ExtensionType,
- ) {
- match typ {
- $(
- $item_id => self.$item_slot = source.$item_slot.clone(),
- )*
- _ => {},
- }
- }
-
- /// Remove the extension identified by `typ` from `self`.
- #[allow(dead_code)]
- pub(crate) fn clear(&mut self, typ: ExtensionType) {
- match typ {
- $(
- $item_id => self.$item_slot = None,
- )*
- _ => {},
- }
- }
-
- /// Return true if all present extensions are named in `allowed`
- #[allow(dead_code)]
- pub(crate) fn only_contains(&self, allowed: &[ExtensionType]) -> bool {
- $(
- if let Some(_) = &self.$item_slot {
- if !allowed.contains(&$item_id) {
- return false;
- }
- }
- )*
-
- true
- }
-
- /// Return true if any extension named in `exts` is present.
- #[allow(dead_code)]
- pub(crate) fn contains_any(&self, exts: &[ExtensionType]) -> bool {
- for e in exts {
- if self.contains(*e) {
- return true;
- }
- }
- false
- }
-
- fn contains(&self, e: ExtensionType) -> bool {
- match e {
- $(
-
- $item_id => self.$item_slot.is_some(),
- )*
- _ => false,
- }
- }
-
- /// Every `ExtensionType` this structure may encode/decode.
- const ALL_EXTENSIONS: &'static [ExtensionType] = &[
- $($item_id,)*
- ];
- }
-
- impl<'a> core::fmt::Debug for $struct_name$(<$struct_lt>)* {
- fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
- let mut ds = f.debug_struct(stringify!($struct_name));
- $(
- if let Some(ext) = &self.$item_slot {
- ds.field(stringify!($item_slot), ext);
- }
- )*
- $($(
- ds.field(stringify!($meta_slot), &self.$meta_slot);
- )+)*
- ds.finish_non_exhaustive()
- }
- }
- }
-}
diff --git a/vendor/rustls/src/msgs/message/inbound.rs b/vendor/rustls/src/msgs/message/inbound.rs
deleted file mode 100644
index f8b2181c..00000000
--- a/vendor/rustls/src/msgs/message/inbound.rs
+++ /dev/null
@@ -1,161 +0,0 @@
-use core::ops::{Deref, DerefMut, Range};
-
-use crate::enums::{ContentType, ProtocolVersion};
-use crate::error::{Error, PeerMisbehaved};
-use crate::msgs::fragmenter::MAX_FRAGMENT_LEN;
-
-/// A TLS frame, named TLSPlaintext in the standard.
-///
-/// This inbound type borrows its encrypted payload from a buffer elsewhere.
-/// It is used for joining and is consumed by decryption.
-pub struct InboundOpaqueMessage<'a> {
- pub typ: ContentType,
- pub version: ProtocolVersion,
- pub payload: BorrowedPayload<'a>,
-}
-
-impl<'a> InboundOpaqueMessage<'a> {
- /// Construct a new `InboundOpaqueMessage` from constituent fields.
- ///
- /// `payload` is borrowed.
- pub fn new(typ: ContentType, version: ProtocolVersion, payload: &'a mut [u8]) -> Self {
- Self {
- typ,
- version,
- payload: BorrowedPayload(payload),
- }
- }
-
- /// Force conversion into a plaintext message.
- ///
- /// This should only be used for messages that are known to be in plaintext. Otherwise, the
- /// `InboundOpaqueMessage` should be decrypted into a `PlainMessage` using a `MessageDecrypter`.
- pub fn into_plain_message(self) -> InboundPlainMessage<'a> {
- InboundPlainMessage {
- typ: self.typ,
- version: self.version,
- payload: self.payload.into_inner(),
- }
- }
-
- /// Force conversion into a plaintext message.
- ///
- /// `range` restricts the resulting message: this function panics if it is out of range for
- /// the underlying message payload.
- ///
- /// This should only be used for messages that are known to be in plaintext. Otherwise, the
- /// `InboundOpaqueMessage` should be decrypted into a `PlainMessage` using a `MessageDecrypter`.
- pub fn into_plain_message_range(self, range: Range<usize>) -> InboundPlainMessage<'a> {
- InboundPlainMessage {
- typ: self.typ,
- version: self.version,
- payload: &self.payload.into_inner()[range],
- }
- }
-
- /// For TLS1.3 (only), checks the length msg.payload is valid and removes the padding.
- ///
- /// Returns an error if the message (pre-unpadding) is too long, or the padding is invalid,
- /// or the message (post-unpadding) is too long.
- pub fn into_tls13_unpadded_message(mut self) -> Result<InboundPlainMessage<'a>, Error> {
- let payload = &mut self.payload;
-
- if payload.len() > MAX_FRAGMENT_LEN + 1 {
- return Err(Error::PeerSentOversizedRecord);
- }
-
- self.typ = unpad_tls13_payload(payload);
- if self.typ == ContentType::Unknown(0) {
- return Err(PeerMisbehaved::IllegalTlsInnerPlaintext.into());
- }
-
- if payload.len() > MAX_FRAGMENT_LEN {
- return Err(Error::PeerSentOversizedRecord);
- }
-
- self.version = ProtocolVersion::TLSv1_3;
- Ok(self.into_plain_message())
- }
-}
-
-pub struct BorrowedPayload<'a>(&'a mut [u8]);
-
-impl Deref for BorrowedPayload<'_> {
- type Target = [u8];
-
- fn deref(&self) -> &Self::Target {
- self.0
- }
-}
-
-impl DerefMut for BorrowedPayload<'_> {
- fn deref_mut(&mut self) -> &mut Self::Target {
- self.0
- }
-}
-
-impl<'a> BorrowedPayload<'a> {
- pub fn truncate(&mut self, len: usize) {
- if len >= self.len() {
- return;
- }
-
- self.0 = core::mem::take(&mut self.0)
- .split_at_mut(len)
- .0;
- }
-
- pub(crate) fn into_inner(self) -> &'a mut [u8] {
- self.0
- }
-
- pub(crate) fn pop(&mut self) -> Option<u8> {
- if self.is_empty() {
- return None;
- }
-
- let len = self.len();
- let last = self[len - 1];
- self.truncate(len - 1);
- Some(last)
- }
-}
-
-/// A TLS frame, named `TLSPlaintext` in the standard.
-///
-/// This inbound type borrows its decrypted payload from the original buffer.
-/// It results from decryption.
-#[derive(Debug)]
-pub struct InboundPlainMessage<'a> {
- pub typ: ContentType,
- pub version: ProtocolVersion,
- pub payload: &'a [u8],
-}
-
-impl InboundPlainMessage<'_> {
- /// Returns true if the payload is a CCS message.
- ///
- /// We passthrough ChangeCipherSpec messages in the deframer without decrypting them.
- /// Note: this is prior to the record layer, so is unencrypted. See
- /// third paragraph of section 5 in RFC8446.
- pub(crate) fn is_valid_ccs(&self) -> bool {
- self.typ == ContentType::ChangeCipherSpec && self.payload == [0x01]
- }
-}
-
-/// Decode a TLS1.3 `TLSInnerPlaintext` encoding.
-///
-/// `p` is a message payload, immediately post-decryption. This function
-/// removes zero padding bytes, until a non-zero byte is encountered which is
-/// the content type, which is returned. See RFC8446 s5.2.
-///
-/// ContentType(0) is returned if the message payload is empty or all zeroes.
-fn unpad_tls13_payload(p: &mut BorrowedPayload<'_>) -> ContentType {
- loop {
- match p.pop() {
- Some(0) => {}
- Some(content_type) => return ContentType::from(content_type),
- None => return ContentType::Unknown(0),
- }
- }
-}
diff --git a/vendor/rustls/src/msgs/message/mod.rs b/vendor/rustls/src/msgs/message/mod.rs
deleted file mode 100644
index d5cecc94..00000000
--- a/vendor/rustls/src/msgs/message/mod.rs
+++ /dev/null
@@ -1,262 +0,0 @@
-use crate::enums::{AlertDescription, ContentType, HandshakeType, ProtocolVersion};
-use crate::error::InvalidMessage;
-use crate::msgs::alert::AlertMessagePayload;
-use crate::msgs::base::Payload;
-use crate::msgs::ccs::ChangeCipherSpecPayload;
-use crate::msgs::codec::{Codec, Reader};
-use crate::msgs::enums::{AlertLevel, KeyUpdateRequest};
-use crate::msgs::handshake::{HandshakeMessagePayload, HandshakePayload};
-
-mod inbound;
-pub use inbound::{BorrowedPayload, InboundOpaqueMessage, InboundPlainMessage};
-
-mod outbound;
-use alloc::vec::Vec;
-
-pub(crate) use outbound::read_opaque_message_header;
-pub use outbound::{OutboundChunks, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload};
-
-#[derive(Debug)]
-pub enum MessagePayload<'a> {
- Alert(AlertMessagePayload),
- // one handshake message, parsed
- Handshake {
- parsed: HandshakeMessagePayload<'a>,
- encoded: Payload<'a>,
- },
- // (potentially) multiple handshake messages, unparsed
- HandshakeFlight(Payload<'a>),
- ChangeCipherSpec(ChangeCipherSpecPayload),
- ApplicationData(Payload<'a>),
-}
-
-impl<'a> MessagePayload<'a> {
- pub fn encode(&self, bytes: &mut Vec<u8>) {
- match self {
- Self::Alert(x) => x.encode(bytes),
- Self::Handshake { encoded, .. } => bytes.extend(encoded.bytes()),
- Self::HandshakeFlight(x) => bytes.extend(x.bytes()),
- Self::ChangeCipherSpec(x) => x.encode(bytes),
- Self::ApplicationData(x) => x.encode(bytes),
- }
- }
-
- pub fn handshake(parsed: HandshakeMessagePayload<'a>) -> Self {
- Self::Handshake {
- encoded: Payload::new(parsed.get_encoding()),
- parsed,
- }
- }
-
- pub fn new(
- typ: ContentType,
- vers: ProtocolVersion,
- payload: &'a [u8],
- ) -> Result<Self, InvalidMessage> {
- let mut r = Reader::init(payload);
- match typ {
- ContentType::ApplicationData => Ok(Self::ApplicationData(Payload::Borrowed(payload))),
- ContentType::Alert => AlertMessagePayload::read(&mut r).map(MessagePayload::Alert),
- ContentType::Handshake => {
- HandshakeMessagePayload::read_version(&mut r, vers).map(|parsed| Self::Handshake {
- parsed,
- encoded: Payload::Borrowed(payload),
- })
- }
- ContentType::ChangeCipherSpec => {
- ChangeCipherSpecPayload::read(&mut r).map(MessagePayload::ChangeCipherSpec)
- }
- _ => Err(InvalidMessage::InvalidContentType),
- }
- }
-
- pub fn content_type(&self) -> ContentType {
- match self {
- Self::Alert(_) => ContentType::Alert,
- Self::Handshake { .. } | Self::HandshakeFlight(_) => ContentType::Handshake,
- Self::ChangeCipherSpec(_) => ContentType::ChangeCipherSpec,
- Self::ApplicationData(_) => ContentType::ApplicationData,
- }
- }
-
- pub(crate) fn into_owned(self) -> MessagePayload<'static> {
- use MessagePayload::*;
- match self {
- Alert(x) => Alert(x),
- Handshake { parsed, encoded } => Handshake {
- parsed: parsed.into_owned(),
- encoded: encoded.into_owned(),
- },
- HandshakeFlight(x) => HandshakeFlight(x.into_owned()),
- ChangeCipherSpec(x) => ChangeCipherSpec(x),
- ApplicationData(x) => ApplicationData(x.into_owned()),
- }
- }
-}
-
-impl From<Message<'_>> for PlainMessage {
- fn from(msg: Message<'_>) -> Self {
- let typ = msg.payload.content_type();
- let payload = match msg.payload {
- MessagePayload::ApplicationData(payload) => payload.into_owned(),
- _ => {
- let mut buf = Vec::new();
- msg.payload.encode(&mut buf);
- Payload::Owned(buf)
- }
- };
-
- Self {
- typ,
- version: msg.version,
- payload,
- }
- }
-}
-
-/// A decrypted TLS frame
-///
-/// This type owns all memory for its interior parts. It can be decrypted from an OpaqueMessage
-/// or encrypted into an OpaqueMessage, and it is also used for joining and fragmenting.
-#[derive(Clone, Debug)]
-pub struct PlainMessage {
- pub typ: ContentType,
- pub version: ProtocolVersion,
- pub payload: Payload<'static>,
-}
-
-impl PlainMessage {
- pub fn into_unencrypted_opaque(self) -> OutboundOpaqueMessage {
- OutboundOpaqueMessage {
- version: self.version,
- typ: self.typ,
- payload: PrefixedPayload::from(self.payload.bytes()),
- }
- }
-
- pub fn borrow_inbound(&self) -> InboundPlainMessage<'_> {
- InboundPlainMessage {
- version: self.version,
- typ: self.typ,
- payload: self.payload.bytes(),
- }
- }
-
- pub fn borrow_outbound(&self) -> OutboundPlainMessage<'_> {
- OutboundPlainMessage {
- version: self.version,
- typ: self.typ,
- payload: self.payload.bytes().into(),
- }
- }
-}
-
-/// A message with decoded payload
-#[derive(Debug)]
-pub struct Message<'a> {
- pub version: ProtocolVersion,
- pub payload: MessagePayload<'a>,
-}
-
-impl Message<'_> {
- pub fn is_handshake_type(&self, hstyp: HandshakeType) -> bool {
- // Bit of a layering violation, but OK.
- if let MessagePayload::Handshake { parsed, .. } = &self.payload {
- parsed.0.handshake_type() == hstyp
- } else {
- false
- }
- }
-
- pub fn build_alert(level: AlertLevel, desc: AlertDescription) -> Self {
- Self {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::Alert(AlertMessagePayload {
- level,
- description: desc,
- }),
- }
- }
-
- pub fn build_key_update_notify() -> Self {
- Self {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::KeyUpdate(KeyUpdateRequest::UpdateNotRequested),
- )),
- }
- }
-
- pub fn build_key_update_request() -> Self {
- Self {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::KeyUpdate(KeyUpdateRequest::UpdateRequested),
- )),
- }
- }
-
- #[cfg(feature = "std")]
- pub(crate) fn into_owned(self) -> Message<'static> {
- let Self { version, payload } = self;
- Message {
- version,
- payload: payload.into_owned(),
- }
- }
-
- #[cfg(test)]
- pub(crate) fn into_wire_bytes(self) -> Vec<u8> {
- PlainMessage::from(self)
- .into_unencrypted_opaque()
- .encode()
- }
-}
-
-impl TryFrom<PlainMessage> for Message<'static> {
- type Error = InvalidMessage;
-
- fn try_from(plain: PlainMessage) -> Result<Self, Self::Error> {
- Ok(Self {
- version: plain.version,
- payload: MessagePayload::new(plain.typ, plain.version, plain.payload.bytes())?
- .into_owned(),
- })
- }
-}
-
-/// Parses a plaintext message into a well-typed [`Message`].
-///
-/// A [`PlainMessage`] must contain plaintext content. Encrypted content should be stored in an
-/// [`InboundOpaqueMessage`] and decrypted before being stored into a [`PlainMessage`].
-impl<'a> TryFrom<InboundPlainMessage<'a>> for Message<'a> {
- type Error = InvalidMessage;
-
- fn try_from(plain: InboundPlainMessage<'a>) -> Result<Self, Self::Error> {
- Ok(Self {
- version: plain.version,
- payload: MessagePayload::new(plain.typ, plain.version, plain.payload)?,
- })
- }
-}
-
-#[derive(Debug)]
-pub enum MessageError {
- TooShortForHeader,
- TooShortForLength,
- InvalidEmptyPayload,
- MessageTooLarge,
- InvalidContentType,
- UnknownProtocolVersion,
-}
-
-/// Content type, version and size.
-pub(crate) const HEADER_SIZE: usize = 1 + 2 + 2;
-
-/// Maximum message payload size.
-/// That's 2^14 payload bytes and a 2KB allowance for ciphertext overheads.
-const MAX_PAYLOAD: u16 = 16_384 + 2048;
-
-/// Maximum on-the-wire message size.
-#[cfg(feature = "std")]
-pub(crate) const MAX_WIRE_SIZE: usize = MAX_PAYLOAD as usize + HEADER_SIZE;
diff --git a/vendor/rustls/src/msgs/message/outbound.rs b/vendor/rustls/src/msgs/message/outbound.rs
deleted file mode 100644
index 810c066c..00000000
--- a/vendor/rustls/src/msgs/message/outbound.rs
+++ /dev/null
@@ -1,422 +0,0 @@
-use alloc::vec::Vec;
-
-use super::{HEADER_SIZE, MAX_PAYLOAD, MessageError, PlainMessage};
-use crate::enums::{ContentType, ProtocolVersion};
-use crate::msgs::base::Payload;
-use crate::msgs::codec::{Codec, Reader};
-use crate::record_layer::RecordLayer;
-
-/// A TLS frame, named `TLSPlaintext` in the standard.
-///
-/// This outbound type borrows its "to be encrypted" payload from the "user".
-/// It is used for fragmenting and is consumed by encryption.
-#[derive(Debug)]
-pub struct OutboundPlainMessage<'a> {
- pub typ: ContentType,
- pub version: ProtocolVersion,
- pub payload: OutboundChunks<'a>,
-}
-
-impl OutboundPlainMessage<'_> {
- pub(crate) fn encoded_len(&self, record_layer: &RecordLayer) -> usize {
- HEADER_SIZE + record_layer.encrypted_len(self.payload.len())
- }
-
- pub(crate) fn to_unencrypted_opaque(&self) -> OutboundOpaqueMessage {
- let mut payload = PrefixedPayload::with_capacity(self.payload.len());
- payload.extend_from_chunks(&self.payload);
- OutboundOpaqueMessage {
- version: self.version,
- typ: self.typ,
- payload,
- }
- }
-}
-
-/// A collection of borrowed plaintext slices.
-///
-/// Warning: OutboundChunks does not guarantee that the simplest variant is used.
-/// Multiple can hold non fragmented or empty payloads.
-#[derive(Debug, Clone)]
-pub enum OutboundChunks<'a> {
- /// A single byte slice. Contrary to `Multiple`, this uses a single pointer indirection
- Single(&'a [u8]),
- /// A collection of chunks (byte slices)
- /// and cursors to single out a fragmented range of bytes.
- /// OutboundChunks assumes that start <= end
- Multiple {
- chunks: &'a [&'a [u8]],
- start: usize,
- end: usize,
- },
-}
-
-impl<'a> OutboundChunks<'a> {
- /// Create a payload from a slice of byte slices.
- /// If fragmented the cursors are added by default: start = 0, end = length
- pub fn new(chunks: &'a [&'a [u8]]) -> Self {
- if chunks.len() == 1 {
- Self::Single(chunks[0])
- } else {
- Self::Multiple {
- chunks,
- start: 0,
- end: chunks
- .iter()
- .map(|chunk| chunk.len())
- .sum(),
- }
- }
- }
-
- /// Create a payload with a single empty slice
- pub fn new_empty() -> Self {
- Self::Single(&[])
- }
-
- /// Flatten the slice of byte slices to an owned vector of bytes
- pub fn to_vec(&self) -> Vec<u8> {
- let mut vec = Vec::with_capacity(self.len());
- self.copy_to_vec(&mut vec);
- vec
- }
-
- /// Append all bytes to a vector
- pub fn copy_to_vec(&self, vec: &mut Vec<u8>) {
- match *self {
- Self::Single(chunk) => vec.extend_from_slice(chunk),
- Self::Multiple { chunks, start, end } => {
- let mut size = 0;
- for chunk in chunks.iter() {
- let psize = size;
- let len = chunk.len();
- size += len;
- if size <= start || psize >= end {
- continue;
- }
- let start = start.saturating_sub(psize);
- let end = if end - psize < len { end - psize } else { len };
- vec.extend_from_slice(&chunk[start..end]);
- }
- }
- }
- }
-
- /// Split self in two, around an index
- /// Works similarly to `split_at` in the core library, except it doesn't panic if out of bound
- pub fn split_at(&self, mid: usize) -> (Self, Self) {
- match *self {
- Self::Single(chunk) => {
- let mid = Ord::min(mid, chunk.len());
- (Self::Single(&chunk[..mid]), Self::Single(&chunk[mid..]))
- }
- Self::Multiple { chunks, start, end } => {
- let mid = Ord::min(start + mid, end);
- (
- Self::Multiple {
- chunks,
- start,
- end: mid,
- },
- Self::Multiple {
- chunks,
- start: mid,
- end,
- },
- )
- }
- }
- }
-
- /// Returns true if the payload is empty
- pub fn is_empty(&self) -> bool {
- self.len() == 0
- }
-
- /// Returns the cumulative length of all chunks
- pub fn len(&self) -> usize {
- match self {
- Self::Single(chunk) => chunk.len(),
- Self::Multiple { start, end, .. } => end - start,
- }
- }
-}
-
-impl<'a> From<&'a [u8]> for OutboundChunks<'a> {
- fn from(payload: &'a [u8]) -> Self {
- Self::Single(payload)
- }
-}
-
-/// A TLS frame, named `TLSPlaintext` in the standard.
-///
-/// This outbound type owns all memory for its interior parts.
-/// It results from encryption and is used for io write.
-#[derive(Clone, Debug)]
-pub struct OutboundOpaqueMessage {
- pub typ: ContentType,
- pub version: ProtocolVersion,
- pub payload: PrefixedPayload,
-}
-
-impl OutboundOpaqueMessage {
- /// Construct a new `OpaqueMessage` from constituent fields.
- ///
- /// `body` is moved into the `payload` field.
- pub fn new(typ: ContentType, version: ProtocolVersion, payload: PrefixedPayload) -> Self {
- Self {
- typ,
- version,
- payload,
- }
- }
-
- /// Construct by decoding from a [`Reader`].
- ///
- /// `MessageError` allows callers to distinguish between valid prefixes (might
- /// become valid if we read more data) and invalid data.
- pub fn read(r: &mut Reader<'_>) -> Result<Self, MessageError> {
- let (typ, version, len) = read_opaque_message_header(r)?;
-
- let content = r
- .take(len as usize)
- .ok_or(MessageError::TooShortForLength)?;
-
- Ok(Self {
- typ,
- version,
- payload: PrefixedPayload::from(content),
- })
- }
-
- pub fn encode(self) -> Vec<u8> {
- let length = self.payload.len() as u16;
- let mut encoded_payload = self.payload.0;
- encoded_payload[0] = self.typ.into();
- encoded_payload[1..3].copy_from_slice(&self.version.to_array());
- encoded_payload[3..5].copy_from_slice(&(length).to_be_bytes());
- encoded_payload
- }
-
- /// Force conversion into a plaintext message.
- ///
- /// This should only be used for messages that are known to be in plaintext. Otherwise, the
- /// `OutboundOpaqueMessage` should be decrypted into a `PlainMessage` using a `MessageDecrypter`.
- pub fn into_plain_message(self) -> PlainMessage {
- PlainMessage {
- version: self.version,
- typ: self.typ,
- payload: Payload::Owned(self.payload.as_ref().to_vec()),
- }
- }
-}
-
-#[derive(Clone, Debug)]
-pub struct PrefixedPayload(Vec<u8>);
-
-impl PrefixedPayload {
- pub fn with_capacity(capacity: usize) -> Self {
- let mut prefixed_payload = Vec::with_capacity(HEADER_SIZE + capacity);
- prefixed_payload.resize(HEADER_SIZE, 0);
- Self(prefixed_payload)
- }
-
- pub fn extend_from_slice(&mut self, slice: &[u8]) {
- self.0.extend_from_slice(slice)
- }
-
- pub fn extend_from_chunks(&mut self, chunks: &OutboundChunks<'_>) {
- chunks.copy_to_vec(&mut self.0)
- }
-
- pub fn truncate(&mut self, len: usize) {
- self.0.truncate(len + HEADER_SIZE)
- }
-
- fn len(&self) -> usize {
- self.0.len() - HEADER_SIZE
- }
-}
-
-impl AsRef<[u8]> for PrefixedPayload {
- fn as_ref(&self) -> &[u8] {
- &self.0[HEADER_SIZE..]
- }
-}
-
-impl AsMut<[u8]> for PrefixedPayload {
- fn as_mut(&mut self) -> &mut [u8] {
- &mut self.0[HEADER_SIZE..]
- }
-}
-
-impl<'a> Extend<&'a u8> for PrefixedPayload {
- fn extend<T: IntoIterator<Item = &'a u8>>(&mut self, iter: T) {
- self.0.extend(iter)
- }
-}
-
-impl From<&[u8]> for PrefixedPayload {
- fn from(content: &[u8]) -> Self {
- let mut payload = Vec::with_capacity(HEADER_SIZE + content.len());
- payload.extend(&[0u8; HEADER_SIZE]);
- payload.extend(content);
- Self(payload)
- }
-}
-
-impl<const N: usize> From<&[u8; N]> for PrefixedPayload {
- fn from(content: &[u8; N]) -> Self {
- Self::from(&content[..])
- }
-}
-
-pub(crate) fn read_opaque_message_header(
- r: &mut Reader<'_>,
-) -> Result<(ContentType, ProtocolVersion, u16), MessageError> {
- let typ = ContentType::read(r).map_err(|_| MessageError::TooShortForHeader)?;
- // Don't accept any new content-types.
- if let ContentType::Unknown(_) = typ {
- return Err(MessageError::InvalidContentType);
- }
-
- let version = ProtocolVersion::read(r).map_err(|_| MessageError::TooShortForHeader)?;
- // Accept only versions 0x03XX for any XX.
- match &version {
- ProtocolVersion::Unknown(v) if (v & 0xff00) != 0x0300 => {
- return Err(MessageError::UnknownProtocolVersion);
- }
- _ => {}
- };
-
- let len = u16::read(r).map_err(|_| MessageError::TooShortForHeader)?;
-
- // Reject undersize messages
- // implemented per section 5.1 of RFC8446 (TLSv1.3)
- // per section 6.2.1 of RFC5246 (TLSv1.2)
- if typ != ContentType::ApplicationData && len == 0 {
- return Err(MessageError::InvalidEmptyPayload);
- }
-
- // Reject oversize messages
- if len >= MAX_PAYLOAD {
- return Err(MessageError::MessageTooLarge);
- }
-
- Ok((typ, version, len))
-}
-
-#[cfg(test)]
-mod tests {
- use std::{println, vec};
-
- use super::*;
-
- #[test]
- fn split_at_with_single_slice() {
- let owner: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7];
- let borrowed_payload = OutboundChunks::Single(owner);
-
- let (before, after) = borrowed_payload.split_at(6);
- println!("before:{before:?}\nafter:{after:?}");
- assert_eq!(before.to_vec(), &[0, 1, 2, 3, 4, 5]);
- assert_eq!(after.to_vec(), &[6, 7]);
- }
-
- #[test]
- fn split_at_with_multiple_slices() {
- let owner: Vec<&[u8]> = vec![&[0, 1, 2, 3], &[4, 5], &[6, 7, 8], &[9, 10, 11, 12]];
- let borrowed_payload = OutboundChunks::new(&owner);
-
- let (before, after) = borrowed_payload.split_at(3);
- println!("before:{before:?}\nafter:{after:?}");
- assert_eq!(before.to_vec(), &[0, 1, 2]);
- assert_eq!(after.to_vec(), &[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
-
- let (before, after) = borrowed_payload.split_at(8);
- println!("before:{before:?}\nafter:{after:?}");
- assert_eq!(before.to_vec(), &[0, 1, 2, 3, 4, 5, 6, 7]);
- assert_eq!(after.to_vec(), &[8, 9, 10, 11, 12]);
-
- let (before, after) = borrowed_payload.split_at(11);
- println!("before:{before:?}\nafter:{after:?}");
- assert_eq!(before.to_vec(), &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
- assert_eq!(after.to_vec(), &[11, 12]);
- }
-
- #[test]
- fn split_out_of_bounds() {
- let owner: Vec<&[u8]> = vec![&[0, 1, 2, 3], &[4, 5], &[6, 7, 8], &[9, 10, 11, 12]];
-
- let single_payload = OutboundChunks::Single(owner[0]);
- let (before, after) = single_payload.split_at(17);
- println!("before:{before:?}\nafter:{after:?}");
- assert_eq!(before.to_vec(), &[0, 1, 2, 3]);
- assert!(after.is_empty());
-
- let multiple_payload = OutboundChunks::new(&owner);
- let (before, after) = multiple_payload.split_at(17);
- println!("before:{before:?}\nafter:{after:?}");
- assert_eq!(before.to_vec(), &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
- assert!(after.is_empty());
-
- let empty_payload = OutboundChunks::new_empty();
- let (before, after) = empty_payload.split_at(17);
- println!("before:{before:?}\nafter:{after:?}");
- assert!(before.is_empty());
- assert!(after.is_empty());
- }
-
- #[test]
- fn empty_slices_mixed() {
- let owner: Vec<&[u8]> = vec![&[], &[], &[0], &[], &[1, 2], &[], &[3], &[4], &[], &[]];
- let mut borrowed_payload = OutboundChunks::new(&owner);
- let mut fragment_count = 0;
- let mut fragment;
- let expected_fragments: &[&[u8]] = &[&[0, 1], &[2, 3], &[4]];
-
- while !borrowed_payload.is_empty() {
- (fragment, borrowed_payload) = borrowed_payload.split_at(2);
- println!("{fragment:?}");
- assert_eq!(&expected_fragments[fragment_count], &fragment.to_vec());
- fragment_count += 1;
- }
- assert_eq!(fragment_count, expected_fragments.len());
- }
-
- #[test]
- fn exhaustive_splitting() {
- let owner: Vec<u8> = (0..127).collect();
- let slices = (0..7)
- .map(|i| &owner[((1 << i) - 1)..((1 << (i + 1)) - 1)])
- .collect::<Vec<_>>();
- let payload = OutboundChunks::new(&slices);
-
- assert_eq!(payload.to_vec(), owner);
- println!("{payload:#?}");
-
- for start in 0..128 {
- for end in start..128 {
- for mid in 0..(end - start) {
- let witness = owner[start..end].split_at(mid);
- let split_payload = payload
- .split_at(end)
- .0
- .split_at(start)
- .1
- .split_at(mid);
- assert_eq!(
- witness.0,
- split_payload.0.to_vec(),
- "start: {start}, mid:{mid}, end:{end}"
- );
- assert_eq!(
- witness.1,
- split_payload.1.to_vec(),
- "start: {start}, mid:{mid}, end:{end}"
- );
- }
- }
- }
- }
-}
diff --git a/vendor/rustls/src/msgs/message_test.rs b/vendor/rustls/src/msgs/message_test.rs
deleted file mode 100644
index 965a3572..00000000
--- a/vendor/rustls/src/msgs/message_test.rs
+++ /dev/null
@@ -1,124 +0,0 @@
-use std::io::Read;
-use std::path::{Path, PathBuf};
-use std::prelude::v1::*;
-use std::{format, fs, println, vec};
-
-use super::base::Payload;
-use super::codec::Reader;
-use super::enums::AlertLevel;
-use super::message::{Message, OutboundOpaqueMessage, PlainMessage};
-use crate::enums::{AlertDescription, HandshakeType};
-use crate::msgs::base::{MaybeEmpty, NonEmpty, PayloadU8, PayloadU16, PayloadU24};
-
-#[test]
-fn test_read_fuzz_corpus() {
- fn corpus_dir() -> PathBuf {
- let from_subcrate = Path::new("../fuzz/corpus/message");
- let from_root = Path::new("fuzz/corpus/message");
-
- if from_root.is_dir() {
- from_root.to_path_buf()
- } else {
- from_subcrate.to_path_buf()
- }
- }
-
- for file in fs::read_dir(corpus_dir()).unwrap() {
- let mut f = fs::File::open(file.unwrap().path()).unwrap();
- let mut bytes = Vec::new();
- f.read_to_end(&mut bytes).unwrap();
-
- let mut rd = Reader::init(&bytes);
- let msg = OutboundOpaqueMessage::read(&mut rd)
- .unwrap()
- .into_plain_message();
- println!("{msg:?}");
-
- let Ok(msg) = Message::try_from(msg) else {
- continue;
- };
-
- let enc = PlainMessage::from(msg)
- .into_unencrypted_opaque()
- .encode();
- assert_eq!(bytes.to_vec(), enc);
- assert_eq!(bytes[..rd.used()].to_vec(), enc);
- }
-}
-
-#[test]
-fn can_read_safari_client_hello_with_ip_address_in_sni_extension() {
- let _ = env_logger::Builder::new()
- .filter(None, log::LevelFilter::Trace)
- .try_init();
-
- let bytes = b"\
- \x16\x03\x01\x00\xeb\x01\x00\x00\xe7\x03\x03\xb6\x1f\xe4\x3a\x55\
- \x90\x3e\xc0\x28\x9c\x12\xe0\x5c\x84\xea\x90\x1b\xfb\x11\xfc\xbd\
- \x25\x55\xda\x9f\x51\x93\x1b\x8d\x92\x66\xfd\x00\x00\x2e\xc0\x2c\
- \xc0\x2b\xc0\x24\xc0\x23\xc0\x0a\xc0\x09\xcc\xa9\xc0\x30\xc0\x2f\
- \xc0\x28\xc0\x27\xc0\x14\xc0\x13\xcc\xa8\x00\x9d\x00\x9c\x00\x3d\
- \x00\x3c\x00\x35\x00\x2f\xc0\x08\xc0\x12\x00\x0a\x01\x00\x00\x90\
- \xff\x01\x00\x01\x00\x00\x00\x00\x0e\x00\x0c\x00\x00\x09\x31\x32\
- \x37\x2e\x30\x2e\x30\x2e\x31\x00\x17\x00\x00\x00\x0d\x00\x18\x00\
- \x16\x04\x03\x08\x04\x04\x01\x05\x03\x02\x03\x08\x05\x08\x05\x05\
- \x01\x08\x06\x06\x01\x02\x01\x00\x05\x00\x05\x01\x00\x00\x00\x00\
- \x33\x74\x00\x00\x00\x12\x00\x00\x00\x10\x00\x30\x00\x2e\x02\x68\
- \x32\x05\x68\x32\x2d\x31\x36\x05\x68\x32\x2d\x31\x35\x05\x68\x32\
- \x2d\x31\x34\x08\x73\x70\x64\x79\x2f\x33\x2e\x31\x06\x73\x70\x64\
- \x79\x2f\x33\x08\x68\x74\x74\x70\x2f\x31\x2e\x31\x00\x0b\x00\x02\
- \x01\x00\x00\x0a\x00\x0a\x00\x08\x00\x1d\x00\x17\x00\x18\x00\x19";
- let mut rd = Reader::init(bytes);
- let m = OutboundOpaqueMessage::read(&mut rd).unwrap();
- println!("m = {m:?}");
- Message::try_from(m.into_plain_message()).unwrap();
-}
-
-#[test]
-fn alert_is_not_handshake() {
- let m = Message::build_alert(AlertLevel::Fatal, AlertDescription::DecodeError);
- assert!(!m.is_handshake_type(HandshakeType::ClientHello));
-}
-
-#[test]
-fn construct_all_types() {
- let samples = [
- &b"\x14\x03\x04\x00\x01\x01"[..],
- &b"\x15\x03\x04\x00\x02\x01\x16"[..],
- &b"\x16\x03\x04\x00\x05\x18\x00\x00\x01\x00"[..],
- &b"\x17\x03\x04\x00\x04\x11\x22\x33\x44"[..],
- &b"\x18\x03\x04\x00\x04\x11\x22\x33\x44"[..],
- ];
- for &bytes in samples.iter() {
- let m = OutboundOpaqueMessage::read(&mut Reader::init(bytes)).unwrap();
- println!("m = {m:?}");
- let m = Message::try_from(m.into_plain_message());
- println!("m' = {m:?}");
- }
-}
-
-#[test]
-fn debug_payload() {
- assert_eq!("01020304", format!("{:?}", Payload::new(vec![1, 2, 3, 4])));
- assert_eq!(
- "01020304",
- format!("{:?}", PayloadU8::<NonEmpty>::new(vec![1, 2, 3, 4]))
- );
- assert_eq!(
- "01020304",
- format!("{:?}", PayloadU16::<MaybeEmpty>::new(vec![1, 2, 3, 4]))
- );
- assert_eq!(
- "01020304",
- format!("{:?}", PayloadU24(Payload::new(vec![1, 2, 3, 4])))
- );
-}
-
-#[test]
-fn into_wire_format() {
- // Message::into_wire_bytes() include both message-level and handshake-level headers
- assert_eq!(
- Message::build_key_update_request().into_wire_bytes(),
- &[0x16, 0x3, 0x4, 0x0, 0x5, 0x18, 0x0, 0x0, 0x1, 0x1]
- );
-}
diff --git a/vendor/rustls/src/msgs/mod.rs b/vendor/rustls/src/msgs/mod.rs
deleted file mode 100644
index 270c2dbc..00000000
--- a/vendor/rustls/src/msgs/mod.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-#![allow(missing_docs)]
-//! <https://langsec.org> cat says:
-//!
-//! ```text
-//! ___ _ _ _ _ ___ ___ ___ ___ ___ _ _ ___ _____ ___ ___ _ _
-//! | __| | | | | | | | _ \ __/ __/ _ \ / __| \| |_ _|_ _|_ _/ _ \| \| |
-//! | _|| |_| | |__| |__ | / _| (_| (_) | (_ | .` || | | | | | (_) | .` |
-//! |_| \___/|____|____| |_|_\___\___\___/ \___|_|\_|___| |_| |___\___/|_|\_|
-//!
-//!
-//! .__....._ _.....__,
-//! .": o :': ;': o :".
-//! `. `-' .'. .'. `-' .'
-//! `---' `---'
-//!
-//! _...----... ... ... ...----..._
-//! .-'__..-""'---- `. `"` .' ----'""-..__`-.
-//! '.-' _.--"""' `-._.-' '"""--._ `-.`
-//! ' .-"' : `"-. `
-//! ' `. _.'"'._ .' `
-//! `. ,.-'" "'-., .'
-//! `. .'
-//! `-._ _.-'
-//! `"'--...___...--'"`
-//!
-//! ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ _ _ ___
-//! | _ ) __| __/ _ \| _ \ __| | _ \ _ \/ _ \ / __| __/ __/ __|_ _| \| |/ __|
-//! | _ \ _|| _| (_) | / _| | _/ / (_) | (__| _|\__ \__ \| || .` | (_ |
-//! |___/___|_| \___/|_|_\___| |_| |_|_\\___/ \___|___|___/___/___|_|\_|\___|
-//! ```
-//!
-//! <https://langsec.org/ForWantOfANail-h2hc2014.pdf>
-
-#[macro_use]
-mod macros;
-
-pub(crate) mod alert;
-pub(crate) mod base;
-pub(crate) mod ccs;
-pub(crate) mod codec;
-pub(crate) mod deframer;
-pub(crate) mod enums;
-pub(crate) mod fragmenter;
-pub(crate) mod handshake;
-pub(crate) mod message;
-pub(crate) mod persist;
-
-#[cfg(test)]
-mod handshake_test;
-
-pub mod ffdhe_groups;
-#[cfg(test)]
-mod message_test;
-
-#[cfg(test)]
-mod tests {
- use super::codec::Reader;
- use super::message::{Message, OutboundOpaqueMessage};
-
- #[test]
- fn smoketest() {
- let bytes = include_bytes!("../testdata/handshake-test.1.bin");
- let mut r = Reader::init(bytes);
-
- while r.any_left() {
- let m = OutboundOpaqueMessage::read(&mut r).unwrap();
-
- let out = m.clone().encode();
- assert!(!out.is_empty());
-
- Message::try_from(m.into_plain_message()).unwrap();
- }
- }
-}
diff --git a/vendor/rustls/src/msgs/persist.rs b/vendor/rustls/src/msgs/persist.rs
deleted file mode 100644
index 8231c8ff..00000000
--- a/vendor/rustls/src/msgs/persist.rs
+++ /dev/null
@@ -1,492 +0,0 @@
-use alloc::vec::Vec;
-use core::cmp;
-
-use pki_types::{DnsName, UnixTime};
-use zeroize::Zeroizing;
-
-use crate::client::ResolvesClientCert;
-use crate::enums::{CipherSuite, ProtocolVersion};
-use crate::error::InvalidMessage;
-use crate::msgs::base::{MaybeEmpty, PayloadU8, PayloadU16};
-use crate::msgs::codec::{Codec, Reader};
-#[cfg(feature = "tls12")]
-use crate::msgs::handshake::SessionId;
-use crate::msgs::handshake::{CertificateChain, ProtocolName};
-use crate::sync::{Arc, Weak};
-#[cfg(feature = "tls12")]
-use crate::tls12::Tls12CipherSuite;
-use crate::tls13::Tls13CipherSuite;
-use crate::verify::ServerCertVerifier;
-
-pub(crate) struct Retrieved<T> {
- pub(crate) value: T,
- retrieved_at: UnixTime,
-}
-
-impl<T> Retrieved<T> {
- pub(crate) fn new(value: T, retrieved_at: UnixTime) -> Self {
- Self {
- value,
- retrieved_at,
- }
- }
-
- pub(crate) fn map<M>(&self, f: impl FnOnce(&T) -> Option<&M>) -> Option<Retrieved<&M>> {
- Some(Retrieved {
- value: f(&self.value)?,
- retrieved_at: self.retrieved_at,
- })
- }
-}
-
-impl Retrieved<&Tls13ClientSessionValue> {
- pub(crate) fn obfuscated_ticket_age(&self) -> u32 {
- let age_secs = self
- .retrieved_at
- .as_secs()
- .saturating_sub(self.value.common.epoch);
- let age_millis = age_secs as u32 * 1000;
- age_millis.wrapping_add(self.value.age_add)
- }
-}
-
-impl<T: core::ops::Deref<Target = ClientSessionCommon>> Retrieved<T> {
- pub(crate) fn has_expired(&self) -> bool {
- let common = &*self.value;
- common.lifetime_secs != 0
- && common
- .epoch
- .saturating_add(u64::from(common.lifetime_secs))
- < self.retrieved_at.as_secs()
- }
-}
-
-impl<T> core::ops::Deref for Retrieved<T> {
- type Target = T;
-
- fn deref(&self) -> &Self::Target {
- &self.value
- }
-}
-
-#[derive(Debug)]
-pub struct Tls13ClientSessionValue {
- suite: &'static Tls13CipherSuite,
- age_add: u32,
- max_early_data_size: u32,
- pub(crate) common: ClientSessionCommon,
- quic_params: PayloadU16,
-}
-
-impl Tls13ClientSessionValue {
- pub(crate) fn new(
- suite: &'static Tls13CipherSuite,
- ticket: Arc<PayloadU16>,
- secret: &[u8],
- server_cert_chain: CertificateChain<'static>,
- server_cert_verifier: &Arc<dyn ServerCertVerifier>,
- client_creds: &Arc<dyn ResolvesClientCert>,
- time_now: UnixTime,
- lifetime_secs: u32,
- age_add: u32,
- max_early_data_size: u32,
- ) -> Self {
- Self {
- suite,
- age_add,
- max_early_data_size,
- common: ClientSessionCommon::new(
- ticket,
- secret,
- time_now,
- lifetime_secs,
- server_cert_chain,
- server_cert_verifier,
- client_creds,
- ),
- quic_params: PayloadU16::new(Vec::new()),
- }
- }
-
- pub fn max_early_data_size(&self) -> u32 {
- self.max_early_data_size
- }
-
- pub fn suite(&self) -> &'static Tls13CipherSuite {
- self.suite
- }
-
- #[doc(hidden)]
- /// Test only: rewind epoch by `delta` seconds.
- pub fn rewind_epoch(&mut self, delta: u32) {
- self.common.epoch -= delta as u64;
- }
-
- #[doc(hidden)]
- /// Test only: replace `max_early_data_size` with `new`
- pub fn _private_set_max_early_data_size(&mut self, new: u32) {
- self.max_early_data_size = new;
- }
-
- pub fn set_quic_params(&mut self, quic_params: &[u8]) {
- self.quic_params = PayloadU16::new(quic_params.to_vec());
- }
-
- pub fn quic_params(&self) -> Vec<u8> {
- self.quic_params.0.clone()
- }
-}
-
-impl core::ops::Deref for Tls13ClientSessionValue {
- type Target = ClientSessionCommon;
-
- fn deref(&self) -> &Self::Target {
- &self.common
- }
-}
-
-#[derive(Debug, Clone)]
-pub struct Tls12ClientSessionValue {
- #[cfg(feature = "tls12")]
- suite: &'static Tls12CipherSuite,
- #[cfg(feature = "tls12")]
- pub(crate) session_id: SessionId,
- #[cfg(feature = "tls12")]
- extended_ms: bool,
- #[doc(hidden)]
- #[cfg(feature = "tls12")]
- pub(crate) common: ClientSessionCommon,
-}
-
-#[cfg(feature = "tls12")]
-impl Tls12ClientSessionValue {
- pub(crate) fn new(
- suite: &'static Tls12CipherSuite,
- session_id: SessionId,
- ticket: Arc<PayloadU16>,
- master_secret: &[u8],
- server_cert_chain: CertificateChain<'static>,
- server_cert_verifier: &Arc<dyn ServerCertVerifier>,
- client_creds: &Arc<dyn ResolvesClientCert>,
- time_now: UnixTime,
- lifetime_secs: u32,
- extended_ms: bool,
- ) -> Self {
- Self {
- suite,
- session_id,
- extended_ms,
- common: ClientSessionCommon::new(
- ticket,
- master_secret,
- time_now,
- lifetime_secs,
- server_cert_chain,
- server_cert_verifier,
- client_creds,
- ),
- }
- }
-
- pub(crate) fn ticket(&mut self) -> Arc<PayloadU16> {
- self.common.ticket.clone()
- }
-
- pub(crate) fn extended_ms(&self) -> bool {
- self.extended_ms
- }
-
- pub(crate) fn suite(&self) -> &'static Tls12CipherSuite {
- self.suite
- }
-
- #[doc(hidden)]
- /// Test only: rewind epoch by `delta` seconds.
- pub fn rewind_epoch(&mut self, delta: u32) {
- self.common.epoch -= delta as u64;
- }
-}
-
-#[cfg(feature = "tls12")]
-impl core::ops::Deref for Tls12ClientSessionValue {
- type Target = ClientSessionCommon;
-
- fn deref(&self) -> &Self::Target {
- &self.common
- }
-}
-
-#[derive(Debug, Clone)]
-pub struct ClientSessionCommon {
- ticket: Arc<PayloadU16>,
- secret: Zeroizing<PayloadU8>,
- epoch: u64,
- lifetime_secs: u32,
- server_cert_chain: Arc<CertificateChain<'static>>,
- server_cert_verifier: Weak<dyn ServerCertVerifier>,
- client_creds: Weak<dyn ResolvesClientCert>,
-}
-
-impl ClientSessionCommon {
- fn new(
- ticket: Arc<PayloadU16>,
- secret: &[u8],
- time_now: UnixTime,
- lifetime_secs: u32,
- server_cert_chain: CertificateChain<'static>,
- server_cert_verifier: &Arc<dyn ServerCertVerifier>,
- client_creds: &Arc<dyn ResolvesClientCert>,
- ) -> Self {
- Self {
- ticket,
- secret: Zeroizing::new(PayloadU8::new(secret.to_vec())),
- epoch: time_now.as_secs(),
- lifetime_secs: cmp::min(lifetime_secs, MAX_TICKET_LIFETIME),
- server_cert_chain: Arc::new(server_cert_chain),
- server_cert_verifier: Arc::downgrade(server_cert_verifier),
- client_creds: Arc::downgrade(client_creds),
- }
- }
-
- pub(crate) fn compatible_config(
- &self,
- server_cert_verifier: &Arc<dyn ServerCertVerifier>,
- client_creds: &Arc<dyn ResolvesClientCert>,
- ) -> bool {
- let same_verifier = Weak::ptr_eq(
- &Arc::downgrade(server_cert_verifier),
- &self.server_cert_verifier,
- );
- let same_creds = Weak::ptr_eq(&Arc::downgrade(client_creds), &self.client_creds);
-
- match (same_verifier, same_creds) {
- (true, true) => true,
- (false, _) => {
- crate::log::trace!("resumption not allowed between different ServerCertVerifiers");
- false
- }
- (_, _) => {
- crate::log::trace!(
- "resumption not allowed between different ResolvesClientCert values"
- );
- false
- }
- }
- }
-
- pub(crate) fn server_cert_chain(&self) -> &CertificateChain<'static> {
- &self.server_cert_chain
- }
-
- pub(crate) fn secret(&self) -> &[u8] {
- self.secret.0.as_ref()
- }
-
- pub(crate) fn ticket(&self) -> &[u8] {
- self.ticket.0.as_ref()
- }
-}
-
-static MAX_TICKET_LIFETIME: u32 = 7 * 24 * 60 * 60;
-
-/// This is the maximum allowed skew between server and client clocks, over
-/// the maximum ticket lifetime period. This encompasses TCP retransmission
-/// times in case packet loss occurs when the client sends the ClientHello
-/// or receives the NewSessionTicket, _and_ actual clock skew over this period.
-static MAX_FRESHNESS_SKEW_MS: u32 = 60 * 1000;
-
-// --- Server types ---
-#[derive(Debug)]
-pub struct ServerSessionValue {
- pub(crate) sni: Option<DnsName<'static>>,
- pub(crate) version: ProtocolVersion,
- pub(crate) cipher_suite: CipherSuite,
- pub(crate) master_secret: Zeroizing<PayloadU8>,
- pub(crate) extended_ms: bool,
- pub(crate) client_cert_chain: Option<CertificateChain<'static>>,
- pub(crate) alpn: Option<PayloadU8>,
- pub(crate) application_data: PayloadU16,
- pub creation_time_sec: u64,
- pub(crate) age_obfuscation_offset: u32,
- freshness: Option<bool>,
-}
-
-impl Codec<'_> for ServerSessionValue {
- fn encode(&self, bytes: &mut Vec<u8>) {
- if let Some(sni) = &self.sni {
- 1u8.encode(bytes);
- let sni_bytes: &str = sni.as_ref();
- PayloadU8::<MaybeEmpty>::encode_slice(sni_bytes.as_bytes(), bytes);
- } else {
- 0u8.encode(bytes);
- }
- self.version.encode(bytes);
- self.cipher_suite.encode(bytes);
- self.master_secret.encode(bytes);
- (u8::from(self.extended_ms)).encode(bytes);
- if let Some(chain) = &self.client_cert_chain {
- 1u8.encode(bytes);
- chain.encode(bytes);
- } else {
- 0u8.encode(bytes);
- }
- if let Some(alpn) = &self.alpn {
- 1u8.encode(bytes);
- alpn.encode(bytes);
- } else {
- 0u8.encode(bytes);
- }
- self.application_data.encode(bytes);
- self.creation_time_sec.encode(bytes);
- self.age_obfuscation_offset
- .encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let has_sni = u8::read(r)?;
- let sni = if has_sni == 1 {
- let dns_name = PayloadU8::<MaybeEmpty>::read(r)?;
- let dns_name = match DnsName::try_from(dns_name.0.as_slice()) {
- Ok(dns_name) => dns_name.to_owned(),
- Err(_) => return Err(InvalidMessage::InvalidServerName),
- };
-
- Some(dns_name)
- } else {
- None
- };
-
- let v = ProtocolVersion::read(r)?;
- let cs = CipherSuite::read(r)?;
- let ms = Zeroizing::new(PayloadU8::read(r)?);
- let ems = u8::read(r)?;
- let has_ccert = u8::read(r)? == 1;
- let ccert = if has_ccert {
- Some(CertificateChain::read(r)?.into_owned())
- } else {
- None
- };
- let has_alpn = u8::read(r)? == 1;
- let alpn = if has_alpn {
- Some(PayloadU8::read(r)?)
- } else {
- None
- };
- let application_data = PayloadU16::read(r)?;
- let creation_time_sec = u64::read(r)?;
- let age_obfuscation_offset = u32::read(r)?;
-
- Ok(Self {
- sni,
- version: v,
- cipher_suite: cs,
- master_secret: ms,
- extended_ms: ems == 1u8,
- client_cert_chain: ccert,
- alpn,
- application_data,
- creation_time_sec,
- age_obfuscation_offset,
- freshness: None,
- })
- }
-}
-
-impl ServerSessionValue {
- pub(crate) fn new(
- sni: Option<&DnsName<'_>>,
- v: ProtocolVersion,
- cs: CipherSuite,
- ms: &[u8],
- client_cert_chain: Option<CertificateChain<'static>>,
- alpn: Option<ProtocolName>,
- application_data: Vec<u8>,
- creation_time: UnixTime,
- age_obfuscation_offset: u32,
- ) -> Self {
- Self {
- sni: sni.map(|dns| dns.to_owned()),
- version: v,
- cipher_suite: cs,
- master_secret: Zeroizing::new(PayloadU8::new(ms.to_vec())),
- extended_ms: false,
- client_cert_chain,
- alpn: alpn.map(|p| PayloadU8::new(p.as_ref().to_vec())),
- application_data: PayloadU16::new(application_data),
- creation_time_sec: creation_time.as_secs(),
- age_obfuscation_offset,
- freshness: None,
- }
- }
-
- #[cfg(feature = "tls12")]
- pub(crate) fn set_extended_ms_used(&mut self) {
- self.extended_ms = true;
- }
-
- pub(crate) fn set_freshness(
- mut self,
- obfuscated_client_age_ms: u32,
- time_now: UnixTime,
- ) -> Self {
- let client_age_ms = obfuscated_client_age_ms.wrapping_sub(self.age_obfuscation_offset);
- let server_age_ms = (time_now
- .as_secs()
- .saturating_sub(self.creation_time_sec) as u32)
- .saturating_mul(1000);
-
- let age_difference = server_age_ms.abs_diff(client_age_ms);
-
- self.freshness = Some(age_difference <= MAX_FRESHNESS_SKEW_MS);
- self
- }
-
- pub(crate) fn is_fresh(&self) -> bool {
- self.freshness.unwrap_or_default()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[cfg(feature = "std")] // for UnixTime::now
- #[test]
- fn serversessionvalue_is_debug() {
- use std::{println, vec};
- let ssv = ServerSessionValue::new(
- None,
- ProtocolVersion::TLSv1_3,
- CipherSuite::TLS13_AES_128_GCM_SHA256,
- &[1, 2, 3],
- None,
- None,
- vec![4, 5, 6],
- UnixTime::now(),
- 0x12345678,
- );
- println!("{ssv:?}");
- }
-
- #[test]
- fn serversessionvalue_no_sni() {
- let bytes = [
- 0x00, 0x03, 0x03, 0xc0, 0x23, 0x03, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, 0xfe, 0xed, 0xf0, 0x0d,
- ];
- let mut rd = Reader::init(&bytes);
- let ssv = ServerSessionValue::read(&mut rd).unwrap();
- assert_eq!(ssv.get_encoding(), bytes);
- }
-
- #[test]
- fn serversessionvalue_with_cert() {
- let bytes = [
- 0x00, 0x03, 0x03, 0xc0, 0x23, 0x03, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, 0xfe, 0xed, 0xf0, 0x0d,
- ];
- let mut rd = Reader::init(&bytes);
- let ssv = ServerSessionValue::read(&mut rd).unwrap();
- assert_eq!(ssv.get_encoding(), bytes);
- }
-}
diff --git a/vendor/rustls/src/polyfill.rs b/vendor/rustls/src/polyfill.rs
deleted file mode 100644
index 82571a22..00000000
--- a/vendor/rustls/src/polyfill.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-/// Non-panicking `let (nonce, ciphertext) = ciphertext.split_at(...)`.
-// TODO(XXX): remove once MSRV reaches 1.80
-#[allow(dead_code)] // Complicated conditional compilation guards elided
-pub(crate) fn try_split_at(slice: &[u8], mid: usize) -> Option<(&[u8], &[u8])> {
- match mid > slice.len() {
- true => None,
- false => Some(slice.split_at(mid)),
- }
-}
diff --git a/vendor/rustls/src/quic.rs b/vendor/rustls/src/quic.rs
deleted file mode 100644
index f00f3bba..00000000
--- a/vendor/rustls/src/quic.rs
+++ /dev/null
@@ -1,1022 +0,0 @@
-use alloc::boxed::Box;
-use alloc::collections::VecDeque;
-use alloc::vec::Vec;
-#[cfg(feature = "std")]
-use core::fmt::Debug;
-
-/// This module contains optional APIs for implementing QUIC TLS.
-use crate::common_state::Side;
-use crate::crypto::cipher::{AeadKey, Iv};
-use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock};
-use crate::enums::AlertDescription;
-use crate::error::Error;
-use crate::tls13::Tls13CipherSuite;
-use crate::tls13::key_schedule::{
- hkdf_expand_label, hkdf_expand_label_aead_key, hkdf_expand_label_block,
-};
-
-#[cfg(feature = "std")]
-mod connection {
- use alloc::vec::Vec;
- use core::fmt::{self, Debug};
- use core::ops::{Deref, DerefMut};
-
- use pki_types::ServerName;
-
- use super::{DirectionalKeys, KeyChange, Version};
- use crate::client::{ClientConfig, ClientConnectionData};
- use crate::common_state::{CommonState, DEFAULT_BUFFER_LIMIT, Protocol};
- use crate::conn::{ConnectionCore, SideData};
- use crate::enums::{AlertDescription, ContentType, ProtocolVersion};
- use crate::error::Error;
- use crate::msgs::base::Payload;
- use crate::msgs::deframer::buffers::{DeframerVecBuffer, Locator};
- use crate::msgs::handshake::{
- ClientExtensionsInput, ServerExtensionsInput, TransportParameters,
- };
- use crate::msgs::message::InboundPlainMessage;
- use crate::server::{ServerConfig, ServerConnectionData};
- use crate::sync::Arc;
- use crate::vecbuf::ChunkVecBuffer;
-
- /// A QUIC client or server connection.
- #[derive(Debug)]
- pub enum Connection {
- /// A client connection
- Client(ClientConnection),
- /// A server connection
- Server(ServerConnection),
- }
-
- impl Connection {
- /// Return the TLS-encoded transport parameters for the session's peer.
- ///
- /// See [`ConnectionCommon::quic_transport_parameters()`] for more details.
- pub fn quic_transport_parameters(&self) -> Option<&[u8]> {
- match self {
- Self::Client(conn) => conn.quic_transport_parameters(),
- Self::Server(conn) => conn.quic_transport_parameters(),
- }
- }
-
- /// Compute the keys for encrypting/decrypting 0-RTT packets, if available
- pub fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
- match self {
- Self::Client(conn) => conn.zero_rtt_keys(),
- Self::Server(conn) => conn.zero_rtt_keys(),
- }
- }
-
- /// Consume unencrypted TLS handshake data.
- ///
- /// Handshake data obtained from separate encryption levels should be supplied in separate calls.
- pub fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), Error> {
- match self {
- Self::Client(conn) => conn.read_hs(plaintext),
- Self::Server(conn) => conn.read_hs(plaintext),
- }
- }
-
- /// Emit unencrypted TLS handshake data.
- ///
- /// When this returns `Some(_)`, the new keys must be used for future handshake data.
- pub fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> {
- match self {
- Self::Client(conn) => conn.write_hs(buf),
- Self::Server(conn) => conn.write_hs(buf),
- }
- }
-
- /// Emit the TLS description code of a fatal alert, if one has arisen.
- ///
- /// Check after `read_hs` returns `Err(_)`.
- pub fn alert(&self) -> Option<AlertDescription> {
- match self {
- Self::Client(conn) => conn.alert(),
- Self::Server(conn) => conn.alert(),
- }
- }
-
- /// Derives key material from the agreed connection secrets.
- ///
- /// This function fills in `output` with `output.len()` bytes of key
- /// material derived from the master session secret using `label`
- /// and `context` for diversification. Ownership of the buffer is taken
- /// by the function and returned via the Ok result to ensure no key
- /// material leaks if the function fails.
- ///
- /// See RFC5705 for more details on what this does and is for.
- ///
- /// For TLS1.3 connections, this function does not use the
- /// "early" exporter at any point.
- ///
- /// This function fails if called prior to the handshake completing;
- /// check with [`CommonState::is_handshaking`] first.
- #[inline]
- pub fn export_keying_material<T: AsMut<[u8]>>(
- &self,
- output: T,
- label: &[u8],
- context: Option<&[u8]>,
- ) -> Result<T, Error> {
- match self {
- Self::Client(conn) => conn
- .core
- .export_keying_material(output, label, context),
- Self::Server(conn) => conn
- .core
- .export_keying_material(output, label, context),
- }
- }
- }
-
- impl Deref for Connection {
- type Target = CommonState;
-
- fn deref(&self) -> &Self::Target {
- match self {
- Self::Client(conn) => &conn.core.common_state,
- Self::Server(conn) => &conn.core.common_state,
- }
- }
- }
-
- impl DerefMut for Connection {
- fn deref_mut(&mut self) -> &mut Self::Target {
- match self {
- Self::Client(conn) => &mut conn.core.common_state,
- Self::Server(conn) => &mut conn.core.common_state,
- }
- }
- }
-
- /// A QUIC client connection.
- pub struct ClientConnection {
- inner: ConnectionCommon<ClientConnectionData>,
- }
-
- impl ClientConnection {
- /// Make a new QUIC ClientConnection.
- ///
- /// This differs from `ClientConnection::new()` in that it takes an extra `params` argument,
- /// which contains the TLS-encoded transport parameters to send.
- pub fn new(
- config: Arc<ClientConfig>,
- quic_version: Version,
- name: ServerName<'static>,
- params: Vec<u8>,
- ) -> Result<Self, Error> {
- Self::new_with_alpn(
- config.clone(),
- quic_version,
- name,
- params,
- config.alpn_protocols.clone(),
- )
- }
-
- /// Make a new QUIC ClientConnection with custom ALPN protocols.
- pub fn new_with_alpn(
- config: Arc<ClientConfig>,
- quic_version: Version,
- name: ServerName<'static>,
- params: Vec<u8>,
- alpn_protocols: Vec<Vec<u8>>,
- ) -> Result<Self, Error> {
- if !config.supports_version(ProtocolVersion::TLSv1_3) {
- return Err(Error::General(
- "TLS 1.3 support is required for QUIC".into(),
- ));
- }
-
- if !config.supports_protocol(Protocol::Quic) {
- return Err(Error::General(
- "at least one ciphersuite must support QUIC".into(),
- ));
- }
-
- let exts = ClientExtensionsInput {
- transport_parameters: Some(match quic_version {
- Version::V1Draft => TransportParameters::QuicDraft(Payload::new(params)),
- Version::V1 | Version::V2 => TransportParameters::Quic(Payload::new(params)),
- }),
-
- ..ClientExtensionsInput::from_alpn(alpn_protocols)
- };
-
- let mut inner = ConnectionCore::for_client(config, name, exts, Protocol::Quic)?;
- inner.common_state.quic.version = quic_version;
- Ok(Self {
- inner: inner.into(),
- })
- }
-
- /// Returns True if the server signalled it will process early data.
- ///
- /// If you sent early data and this returns false at the end of the
- /// handshake then the server will not process the data. This
- /// is not an error, but you may wish to resend the data.
- pub fn is_early_data_accepted(&self) -> bool {
- self.inner.core.is_early_data_accepted()
- }
-
- /// Returns the number of TLS1.3 tickets that have been received.
- pub fn tls13_tickets_received(&self) -> u32 {
- self.inner.tls13_tickets_received
- }
- }
-
- impl Deref for ClientConnection {
- type Target = ConnectionCommon<ClientConnectionData>;
-
- fn deref(&self) -> &Self::Target {
- &self.inner
- }
- }
-
- impl DerefMut for ClientConnection {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.inner
- }
- }
-
- impl Debug for ClientConnection {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("quic::ClientConnection")
- .finish()
- }
- }
-
- impl From<ClientConnection> for Connection {
- fn from(c: ClientConnection) -> Self {
- Self::Client(c)
- }
- }
-
- /// A QUIC server connection.
- pub struct ServerConnection {
- inner: ConnectionCommon<ServerConnectionData>,
- }
-
- impl ServerConnection {
- /// Make a new QUIC ServerConnection.
- ///
- /// This differs from `ServerConnection::new()` in that it takes an extra `params` argument,
- /// which contains the TLS-encoded transport parameters to send.
- pub fn new(
- config: Arc<ServerConfig>,
- quic_version: Version,
- params: Vec<u8>,
- ) -> Result<Self, Error> {
- if !config.supports_version(ProtocolVersion::TLSv1_3) {
- return Err(Error::General(
- "TLS 1.3 support is required for QUIC".into(),
- ));
- }
-
- if !config.supports_protocol(Protocol::Quic) {
- return Err(Error::General(
- "at least one ciphersuite must support QUIC".into(),
- ));
- }
-
- if config.max_early_data_size != 0 && config.max_early_data_size != 0xffff_ffff {
- return Err(Error::General(
- "QUIC sessions must set a max early data of 0 or 2^32-1".into(),
- ));
- }
-
- let exts = ServerExtensionsInput {
- transport_parameters: Some(match quic_version {
- Version::V1Draft => TransportParameters::QuicDraft(Payload::new(params)),
- Version::V1 | Version::V2 => TransportParameters::Quic(Payload::new(params)),
- }),
- };
-
- let mut core = ConnectionCore::for_server(config, exts)?;
- core.common_state.protocol = Protocol::Quic;
- core.common_state.quic.version = quic_version;
- Ok(Self { inner: core.into() })
- }
-
- /// Explicitly discard early data, notifying the client
- ///
- /// Useful if invariants encoded in `received_resumption_data()` cannot be respected.
- ///
- /// Must be called while `is_handshaking` is true.
- pub fn reject_early_data(&mut self) {
- self.inner.core.reject_early_data()
- }
-
- /// Retrieves the server name, if any, used to select the certificate and
- /// private key.
- ///
- /// This returns `None` until some time after the client's server name indication
- /// (SNI) extension value is processed during the handshake. It will never be
- /// `None` when the connection is ready to send or process application data,
- /// unless the client does not support SNI.
- ///
- /// This is useful for application protocols that need to enforce that the
- /// server name matches an application layer protocol hostname. For
- /// example, HTTP/1.1 servers commonly expect the `Host:` header field of
- /// every request on a connection to match the hostname in the SNI extension
- /// when the client provides the SNI extension.
- ///
- /// The server name is also used to match sessions during session resumption.
- pub fn server_name(&self) -> Option<&str> {
- self.inner.core.get_sni_str()
- }
- }
-
- impl Deref for ServerConnection {
- type Target = ConnectionCommon<ServerConnectionData>;
-
- fn deref(&self) -> &Self::Target {
- &self.inner
- }
- }
-
- impl DerefMut for ServerConnection {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.inner
- }
- }
-
- impl Debug for ServerConnection {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("quic::ServerConnection")
- .finish()
- }
- }
-
- impl From<ServerConnection> for Connection {
- fn from(c: ServerConnection) -> Self {
- Self::Server(c)
- }
- }
-
- /// A shared interface for QUIC connections.
- pub struct ConnectionCommon<Data> {
- core: ConnectionCore<Data>,
- deframer_buffer: DeframerVecBuffer,
- sendable_plaintext: ChunkVecBuffer,
- }
-
- impl<Data: SideData> ConnectionCommon<Data> {
- /// Return the TLS-encoded transport parameters for the session's peer.
- ///
- /// While the transport parameters are technically available prior to the
- /// completion of the handshake, they cannot be fully trusted until the
- /// handshake completes, and reliance on them should be minimized.
- /// However, any tampering with the parameters will cause the handshake
- /// to fail.
- pub fn quic_transport_parameters(&self) -> Option<&[u8]> {
- self.core
- .common_state
- .quic
- .params
- .as_ref()
- .map(|v| v.as_ref())
- }
-
- /// Compute the keys for encrypting/decrypting 0-RTT packets, if available
- pub fn zero_rtt_keys(&self) -> Option<DirectionalKeys> {
- let suite = self
- .core
- .common_state
- .suite
- .and_then(|suite| suite.tls13())?;
- Some(DirectionalKeys::new(
- suite,
- suite.quic?,
- self.core
- .common_state
- .quic
- .early_secret
- .as_ref()?,
- self.core.common_state.quic.version,
- ))
- }
-
- /// Consume unencrypted TLS handshake data.
- ///
- /// Handshake data obtained from separate encryption levels should be supplied in separate calls.
- pub fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), Error> {
- let range = self.deframer_buffer.extend(plaintext);
-
- self.core.hs_deframer.input_message(
- InboundPlainMessage {
- typ: ContentType::Handshake,
- version: ProtocolVersion::TLSv1_3,
- payload: &self.deframer_buffer.filled()[range.clone()],
- },
- &Locator::new(self.deframer_buffer.filled()),
- range.end,
- );
-
- self.core
- .hs_deframer
- .coalesce(self.deframer_buffer.filled_mut())?;
-
- self.core
- .process_new_packets(&mut self.deframer_buffer, &mut self.sendable_plaintext)?;
-
- Ok(())
- }
-
- /// Emit unencrypted TLS handshake data.
- ///
- /// When this returns `Some(_)`, the new keys must be used for future handshake data.
- pub fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> {
- self.core
- .common_state
- .quic
- .write_hs(buf)
- }
-
- /// Emit the TLS description code of a fatal alert, if one has arisen.
- ///
- /// Check after `read_hs` returns `Err(_)`.
- pub fn alert(&self) -> Option<AlertDescription> {
- self.core.common_state.quic.alert
- }
- }
-
- impl<Data> Deref for ConnectionCommon<Data> {
- type Target = CommonState;
-
- fn deref(&self) -> &Self::Target {
- &self.core.common_state
- }
- }
-
- impl<Data> DerefMut for ConnectionCommon<Data> {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.core.common_state
- }
- }
-
- impl<Data> From<ConnectionCore<Data>> for ConnectionCommon<Data> {
- fn from(core: ConnectionCore<Data>) -> Self {
- Self {
- core,
- deframer_buffer: DeframerVecBuffer::default(),
- sendable_plaintext: ChunkVecBuffer::new(Some(DEFAULT_BUFFER_LIMIT)),
- }
- }
- }
-}
-
-#[cfg(feature = "std")]
-pub use connection::{ClientConnection, Connection, ConnectionCommon, ServerConnection};
-
-#[derive(Default)]
-pub(crate) struct Quic {
- /// QUIC transport parameters received from the peer during the handshake
- pub(crate) params: Option<Vec<u8>>,
- pub(crate) alert: Option<AlertDescription>,
- pub(crate) hs_queue: VecDeque<(bool, Vec<u8>)>,
- pub(crate) early_secret: Option<OkmBlock>,
- pub(crate) hs_secrets: Option<Secrets>,
- pub(crate) traffic_secrets: Option<Secrets>,
- /// Whether keys derived from traffic_secrets have been passed to the QUIC implementation
- #[cfg(feature = "std")]
- pub(crate) returned_traffic_keys: bool,
- pub(crate) version: Version,
-}
-
-#[cfg(feature = "std")]
-impl Quic {
- pub(crate) fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<KeyChange> {
- while let Some((_, msg)) = self.hs_queue.pop_front() {
- buf.extend_from_slice(&msg);
- if let Some(&(true, _)) = self.hs_queue.front() {
- if self.hs_secrets.is_some() {
- // Allow the caller to switch keys before proceeding.
- break;
- }
- }
- }
-
- if let Some(secrets) = self.hs_secrets.take() {
- return Some(KeyChange::Handshake {
- keys: Keys::new(&secrets),
- });
- }
-
- if let Some(mut secrets) = self.traffic_secrets.take() {
- if !self.returned_traffic_keys {
- self.returned_traffic_keys = true;
- let keys = Keys::new(&secrets);
- secrets.update();
- return Some(KeyChange::OneRtt {
- keys,
- next: secrets,
- });
- }
- }
-
- None
- }
-}
-
-/// Secrets used to encrypt/decrypt traffic
-#[derive(Clone)]
-pub struct Secrets {
- /// Secret used to encrypt packets transmitted by the client
- pub(crate) client: OkmBlock,
- /// Secret used to encrypt packets transmitted by the server
- pub(crate) server: OkmBlock,
- /// Cipher suite used with these secrets
- suite: &'static Tls13CipherSuite,
- quic: &'static dyn Algorithm,
- side: Side,
- version: Version,
-}
-
-impl Secrets {
- pub(crate) fn new(
- client: OkmBlock,
- server: OkmBlock,
- suite: &'static Tls13CipherSuite,
- quic: &'static dyn Algorithm,
- side: Side,
- version: Version,
- ) -> Self {
- Self {
- client,
- server,
- suite,
- quic,
- side,
- version,
- }
- }
-
- /// Derive the next set of packet keys
- pub fn next_packet_keys(&mut self) -> PacketKeySet {
- let keys = PacketKeySet::new(self);
- self.update();
- keys
- }
-
- pub(crate) fn update(&mut self) {
- self.client = hkdf_expand_label_block(
- self.suite
- .hkdf_provider
- .expander_for_okm(&self.client)
- .as_ref(),
- self.version.key_update_label(),
- &[],
- );
- self.server = hkdf_expand_label_block(
- self.suite
- .hkdf_provider
- .expander_for_okm(&self.server)
- .as_ref(),
- self.version.key_update_label(),
- &[],
- );
- }
-
- fn local_remote(&self) -> (&OkmBlock, &OkmBlock) {
- match self.side {
- Side::Client => (&self.client, &self.server),
- Side::Server => (&self.server, &self.client),
- }
- }
-}
-
-/// Keys used to communicate in a single direction
-pub struct DirectionalKeys {
- /// Encrypts or decrypts a packet's headers
- pub header: Box<dyn HeaderProtectionKey>,
- /// Encrypts or decrypts the payload of a packet
- pub packet: Box<dyn PacketKey>,
-}
-
-impl DirectionalKeys {
- pub(crate) fn new(
- suite: &'static Tls13CipherSuite,
- quic: &'static dyn Algorithm,
- secret: &OkmBlock,
- version: Version,
- ) -> Self {
- let builder = KeyBuilder::new(secret, version, quic, suite.hkdf_provider);
- Self {
- header: builder.header_protection_key(),
- packet: builder.packet_key(),
- }
- }
-}
-
-/// All AEADs we support have 16-byte tags.
-const TAG_LEN: usize = 16;
-
-/// Authentication tag from an AEAD seal operation.
-pub struct Tag([u8; TAG_LEN]);
-
-impl From<&[u8]> for Tag {
- fn from(value: &[u8]) -> Self {
- let mut array = [0u8; TAG_LEN];
- array.copy_from_slice(value);
- Self(array)
- }
-}
-
-impl AsRef<[u8]> for Tag {
- fn as_ref(&self) -> &[u8] {
- &self.0
- }
-}
-
-/// How a `Tls13CipherSuite` generates `PacketKey`s and `HeaderProtectionKey`s.
-pub trait Algorithm: Send + Sync {
- /// Produce a `PacketKey` encrypter/decrypter for this suite.
- ///
- /// `suite` is the entire suite this `Algorithm` appeared in.
- /// `key` and `iv` is the key material to use.
- fn packet_key(&self, key: AeadKey, iv: Iv) -> Box<dyn PacketKey>;
-
- /// Produce a `HeaderProtectionKey` encrypter/decrypter for this suite.
- ///
- /// `key` is the key material, which is `aead_key_len()` bytes in length.
- fn header_protection_key(&self, key: AeadKey) -> Box<dyn HeaderProtectionKey>;
-
- /// The length in bytes of keys for this Algorithm.
- ///
- /// This controls the size of `AeadKey`s presented to `packet_key()` and `header_protection_key()`.
- fn aead_key_len(&self) -> usize;
-
- /// Whether this algorithm is FIPS-approved.
- fn fips(&self) -> bool {
- false
- }
-}
-
-/// A QUIC header protection key
-pub trait HeaderProtectionKey: Send + Sync {
- /// Adds QUIC Header Protection.
- ///
- /// `sample` must contain the sample of encrypted payload; see
- /// [Header Protection Sample].
- ///
- /// `first` must reference the first byte of the header, referred to as
- /// `packet[0]` in [Header Protection Application].
- ///
- /// `packet_number` must reference the Packet Number field; this is
- /// `packet[pn_offset:pn_offset+pn_length]` in [Header Protection Application].
- ///
- /// Returns an error without modifying anything if `sample` is not
- /// the correct length (see [Header Protection Sample] and [`Self::sample_len()`]),
- /// or `packet_number` is longer than allowed (see [Packet Number Encoding and Decoding]).
- ///
- /// Otherwise, `first` and `packet_number` will have the header protection added.
- ///
- /// [Header Protection Application]: https://datatracker.ietf.org/doc/html/rfc9001#section-5.4.1
- /// [Header Protection Sample]: https://datatracker.ietf.org/doc/html/rfc9001#section-5.4.2
- /// [Packet Number Encoding and Decoding]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.1
- fn encrypt_in_place(
- &self,
- sample: &[u8],
- first: &mut u8,
- packet_number: &mut [u8],
- ) -> Result<(), Error>;
-
- /// Removes QUIC Header Protection.
- ///
- /// `sample` must contain the sample of encrypted payload; see
- /// [Header Protection Sample].
- ///
- /// `first` must reference the first byte of the header, referred to as
- /// `packet[0]` in [Header Protection Application].
- ///
- /// `packet_number` must reference the Packet Number field; this is
- /// `packet[pn_offset:pn_offset+pn_length]` in [Header Protection Application].
- ///
- /// Returns an error without modifying anything if `sample` is not
- /// the correct length (see [Header Protection Sample] and [`Self::sample_len()`]),
- /// or `packet_number` is longer than allowed (see
- /// [Packet Number Encoding and Decoding]).
- ///
- /// Otherwise, `first` and `packet_number` will have the header protection removed.
- ///
- /// [Header Protection Application]: https://datatracker.ietf.org/doc/html/rfc9001#section-5.4.1
- /// [Header Protection Sample]: https://datatracker.ietf.org/doc/html/rfc9001#section-5.4.2
- /// [Packet Number Encoding and Decoding]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.1
- fn decrypt_in_place(
- &self,
- sample: &[u8],
- first: &mut u8,
- packet_number: &mut [u8],
- ) -> Result<(), Error>;
-
- /// Expected sample length for the key's algorithm
- fn sample_len(&self) -> usize;
-}
-
-/// Keys to encrypt or decrypt the payload of a packet
-pub trait PacketKey: Send + Sync {
- /// Encrypt a QUIC packet
- ///
- /// Takes a `packet_number`, used to derive the nonce; the packet `header`, which is used as
- /// the additional authenticated data; and the `payload`. The authentication tag is returned if
- /// encryption succeeds.
- ///
- /// Fails if and only if the payload is longer than allowed by the cipher suite's AEAD algorithm.
- fn encrypt_in_place(
- &self,
- packet_number: u64,
- header: &[u8],
- payload: &mut [u8],
- ) -> Result<Tag, Error>;
-
- /// 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,
- header: &[u8],
- payload: &'a mut [u8],
- ) -> Result<&'a [u8], Error>;
-
- /// Tag length for the underlying AEAD algorithm
- fn tag_len(&self) -> usize;
-
- /// Number of QUIC messages that can be safely encrypted with a single key of this type.
- ///
- /// Once a `MessageEncrypter` produced for this suite has encrypted more than
- /// `confidentiality_limit` messages, an attacker gains an advantage in distinguishing it
- /// from an ideal pseudorandom permutation (PRP).
- ///
- /// This is to be set on the assumption that messages are maximally sized --
- /// 2 ** 16. For non-QUIC TCP connections see [`CipherSuiteCommon::confidentiality_limit`][csc-limit].
- ///
- /// [csc-limit]: crate::crypto::CipherSuiteCommon::confidentiality_limit
- fn confidentiality_limit(&self) -> u64;
-
- /// Number of QUIC messages that can be safely decrypted with a single key of this type
- ///
- /// Once a `MessageDecrypter` produced for this suite has failed to decrypt `integrity_limit`
- /// messages, an attacker gains an advantage in forging messages.
- ///
- /// This is not relevant for TLS over TCP (which is also implemented in this crate)
- /// because a single failed decryption is fatal to the connection.
- /// However, this quantity is used by QUIC.
- fn integrity_limit(&self) -> u64;
-}
-
-/// Packet protection keys for bidirectional 1-RTT communication
-pub struct PacketKeySet {
- /// Encrypts outgoing packets
- pub local: Box<dyn PacketKey>,
- /// Decrypts incoming packets
- pub remote: Box<dyn PacketKey>,
-}
-
-impl PacketKeySet {
- fn new(secrets: &Secrets) -> Self {
- let (local, remote) = secrets.local_remote();
- let (version, alg, hkdf) = (secrets.version, secrets.quic, secrets.suite.hkdf_provider);
- Self {
- local: KeyBuilder::new(local, version, alg, hkdf).packet_key(),
- remote: KeyBuilder::new(remote, version, alg, hkdf).packet_key(),
- }
- }
-}
-
-pub(crate) struct KeyBuilder<'a> {
- expander: Box<dyn HkdfExpander>,
- version: Version,
- alg: &'a dyn Algorithm,
-}
-
-impl<'a> KeyBuilder<'a> {
- pub(crate) fn new(
- secret: &OkmBlock,
- version: Version,
- alg: &'a dyn Algorithm,
- hkdf: &'a dyn Hkdf,
- ) -> Self {
- Self {
- expander: hkdf.expander_for_okm(secret),
- version,
- alg,
- }
- }
-
- /// Derive packet keys
- pub(crate) fn packet_key(&self) -> Box<dyn PacketKey> {
- let aead_key_len = self.alg.aead_key_len();
- let packet_key = hkdf_expand_label_aead_key(
- self.expander.as_ref(),
- aead_key_len,
- self.version.packet_key_label(),
- &[],
- );
-
- let packet_iv =
- hkdf_expand_label(self.expander.as_ref(), self.version.packet_iv_label(), &[]);
- self.alg
- .packet_key(packet_key, packet_iv)
- }
-
- /// Derive header protection keys
- pub(crate) fn header_protection_key(&self) -> Box<dyn HeaderProtectionKey> {
- let header_key = hkdf_expand_label_aead_key(
- self.expander.as_ref(),
- self.alg.aead_key_len(),
- self.version.header_key_label(),
- &[],
- );
- self.alg
- .header_protection_key(header_key)
- }
-}
-
-/// Produces QUIC initial keys from a TLS 1.3 ciphersuite and a QUIC key generation algorithm.
-#[derive(Clone, Copy)]
-pub struct Suite {
- /// The TLS 1.3 ciphersuite used to derive keys.
- pub suite: &'static Tls13CipherSuite,
- /// The QUIC key generation algorithm used to derive keys.
- pub quic: &'static dyn Algorithm,
-}
-
-impl Suite {
- /// Produce a set of initial keys given the connection ID, side and version
- pub fn keys(&self, client_dst_connection_id: &[u8], side: Side, version: Version) -> Keys {
- Keys::initial(
- version,
- self.suite,
- self.quic,
- client_dst_connection_id,
- side,
- )
- }
-}
-
-/// Complete set of keys used to communicate with the peer
-pub struct Keys {
- /// Encrypts outgoing packets
- pub local: DirectionalKeys,
- /// Decrypts incoming packets
- pub remote: DirectionalKeys,
-}
-
-impl Keys {
- /// Construct keys for use with initial packets
- pub fn initial(
- version: Version,
- suite: &'static Tls13CipherSuite,
- quic: &'static dyn Algorithm,
- client_dst_connection_id: &[u8],
- side: Side,
- ) -> Self {
- const CLIENT_LABEL: &[u8] = b"client in";
- const SERVER_LABEL: &[u8] = b"server in";
- let salt = version.initial_salt();
- let hs_secret = suite
- .hkdf_provider
- .extract_from_secret(Some(salt), client_dst_connection_id);
-
- let secrets = Secrets {
- version,
- client: hkdf_expand_label_block(hs_secret.as_ref(), CLIENT_LABEL, &[]),
- server: hkdf_expand_label_block(hs_secret.as_ref(), SERVER_LABEL, &[]),
- suite,
- quic,
- side,
- };
- Self::new(&secrets)
- }
-
- fn new(secrets: &Secrets) -> Self {
- let (local, remote) = secrets.local_remote();
- Self {
- local: DirectionalKeys::new(secrets.suite, secrets.quic, local, secrets.version),
- remote: DirectionalKeys::new(secrets.suite, secrets.quic, remote, secrets.version),
- }
- }
-}
-
-/// Key material for use in QUIC packet spaces
-///
-/// QUIC uses 4 different sets of keys (and progressive key updates for long-running connections):
-///
-/// * Initial: these can be created from [`Keys::initial()`]
-/// * 0-RTT keys: can be retrieved from [`ConnectionCommon::zero_rtt_keys()`]
-/// * Handshake: these are returned from [`ConnectionCommon::write_hs()`] after `ClientHello` and
-/// `ServerHello` messages have been exchanged
-/// * 1-RTT keys: these are returned from [`ConnectionCommon::write_hs()`] after the handshake is done
-///
-/// Once the 1-RTT keys have been exchanged, either side may initiate a key update. Progressive
-/// update keys can be obtained from the [`Secrets`] returned in [`KeyChange::OneRtt`]. Note that
-/// only packet keys are updated by key updates; header protection keys remain the same.
-pub enum KeyChange {
- /// Keys for the handshake space
- Handshake {
- /// Header and packet keys for the handshake space
- keys: Keys,
- },
- /// Keys for 1-RTT data
- OneRtt {
- /// Header and packet keys for 1-RTT data
- keys: Keys,
- /// Secrets to derive updated keys from
- next: Secrets,
- },
-}
-
-/// QUIC protocol version
-///
-/// Governs version-specific behavior in the TLS layer
-#[non_exhaustive]
-#[derive(Clone, Copy, Debug)]
-pub enum Version {
- /// Draft versions 29, 30, 31 and 32
- V1Draft,
- /// First stable RFC
- V1,
- /// Anti-ossification variant of V1
- V2,
-}
-
-impl Version {
- fn initial_salt(self) -> &'static [u8; 20] {
- match self {
- Self::V1Draft => &[
- // https://datatracker.ietf.org/doc/html/draft-ietf-quic-tls-32#section-5.2
- 0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c, 0x9e, 0x97, 0x86, 0xf1, 0x9c, 0x61,
- 0x11, 0xe0, 0x43, 0x90, 0xa8, 0x99,
- ],
- Self::V1 => &[
- // https://www.rfc-editor.org/rfc/rfc9001.html#name-initial-secrets
- 0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8,
- 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a,
- ],
- Self::V2 => &[
- // https://www.ietf.org/archive/id/draft-ietf-quic-v2-10.html#name-initial-salt-2
- 0x0d, 0xed, 0xe3, 0xde, 0xf7, 0x00, 0xa6, 0xdb, 0x81, 0x93, 0x81, 0xbe, 0x6e, 0x26,
- 0x9d, 0xcb, 0xf9, 0xbd, 0x2e, 0xd9,
- ],
- }
- }
-
- /// Key derivation label for packet keys.
- pub(crate) fn packet_key_label(&self) -> &'static [u8] {
- match self {
- Self::V1Draft | Self::V1 => b"quic key",
- Self::V2 => b"quicv2 key",
- }
- }
-
- /// Key derivation label for packet "IV"s.
- pub(crate) fn packet_iv_label(&self) -> &'static [u8] {
- match self {
- Self::V1Draft | Self::V1 => b"quic iv",
- Self::V2 => b"quicv2 iv",
- }
- }
-
- /// Key derivation for header keys.
- pub(crate) fn header_key_label(&self) -> &'static [u8] {
- match self {
- Self::V1Draft | Self::V1 => b"quic hp",
- Self::V2 => b"quicv2 hp",
- }
- }
-
- fn key_update_label(&self) -> &'static [u8] {
- match self {
- Self::V1Draft | Self::V1 => b"quic ku",
- Self::V2 => b"quicv2 ku",
- }
- }
-}
-
-impl Default for Version {
- fn default() -> Self {
- Self::V1
- }
-}
-
-#[cfg(test)]
-mod tests {
- use std::prelude::v1::*;
-
- use super::PacketKey;
- use crate::quic::HeaderProtectionKey;
-
- #[test]
- fn auto_traits() {
- fn assert_auto<T: Send + Sync>() {}
- assert_auto::<Box<dyn PacketKey>>();
- assert_auto::<Box<dyn HeaderProtectionKey>>();
- }
-}
diff --git a/vendor/rustls/src/rand.rs b/vendor/rustls/src/rand.rs
deleted file mode 100644
index 23593863..00000000
--- a/vendor/rustls/src/rand.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-//! The single place where we generate random material for our own use.
-
-use alloc::vec;
-use alloc::vec::Vec;
-
-use crate::crypto::SecureRandom;
-
-/// Make a [`Vec<u8>`] of the given size containing random material.
-pub(crate) fn random_vec(
- secure_random: &dyn SecureRandom,
- len: usize,
-) -> Result<Vec<u8>, GetRandomFailed> {
- let mut v = vec![0; len];
- secure_random.fill(&mut v)?;
- Ok(v)
-}
-
-/// Return a uniformly random [`u32`].
-pub(crate) fn random_u32(secure_random: &dyn SecureRandom) -> Result<u32, GetRandomFailed> {
- let mut buf = [0u8; 4];
- secure_random.fill(&mut buf)?;
- Ok(u32::from_be_bytes(buf))
-}
-
-/// Return a uniformly random [`u16`].
-pub(crate) fn random_u16(secure_random: &dyn SecureRandom) -> Result<u16, GetRandomFailed> {
- let mut buf = [0u8; 2];
- secure_random.fill(&mut buf)?;
- Ok(u16::from_be_bytes(buf))
-}
-
-/// Random material generation failed.
-#[derive(Debug)]
-pub struct GetRandomFailed;
diff --git a/vendor/rustls/src/record_layer.rs b/vendor/rustls/src/record_layer.rs
deleted file mode 100644
index 8c2ea6b9..00000000
--- a/vendor/rustls/src/record_layer.rs
+++ /dev/null
@@ -1,336 +0,0 @@
-use alloc::boxed::Box;
-use core::cmp::min;
-
-use crate::crypto::cipher::{InboundOpaqueMessage, MessageDecrypter, MessageEncrypter};
-use crate::error::Error;
-use crate::log::trace;
-use crate::msgs::message::{InboundPlainMessage, OutboundOpaqueMessage, OutboundPlainMessage};
-
-#[derive(PartialEq)]
-enum DirectionState {
- /// No keying material.
- Invalid,
-
- /// Keying material present, but not yet in use.
- Prepared,
-
- /// Keying material in use.
- Active,
-}
-
-/// Record layer that tracks decryption and encryption keys.
-pub(crate) struct RecordLayer {
- message_encrypter: Box<dyn MessageEncrypter>,
- message_decrypter: Box<dyn MessageDecrypter>,
- write_seq_max: u64,
- write_seq: u64,
- read_seq: u64,
- has_decrypted: bool,
- encrypt_state: DirectionState,
- decrypt_state: DirectionState,
-
- // Message encrypted with other keys may be encountered, so failures
- // should be swallowed by the caller. This struct tracks the amount
- // of message size this is allowed for.
- trial_decryption_len: Option<usize>,
-}
-
-impl RecordLayer {
- /// Create new record layer with no keys.
- pub(crate) fn new() -> Self {
- Self {
- message_encrypter: <dyn MessageEncrypter>::invalid(),
- message_decrypter: <dyn MessageDecrypter>::invalid(),
- write_seq_max: 0,
- write_seq: 0,
- read_seq: 0,
- has_decrypted: false,
- encrypt_state: DirectionState::Invalid,
- decrypt_state: DirectionState::Invalid,
- trial_decryption_len: None,
- }
- }
-
- /// Decrypt a TLS message.
- ///
- /// `encr` is a decoded message allegedly received from the peer.
- /// If it can be decrypted, its decryption is returned. Otherwise,
- /// an error is returned.
- pub(crate) fn decrypt_incoming<'a>(
- &mut self,
- encr: InboundOpaqueMessage<'a>,
- ) -> Result<Option<Decrypted<'a>>, Error> {
- if self.decrypt_state != DirectionState::Active {
- return Ok(Some(Decrypted {
- want_close_before_decrypt: false,
- plaintext: encr.into_plain_message(),
- }));
- }
-
- // Set to `true` if the peer appears to getting close to encrypting
- // too many messages with this key.
- //
- // Perhaps if we send an alert well before their counter wraps, a
- // buggy peer won't make a terrible mistake here?
- //
- // Note that there's no reason to refuse to decrypt: the security
- // failure has already happened.
- let want_close_before_decrypt = self.read_seq == SEQ_SOFT_LIMIT;
-
- let encrypted_len = encr.payload.len();
- match self
- .message_decrypter
- .decrypt(encr, self.read_seq)
- {
- Ok(plaintext) => {
- self.read_seq += 1;
- if !self.has_decrypted {
- self.has_decrypted = true;
- }
- Ok(Some(Decrypted {
- want_close_before_decrypt,
- plaintext,
- }))
- }
- Err(Error::DecryptError) if self.doing_trial_decryption(encrypted_len) => {
- trace!("Dropping undecryptable message after aborted early_data");
- Ok(None)
- }
- Err(err) => Err(err),
- }
- }
-
- /// Encrypt a TLS message.
- ///
- /// `plain` is a TLS message we'd like to send. This function
- /// panics if the requisite keying material hasn't been established yet.
- pub(crate) fn encrypt_outgoing(
- &mut self,
- plain: OutboundPlainMessage<'_>,
- ) -> OutboundOpaqueMessage {
- debug_assert!(self.encrypt_state == DirectionState::Active);
- assert!(self.next_pre_encrypt_action() != PreEncryptAction::Refuse);
- let seq = self.write_seq;
- self.write_seq += 1;
- self.message_encrypter
- .encrypt(plain, seq)
- .unwrap()
- }
-
- /// Prepare to use the given `MessageEncrypter` for future message encryption.
- /// It is not used until you call `start_encrypting`.
- pub(crate) fn prepare_message_encrypter(
- &mut self,
- cipher: Box<dyn MessageEncrypter>,
- max_messages: u64,
- ) {
- self.message_encrypter = cipher;
- self.write_seq = 0;
- self.write_seq_max = min(SEQ_SOFT_LIMIT, max_messages);
- self.encrypt_state = DirectionState::Prepared;
- }
-
- /// Prepare to use the given `MessageDecrypter` for future message decryption.
- /// It is not used until you call `start_decrypting`.
- pub(crate) fn prepare_message_decrypter(&mut self, cipher: Box<dyn MessageDecrypter>) {
- self.message_decrypter = cipher;
- self.read_seq = 0;
- self.decrypt_state = DirectionState::Prepared;
- }
-
- /// Start using the `MessageEncrypter` previously provided to the previous
- /// call to `prepare_message_encrypter`.
- pub(crate) fn start_encrypting(&mut self) {
- debug_assert!(self.encrypt_state == DirectionState::Prepared);
- self.encrypt_state = DirectionState::Active;
- }
-
- /// Start using the `MessageDecrypter` previously provided to the previous
- /// call to `prepare_message_decrypter`.
- pub(crate) fn start_decrypting(&mut self) {
- debug_assert!(self.decrypt_state == DirectionState::Prepared);
- self.decrypt_state = DirectionState::Active;
- }
-
- /// Set and start using the given `MessageEncrypter` for future outgoing
- /// message encryption.
- pub(crate) fn set_message_encrypter(
- &mut self,
- cipher: Box<dyn MessageEncrypter>,
- max_messages: u64,
- ) {
- self.prepare_message_encrypter(cipher, max_messages);
- self.start_encrypting();
- }
-
- /// Set and start using the given `MessageDecrypter` for future incoming
- /// message decryption.
- pub(crate) fn set_message_decrypter(&mut self, cipher: Box<dyn MessageDecrypter>) {
- self.prepare_message_decrypter(cipher);
- self.start_decrypting();
- self.trial_decryption_len = None;
- }
-
- /// Set and start using the given `MessageDecrypter` for future incoming
- /// message decryption, and enable "trial decryption" mode for when TLS1.3
- /// 0-RTT is attempted but rejected by the server.
- pub(crate) fn set_message_decrypter_with_trial_decryption(
- &mut self,
- cipher: Box<dyn MessageDecrypter>,
- max_length: usize,
- ) {
- self.prepare_message_decrypter(cipher);
- self.start_decrypting();
- self.trial_decryption_len = Some(max_length);
- }
-
- pub(crate) fn finish_trial_decryption(&mut self) {
- self.trial_decryption_len = None;
- }
-
- pub(crate) fn next_pre_encrypt_action(&self) -> PreEncryptAction {
- self.pre_encrypt_action(0)
- }
-
- /// Return a remedial action when we are near to encrypting too many messages.
- ///
- /// `add` is added to the current sequence number. `add` as `0` means
- /// "the next message processed by `encrypt_outgoing`"
- pub(crate) fn pre_encrypt_action(&self, add: u64) -> PreEncryptAction {
- match self.write_seq.saturating_add(add) {
- v if v == self.write_seq_max => PreEncryptAction::RefreshOrClose,
- SEQ_HARD_LIMIT.. => PreEncryptAction::Refuse,
- _ => PreEncryptAction::Nothing,
- }
- }
-
- pub(crate) fn is_encrypting(&self) -> bool {
- self.encrypt_state == DirectionState::Active
- }
-
- /// Return true if we have ever decrypted a message. This is used in place
- /// of checking the read_seq since that will be reset on key updates.
- pub(crate) fn has_decrypted(&self) -> bool {
- self.has_decrypted
- }
-
- pub(crate) fn write_seq(&self) -> u64 {
- self.write_seq
- }
-
- pub(crate) fn read_seq(&self) -> u64 {
- self.read_seq
- }
-
- pub(crate) fn encrypted_len(&self, payload_len: usize) -> usize {
- self.message_encrypter
- .encrypted_payload_len(payload_len)
- }
-
- fn doing_trial_decryption(&mut self, requested: usize) -> bool {
- match self
- .trial_decryption_len
- .and_then(|value| value.checked_sub(requested))
- {
- Some(remaining) => {
- self.trial_decryption_len = Some(remaining);
- true
- }
- _ => false,
- }
- }
-}
-
-/// Result of decryption.
-#[derive(Debug)]
-pub(crate) struct Decrypted<'a> {
- /// Whether the peer appears to be getting close to encrypting too many messages with this key.
- pub(crate) want_close_before_decrypt: bool,
- /// The decrypted message.
- pub(crate) plaintext: InboundPlainMessage<'a>,
-}
-
-#[derive(Debug, Eq, PartialEq)]
-pub(crate) enum PreEncryptAction {
- /// No action is needed before calling `encrypt_outgoing`
- Nothing,
-
- /// A `key_update` request should be sent ASAP.
- ///
- /// If that is not possible (for example, the connection is TLS1.2), a `close_notify`
- /// alert should be sent instead.
- RefreshOrClose,
-
- /// Do not call `encrypt_outgoing` further, it will panic rather than
- /// over-use the key.
- Refuse,
-}
-
-const SEQ_SOFT_LIMIT: u64 = 0xffff_ffff_ffff_0000u64;
-const SEQ_HARD_LIMIT: u64 = 0xffff_ffff_ffff_fffeu64;
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn test_has_decrypted() {
- use crate::{ContentType, ProtocolVersion};
-
- struct PassThroughDecrypter;
- impl MessageDecrypter for PassThroughDecrypter {
- fn decrypt<'a>(
- &mut self,
- m: InboundOpaqueMessage<'a>,
- _: u64,
- ) -> Result<InboundPlainMessage<'a>, Error> {
- Ok(m.into_plain_message())
- }
- }
-
- // A record layer starts out invalid, having never decrypted.
- let mut record_layer = RecordLayer::new();
- assert!(matches!(
- record_layer.decrypt_state,
- DirectionState::Invalid
- ));
- assert_eq!(record_layer.read_seq, 0);
- assert!(!record_layer.has_decrypted());
-
- // Preparing the record layer should update the decrypt state, but shouldn't affect whether it
- // has decrypted.
- record_layer.prepare_message_decrypter(Box::new(PassThroughDecrypter));
- assert!(matches!(
- record_layer.decrypt_state,
- DirectionState::Prepared
- ));
- assert_eq!(record_layer.read_seq, 0);
- assert!(!record_layer.has_decrypted());
-
- // Starting decryption should update the decrypt state, but not affect whether it has decrypted.
- record_layer.start_decrypting();
- assert!(matches!(record_layer.decrypt_state, DirectionState::Active));
- assert_eq!(record_layer.read_seq, 0);
- assert!(!record_layer.has_decrypted());
-
- // Decrypting a message should update the read_seq and track that we have now performed
- // a decryption.
- record_layer
- .decrypt_incoming(InboundOpaqueMessage::new(
- ContentType::Handshake,
- ProtocolVersion::TLSv1_2,
- &mut [0xC0, 0xFF, 0xEE],
- ))
- .unwrap();
- assert!(matches!(record_layer.decrypt_state, DirectionState::Active));
- assert_eq!(record_layer.read_seq, 1);
- assert!(record_layer.has_decrypted());
-
- // Resetting the record layer message decrypter (as if a key update occurred) should reset
- // the read_seq number, but not our knowledge of whether we have decrypted previously.
- record_layer.set_message_decrypter(Box::new(PassThroughDecrypter));
- assert!(matches!(record_layer.decrypt_state, DirectionState::Active));
- assert_eq!(record_layer.read_seq, 0);
- assert!(record_layer.has_decrypted());
- }
-}
diff --git a/vendor/rustls/src/server/builder.rs b/vendor/rustls/src/server/builder.rs
deleted file mode 100644
index d1b7b24a..00000000
--- a/vendor/rustls/src/server/builder.rs
+++ /dev/null
@@ -1,127 +0,0 @@
-use alloc::vec::Vec;
-use core::marker::PhantomData;
-
-use pki_types::{CertificateDer, PrivateKeyDer};
-
-use super::{ResolvesServerCert, ServerConfig, handy};
-use crate::builder::{ConfigBuilder, WantsVerifier};
-use crate::error::Error;
-use crate::sign::{CertifiedKey, SingleCertAndKey};
-use crate::sync::Arc;
-use crate::verify::{ClientCertVerifier, NoClientAuth};
-use crate::{NoKeyLog, compress, versions};
-
-impl ConfigBuilder<ServerConfig, WantsVerifier> {
- /// Choose how to verify client certificates.
- pub fn with_client_cert_verifier(
- self,
- client_cert_verifier: Arc<dyn ClientCertVerifier>,
- ) -> ConfigBuilder<ServerConfig, WantsServerCert> {
- ConfigBuilder {
- state: WantsServerCert {
- versions: self.state.versions,
- verifier: client_cert_verifier,
- },
- provider: self.provider,
- time_provider: self.time_provider,
- side: PhantomData,
- }
- }
-
- /// Disable client authentication.
- pub fn with_no_client_auth(self) -> ConfigBuilder<ServerConfig, WantsServerCert> {
- self.with_client_cert_verifier(Arc::new(NoClientAuth))
- }
-}
-
-/// A config builder state where the caller must supply how to provide a server certificate to
-/// the connecting peer.
-///
-/// For more information, see the [`ConfigBuilder`] documentation.
-#[derive(Clone, Debug)]
-pub struct WantsServerCert {
- versions: versions::EnabledVersions,
- verifier: Arc<dyn ClientCertVerifier>,
-}
-
-impl ConfigBuilder<ServerConfig, WantsServerCert> {
- /// Sets a single certificate chain and matching private key. This
- /// certificate and key is used for all subsequent connections,
- /// irrespective of things like SNI hostname.
- ///
- /// Note that the end-entity certificate must have the
- /// [Subject Alternative Name](https://tools.ietf.org/html/rfc6125#section-4.1)
- /// extension to describe, e.g., the valid DNS name. The `commonName` field is
- /// disregarded.
- ///
- /// `cert_chain` is a vector of DER-encoded certificates.
- /// `key_der` is a DER-encoded private key as PKCS#1, PKCS#8, or SEC1. The
- /// `aws-lc-rs` and `ring` [`CryptoProvider`][crate::CryptoProvider]s support
- /// all three encodings, but other `CryptoProviders` may not.
- ///
- /// This function fails if `key_der` is invalid, or if the
- /// `SubjectPublicKeyInfo` from the private key does not match the public
- /// key for the end-entity certificate from the `cert_chain`.
- pub fn with_single_cert(
- self,
- cert_chain: Vec<CertificateDer<'static>>,
- key_der: PrivateKeyDer<'static>,
- ) -> Result<ServerConfig, Error> {
- let certified_key = CertifiedKey::from_der(cert_chain, key_der, self.crypto_provider())?;
- Ok(self.with_cert_resolver(Arc::new(SingleCertAndKey::from(certified_key))))
- }
-
- /// Sets a single certificate chain, matching private key and optional OCSP
- /// response. This certificate and key is used for all
- /// subsequent connections, irrespective of things like SNI hostname.
- ///
- /// `cert_chain` is a vector of DER-encoded certificates.
- /// `key_der` is a DER-encoded private key as PKCS#1, PKCS#8, or SEC1. The
- /// `aws-lc-rs` and `ring` [`CryptoProvider`][crate::CryptoProvider]s support
- /// all three encodings, but other `CryptoProviders` may not.
- /// `ocsp` is a DER-encoded OCSP response. Ignored if zero length.
- ///
- /// This function fails if `key_der` is invalid, or if the
- /// `SubjectPublicKeyInfo` from the private key does not match the public
- /// key for the end-entity certificate from the `cert_chain`.
- pub fn with_single_cert_with_ocsp(
- self,
- cert_chain: Vec<CertificateDer<'static>>,
- key_der: PrivateKeyDer<'static>,
- ocsp: Vec<u8>,
- ) -> Result<ServerConfig, Error> {
- let mut certified_key =
- CertifiedKey::from_der(cert_chain, key_der, self.crypto_provider())?;
- certified_key.ocsp = Some(ocsp);
- Ok(self.with_cert_resolver(Arc::new(SingleCertAndKey::from(certified_key))))
- }
-
- /// Sets a custom [`ResolvesServerCert`].
- pub fn with_cert_resolver(self, cert_resolver: Arc<dyn ResolvesServerCert>) -> ServerConfig {
- ServerConfig {
- provider: self.provider,
- verifier: self.state.verifier,
- cert_resolver,
- ignore_client_order: false,
- max_fragment_size: None,
- #[cfg(feature = "std")]
- session_storage: handy::ServerSessionMemoryCache::new(256),
- #[cfg(not(feature = "std"))]
- session_storage: Arc::new(handy::NoServerSessionStorage {}),
- ticketer: Arc::new(handy::NeverProducesTickets {}),
- alpn_protocols: Vec::new(),
- versions: self.state.versions,
- key_log: Arc::new(NoKeyLog {}),
- enable_secret_extraction: false,
- max_early_data_size: 0,
- send_half_rtt_data: false,
- send_tls13_tickets: 2,
- #[cfg(feature = "tls12")]
- require_ems: cfg!(feature = "fips"),
- time_provider: self.time_provider,
- cert_compressors: compress::default_cert_compressors().to_vec(),
- cert_compression_cache: Arc::new(compress::CompressionCache::default()),
- cert_decompressors: compress::default_cert_decompressors().to_vec(),
- }
- }
-}
diff --git a/vendor/rustls/src/server/common.rs b/vendor/rustls/src/server/common.rs
deleted file mode 100644
index 8310998a..00000000
--- a/vendor/rustls/src/server/common.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-use pki_types::CertificateDer;
-
-use crate::sign;
-
-/// ActiveCertifiedKey wraps [`sign::CertifiedKey`] and tracks OSCP state in a single handshake.
-pub(super) struct ActiveCertifiedKey<'a> {
- key: &'a sign::CertifiedKey,
- ocsp: Option<&'a [u8]>,
-}
-
-impl ActiveCertifiedKey<'_> {
- pub(super) fn from_certified_key(key: &sign::CertifiedKey) -> ActiveCertifiedKey<'_> {
- ActiveCertifiedKey {
- key,
- ocsp: key.ocsp.as_deref(),
- }
- }
-
- /// Get the certificate chain
- #[inline]
- pub(super) fn get_cert(&self) -> &[CertificateDer<'static>] {
- &self.key.cert
- }
-
- /// Get the signing key
- #[inline]
- pub(super) fn get_key(&self) -> &dyn sign::SigningKey {
- &*self.key.key
- }
-
- #[inline]
- pub(super) fn get_ocsp(&self) -> Option<&[u8]> {
- self.ocsp
- }
-}
diff --git a/vendor/rustls/src/server/handy.rs b/vendor/rustls/src/server/handy.rs
deleted file mode 100644
index ea3ec5d9..00000000
--- a/vendor/rustls/src/server/handy.rs
+++ /dev/null
@@ -1,356 +0,0 @@
-use alloc::vec::Vec;
-use core::fmt::Debug;
-
-use crate::server::ClientHello;
-use crate::sync::Arc;
-use crate::{server, sign};
-
-/// Something which never stores sessions.
-#[derive(Debug)]
-pub struct NoServerSessionStorage {}
-
-impl server::StoresServerSessions for NoServerSessionStorage {
- fn put(&self, _id: Vec<u8>, _sec: Vec<u8>) -> bool {
- false
- }
- fn get(&self, _id: &[u8]) -> Option<Vec<u8>> {
- None
- }
- fn take(&self, _id: &[u8]) -> Option<Vec<u8>> {
- None
- }
- fn can_cache(&self) -> bool {
- false
- }
-}
-
-#[cfg(any(feature = "std", feature = "hashbrown"))]
-mod cache {
- use alloc::vec::Vec;
- use core::fmt::{Debug, Formatter};
-
- use crate::lock::Mutex;
- use crate::sync::Arc;
- use crate::{limited_cache, server};
-
- /// An implementer of `StoresServerSessions` that stores everything
- /// in memory. If enforces a limit on the number of stored sessions
- /// to bound memory usage.
- pub struct ServerSessionMemoryCache {
- cache: Mutex<limited_cache::LimitedCache<Vec<u8>, Vec<u8>>>,
- }
-
- impl ServerSessionMemoryCache {
- /// Make a new ServerSessionMemoryCache. `size` is the maximum
- /// number of stored sessions, and may be rounded-up for
- /// efficiency.
- #[cfg(feature = "std")]
- pub fn new(size: usize) -> Arc<Self> {
- Arc::new(Self {
- cache: Mutex::new(limited_cache::LimitedCache::new(size)),
- })
- }
-
- /// Make a new ServerSessionMemoryCache. `size` is the maximum
- /// number of stored sessions, and may be rounded-up for
- /// efficiency.
- #[cfg(not(feature = "std"))]
- pub fn new<M: crate::lock::MakeMutex>(size: usize) -> Arc<Self> {
- Arc::new(Self {
- cache: Mutex::new::<M>(limited_cache::LimitedCache::new(size)),
- })
- }
- }
-
- impl server::StoresServerSessions for ServerSessionMemoryCache {
- fn put(&self, key: Vec<u8>, value: Vec<u8>) -> bool {
- self.cache
- .lock()
- .unwrap()
- .insert(key, value);
- true
- }
-
- fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
- self.cache
- .lock()
- .unwrap()
- .get(key)
- .cloned()
- }
-
- fn take(&self, key: &[u8]) -> Option<Vec<u8>> {
- self.cache.lock().unwrap().remove(key)
- }
-
- fn can_cache(&self) -> bool {
- true
- }
- }
-
- impl Debug for ServerSessionMemoryCache {
- fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
- f.debug_struct("ServerSessionMemoryCache")
- .finish()
- }
- }
-
- #[cfg(test)]
- mod tests {
- use std::vec;
-
- use super::*;
- use crate::server::StoresServerSessions;
-
- #[test]
- fn test_serversessionmemorycache_accepts_put() {
- let c = ServerSessionMemoryCache::new(4);
- assert!(c.put(vec![0x01], vec![0x02]));
- }
-
- #[test]
- fn test_serversessionmemorycache_persists_put() {
- let c = ServerSessionMemoryCache::new(4);
- assert!(c.put(vec![0x01], vec![0x02]));
- assert_eq!(c.get(&[0x01]), Some(vec![0x02]));
- assert_eq!(c.get(&[0x01]), Some(vec![0x02]));
- }
-
- #[test]
- fn test_serversessionmemorycache_overwrites_put() {
- let c = ServerSessionMemoryCache::new(4);
- assert!(c.put(vec![0x01], vec![0x02]));
- assert!(c.put(vec![0x01], vec![0x04]));
- assert_eq!(c.get(&[0x01]), Some(vec![0x04]));
- }
-
- #[test]
- fn test_serversessionmemorycache_drops_to_maintain_size_invariant() {
- let c = ServerSessionMemoryCache::new(2);
- assert!(c.put(vec![0x01], vec![0x02]));
- assert!(c.put(vec![0x03], vec![0x04]));
- assert!(c.put(vec![0x05], vec![0x06]));
- assert!(c.put(vec![0x07], vec![0x08]));
- assert!(c.put(vec![0x09], vec![0x0a]));
-
- let count = c.get(&[0x01]).iter().count()
- + c.get(&[0x03]).iter().count()
- + c.get(&[0x05]).iter().count()
- + c.get(&[0x07]).iter().count()
- + c.get(&[0x09]).iter().count();
-
- assert!(count < 5);
- }
- }
-}
-
-#[cfg(any(feature = "std", feature = "hashbrown"))]
-pub use cache::ServerSessionMemoryCache;
-
-/// Something which never produces tickets.
-#[derive(Debug)]
-pub(super) struct NeverProducesTickets {}
-
-impl server::ProducesTickets for NeverProducesTickets {
- fn enabled(&self) -> bool {
- false
- }
- fn lifetime(&self) -> u32 {
- 0
- }
- fn encrypt(&self, _bytes: &[u8]) -> Option<Vec<u8>> {
- None
- }
- fn decrypt(&self, _bytes: &[u8]) -> Option<Vec<u8>> {
- None
- }
-}
-
-/// An exemplar `ResolvesServerCert` implementation that always resolves to a single
-/// [RFC 7250] raw public key.
-///
-/// [RFC 7250]: https://tools.ietf.org/html/rfc7250
-#[derive(Clone, Debug)]
-pub struct AlwaysResolvesServerRawPublicKeys(Arc<sign::CertifiedKey>);
-
-impl AlwaysResolvesServerRawPublicKeys {
- /// Create a new `AlwaysResolvesServerRawPublicKeys` instance.
- pub fn new(certified_key: Arc<sign::CertifiedKey>) -> Self {
- Self(certified_key)
- }
-}
-
-impl server::ResolvesServerCert for AlwaysResolvesServerRawPublicKeys {
- fn resolve(&self, _client_hello: ClientHello<'_>) -> Option<Arc<sign::CertifiedKey>> {
- Some(self.0.clone())
- }
-
- fn only_raw_public_keys(&self) -> bool {
- true
- }
-}
-
-#[cfg(any(feature = "std", feature = "hashbrown"))]
-mod sni_resolver {
- use alloc::string::{String, ToString};
- use core::fmt::Debug;
-
- use pki_types::{DnsName, ServerName};
-
- use crate::error::Error;
- use crate::hash_map::HashMap;
- use crate::server::ClientHello;
- use crate::sync::Arc;
- use crate::webpki::{ParsedCertificate, verify_server_name};
- use crate::{server, sign};
-
- /// Something that resolves do different cert chains/keys based
- /// on client-supplied server name (via SNI).
- #[derive(Debug)]
- pub struct ResolvesServerCertUsingSni {
- by_name: HashMap<String, Arc<sign::CertifiedKey>>,
- }
-
- impl ResolvesServerCertUsingSni {
- /// Create a new and empty (i.e., knows no certificates) resolver.
- pub fn new() -> Self {
- Self {
- by_name: HashMap::new(),
- }
- }
-
- /// Add a new `sign::CertifiedKey` to be used for the given SNI `name`.
- ///
- /// This function fails if `name` is not a valid DNS name, or if
- /// it's not valid for the supplied certificate, or if the certificate
- /// chain is syntactically faulty.
- pub fn add(&mut self, name: &str, ck: sign::CertifiedKey) -> Result<(), Error> {
- let server_name = {
- let checked_name = DnsName::try_from(name)
- .map_err(|_| Error::General("Bad DNS name".into()))
- .map(|name| name.to_lowercase_owned())?;
- ServerName::DnsName(checked_name)
- };
-
- // Check the certificate chain for validity:
- // - it should be non-empty list
- // - the first certificate should be parsable as a x509v3,
- // - the first certificate should quote the given server name
- // (if provided)
- //
- // These checks are not security-sensitive. They are the
- // *server* attempting to detect accidental misconfiguration.
-
- ck.end_entity_cert()
- .and_then(ParsedCertificate::try_from)
- .and_then(|cert| verify_server_name(&cert, &server_name))?;
-
- if let ServerName::DnsName(name) = server_name {
- self.by_name
- .insert(name.as_ref().to_string(), Arc::new(ck));
- }
- Ok(())
- }
- }
-
- impl server::ResolvesServerCert for ResolvesServerCertUsingSni {
- fn resolve(&self, client_hello: ClientHello<'_>) -> Option<Arc<sign::CertifiedKey>> {
- if let Some(name) = client_hello.server_name() {
- self.by_name.get(name).cloned()
- } else {
- // This kind of resolver requires SNI
- None
- }
- }
- }
-
- #[cfg(test)]
- mod tests {
- use super::*;
- use crate::server::ResolvesServerCert;
-
- #[test]
- fn test_resolvesservercertusingsni_requires_sni() {
- let rscsni = ResolvesServerCertUsingSni::new();
- assert!(
- rscsni
- .resolve(ClientHello {
- server_name: &None,
- signature_schemes: &[],
- alpn: None,
- server_cert_types: None,
- client_cert_types: None,
- cipher_suites: &[],
- certificate_authorities: None,
- named_groups: None,
- })
- .is_none()
- );
- }
-
- #[test]
- fn test_resolvesservercertusingsni_handles_unknown_name() {
- let rscsni = ResolvesServerCertUsingSni::new();
- let name = DnsName::try_from("hello.com")
- .unwrap()
- .to_owned();
- assert!(
- rscsni
- .resolve(ClientHello {
- server_name: &Some(name),
- signature_schemes: &[],
- alpn: None,
- server_cert_types: None,
- client_cert_types: None,
- cipher_suites: &[],
- certificate_authorities: None,
- named_groups: None,
- })
- .is_none()
- );
- }
- }
-}
-
-#[cfg(any(feature = "std", feature = "hashbrown"))]
-pub use sni_resolver::ResolvesServerCertUsingSni;
-
-#[cfg(test)]
-mod tests {
- use std::vec;
-
- use super::*;
- use crate::server::{ProducesTickets, StoresServerSessions};
-
- #[test]
- fn test_noserversessionstorage_drops_put() {
- let c = NoServerSessionStorage {};
- assert!(!c.put(vec![0x01], vec![0x02]));
- }
-
- #[test]
- fn test_noserversessionstorage_denies_gets() {
- let c = NoServerSessionStorage {};
- c.put(vec![0x01], vec![0x02]);
- assert_eq!(c.get(&[]), None);
- assert_eq!(c.get(&[0x01]), None);
- assert_eq!(c.get(&[0x02]), None);
- }
-
- #[test]
- fn test_noserversessionstorage_denies_takes() {
- let c = NoServerSessionStorage {};
- assert_eq!(c.take(&[]), None);
- assert_eq!(c.take(&[0x01]), None);
- assert_eq!(c.take(&[0x02]), None);
- }
-
- #[test]
- fn test_neverproducestickets_does_nothing() {
- let npt = NeverProducesTickets {};
- assert!(!npt.enabled());
- assert_eq!(0, npt.lifetime());
- assert_eq!(None, npt.encrypt(&[]));
- assert_eq!(None, npt.decrypt(&[]));
- }
-}
diff --git a/vendor/rustls/src/server/hs.rs b/vendor/rustls/src/server/hs.rs
deleted file mode 100644
index d98336e4..00000000
--- a/vendor/rustls/src/server/hs.rs
+++ /dev/null
@@ -1,763 +0,0 @@
-use alloc::borrow::ToOwned;
-use alloc::boxed::Box;
-use alloc::vec::Vec;
-
-use pki_types::DnsName;
-
-use super::server_conn::ServerConnectionData;
-#[cfg(feature = "tls12")]
-use super::tls12;
-use crate::common_state::{KxState, Protocol, State};
-use crate::conn::ConnectionRandoms;
-use crate::crypto::SupportedKxGroup;
-use crate::enums::{
- AlertDescription, CertificateType, CipherSuite, HandshakeType, ProtocolVersion,
- SignatureAlgorithm, SignatureScheme,
-};
-use crate::error::{Error, PeerIncompatible, PeerMisbehaved};
-use crate::hash_hs::{HandshakeHash, HandshakeHashBuffer};
-use crate::log::{debug, trace};
-use crate::msgs::enums::{Compression, ExtensionType, NamedGroup};
-#[cfg(feature = "tls12")]
-use crate::msgs::handshake::SessionId;
-use crate::msgs::handshake::{
- ClientHelloPayload, HandshakePayload, KeyExchangeAlgorithm, ProtocolName, Random,
- ServerExtensions, ServerExtensionsInput, ServerNamePayload, SingleProtocolName,
- TransportParameters,
-};
-use crate::msgs::message::{Message, MessagePayload};
-use crate::msgs::persist;
-use crate::server::common::ActiveCertifiedKey;
-use crate::server::{ClientHello, ServerConfig, tls13};
-use crate::sync::Arc;
-use crate::{SupportedCipherSuite, suites};
-
-pub(super) type NextState<'a> = Box<dyn State<ServerConnectionData> + 'a>;
-pub(super) type NextStateOrError<'a> = Result<NextState<'a>, Error>;
-pub(super) type ServerContext<'a> = crate::common_state::Context<'a, ServerConnectionData>;
-
-pub(super) fn can_resume(
- suite: SupportedCipherSuite,
- sni: &Option<DnsName<'_>>,
- using_ems: bool,
- resumedata: &persist::ServerSessionValue,
-) -> bool {
- // The RFCs underspecify what happens if we try to resume to
- // an unoffered/varying suite. We merely don't resume in weird cases.
- //
- // RFC 6066 says "A server that implements this extension MUST NOT accept
- // the request to resume the session if the server_name extension contains
- // a different name. Instead, it proceeds with a full handshake to
- // establish a new session."
- //
- // RFC 8446: "The server MUST ensure that it selects
- // a compatible PSK (if any) and cipher suite."
- resumedata.cipher_suite == suite.suite()
- && (resumedata.extended_ms == using_ems || (resumedata.extended_ms && !using_ems))
- && &resumedata.sni == sni
-}
-
-#[derive(Default)]
-pub(super) struct ExtensionProcessing {
- // extensions to reply with
- pub(super) extensions: Box<ServerExtensions<'static>>,
- #[cfg(feature = "tls12")]
- pub(super) send_ticket: bool,
-}
-
-impl ExtensionProcessing {
- pub(super) fn new(extra_exts: ServerExtensionsInput<'static>) -> Self {
- let ServerExtensionsInput {
- transport_parameters,
- } = extra_exts;
-
- let mut extensions = Box::new(ServerExtensions::default());
- match transport_parameters {
- Some(TransportParameters::Quic(v)) => extensions.transport_parameters = Some(v),
- Some(TransportParameters::QuicDraft(v)) => {
- extensions.transport_parameters_draft = Some(v)
- }
- None => {}
- }
-
- Self {
- extensions,
- #[cfg(feature = "tls12")]
- send_ticket: false,
- }
- }
-
- pub(super) fn process_common(
- &mut self,
- config: &ServerConfig,
- cx: &mut ServerContext<'_>,
- ocsp_response: &mut Option<&[u8]>,
- hello: &ClientHelloPayload,
- resumedata: Option<&persist::ServerSessionValue>,
- ) -> Result<(), Error> {
- // ALPN
- let our_protocols = &config.alpn_protocols;
- if let Some(their_protocols) = &hello.protocols {
- cx.common.alpn_protocol = our_protocols
- .iter()
- .find(|ours| {
- their_protocols
- .iter()
- .any(|theirs| theirs.as_ref() == ours.as_slice())
- })
- .map(|bytes| ProtocolName::from(bytes.clone()));
- if let Some(selected_protocol) = &cx.common.alpn_protocol {
- debug!("Chosen ALPN protocol {selected_protocol:?}");
-
- self.extensions.selected_protocol =
- Some(SingleProtocolName::new(selected_protocol.clone()));
- } else if !our_protocols.is_empty() {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::NoApplicationProtocol,
- Error::NoApplicationProtocol,
- ));
- }
- }
-
- if cx.common.is_quic() {
- // QUIC has strict ALPN, unlike TLS's more backwards-compatible behavior. RFC 9001
- // says: "The server MUST treat the inability to select a compatible application
- // protocol as a connection error of type 0x0178". We judge that ALPN was desired
- // (rather than some out-of-band protocol negotiation mechanism) if and only if any ALPN
- // protocols were configured locally or offered by the client. This helps prevent
- // successful establishment of connections between peers that can't understand
- // each other.
- if cx.common.alpn_protocol.is_none()
- && (!our_protocols.is_empty() || hello.protocols.is_some())
- {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::NoApplicationProtocol,
- Error::NoApplicationProtocol,
- ));
- }
-
- let transport_params = hello
- .transport_parameters
- .as_ref()
- .or(hello
- .transport_parameters_draft
- .as_ref());
- match transport_params {
- Some(params) => cx.common.quic.params = Some(params.to_owned().into_vec()),
- None => {
- return Err(cx
- .common
- .missing_extension(PeerMisbehaved::MissingQuicTransportParameters));
- }
- }
- }
-
- let for_resume = resumedata.is_some();
- // SNI
- if let (false, Some(ServerNamePayload::SingleDnsName(_))) = (for_resume, &hello.server_name)
- {
- self.extensions.server_name_ack = Some(());
- }
-
- // Send status_request response if we have one. This is not allowed
- // if we're resuming, and is only triggered if we have an OCSP response
- // to send.
- if !for_resume
- && hello
- .certificate_status_request
- .is_some()
- {
- if ocsp_response.is_some() && !cx.common.is_tls13() {
- // Only TLS1.2 sends confirmation in ServerHello
- self.extensions
- .certificate_status_request_ack = Some(());
- }
- } else {
- // Throw away any OCSP response so we don't try to send it later.
- ocsp_response.take();
- }
-
- self.validate_server_cert_type_extension(hello, config, cx)?;
- self.validate_client_cert_type_extension(hello, config, cx)?;
-
- Ok(())
- }
-
- #[cfg(feature = "tls12")]
- pub(super) fn process_tls12(
- &mut self,
- config: &ServerConfig,
- hello: &ClientHelloPayload,
- using_ems: bool,
- ) {
- // Renegotiation.
- // (We don't do reneg at all, but would support the secure version if we did.)
-
- use crate::msgs::base::PayloadU8;
- let secure_reneg_offered = hello.renegotiation_info.is_some()
- || hello
- .cipher_suites
- .contains(&CipherSuite::TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
-
- if secure_reneg_offered {
- self.extensions.renegotiation_info = Some(PayloadU8::new(Vec::new()));
- }
-
- // Tickets:
- // If we get any SessionTicket extension and have tickets enabled,
- // we send an ack.
- if hello.session_ticket.is_some() && config.ticketer.enabled() {
- self.send_ticket = true;
- self.extensions.session_ticket_ack = Some(());
- }
-
- // Confirm use of EMS if offered.
- if using_ems {
- self.extensions
- .extended_master_secret_ack = Some(());
- }
- }
-
- fn validate_server_cert_type_extension(
- &mut self,
- hello: &ClientHelloPayload,
- config: &ServerConfig,
- cx: &mut ServerContext<'_>,
- ) -> Result<(), Error> {
- let client_supports = hello
- .server_certificate_types
- .as_deref()
- .unwrap_or_default();
-
- self.process_cert_type_extension(
- client_supports,
- config
- .cert_resolver
- .only_raw_public_keys(),
- ExtensionType::ServerCertificateType,
- cx,
- )
- }
-
- fn validate_client_cert_type_extension(
- &mut self,
- hello: &ClientHelloPayload,
- config: &ServerConfig,
- cx: &mut ServerContext<'_>,
- ) -> Result<(), Error> {
- let client_supports = hello
- .client_certificate_types
- .as_deref()
- .unwrap_or_default();
-
- self.process_cert_type_extension(
- client_supports,
- config
- .verifier
- .requires_raw_public_keys(),
- ExtensionType::ClientCertificateType,
- cx,
- )
- }
-
- fn process_cert_type_extension(
- &mut self,
- client_supports: &[CertificateType],
- requires_raw_keys: bool,
- extension_type: ExtensionType,
- cx: &mut ServerContext<'_>,
- ) -> Result<(), Error> {
- debug_assert!(
- extension_type == ExtensionType::ClientCertificateType
- || extension_type == ExtensionType::ServerCertificateType
- );
- let raw_key_negotation_result = match (
- requires_raw_keys,
- client_supports.contains(&CertificateType::RawPublicKey),
- client_supports.contains(&CertificateType::X509),
- ) {
- (true, true, _) => Ok((extension_type, CertificateType::RawPublicKey)),
- (false, _, true) => Ok((extension_type, CertificateType::X509)),
- (false, true, false) => Err(Error::PeerIncompatible(
- PeerIncompatible::IncorrectCertificateTypeExtension,
- )),
- (true, false, _) => Err(Error::PeerIncompatible(
- PeerIncompatible::IncorrectCertificateTypeExtension,
- )),
- (false, false, false) => return Ok(()),
- };
-
- match raw_key_negotation_result {
- Ok((ExtensionType::ClientCertificateType, cert_type)) => {
- self.extensions.client_certificate_type = Some(cert_type);
- }
- Ok((ExtensionType::ServerCertificateType, cert_type)) => {
- self.extensions.server_certificate_type = Some(cert_type);
- }
- Err(err) => {
- return Err(cx
- .common
- .send_fatal_alert(AlertDescription::HandshakeFailure, err));
- }
- Ok((_, _)) => unreachable!(),
- }
- Ok(())
- }
-}
-
-pub(super) struct ExpectClientHello {
- pub(super) config: Arc<ServerConfig>,
- pub(super) extra_exts: ServerExtensionsInput<'static>,
- pub(super) transcript: HandshakeHashOrBuffer,
- #[cfg(feature = "tls12")]
- pub(super) session_id: SessionId,
- #[cfg(feature = "tls12")]
- pub(super) using_ems: bool,
- pub(super) done_retry: bool,
- pub(super) send_tickets: usize,
-}
-
-impl ExpectClientHello {
- pub(super) fn new(
- config: Arc<ServerConfig>,
- extra_exts: ServerExtensionsInput<'static>,
- ) -> Self {
- let mut transcript_buffer = HandshakeHashBuffer::new();
-
- if config.verifier.offer_client_auth() {
- transcript_buffer.set_client_auth_enabled();
- }
-
- Self {
- config,
- extra_exts,
- transcript: HandshakeHashOrBuffer::Buffer(transcript_buffer),
- #[cfg(feature = "tls12")]
- session_id: SessionId::empty(),
- #[cfg(feature = "tls12")]
- using_ems: false,
- done_retry: false,
- send_tickets: 0,
- }
- }
-
- /// Continues handling of a `ClientHello` message once config and certificate are available.
- pub(super) fn with_certified_key(
- self,
- mut sig_schemes: Vec<SignatureScheme>,
- client_hello: &ClientHelloPayload,
- m: &Message<'_>,
- cx: &mut ServerContext<'_>,
- ) -> NextStateOrError<'static> {
- let tls13_enabled = self
- .config
- .supports_version(ProtocolVersion::TLSv1_3);
- let tls12_enabled = self
- .config
- .supports_version(ProtocolVersion::TLSv1_2);
-
- // Are we doing TLS1.3?
- let version = if let Some(versions) = &client_hello.supported_versions {
- if versions.tls13 && tls13_enabled {
- ProtocolVersion::TLSv1_3
- } else if !versions.tls12 || !tls12_enabled {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::ProtocolVersion,
- PeerIncompatible::Tls12NotOfferedOrEnabled,
- ));
- } else if cx.common.is_quic() {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::ProtocolVersion,
- PeerIncompatible::Tls13RequiredForQuic,
- ));
- } else {
- ProtocolVersion::TLSv1_2
- }
- } else if u16::from(client_hello.client_version) < u16::from(ProtocolVersion::TLSv1_2) {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::ProtocolVersion,
- PeerIncompatible::Tls12NotOffered,
- ));
- } else if !tls12_enabled && tls13_enabled {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::ProtocolVersion,
- PeerIncompatible::SupportedVersionsExtensionRequired,
- ));
- } else if cx.common.is_quic() {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::ProtocolVersion,
- PeerIncompatible::Tls13RequiredForQuic,
- ));
- } else {
- ProtocolVersion::TLSv1_2
- };
-
- cx.common.negotiated_version = Some(version);
-
- // We communicate to the upper layer what kind of key they should choose
- // via the sigschemes value. Clients tend to treat this extension
- // orthogonally to offered ciphersuites (even though, in TLS1.2 it is not).
- // So: reduce the offered sigschemes to those compatible with the
- // intersection of ciphersuites.
- let client_suites = self
- .config
- .provider
- .cipher_suites
- .iter()
- .copied()
- .filter(|scs| {
- client_hello
- .cipher_suites
- .contains(&scs.suite())
- })
- .collect::<Vec<_>>();
-
- sig_schemes
- .retain(|scheme| suites::compatible_sigscheme_for_suites(*scheme, &client_suites));
-
- // We adhere to the TLS 1.2 RFC by not exposing this to the cert resolver if TLS version is 1.2
- let certificate_authorities = match version {
- ProtocolVersion::TLSv1_2 => None,
- _ => client_hello
- .certificate_authority_names
- .as_deref(),
- };
- // Choose a certificate.
- let certkey = {
- let client_hello = ClientHello {
- server_name: &cx.data.sni,
- signature_schemes: &sig_schemes,
- alpn: client_hello.protocols.as_ref(),
- client_cert_types: client_hello
- .client_certificate_types
- .as_deref(),
- server_cert_types: client_hello
- .server_certificate_types
- .as_deref(),
- cipher_suites: &client_hello.cipher_suites,
- certificate_authorities,
- named_groups: client_hello.named_groups.as_deref(),
- };
- trace!("Resolving server certificate: {client_hello:#?}");
-
- let certkey = self
- .config
- .cert_resolver
- .resolve(client_hello);
-
- certkey.ok_or_else(|| {
- cx.common.send_fatal_alert(
- AlertDescription::AccessDenied,
- Error::General("no server certificate chain resolved".to_owned()),
- )
- })?
- };
- let certkey = ActiveCertifiedKey::from_certified_key(&certkey);
-
- let (suite, skxg) = self
- .choose_suite_and_kx_group(
- version,
- certkey.get_key().algorithm(),
- cx.common.protocol,
- client_hello
- .named_groups
- .as_deref()
- .unwrap_or_default(),
- &client_hello.cipher_suites,
- )
- .map_err(|incompat| {
- cx.common
- .send_fatal_alert(AlertDescription::HandshakeFailure, incompat)
- })?;
-
- debug!("decided upon suite {suite:?}");
- cx.common.suite = Some(suite);
- cx.common.kx_state = KxState::Start(skxg);
-
- // Start handshake hash.
- let starting_hash = suite.hash_provider();
- let transcript = match self.transcript {
- HandshakeHashOrBuffer::Buffer(inner) => inner.start_hash(starting_hash),
- HandshakeHashOrBuffer::Hash(inner)
- if inner.algorithm() == starting_hash.algorithm() =>
- {
- inner
- }
- _ => {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::HandshakeHashVariedAfterRetry,
- ));
- }
- };
-
- // Save their Random.
- let randoms = ConnectionRandoms::new(
- client_hello.random,
- Random::new(self.config.provider.secure_random)?,
- );
- match suite {
- SupportedCipherSuite::Tls13(suite) => tls13::CompleteClientHelloHandling {
- config: self.config,
- transcript,
- suite,
- randoms,
- done_retry: self.done_retry,
- send_tickets: self.send_tickets,
- extra_exts: self.extra_exts,
- }
- .handle_client_hello(cx, certkey, m, client_hello, skxg, sig_schemes),
- #[cfg(feature = "tls12")]
- SupportedCipherSuite::Tls12(suite) => tls12::CompleteClientHelloHandling {
- config: self.config,
- transcript,
- session_id: self.session_id,
- suite,
- using_ems: self.using_ems,
- randoms,
- send_ticket: self.send_tickets > 0,
- extra_exts: self.extra_exts,
- }
- .handle_client_hello(
- cx,
- certkey,
- m,
- client_hello,
- skxg,
- sig_schemes,
- tls13_enabled,
- ),
- }
- }
-
- fn choose_suite_and_kx_group(
- &self,
- selected_version: ProtocolVersion,
- sig_key_algorithm: SignatureAlgorithm,
- protocol: Protocol,
- client_groups: &[NamedGroup],
- client_suites: &[CipherSuite],
- ) -> Result<(SupportedCipherSuite, &'static dyn SupportedKxGroup), PeerIncompatible> {
- // Determine which `KeyExchangeAlgorithm`s are theoretically possible, based
- // on the offered and supported groups.
- let mut ecdhe_possible = false;
- let mut ffdhe_possible = false;
- let mut ffdhe_offered = false;
- let mut supported_groups = Vec::with_capacity(client_groups.len());
-
- for offered_group in client_groups {
- let supported = self
- .config
- .provider
- .kx_groups
- .iter()
- .find(|skxg| {
- skxg.usable_for_version(selected_version) && skxg.name() == *offered_group
- });
-
- match offered_group.key_exchange_algorithm() {
- KeyExchangeAlgorithm::DHE => {
- ffdhe_possible |= supported.is_some();
- ffdhe_offered = true;
- }
- KeyExchangeAlgorithm::ECDHE => {
- ecdhe_possible |= supported.is_some();
- }
- }
-
- supported_groups.push(supported);
- }
-
- let first_supported_dhe_kxg = if selected_version == ProtocolVersion::TLSv1_2 {
- // https://datatracker.ietf.org/doc/html/rfc7919#section-4 (paragraph 2)
- let first_supported_dhe_kxg = self
- .config
- .provider
- .kx_groups
- .iter()
- .find(|skxg| skxg.name().key_exchange_algorithm() == KeyExchangeAlgorithm::DHE);
- ffdhe_possible |= !ffdhe_offered && first_supported_dhe_kxg.is_some();
- first_supported_dhe_kxg
- } else {
- // In TLS1.3, the server may only directly negotiate a group.
- None
- };
-
- if !ecdhe_possible && !ffdhe_possible {
- return Err(PeerIncompatible::NoKxGroupsInCommon);
- }
-
- let mut suitable_suites_iter = self
- .config
- .provider
- .cipher_suites
- .iter()
- .filter(|suite| {
- // Reduce our supported ciphersuites by the certified key's algorithm.
- suite.usable_for_signature_algorithm(sig_key_algorithm)
- // And version
- && suite.version().version == selected_version
- // And protocol
- && suite.usable_for_protocol(protocol)
- // And support one of key exchange groups
- && (ecdhe_possible && suite.usable_for_kx_algorithm(KeyExchangeAlgorithm::ECDHE)
- || ffdhe_possible && suite.usable_for_kx_algorithm(KeyExchangeAlgorithm::DHE))
- });
-
- // RFC 7919 (https://datatracker.ietf.org/doc/html/rfc7919#section-4) requires us to send
- // the InsufficientSecurity alert in case we don't recognize client's FFDHE groups (i.e.,
- // `suitable_suites` becomes empty). But that does not make a lot of sense (e.g., client
- // proposes FFDHE4096 and we only support FFDHE2048), so we ignore that requirement here,
- // and continue to send HandshakeFailure.
-
- let suite = if self.config.ignore_client_order {
- suitable_suites_iter.find(|suite| client_suites.contains(&suite.suite()))
- } else {
- let suitable_suites = suitable_suites_iter.collect::<Vec<_>>();
- client_suites
- .iter()
- .find_map(|client_suite| {
- suitable_suites
- .iter()
- .find(|x| *client_suite == x.suite())
- })
- .copied()
- }
- .ok_or(PeerIncompatible::NoCipherSuitesInCommon)?;
-
- // Finally, choose a key exchange group that is compatible with the selected cipher
- // suite.
- let maybe_skxg = supported_groups
- .iter()
- .find_map(|maybe_skxg| match maybe_skxg {
- Some(skxg) => suite
- .usable_for_kx_algorithm(skxg.name().key_exchange_algorithm())
- .then_some(*skxg),
- None => None,
- });
-
- if selected_version == ProtocolVersion::TLSv1_3 {
- // This unwrap is structurally guaranteed by the early return for `!ffdhe_possible && !ecdhe_possible`
- return Ok((*suite, *maybe_skxg.unwrap()));
- }
-
- // For TLS1.2, the server can unilaterally choose a DHE group if it has one and
- // there was no better option.
- match maybe_skxg {
- Some(skxg) => Ok((*suite, *skxg)),
- None if suite.usable_for_kx_algorithm(KeyExchangeAlgorithm::DHE) => {
- // If kx for the selected cipher suite is DHE and no DHE groups are specified in the extension,
- // the server is free to choose DHE params, we choose the first DHE kx group of the provider.
- if let Some(server_selected_ffdhe_skxg) = first_supported_dhe_kxg {
- Ok((*suite, *server_selected_ffdhe_skxg))
- } else {
- Err(PeerIncompatible::NoKxGroupsInCommon)
- }
- }
- None => Err(PeerIncompatible::NoKxGroupsInCommon),
- }
- }
-}
-
-impl State<ServerConnectionData> for ExpectClientHello {
- fn handle<'m>(
- self: Box<Self>,
- cx: &mut ServerContext<'_>,
- m: Message<'m>,
- ) -> NextStateOrError<'m>
- where
- Self: 'm,
- {
- let (client_hello, sig_schemes) = process_client_hello(&m, self.done_retry, cx)?;
- self.with_certified_key(sig_schemes, client_hello, &m, cx)
- }
-
- fn into_owned(self: Box<Self>) -> NextState<'static> {
- self
- }
-}
-
-/// Configuration-independent validation of a `ClientHello` message.
-///
-/// This represents the first part of the `ClientHello` handling, where we do all validation that
-/// doesn't depend on a `ServerConfig` being available and extract everything needed to build a
-/// [`ClientHello`] value for a [`ResolvesServerCert`].
-///
-/// Note that this will modify `data.sni` even if config or certificate resolution fail.
-///
-/// [`ResolvesServerCert`]: crate::server::ResolvesServerCert
-pub(super) fn process_client_hello<'m>(
- m: &'m Message<'m>,
- done_retry: bool,
- cx: &mut ServerContext<'_>,
-) -> Result<(&'m ClientHelloPayload, Vec<SignatureScheme>), Error> {
- let client_hello =
- require_handshake_msg!(m, HandshakeType::ClientHello, HandshakePayload::ClientHello)?;
- trace!("we got a clienthello {client_hello:?}");
-
- if !client_hello
- .compression_methods
- .contains(&Compression::Null)
- {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerIncompatible::NullCompressionRequired,
- ));
- }
-
- // No handshake messages should follow this one in this flight.
- cx.common.check_aligned_handshake()?;
-
- // Extract and validate the SNI DNS name, if any, before giving it to
- // the cert resolver. In particular, if it is invalid then we should
- // send an Illegal Parameter alert instead of the Internal Error alert
- // (or whatever) that we'd send if this were checked later or in a
- // different way.
- //
- // [RFC6066][] specifies that literal IP addresses are illegal in
- // `ServerName`s with a `name_type` of `host_name`.
- //
- // Some clients incorrectly send such extensions: we choose to
- // successfully parse these (into `ServerNamePayload::IpAddress`)
- // but then act like the client sent no `server_name` extension.
- //
- // [RFC6066]: https://datatracker.ietf.org/doc/html/rfc6066#section-3
- let sni = match &client_hello.server_name {
- Some(ServerNamePayload::SingleDnsName(dns_name)) => Some(dns_name.to_lowercase_owned()),
- Some(ServerNamePayload::IpAddress) => None,
- Some(ServerNamePayload::Invalid) => {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::ServerNameMustContainOneHostName,
- ));
- }
- None => None,
- };
-
- // save only the first SNI
- if let (Some(sni), false) = (&sni, done_retry) {
- // Save the SNI into the session.
- // The SNI hostname is immutable once set.
- assert!(cx.data.sni.is_none());
- cx.data.sni = Some(sni.clone());
- } else if cx.data.sni != sni {
- return Err(PeerMisbehaved::ServerNameDifferedOnRetry.into());
- }
-
- let sig_schemes = client_hello
- .signature_schemes
- .as_ref()
- .ok_or_else(|| {
- cx.common.send_fatal_alert(
- AlertDescription::HandshakeFailure,
- PeerIncompatible::SignatureAlgorithmsExtensionRequired,
- )
- })?;
-
- Ok((client_hello, sig_schemes.to_owned()))
-}
-
-pub(crate) enum HandshakeHashOrBuffer {
- Buffer(HandshakeHashBuffer),
- Hash(HandshakeHash),
-}
diff --git a/vendor/rustls/src/server/server_conn.rs b/vendor/rustls/src/server/server_conn.rs
deleted file mode 100644
index d1024b14..00000000
--- a/vendor/rustls/src/server/server_conn.rs
+++ /dev/null
@@ -1,1288 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec::Vec;
-use core::fmt;
-use core::fmt::{Debug, Formatter};
-use core::marker::PhantomData;
-use core::ops::{Deref, DerefMut};
-#[cfg(feature = "std")]
-use std::io;
-
-use pki_types::{DnsName, UnixTime};
-
-use super::hs;
-#[cfg(feature = "std")]
-use crate::WantsVerifier;
-use crate::builder::ConfigBuilder;
-use crate::common_state::{CommonState, Side};
-#[cfg(feature = "std")]
-use crate::common_state::{Protocol, State};
-use crate::conn::{ConnectionCommon, ConnectionCore, UnbufferedConnectionCommon};
-#[cfg(doc)]
-use crate::crypto;
-use crate::crypto::CryptoProvider;
-use crate::enums::{CertificateType, CipherSuite, ProtocolVersion, SignatureScheme};
-use crate::error::Error;
-use crate::kernel::KernelConnection;
-use crate::log::trace;
-use crate::msgs::base::Payload;
-use crate::msgs::handshake::{ClientHelloPayload, ProtocolName, ServerExtensionsInput};
-use crate::msgs::message::Message;
-use crate::suites::ExtractedSecrets;
-use crate::sync::Arc;
-#[cfg(feature = "std")]
-use crate::time_provider::DefaultTimeProvider;
-use crate::time_provider::TimeProvider;
-use crate::vecbuf::ChunkVecBuffer;
-use crate::{
- DistinguishedName, KeyLog, NamedGroup, WantsVersions, compress, sign, verify, versions,
-};
-
-/// A trait for the ability to store server session data.
-///
-/// The keys and values are opaque.
-///
-/// Inserted keys are randomly chosen by the library and have
-/// no internal structure (in other words, you may rely on all
-/// bits being uniformly random). Queried keys are untrusted data.
-///
-/// Both the keys and values should be treated as
-/// **highly sensitive data**, containing enough key material
-/// to break all security of the corresponding sessions.
-///
-/// Implementations can be lossy (in other words, forgetting
-/// key/value pairs) without any negative security consequences.
-///
-/// However, note that `take` **must** reliably delete a returned
-/// value. If it does not, there may be security consequences.
-///
-/// `put` and `take` are mutating operations; this isn't expressed
-/// in the type system to allow implementations freedom in
-/// how to achieve interior mutability. `Mutex` is a common
-/// choice.
-pub trait StoresServerSessions: Debug + Send + Sync {
- /// Store session secrets encoded in `value` against `key`,
- /// overwrites any existing value against `key`. Returns `true`
- /// if the value was stored.
- fn put(&self, key: Vec<u8>, value: Vec<u8>) -> bool;
-
- /// Find a value with the given `key`. Return it, or None
- /// if it doesn't exist.
- fn get(&self, key: &[u8]) -> Option<Vec<u8>>;
-
- /// Find a value with the given `key`. Return it and delete it;
- /// or None if it doesn't exist.
- fn take(&self, key: &[u8]) -> Option<Vec<u8>>;
-
- /// Whether the store can cache another session. This is used to indicate to clients
- /// whether their session can be resumed; the implementation is not required to remember
- /// a session even if it returns `true` here.
- fn can_cache(&self) -> bool;
-}
-
-/// A trait for the ability to encrypt and decrypt tickets.
-pub trait ProducesTickets: Debug + Send + Sync {
- /// Returns true if this implementation will encrypt/decrypt
- /// tickets. Should return false if this is a dummy
- /// implementation: the server will not send the SessionTicket
- /// extension and will not call the other functions.
- fn enabled(&self) -> bool;
-
- /// Returns the lifetime in seconds of tickets produced now.
- /// The lifetime is provided as a hint to clients that the
- /// ticket will not be useful after the given time.
- ///
- /// This lifetime must be implemented by key rolling and
- /// erasure, *not* by storing a lifetime in the ticket.
- ///
- /// The objective is to limit damage to forward secrecy caused
- /// by tickets, not just limiting their lifetime.
- fn lifetime(&self) -> u32;
-
- /// Encrypt and authenticate `plain`, returning the resulting
- /// ticket. Return None if `plain` cannot be encrypted for
- /// some reason: an empty ticket will be sent and the connection
- /// will continue.
- fn encrypt(&self, plain: &[u8]) -> Option<Vec<u8>>;
-
- /// Decrypt `cipher`, validating its authenticity protection
- /// and recovering the plaintext. `cipher` is fully attacker
- /// controlled, so this decryption must be side-channel free,
- /// panic-proof, and otherwise bullet-proof. If the decryption
- /// fails, return None.
- fn decrypt(&self, cipher: &[u8]) -> Option<Vec<u8>>;
-}
-
-/// How to choose a certificate chain and signing key for use
-/// in server authentication.
-///
-/// This is suitable when selecting a certificate does not require
-/// I/O or when the application is using blocking I/O anyhow.
-///
-/// For applications that use async I/O and need to do I/O to choose
-/// a certificate (for instance, fetching a certificate from a data store),
-/// the [`Acceptor`] interface is more suitable.
-pub trait ResolvesServerCert: Debug + Send + Sync {
- /// Choose a certificate chain and matching key given simplified
- /// ClientHello information.
- ///
- /// Return `None` to abort the handshake.
- fn resolve(&self, client_hello: ClientHello<'_>) -> Option<Arc<sign::CertifiedKey>>;
-
- /// Return true when the server only supports raw public keys.
- fn only_raw_public_keys(&self) -> bool {
- false
- }
-}
-
-/// A struct representing the received Client Hello
-#[derive(Debug)]
-pub struct ClientHello<'a> {
- pub(super) server_name: &'a Option<DnsName<'a>>,
- pub(super) signature_schemes: &'a [SignatureScheme],
- pub(super) alpn: Option<&'a Vec<ProtocolName>>,
- pub(super) server_cert_types: Option<&'a [CertificateType]>,
- pub(super) client_cert_types: Option<&'a [CertificateType]>,
- pub(super) cipher_suites: &'a [CipherSuite],
- /// The [certificate_authorities] extension, if it was sent by the client.
- ///
- /// [certificate_authorities]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.4
- pub(super) certificate_authorities: Option<&'a [DistinguishedName]>,
- pub(super) named_groups: Option<&'a [NamedGroup]>,
-}
-
-impl<'a> ClientHello<'a> {
- /// Get the server name indicator.
- ///
- /// Returns `None` if the client did not supply a SNI.
- pub fn server_name(&self) -> Option<&str> {
- self.server_name
- .as_ref()
- .map(<DnsName<'_> as AsRef<str>>::as_ref)
- }
-
- /// Get the compatible signature schemes.
- ///
- /// Returns standard-specified default if the client omitted this extension.
- pub fn signature_schemes(&self) -> &[SignatureScheme] {
- self.signature_schemes
- }
-
- /// Get the ALPN protocol identifiers submitted by the client.
- ///
- /// Returns `None` if the client did not include an ALPN extension.
- ///
- /// Application Layer Protocol Negotiation (ALPN) is a TLS extension that lets a client
- /// submit a set of identifiers that each a represent an application-layer protocol.
- /// The server will then pick its preferred protocol from the set submitted by the client.
- /// Each identifier is represented as a byte array, although common values are often ASCII-encoded.
- /// See the official RFC-7301 specifications at <https://datatracker.ietf.org/doc/html/rfc7301>
- /// for more information on ALPN.
- ///
- /// For example, a HTTP client might specify "http/1.1" and/or "h2". Other well-known values
- /// are listed in the at IANA registry at
- /// <https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids>.
- ///
- /// The server can specify supported ALPN protocols by setting [`ServerConfig::alpn_protocols`].
- /// During the handshake, the server will select the first protocol configured that the client supports.
- pub fn alpn(&self) -> Option<impl Iterator<Item = &'a [u8]>> {
- self.alpn.map(|protocols| {
- protocols
- .iter()
- .map(|proto| proto.as_ref())
- })
- }
-
- /// Get cipher suites.
- pub fn cipher_suites(&self) -> &[CipherSuite] {
- self.cipher_suites
- }
-
- /// Get the server certificate types offered in the ClientHello.
- ///
- /// Returns `None` if the client did not include a certificate type extension.
- pub fn server_cert_types(&self) -> Option<&'a [CertificateType]> {
- self.server_cert_types
- }
-
- /// Get the client certificate types offered in the ClientHello.
- ///
- /// Returns `None` if the client did not include a certificate type extension.
- pub fn client_cert_types(&self) -> Option<&'a [CertificateType]> {
- self.client_cert_types
- }
-
- /// Get the [certificate_authorities] extension sent by the client.
- ///
- /// Returns `None` if the client did not send this extension.
- ///
- /// [certificate_authorities]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.4
- pub fn certificate_authorities(&self) -> Option<&'a [DistinguishedName]> {
- self.certificate_authorities
- }
-
- /// Get the [`named_groups`] extension sent by the client.
- ///
- /// This means different things in different versions of TLS:
- ///
- /// Originally it was introduced as the "[`elliptic_curves`]" extension for TLS1.2.
- /// It described the elliptic curves supported by a client for all purposes: key
- /// exchange, signature verification (for server authentication), and signing (for
- /// client auth). Later [RFC7919] extended this to include FFDHE "named groups",
- /// but FFDHE groups in this context only relate to key exchange.
- ///
- /// In TLS1.3 it was renamed to "[`named_groups`]" and now describes all types
- /// of key exchange mechanisms, and does not relate at all to elliptic curves
- /// used for signatures.
- ///
- /// [`elliptic_curves`]: https://datatracker.ietf.org/doc/html/rfc4492#section-5.1.1
- /// [RFC7919]: https://datatracker.ietf.org/doc/html/rfc7919#section-2
- /// [`named_groups`]:https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.7
- pub fn named_groups(&self) -> Option<&'a [NamedGroup]> {
- self.named_groups
- }
-}
-
-/// Common configuration for a set of server sessions.
-///
-/// Making one of these is cheap, though one of the inputs may be expensive: gathering trust roots
-/// from the operating system to add to the [`RootCertStore`] passed to a `ClientCertVerifier`
-/// builder may take on the order of a few hundred milliseconds.
-///
-/// These must be created via the [`ServerConfig::builder()`] or [`ServerConfig::builder_with_provider()`]
-/// function.
-///
-/// # Defaults
-///
-/// * [`ServerConfig::max_fragment_size`]: the default is `None` (meaning 16kB).
-/// * [`ServerConfig::session_storage`]: if the `std` feature is enabled, the default stores 256
-/// sessions in memory. If the `std` feature is not enabled, the default is to not store any
-/// sessions. In a no-std context, by enabling the `hashbrown` feature you may provide your
-/// own `session_storage` using [`ServerSessionMemoryCache`] and a `crate::lock::MakeMutex`
-/// implementation.
-/// * [`ServerConfig::alpn_protocols`]: the default is empty -- no ALPN protocol is negotiated.
-/// * [`ServerConfig::key_log`]: key material is not logged.
-/// * [`ServerConfig::send_tls13_tickets`]: 2 tickets are sent.
-/// * [`ServerConfig::cert_compressors`]: depends on the crate features, see [`compress::default_cert_compressors()`].
-/// * [`ServerConfig::cert_compression_cache`]: caches the most recently used 4 compressions
-/// * [`ServerConfig::cert_decompressors`]: depends on the crate features, see [`compress::default_cert_decompressors()`].
-///
-/// # Sharing resumption storage between `ServerConfig`s
-///
-/// In a program using many `ServerConfig`s it may improve resumption rates
-/// (which has a significant impact on connection performance) if those
-/// configs share [`ServerConfig::session_storage`] or [`ServerConfig::ticketer`].
-///
-/// However, caution is needed: other fields influence the security of a session
-/// and resumption between them can be surprising. If sharing
-/// [`ServerConfig::session_storage`] or [`ServerConfig::ticketer`] between two
-/// `ServerConfig`s, you should also evaluate the following fields and ensure
-/// they are equivalent:
-///
-/// * `ServerConfig::verifier` -- client authentication requirements,
-/// * [`ServerConfig::cert_resolver`] -- server identities.
-///
-/// To illustrate, imagine two `ServerConfig`s `A` and `B`. `A` requires
-/// client authentication, `B` does not. If `A` and `B` shared a resumption store,
-/// it would be possible for a session originated by `B` (that is, an unauthenticated client)
-/// to be inserted into the store, and then resumed by `A`. This would give a false
-/// impression to the user of `A` that the client was authenticated. This is possible
-/// whether the resumption is performed statefully (via [`ServerConfig::session_storage`])
-/// or statelessly (via [`ServerConfig::ticketer`]).
-///
-/// _Unlike_ `ClientConfig`, rustls does not enforce any policy here.
-///
-/// [`RootCertStore`]: crate::RootCertStore
-/// [`ServerSessionMemoryCache`]: crate::server::handy::ServerSessionMemoryCache
-#[derive(Clone, Debug)]
-pub struct ServerConfig {
- /// Source of randomness and other crypto.
- pub(super) provider: Arc<CryptoProvider>,
-
- /// Ignore the client's ciphersuite order. Instead,
- /// choose the top ciphersuite in the server list
- /// which is supported by the client.
- pub ignore_client_order: bool,
-
- /// The maximum size of plaintext input to be emitted in a single TLS record.
- /// A value of None is equivalent to the [TLS maximum] of 16 kB.
- ///
- /// rustls enforces an arbitrary minimum of 32 bytes for this field.
- /// Out of range values are reported as errors from [ServerConnection::new].
- ///
- /// Setting this value to a little less than the TCP MSS may improve latency
- /// for stream-y workloads.
- ///
- /// [TLS maximum]: https://datatracker.ietf.org/doc/html/rfc8446#section-5.1
- /// [ServerConnection::new]: crate::server::ServerConnection::new
- pub max_fragment_size: Option<usize>,
-
- /// How to store client sessions.
- ///
- /// See [ServerConfig#sharing-resumption-storage-between-serverconfigs]
- /// for a warning related to this field.
- pub session_storage: Arc<dyn StoresServerSessions>,
-
- /// How to produce tickets.
- ///
- /// See [ServerConfig#sharing-resumption-storage-between-serverconfigs]
- /// for a warning related to this field.
- pub ticketer: Arc<dyn ProducesTickets>,
-
- /// How to choose a server cert and key. This is usually set by
- /// [ConfigBuilder::with_single_cert] or [ConfigBuilder::with_cert_resolver].
- /// For async applications, see also [Acceptor].
- pub cert_resolver: Arc<dyn ResolvesServerCert>,
-
- /// Protocol names we support, most preferred first.
- /// If empty we don't do ALPN at all.
- pub alpn_protocols: Vec<Vec<u8>>,
-
- /// Supported protocol versions, in no particular order.
- /// The default is all supported versions.
- pub(super) versions: versions::EnabledVersions,
-
- /// How to verify client certificates.
- pub(super) verifier: Arc<dyn verify::ClientCertVerifier>,
-
- /// How to output key material for debugging. The default
- /// does nothing.
- pub key_log: Arc<dyn KeyLog>,
-
- /// Allows traffic secrets to be extracted after the handshake,
- /// e.g. for kTLS setup.
- pub enable_secret_extraction: bool,
-
- /// Amount of early data to accept for sessions created by
- /// this config. Specify 0 to disable early data. The
- /// default is 0.
- ///
- /// Read the early data via [`ServerConnection::early_data`].
- ///
- /// The units for this are _both_ plaintext bytes, _and_ ciphertext
- /// bytes, depending on whether the server accepts a client's early_data
- /// or not. It is therefore recommended to include some slop in
- /// this value to account for the unknown amount of ciphertext
- /// expansion in the latter case.
- pub max_early_data_size: u32,
-
- /// Whether the server should send "0.5RTT" data. This means the server
- /// sends data after its first flight of handshake messages, without
- /// waiting for the client to complete the handshake.
- ///
- /// This can improve TTFB latency for either server-speaks-first protocols,
- /// or client-speaks-first protocols when paired with "0RTT" data. This
- /// comes at the cost of a subtle weakening of the normal handshake
- /// integrity guarantees that TLS provides. Note that the initial
- /// `ClientHello` is indirectly authenticated because it is included
- /// in the transcript used to derive the keys used to encrypt the data.
- ///
- /// This only applies to TLS1.3 connections. TLS1.2 connections cannot
- /// do this optimisation and this setting is ignored for them. It is
- /// also ignored for TLS1.3 connections that even attempt client
- /// authentication.
- ///
- /// This defaults to false. This means the first application data
- /// sent by the server comes after receiving and validating the client's
- /// handshake up to the `Finished` message. This is the safest option.
- pub send_half_rtt_data: bool,
-
- /// How many TLS1.3 tickets to send immediately after a successful
- /// handshake.
- ///
- /// Because TLS1.3 tickets are single-use, this allows
- /// a client to perform multiple resumptions.
- ///
- /// The default is 2.
- ///
- /// If this is 0, no tickets are sent and clients will not be able to
- /// do any resumption.
- pub send_tls13_tickets: usize,
-
- /// If set to `true`, requires the client to support the extended
- /// master secret extraction method defined in [RFC 7627].
- ///
- /// The default is `true` if the "fips" crate feature is enabled,
- /// `false` otherwise.
- ///
- /// It must be set to `true` to meet FIPS requirement mentioned in section
- /// **D.Q Transition of the TLS 1.2 KDF to Support the Extended Master
- /// Secret** from [FIPS 140-3 IG.pdf].
- ///
- /// [RFC 7627]: https://datatracker.ietf.org/doc/html/rfc7627
- /// [FIPS 140-3 IG.pdf]: https://csrc.nist.gov/csrc/media/Projects/cryptographic-module-validation-program/documents/fips%20140-3/FIPS%20140-3%20IG.pdf
- #[cfg(feature = "tls12")]
- pub require_ems: bool,
-
- /// Provides the current system time
- pub time_provider: Arc<dyn TimeProvider>,
-
- /// How to compress the server's certificate chain.
- ///
- /// If a client supports this extension, and advertises support
- /// for one of the compression algorithms included here, the
- /// server certificate will be compressed according to [RFC8779].
- ///
- /// This only applies to TLS1.3 connections. It is ignored for
- /// TLS1.2 connections.
- ///
- /// [RFC8779]: https://datatracker.ietf.org/doc/rfc8879/
- pub cert_compressors: Vec<&'static dyn compress::CertCompressor>,
-
- /// Caching for compressed certificates.
- ///
- /// This is optional: [`compress::CompressionCache::Disabled`] gives
- /// a cache that does no caching.
- pub cert_compression_cache: Arc<compress::CompressionCache>,
-
- /// How to decompress the clients's certificate chain.
- ///
- /// If this is non-empty, the [RFC8779] certificate compression
- /// extension is offered when requesting client authentication,
- /// and any compressed certificates are transparently decompressed
- /// during the handshake.
- ///
- /// This only applies to TLS1.3 connections. It is ignored for
- /// TLS1.2 connections.
- ///
- /// [RFC8779]: https://datatracker.ietf.org/doc/rfc8879/
- pub cert_decompressors: Vec<&'static dyn compress::CertDecompressor>,
-}
-
-impl ServerConfig {
- /// Create a builder for a server configuration with
- /// [the process-default `CryptoProvider`][CryptoProvider#using-the-per-process-default-cryptoprovider]
- /// and safe protocol version defaults.
- ///
- /// For more information, see the [`ConfigBuilder`] documentation.
- #[cfg(feature = "std")]
- pub fn builder() -> ConfigBuilder<Self, WantsVerifier> {
- Self::builder_with_protocol_versions(versions::DEFAULT_VERSIONS)
- }
-
- /// Create a builder for a server configuration with
- /// [the process-default `CryptoProvider`][CryptoProvider#using-the-per-process-default-cryptoprovider]
- /// and the provided protocol versions.
- ///
- /// Panics if
- /// - the supported versions are not compatible with the provider (eg.
- /// the combination of ciphersuites supported by the provider and supported
- /// versions lead to zero cipher suites being usable),
- /// - if a `CryptoProvider` cannot be resolved using a combination of
- /// the crate features and process default.
- ///
- /// For more information, see the [`ConfigBuilder`] documentation.
- #[cfg(feature = "std")]
- pub fn builder_with_protocol_versions(
- versions: &[&'static versions::SupportedProtocolVersion],
- ) -> ConfigBuilder<Self, WantsVerifier> {
- // Safety assumptions:
- // 1. that the provider has been installed (explicitly or implicitly)
- // 2. that the process-level default provider is usable with the supplied protocol versions.
- Self::builder_with_provider(
- CryptoProvider::get_default_or_install_from_crate_features().clone(),
- )
- .with_protocol_versions(versions)
- .unwrap()
- }
-
- /// Create a builder for a server configuration with a specific [`CryptoProvider`].
- ///
- /// This will use the provider's configured ciphersuites. You must additionally choose
- /// which protocol versions to enable, using `with_protocol_versions` or
- /// `with_safe_default_protocol_versions` and handling the `Result` in case a protocol
- /// version is not supported by the provider's ciphersuites.
- ///
- /// For more information, see the [`ConfigBuilder`] documentation.
- #[cfg(feature = "std")]
- pub fn builder_with_provider(
- provider: Arc<CryptoProvider>,
- ) -> ConfigBuilder<Self, WantsVersions> {
- ConfigBuilder {
- state: WantsVersions {},
- provider,
- time_provider: Arc::new(DefaultTimeProvider),
- side: PhantomData,
- }
- }
-
- /// Create a builder for a server configuration with no default implementation details.
- ///
- /// This API must be used by `no_std` users.
- ///
- /// You must provide a specific [`TimeProvider`].
- ///
- /// You must provide a specific [`CryptoProvider`].
- ///
- /// This will use the provider's configured ciphersuites. You must additionally choose
- /// which protocol versions to enable, using `with_protocol_versions` or
- /// `with_safe_default_protocol_versions` and handling the `Result` in case a protocol
- /// version is not supported by the provider's ciphersuites.
- ///
- /// For more information, see the [`ConfigBuilder`] documentation.
- pub fn builder_with_details(
- provider: Arc<CryptoProvider>,
- time_provider: Arc<dyn TimeProvider>,
- ) -> ConfigBuilder<Self, WantsVersions> {
- ConfigBuilder {
- state: WantsVersions {},
- provider,
- time_provider,
- side: PhantomData,
- }
- }
-
- /// Return `true` if connections made with this `ServerConfig` will
- /// operate in FIPS mode.
- ///
- /// This is different from [`CryptoProvider::fips()`]: [`CryptoProvider::fips()`]
- /// is concerned only with cryptography, whereas this _also_ covers TLS-level
- /// configuration that NIST recommends.
- pub fn fips(&self) -> bool {
- #[cfg(feature = "tls12")]
- {
- self.provider.fips() && self.require_ems
- }
-
- #[cfg(not(feature = "tls12"))]
- {
- self.provider.fips()
- }
- }
-
- /// Return the crypto provider used to construct this client configuration.
- pub fn crypto_provider(&self) -> &Arc<CryptoProvider> {
- &self.provider
- }
-
- /// We support a given TLS version if it's quoted in the configured
- /// versions *and* at least one ciphersuite for this version is
- /// also configured.
- pub(crate) fn supports_version(&self, v: ProtocolVersion) -> bool {
- self.versions.contains(v)
- && self
- .provider
- .cipher_suites
- .iter()
- .any(|cs| cs.version().version == v)
- }
-
- #[cfg(feature = "std")]
- pub(crate) fn supports_protocol(&self, proto: Protocol) -> bool {
- self.provider
- .cipher_suites
- .iter()
- .any(|cs| cs.usable_for_protocol(proto))
- }
-
- pub(super) fn current_time(&self) -> Result<UnixTime, Error> {
- self.time_provider
- .current_time()
- .ok_or(Error::FailedToGetCurrentTime)
- }
-}
-
-#[cfg(feature = "std")]
-mod connection {
- use alloc::boxed::Box;
- use core::fmt;
- use core::fmt::{Debug, Formatter};
- use core::ops::{Deref, DerefMut};
- use std::io;
-
- use super::{
- Accepted, Accepting, EarlyDataState, ServerConfig, ServerConnectionData,
- ServerExtensionsInput,
- };
- use crate::common_state::{CommonState, Context, Side};
- use crate::conn::{ConnectionCommon, ConnectionCore};
- use crate::error::Error;
- use crate::server::hs;
- use crate::suites::ExtractedSecrets;
- use crate::sync::Arc;
- use crate::vecbuf::ChunkVecBuffer;
-
- /// Allows reading of early data in resumed TLS1.3 connections.
- ///
- /// "Early data" is also known as "0-RTT data".
- ///
- /// This structure implements [`std::io::Read`].
- pub struct ReadEarlyData<'a> {
- early_data: &'a mut EarlyDataState,
- }
-
- impl<'a> ReadEarlyData<'a> {
- fn new(early_data: &'a mut EarlyDataState) -> Self {
- ReadEarlyData { early_data }
- }
- }
-
- impl io::Read for ReadEarlyData<'_> {
- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- self.early_data.read(buf)
- }
-
- #[cfg(read_buf)]
- fn read_buf(&mut self, cursor: core::io::BorrowedCursor<'_>) -> io::Result<()> {
- self.early_data.read_buf(cursor)
- }
- }
-
- /// This represents a single TLS server connection.
- ///
- /// Send TLS-protected data to the peer using the `io::Write` trait implementation.
- /// Read data from the peer using the `io::Read` trait implementation.
- pub struct ServerConnection {
- pub(super) inner: ConnectionCommon<ServerConnectionData>,
- }
-
- impl ServerConnection {
- /// Make a new ServerConnection. `config` controls how
- /// we behave in the TLS protocol.
- pub fn new(config: Arc<ServerConfig>) -> Result<Self, Error> {
- Ok(Self {
- inner: ConnectionCommon::from(ConnectionCore::for_server(
- config,
- ServerExtensionsInput::default(),
- )?),
- })
- }
-
- /// Retrieves the server name, if any, used to select the certificate and
- /// private key.
- ///
- /// This returns `None` until some time after the client's server name indication
- /// (SNI) extension value is processed during the handshake. It will never be
- /// `None` when the connection is ready to send or process application data,
- /// unless the client does not support SNI.
- ///
- /// This is useful for application protocols that need to enforce that the
- /// server name matches an application layer protocol hostname. For
- /// example, HTTP/1.1 servers commonly expect the `Host:` header field of
- /// every request on a connection to match the hostname in the SNI extension
- /// when the client provides the SNI extension.
- ///
- /// The server name is also used to match sessions during session resumption.
- pub fn server_name(&self) -> Option<&str> {
- self.inner.core.get_sni_str()
- }
-
- /// Application-controlled portion of the resumption ticket supplied by the client, if any.
- ///
- /// Recovered from the prior session's `set_resumption_data`. Integrity is guaranteed by rustls.
- ///
- /// Returns `Some` if and only if a valid resumption ticket has been received from the client.
- pub fn received_resumption_data(&self) -> Option<&[u8]> {
- self.inner
- .core
- .data
- .received_resumption_data
- .as_ref()
- .map(|x| &x[..])
- }
-
- /// Set the resumption data to embed in future resumption tickets supplied to the client.
- ///
- /// Defaults to the empty byte string. Must be less than 2^15 bytes to allow room for other
- /// data. Should be called while `is_handshaking` returns true to ensure all transmitted
- /// resumption tickets are affected.
- ///
- /// Integrity will be assured by rustls, but the data will be visible to the client. If secrecy
- /// from the client is desired, encrypt the data separately.
- pub fn set_resumption_data(&mut self, data: &[u8]) {
- assert!(data.len() < 2usize.pow(15));
- self.inner.core.data.resumption_data = data.into();
- }
-
- /// Explicitly discard early data, notifying the client
- ///
- /// Useful if invariants encoded in `received_resumption_data()` cannot be respected.
- ///
- /// Must be called while `is_handshaking` is true.
- pub fn reject_early_data(&mut self) {
- self.inner.core.reject_early_data()
- }
-
- /// Returns an `io::Read` implementer you can read bytes from that are
- /// received from a client as TLS1.3 0RTT/"early" data, during the handshake.
- ///
- /// This returns `None` in many circumstances, such as :
- ///
- /// - Early data is disabled if [`ServerConfig::max_early_data_size`] is zero (the default).
- /// - The session negotiated with the client is not TLS1.3.
- /// - The client just doesn't support early data.
- /// - The connection doesn't resume an existing session.
- /// - The client hasn't sent a full ClientHello yet.
- pub fn early_data(&mut self) -> Option<ReadEarlyData<'_>> {
- let data = &mut self.inner.core.data;
- if data.early_data.was_accepted() {
- Some(ReadEarlyData::new(&mut data.early_data))
- } else {
- None
- }
- }
-
- /// Return true if the connection was made with a `ServerConfig` that is FIPS compatible.
- ///
- /// This is different from [`crate::crypto::CryptoProvider::fips()`]:
- /// it is concerned only with cryptography, whereas this _also_ covers TLS-level
- /// configuration that NIST recommends, as well as ECH HPKE suites if applicable.
- pub fn fips(&self) -> bool {
- self.inner.core.common_state.fips
- }
-
- /// Extract secrets, so they can be used when configuring kTLS, for example.
- /// Should be used with care as it exposes secret key material.
- pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
- self.inner.dangerous_extract_secrets()
- }
- }
-
- impl Debug for ServerConnection {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- f.debug_struct("ServerConnection")
- .finish()
- }
- }
-
- impl Deref for ServerConnection {
- type Target = ConnectionCommon<ServerConnectionData>;
-
- fn deref(&self) -> &Self::Target {
- &self.inner
- }
- }
-
- impl DerefMut for ServerConnection {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.inner
- }
- }
-
- impl From<ServerConnection> for crate::Connection {
- fn from(conn: ServerConnection) -> Self {
- Self::Server(conn)
- }
- }
-
- /// Handle a server-side connection before configuration is available.
- ///
- /// `Acceptor` allows the caller to choose a [`ServerConfig`] after reading
- /// the [`super::ClientHello`] of an incoming connection. This is useful for servers
- /// that choose different certificates or cipher suites based on the
- /// characteristics of the `ClientHello`. In particular it is useful for
- /// servers that need to do some I/O to load a certificate and its private key
- /// and don't want to use the blocking interface provided by
- /// [`super::ResolvesServerCert`].
- ///
- /// Create an Acceptor with [`Acceptor::default()`].
- ///
- /// # Example
- ///
- /// ```no_run
- /// # #[cfg(feature = "aws_lc_rs")] {
- /// # fn choose_server_config(
- /// # _: rustls::server::ClientHello,
- /// # ) -> std::sync::Arc<rustls::ServerConfig> {
- /// # unimplemented!();
- /// # }
- /// # #[allow(unused_variables)]
- /// # fn main() {
- /// use rustls::server::{Acceptor, ServerConfig};
- /// let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
- /// for stream in listener.incoming() {
- /// let mut stream = stream.unwrap();
- /// let mut acceptor = Acceptor::default();
- /// let accepted = loop {
- /// acceptor.read_tls(&mut stream).unwrap();
- /// if let Some(accepted) = acceptor.accept().unwrap() {
- /// break accepted;
- /// }
- /// };
- ///
- /// // For some user-defined choose_server_config:
- /// let config = choose_server_config(accepted.client_hello());
- /// let conn = accepted
- /// .into_connection(config)
- /// .unwrap();
- ///
- /// // Proceed with handling the ServerConnection.
- /// }
- /// # }
- /// # }
- /// ```
- pub struct Acceptor {
- inner: Option<ConnectionCommon<ServerConnectionData>>,
- }
-
- impl Default for Acceptor {
- /// Return an empty Acceptor, ready to receive bytes from a new client connection.
- fn default() -> Self {
- Self {
- inner: Some(
- ConnectionCore::new(
- Box::new(Accepting),
- ServerConnectionData::default(),
- CommonState::new(Side::Server),
- )
- .into(),
- ),
- }
- }
- }
-
- impl Acceptor {
- /// Read TLS content from `rd`.
- ///
- /// Returns an error if this `Acceptor` has already yielded an [`Accepted`]. For more details,
- /// refer to [`Connection::read_tls()`].
- ///
- /// [`Connection::read_tls()`]: crate::Connection::read_tls
- pub fn read_tls(&mut self, rd: &mut dyn io::Read) -> Result<usize, io::Error> {
- match &mut self.inner {
- Some(conn) => conn.read_tls(rd),
- None => Err(io::Error::new(
- io::ErrorKind::Other,
- "acceptor cannot read after successful acceptance",
- )),
- }
- }
-
- /// Check if a `ClientHello` message has been received.
- ///
- /// Returns `Ok(None)` if the complete `ClientHello` has not yet been received.
- /// Do more I/O and then call this function again.
- ///
- /// Returns `Ok(Some(accepted))` if the connection has been accepted. Call
- /// `accepted.into_connection()` to continue. Do not call this function again.
- ///
- /// Returns `Err((err, alert))` if an error occurred. If an alert is returned, the
- /// application should call `alert.write()` to send the alert to the client. It should
- /// not call `accept()` again.
- pub fn accept(&mut self) -> Result<Option<Accepted>, (Error, AcceptedAlert)> {
- let Some(mut connection) = self.inner.take() else {
- return Err((
- Error::General("Acceptor polled after completion".into()),
- AcceptedAlert::empty(),
- ));
- };
-
- let message = match connection.first_handshake_message() {
- Ok(Some(msg)) => msg,
- Ok(None) => {
- self.inner = Some(connection);
- return Ok(None);
- }
- Err(err) => return Err((err, AcceptedAlert::from(connection))),
- };
-
- let mut cx = Context::from(&mut connection);
- let sig_schemes = match hs::process_client_hello(&message, false, &mut cx) {
- Ok((_, sig_schemes)) => sig_schemes,
- Err(err) => {
- return Err((err, AcceptedAlert::from(connection)));
- }
- };
-
- Ok(Some(Accepted {
- connection,
- message,
- sig_schemes,
- }))
- }
- }
-
- /// Represents a TLS alert resulting from handling the client's `ClientHello` message.
- ///
- /// When [`Acceptor::accept()`] returns an error, it yields an `AcceptedAlert` such that the
- /// application can communicate failure to the client via [`AcceptedAlert::write()`].
- pub struct AcceptedAlert(ChunkVecBuffer);
-
- impl AcceptedAlert {
- pub(super) fn empty() -> Self {
- Self(ChunkVecBuffer::new(None))
- }
-
- /// Send the alert to the client.
- ///
- /// To account for short writes this function should be called repeatedly until it
- /// returns `Ok(0)` or an error.
- pub fn write(&mut self, wr: &mut dyn io::Write) -> Result<usize, io::Error> {
- self.0.write_to(wr)
- }
-
- /// Send the alert to the client.
- ///
- /// This function will invoke the writer until the buffer is empty.
- pub fn write_all(&mut self, wr: &mut dyn io::Write) -> Result<(), io::Error> {
- while self.write(wr)? != 0 {}
- Ok(())
- }
- }
-
- impl From<ConnectionCommon<ServerConnectionData>> for AcceptedAlert {
- fn from(conn: ConnectionCommon<ServerConnectionData>) -> Self {
- Self(conn.core.common_state.sendable_tls)
- }
- }
-
- impl Debug for AcceptedAlert {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- f.debug_struct("AcceptedAlert").finish()
- }
- }
-}
-
-#[cfg(feature = "std")]
-pub use connection::{AcceptedAlert, Acceptor, ReadEarlyData, ServerConnection};
-
-/// Unbuffered version of `ServerConnection`
-///
-/// See the [`crate::unbuffered`] module docs for more details
-pub struct UnbufferedServerConnection {
- inner: UnbufferedConnectionCommon<ServerConnectionData>,
-}
-
-impl UnbufferedServerConnection {
- /// Make a new ServerConnection. `config` controls how we behave in the TLS protocol.
- pub fn new(config: Arc<ServerConfig>) -> Result<Self, Error> {
- Ok(Self {
- inner: UnbufferedConnectionCommon::from(ConnectionCore::for_server(
- config,
- ServerExtensionsInput::default(),
- )?),
- })
- }
-
- /// Extract secrets, so they can be used when configuring kTLS, for example.
- /// Should be used with care as it exposes secret key material.
- #[deprecated = "dangerous_extract_secrets() does not support session tickets or \
- key updates, use dangerous_into_kernel_connection() instead"]
- pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
- self.inner.dangerous_extract_secrets()
- }
-
- /// Extract secrets and an [`KernelConnection`] object.
- ///
- /// This allows you use rustls to manage keys and then manage encryption and
- /// decryption yourself (e.g. for kTLS).
- ///
- /// Should be used with care as it exposes secret key material.
- ///
- /// See the [`crate::kernel`] documentations for details on prerequisites
- /// for calling this method.
- pub fn dangerous_into_kernel_connection(
- self,
- ) -> Result<(ExtractedSecrets, KernelConnection<ServerConnectionData>), Error> {
- self.inner
- .core
- .dangerous_into_kernel_connection()
- }
-}
-
-impl Deref for UnbufferedServerConnection {
- type Target = UnbufferedConnectionCommon<ServerConnectionData>;
-
- fn deref(&self) -> &Self::Target {
- &self.inner
- }
-}
-
-impl DerefMut for UnbufferedServerConnection {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.inner
- }
-}
-
-impl UnbufferedConnectionCommon<ServerConnectionData> {
- pub(crate) fn pop_early_data(&mut self) -> Option<Vec<u8>> {
- self.core.data.early_data.pop()
- }
-
- pub(crate) fn peek_early_data(&self) -> Option<&[u8]> {
- self.core.data.early_data.peek()
- }
-}
-
-/// Represents a `ClientHello` message received through the [`Acceptor`].
-///
-/// Contains the state required to resume the connection through [`Accepted::into_connection()`].
-pub struct Accepted {
- connection: ConnectionCommon<ServerConnectionData>,
- message: Message<'static>,
- sig_schemes: Vec<SignatureScheme>,
-}
-
-impl Accepted {
- /// Get the [`ClientHello`] for this connection.
- pub fn client_hello(&self) -> ClientHello<'_> {
- let payload = Self::client_hello_payload(&self.message);
- let ch = ClientHello {
- server_name: &self.connection.core.data.sni,
- signature_schemes: &self.sig_schemes,
- alpn: payload.protocols.as_ref(),
- server_cert_types: payload
- .server_certificate_types
- .as_deref(),
- client_cert_types: payload
- .client_certificate_types
- .as_deref(),
- cipher_suites: &payload.cipher_suites,
- certificate_authorities: payload
- .certificate_authority_names
- .as_deref(),
- named_groups: payload.named_groups.as_deref(),
- };
-
- trace!("Accepted::client_hello(): {ch:#?}");
- ch
- }
-
- /// Convert the [`Accepted`] into a [`ServerConnection`].
- ///
- /// Takes the state returned from [`Acceptor::accept()`] as well as the [`ServerConfig`] and
- /// [`sign::CertifiedKey`] that should be used for the session. Returns an error if
- /// configuration-dependent validation of the received `ClientHello` message fails.
- #[cfg(feature = "std")]
- pub fn into_connection(
- mut self,
- config: Arc<ServerConfig>,
- ) -> Result<ServerConnection, (Error, AcceptedAlert)> {
- if let Err(err) = self
- .connection
- .set_max_fragment_size(config.max_fragment_size)
- {
- // We have a connection here, but it won't contain an alert since the error
- // is with the fragment size configured in the `ServerConfig`.
- return Err((err, AcceptedAlert::empty()));
- }
-
- self.connection.enable_secret_extraction = config.enable_secret_extraction;
-
- let state = hs::ExpectClientHello::new(config, ServerExtensionsInput::default());
- let mut cx = hs::ServerContext::from(&mut self.connection);
-
- let ch = Self::client_hello_payload(&self.message);
- let new = match state.with_certified_key(self.sig_schemes, ch, &self.message, &mut cx) {
- Ok(new) => new,
- Err(err) => return Err((err, AcceptedAlert::from(self.connection))),
- };
-
- self.connection.replace_state(new);
- Ok(ServerConnection {
- inner: self.connection,
- })
- }
-
- fn client_hello_payload<'a>(message: &'a Message<'_>) -> &'a ClientHelloPayload {
- match &message.payload {
- crate::msgs::message::MessagePayload::Handshake { parsed, .. } => match &parsed.0 {
- crate::msgs::handshake::HandshakePayload::ClientHello(ch) => ch,
- _ => unreachable!(),
- },
- _ => unreachable!(),
- }
- }
-}
-
-impl Debug for Accepted {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- f.debug_struct("Accepted").finish()
- }
-}
-
-#[cfg(feature = "std")]
-struct Accepting;
-
-#[cfg(feature = "std")]
-impl State<ServerConnectionData> for Accepting {
- fn handle<'m>(
- self: Box<Self>,
- _cx: &mut hs::ServerContext<'_>,
- _m: Message<'m>,
- ) -> Result<Box<dyn State<ServerConnectionData> + 'm>, Error>
- where
- Self: 'm,
- {
- Err(Error::General("unreachable state".into()))
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-pub(super) enum EarlyDataState {
- New,
- Accepted {
- received: ChunkVecBuffer,
- left: usize,
- },
- Rejected,
-}
-
-impl Default for EarlyDataState {
- fn default() -> Self {
- Self::New
- }
-}
-
-impl EarlyDataState {
- pub(super) fn reject(&mut self) {
- *self = Self::Rejected;
- }
-
- pub(super) fn accept(&mut self, max_size: usize) {
- *self = Self::Accepted {
- received: ChunkVecBuffer::new(Some(max_size)),
- left: max_size,
- };
- }
-
- #[cfg(feature = "std")]
- fn was_accepted(&self) -> bool {
- matches!(self, Self::Accepted { .. })
- }
-
- pub(super) fn was_rejected(&self) -> bool {
- matches!(self, Self::Rejected)
- }
-
- fn peek(&self) -> Option<&[u8]> {
- match self {
- Self::Accepted { received, .. } => received.peek(),
- _ => None,
- }
- }
-
- fn pop(&mut self) -> Option<Vec<u8>> {
- match self {
- Self::Accepted { received, .. } => received.pop(),
- _ => None,
- }
- }
-
- #[cfg(feature = "std")]
- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- match self {
- Self::Accepted { received, .. } => received.read(buf),
- _ => Err(io::Error::from(io::ErrorKind::BrokenPipe)),
- }
- }
-
- #[cfg(read_buf)]
- fn read_buf(&mut self, cursor: core::io::BorrowedCursor<'_>) -> io::Result<()> {
- match self {
- Self::Accepted { received, .. } => received.read_buf(cursor),
- _ => Err(io::Error::from(io::ErrorKind::BrokenPipe)),
- }
- }
-
- pub(super) fn take_received_plaintext(&mut self, bytes: Payload<'_>) -> bool {
- let available = bytes.bytes().len();
- let Self::Accepted { received, left } = self else {
- return false;
- };
-
- if received.apply_limit(available) != available || available > *left {
- return false;
- }
-
- received.append(bytes.into_vec());
- *left -= available;
- true
- }
-}
-
-impl Debug for EarlyDataState {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- match self {
- Self::New => write!(f, "EarlyDataState::New"),
- Self::Accepted { received, left } => write!(
- f,
- "EarlyDataState::Accepted {{ received: {}, left: {} }}",
- received.len(),
- left
- ),
- Self::Rejected => write!(f, "EarlyDataState::Rejected"),
- }
- }
-}
-
-impl ConnectionCore<ServerConnectionData> {
- pub(crate) fn for_server(
- config: Arc<ServerConfig>,
- extra_exts: ServerExtensionsInput<'static>,
- ) -> Result<Self, Error> {
- let mut common = CommonState::new(Side::Server);
- common.set_max_fragment_size(config.max_fragment_size)?;
- common.enable_secret_extraction = config.enable_secret_extraction;
- common.fips = config.fips();
- Ok(Self::new(
- Box::new(hs::ExpectClientHello::new(config, extra_exts)),
- ServerConnectionData::default(),
- common,
- ))
- }
-
- #[cfg(feature = "std")]
- pub(crate) fn reject_early_data(&mut self) {
- assert!(
- self.common_state.is_handshaking(),
- "cannot retroactively reject early data"
- );
- self.data.early_data.reject();
- }
-
- #[cfg(feature = "std")]
- pub(crate) fn get_sni_str(&self) -> Option<&str> {
- self.data.get_sni_str()
- }
-}
-
-/// State associated with a server connection.
-#[derive(Default, Debug)]
-pub struct ServerConnectionData {
- pub(super) sni: Option<DnsName<'static>>,
- pub(super) received_resumption_data: Option<Vec<u8>>,
- pub(super) resumption_data: Vec<u8>,
- pub(super) early_data: EarlyDataState,
-}
-
-impl ServerConnectionData {
- #[cfg(feature = "std")]
- pub(super) fn get_sni_str(&self) -> Option<&str> {
- self.sni.as_ref().map(AsRef::as_ref)
- }
-}
-
-impl crate::conn::SideData for ServerConnectionData {}
-
-#[cfg(feature = "std")]
-#[cfg(test)]
-mod tests {
- use std::format;
-
- use super::*;
-
- // these branches not reachable externally, unless something else goes wrong.
- #[test]
- fn test_read_in_new_state() {
- assert_eq!(
- format!("{:?}", EarlyDataState::default().read(&mut [0u8; 5])),
- "Err(Kind(BrokenPipe))"
- );
- }
-
- #[cfg(read_buf)]
- #[test]
- fn test_read_buf_in_new_state() {
- use core::io::BorrowedBuf;
-
- let mut buf = [0u8; 5];
- let mut buf: BorrowedBuf<'_> = buf.as_mut_slice().into();
- assert_eq!(
- format!("{:?}", EarlyDataState::default().read_buf(buf.unfilled())),
- "Err(Kind(BrokenPipe))"
- );
- }
-}
diff --git a/vendor/rustls/src/server/test.rs b/vendor/rustls/src/server/test.rs
deleted file mode 100644
index 9254dbc6..00000000
--- a/vendor/rustls/src/server/test.rs
+++ /dev/null
@@ -1,369 +0,0 @@
-use std::prelude::v1::*;
-use std::vec;
-
-use super::ServerConnectionData;
-use crate::common_state::Context;
-use crate::enums::{CipherSuite, SignatureScheme};
-use crate::msgs::base::PayloadU16;
-use crate::msgs::enums::{Compression, NamedGroup};
-use crate::msgs::handshake::{
- ClientExtensions, ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, KeyShareEntry,
- Random, ServerNamePayload, SessionId, SupportedProtocolVersions,
-};
-use crate::msgs::message::{Message, MessagePayload};
-use crate::{CommonState, Error, PeerIncompatible, PeerMisbehaved, ProtocolVersion, Side};
-
-#[test]
-fn null_compression_required() {
- assert_eq!(
- test_process_client_hello(ClientHelloPayload {
- compression_methods: vec![],
- ..minimal_client_hello()
- }),
- Err(PeerIncompatible::NullCompressionRequired.into()),
- );
-}
-
-#[test]
-fn server_ignores_sni_with_ip_address() {
- let mut ch = minimal_client_hello();
- ch.extensions.server_name = Some(ServerNamePayload::IpAddress);
- std::println!("{:?}", ch.extensions);
- assert_eq!(test_process_client_hello(ch), Ok(()));
-}
-
-#[test]
-fn server_rejects_sni_with_illegal_dns_name() {
- let mut ch = minimal_client_hello();
- ch.extensions.server_name = Some(ServerNamePayload::Invalid);
- std::println!("{:?}", ch.extensions);
- assert_eq!(
- test_process_client_hello(ch),
- Err(PeerMisbehaved::ServerNameMustContainOneHostName.into())
- );
-}
-
-fn test_process_client_hello(hello: ClientHelloPayload) -> Result<(), Error> {
- let m = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::handshake(HandshakeMessagePayload(HandshakePayload::ClientHello(
- hello,
- ))),
- };
- super::hs::process_client_hello(
- &m,
- false,
- &mut Context {
- common: &mut CommonState::new(Side::Server),
- data: &mut ServerConnectionData::default(),
- sendable_plaintext: None,
- },
- )
- .map(|_| ())
-}
-
-#[macro_rules_attribute::apply(test_for_each_provider)]
-mod tests {
- use super::super::*;
- use crate::common_state::KxState;
- use crate::crypto::{
- ActiveKeyExchange, CryptoProvider, KeyExchangeAlgorithm, SupportedKxGroup,
- };
- use crate::enums::CertificateType;
- use crate::pki_types::pem::PemObject;
- use crate::pki_types::{CertificateDer, PrivateKeyDer};
- use crate::server::{AlwaysResolvesServerRawPublicKeys, ServerConfig, ServerConnection};
- use crate::sign::CertifiedKey;
- use crate::sync::Arc;
- use crate::{CipherSuiteCommon, SupportedCipherSuite, Tls12CipherSuite, version};
-
- #[cfg(feature = "tls12")]
- #[test]
- fn test_server_rejects_no_extended_master_secret_extension_when_require_ems_or_fips() {
- let provider = super::provider::default_provider();
- let mut config = ServerConfig::builder_with_provider(provider.into())
- .with_protocol_versions(&[&version::TLS12])
- .unwrap()
- .with_no_client_auth()
- .with_single_cert(server_cert(), server_key())
- .unwrap();
-
- if config.provider.fips() {
- assert!(config.require_ems);
- } else {
- config.require_ems = true;
- }
- let mut conn = ServerConnection::new(config.into()).unwrap();
-
- let mut ch = minimal_client_hello();
- ch.extensions
- .extended_master_secret_request
- .take();
- let ch = Message {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::ClientHello(ch),
- )),
- };
- conn.read_tls(&mut ch.into_wire_bytes().as_slice())
- .unwrap();
-
- assert_eq!(
- conn.process_new_packets(),
- Err(Error::PeerIncompatible(
- PeerIncompatible::ExtendedMasterSecretExtensionRequired
- ))
- );
- }
-
- #[cfg(feature = "tls12")]
- #[test]
- fn server_picks_ffdhe_group_when_clienthello_has_no_ffdhe_group_in_groups_ext() {
- let config = ServerConfig::builder_with_provider(ffdhe_provider().into())
- .with_protocol_versions(&[&version::TLS12])
- .unwrap()
- .with_no_client_auth()
- .with_single_cert(server_cert(), server_key())
- .unwrap();
-
- let mut ch = minimal_client_hello();
- ch.cipher_suites
- .push(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256.suite());
-
- server_chooses_ffdhe_group_for_client_hello(
- ServerConnection::new(config.into()).unwrap(),
- ch,
- );
- }
-
- #[cfg(feature = "tls12")]
- #[test]
- fn server_picks_ffdhe_group_when_clienthello_has_no_groups_ext() {
- let config = ServerConfig::builder_with_provider(ffdhe_provider().into())
- .with_protocol_versions(&[&version::TLS12])
- .unwrap()
- .with_no_client_auth()
- .with_single_cert(server_cert(), server_key())
- .unwrap();
-
- let mut ch = minimal_client_hello();
- ch.cipher_suites
- .push(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256.suite());
- ch.extensions.named_groups.take();
-
- server_chooses_ffdhe_group_for_client_hello(
- ServerConnection::new(config.into()).unwrap(),
- ch,
- );
- }
-
- #[cfg(feature = "tls12")]
- #[test]
- fn server_accepts_client_with_no_ecpoints_extension_and_only_ffdhe_cipher_suites() {
- let config = ServerConfig::builder_with_provider(ffdhe_provider().into())
- .with_protocol_versions(&[&version::TLS12])
- .unwrap()
- .with_no_client_auth()
- .with_single_cert(server_cert(), server_key())
- .unwrap();
-
- let mut ch = minimal_client_hello();
- ch.cipher_suites
- .push(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256.suite());
- ch.extensions.ec_point_formats.take();
-
- server_chooses_ffdhe_group_for_client_hello(
- ServerConnection::new(config.into()).unwrap(),
- ch,
- );
- }
-
- fn server_chooses_ffdhe_group_for_client_hello(
- mut conn: ServerConnection,
- client_hello: ClientHelloPayload,
- ) {
- let ch = Message {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::ClientHello(client_hello),
- )),
- };
- conn.read_tls(&mut ch.into_wire_bytes().as_slice())
- .unwrap();
- conn.process_new_packets().unwrap();
-
- let KxState::Start(skxg) = &conn.kx_state else {
- panic!("unexpected kx_state");
- };
- assert_eq!(skxg.name(), FAKE_FFDHE_GROUP.name());
- }
-
- #[test]
- fn test_server_requiring_rpk_client_rejects_x509_client() {
- let mut ch = minimal_client_hello();
- ch.extensions.client_certificate_types = Some(vec![CertificateType::X509]);
- let ch = Message {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::ClientHello(ch),
- )),
- };
-
- let mut conn = ServerConnection::new(server_config_for_rpk().into()).unwrap();
- conn.read_tls(&mut ch.into_wire_bytes().as_slice())
- .unwrap();
- assert_eq!(
- conn.process_new_packets().unwrap_err(),
- PeerIncompatible::IncorrectCertificateTypeExtension.into(),
- );
- }
-
- #[test]
- fn test_rpk_only_server_rejects_x509_only_client() {
- let mut ch = minimal_client_hello();
- ch.extensions.server_certificate_types = Some(vec![CertificateType::X509]);
- let ch = Message {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::ClientHello(ch),
- )),
- };
-
- let mut conn = ServerConnection::new(server_config_for_rpk().into()).unwrap();
- conn.read_tls(&mut ch.into_wire_bytes().as_slice())
- .unwrap();
- assert_eq!(
- conn.process_new_packets().unwrap_err(),
- PeerIncompatible::IncorrectCertificateTypeExtension.into(),
- );
- }
-
- fn server_config_for_rpk() -> ServerConfig {
- let x25519_provider = CryptoProvider {
- kx_groups: vec![super::provider::kx_group::X25519],
- ..super::provider::default_provider()
- };
- ServerConfig::builder_with_provider(x25519_provider.into())
- .with_protocol_versions(&[&version::TLS13])
- .unwrap()
- .with_no_client_auth()
- .with_cert_resolver(Arc::new(AlwaysResolvesServerRawPublicKeys::new(Arc::new(
- server_certified_key(),
- ))))
- }
-
- fn server_certified_key() -> CertifiedKey {
- let key = super::provider::default_provider()
- .key_provider
- .load_private_key(server_key())
- .unwrap();
- let public_key_as_cert = vec![CertificateDer::from(
- key.public_key()
- .unwrap()
- .as_ref()
- .to_vec(),
- )];
- CertifiedKey::new(public_key_as_cert, key)
- }
-
- fn server_key() -> PrivateKeyDer<'static> {
- PrivateKeyDer::from_pem_reader(
- &mut include_bytes!("../../../test-ca/rsa-2048/end.key").as_slice(),
- )
- .unwrap()
- }
-
- fn server_cert() -> Vec<CertificateDer<'static>> {
- vec![
- CertificateDer::from(&include_bytes!("../../../test-ca/rsa-2048/end.der")[..]),
- CertificateDer::from(&include_bytes!("../../../test-ca/rsa-2048/inter.der")[..]),
- ]
- }
-
- fn ffdhe_provider() -> CryptoProvider {
- CryptoProvider {
- kx_groups: vec![FAKE_FFDHE_GROUP],
- cipher_suites: vec![TLS_DHE_RSA_WITH_AES_128_GCM_SHA256],
- ..super::provider::default_provider()
- }
- }
-
- static FAKE_FFDHE_GROUP: &'static dyn SupportedKxGroup = &FakeFfdheGroup;
-
- #[derive(Debug)]
- struct FakeFfdheGroup;
-
- impl SupportedKxGroup for FakeFfdheGroup {
- fn name(&self) -> NamedGroup {
- NamedGroup::FFDHE2048
- }
-
- fn start(&self) -> Result<Box<dyn ActiveKeyExchange>, Error> {
- Ok(Box::new(ActiveFakeFfdhe))
- }
- }
-
- #[derive(Debug)]
- struct ActiveFakeFfdhe;
-
- impl ActiveKeyExchange for ActiveFakeFfdhe {
- #[cfg_attr(coverage_nightly, coverage(off))]
- fn complete(
- self: Box<Self>,
- _peer_pub_key: &[u8],
- ) -> Result<crate::crypto::SharedSecret, Error> {
- todo!()
- }
-
- fn pub_key(&self) -> &[u8] {
- b"ActiveFakeFfdhe pub key"
- }
-
- fn group(&self) -> NamedGroup {
- NamedGroup::FFDHE2048
- }
- }
-
- static TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite =
- SupportedCipherSuite::Tls12(&TLS12_DHE_RSA_WITH_AES_128_GCM_SHA256);
-
- static TLS12_DHE_RSA_WITH_AES_128_GCM_SHA256: Tls12CipherSuite =
- match &super::provider::cipher_suite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 {
- SupportedCipherSuite::Tls12(provider) => Tls12CipherSuite {
- common: CipherSuiteCommon {
- suite: CipherSuite::TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
- ..provider.common
- },
- kx: KeyExchangeAlgorithm::DHE,
- ..**provider
- },
- _ => unreachable!(),
- };
-}
-
-fn minimal_client_hello() -> ClientHelloPayload {
- ClientHelloPayload {
- client_version: ProtocolVersion::TLSv1_3,
- random: Random::from([0u8; 32]),
- session_id: SessionId::empty(),
- cipher_suites: vec![
- CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- CipherSuite::TLS13_AES_128_GCM_SHA256,
- ],
- compression_methods: vec![Compression::Null],
- extensions: Box::new(ClientExtensions {
- signature_schemes: Some(vec![SignatureScheme::RSA_PSS_SHA256]),
- named_groups: Some(vec![NamedGroup::X25519, NamedGroup::secp256r1]),
- supported_versions: Some(SupportedProtocolVersions {
- tls12: true,
- tls13: true,
- }),
- key_shares: Some(vec![KeyShareEntry {
- group: NamedGroup::X25519,
- payload: PayloadU16::new(vec![0xab; 32]),
- }]),
- extended_master_secret_request: Some(()),
- ..ClientExtensions::default()
- }),
- }
-}
diff --git a/vendor/rustls/src/server/tls12.rs b/vendor/rustls/src/server/tls12.rs
deleted file mode 100644
index d3dfa5c8..00000000
--- a/vendor/rustls/src/server/tls12.rs
+++ /dev/null
@@ -1,1003 +0,0 @@
-use alloc::boxed::Box;
-use alloc::string::ToString;
-use alloc::vec;
-use alloc::vec::Vec;
-
-pub(super) use client_hello::CompleteClientHelloHandling;
-use pki_types::UnixTime;
-use subtle::ConstantTimeEq;
-
-use super::common::ActiveCertifiedKey;
-use super::hs::{self, ServerContext};
-use super::server_conn::{ProducesTickets, ServerConfig, ServerConnectionData};
-use crate::check::inappropriate_message;
-use crate::common_state::{CommonState, HandshakeFlightTls12, HandshakeKind, Side, State};
-use crate::conn::ConnectionRandoms;
-use crate::conn::kernel::{Direction, KernelContext, KernelState};
-use crate::crypto::ActiveKeyExchange;
-use crate::enums::{AlertDescription, ContentType, HandshakeType, ProtocolVersion};
-use crate::error::{Error, PeerIncompatible, PeerMisbehaved};
-use crate::hash_hs::HandshakeHash;
-use crate::log::{debug, trace};
-use crate::msgs::base::Payload;
-use crate::msgs::ccs::ChangeCipherSpecPayload;
-use crate::msgs::codec::Codec;
-use crate::msgs::handshake::{
- CertificateChain, ClientKeyExchangeParams, HandshakeMessagePayload, HandshakePayload,
- NewSessionTicketPayload, NewSessionTicketPayloadTls13, SessionId,
-};
-use crate::msgs::message::{Message, MessagePayload};
-use crate::msgs::persist;
-use crate::suites::PartiallyExtractedSecrets;
-use crate::sync::Arc;
-use crate::tls12::{self, ConnectionSecrets, Tls12CipherSuite};
-use crate::{ConnectionTrafficSecrets, verify};
-
-mod client_hello {
- use pki_types::CertificateDer;
-
- use super::*;
- use crate::common_state::KxState;
- use crate::crypto::SupportedKxGroup;
- use crate::enums::SignatureScheme;
- use crate::msgs::enums::{ClientCertificateType, Compression};
- use crate::msgs::handshake::{
- CertificateRequestPayload, CertificateStatus, ClientHelloPayload, ClientSessionTicket,
- Random, ServerExtensionsInput, ServerHelloPayload, ServerKeyExchange,
- ServerKeyExchangeParams, ServerKeyExchangePayload,
- };
- use crate::sign;
- use crate::verify::DigitallySignedStruct;
-
- pub(in crate::server) struct CompleteClientHelloHandling {
- pub(in crate::server) config: Arc<ServerConfig>,
- pub(in crate::server) transcript: HandshakeHash,
- pub(in crate::server) session_id: SessionId,
- pub(in crate::server) suite: &'static Tls12CipherSuite,
- pub(in crate::server) using_ems: bool,
- pub(in crate::server) randoms: ConnectionRandoms,
- pub(in crate::server) send_ticket: bool,
- pub(in crate::server) extra_exts: ServerExtensionsInput<'static>,
- }
-
- impl CompleteClientHelloHandling {
- pub(in crate::server) fn handle_client_hello(
- mut self,
- cx: &mut ServerContext<'_>,
- server_key: ActiveCertifiedKey<'_>,
- chm: &Message<'_>,
- client_hello: &ClientHelloPayload,
- selected_kxg: &'static dyn SupportedKxGroup,
- sigschemes_ext: Vec<SignatureScheme>,
- tls13_enabled: bool,
- ) -> hs::NextStateOrError<'static> {
- // -- TLS1.2 only from hereon in --
- self.transcript.add_message(chm);
-
- if client_hello
- .extended_master_secret_request
- .is_some()
- {
- self.using_ems = true;
- } else if self.config.require_ems {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::HandshakeFailure,
- PeerIncompatible::ExtendedMasterSecretExtensionRequired,
- ));
- }
-
- // "RFC 4492 specified that if this extension is missing,
- // it means that only the uncompressed point format is
- // supported"
- // - <https://datatracker.ietf.org/doc/html/rfc8422#section-5.1.2>
- let supported_ec_point_formats = client_hello
- .ec_point_formats
- .unwrap_or_default();
-
- trace!("ecpoints {supported_ec_point_formats:?}");
-
- if !supported_ec_point_formats.uncompressed {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerIncompatible::UncompressedEcPointsRequired,
- ));
- }
-
- // -- If TLS1.3 is enabled, signal the downgrade in the server random
- if tls13_enabled {
- self.randoms.server[24..].copy_from_slice(&tls12::DOWNGRADE_SENTINEL);
- }
-
- // -- Check for resumption --
- // We can do this either by (in order of preference):
- // 1. receiving a ticket that decrypts
- // 2. receiving a sessionid that is in our cache
- //
- // If we receive a ticket, the sessionid won't be in our
- // cache, so don't check.
- //
- // If either works, we end up with a ServerConnectionValue
- // which is passed to start_resumption and concludes
- // our handling of the ClientHello.
- //
- let mut ticket_received = false;
- let resume_data = client_hello
- .session_ticket
- .as_ref()
- .and_then(|ticket_ext| match ticket_ext {
- ClientSessionTicket::Offer(ticket) => Some(ticket),
- _ => None,
- })
- .and_then(|ticket| {
- ticket_received = true;
- debug!("Ticket received");
- let data = self
- .config
- .ticketer
- .decrypt(ticket.bytes());
- if data.is_none() {
- debug!("Ticket didn't decrypt");
- }
- data
- })
- .or_else(|| {
- // Perhaps resume? If we received a ticket, the sessionid
- // does not correspond to a real session.
- if client_hello.session_id.is_empty() || ticket_received {
- return None;
- }
-
- self.config
- .session_storage
- .get(client_hello.session_id.as_ref())
- })
- .and_then(|x| persist::ServerSessionValue::read_bytes(&x).ok())
- .filter(|resumedata| {
- hs::can_resume(self.suite.into(), &cx.data.sni, self.using_ems, resumedata)
- });
-
- if let Some(data) = resume_data {
- return self.start_resumption(cx, client_hello, &client_hello.session_id, data);
- }
-
- // Now we have chosen a ciphersuite, we can make kx decisions.
- let sigschemes = self
- .suite
- .resolve_sig_schemes(&sigschemes_ext);
-
- if sigschemes.is_empty() {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::HandshakeFailure,
- PeerIncompatible::NoSignatureSchemesInCommon,
- ));
- }
-
- let mut ocsp_response = server_key.get_ocsp();
-
- // If we're not offered a ticket or a potential session ID, allocate a session ID.
- if !self.config.session_storage.can_cache() {
- self.session_id = SessionId::empty();
- } else if self.session_id.is_empty() && !ticket_received {
- self.session_id = SessionId::random(self.config.provider.secure_random)?;
- }
-
- cx.common.kx_state = KxState::Start(selected_kxg);
- cx.common.handshake_kind = Some(HandshakeKind::Full);
-
- let mut flight = HandshakeFlightTls12::new(&mut self.transcript);
-
- self.send_ticket = emit_server_hello(
- &mut flight,
- &self.config,
- cx,
- self.session_id,
- self.suite,
- self.using_ems,
- &mut ocsp_response,
- client_hello,
- None,
- &self.randoms,
- self.extra_exts,
- )?;
- emit_certificate(&mut flight, server_key.get_cert());
- if let Some(ocsp_response) = ocsp_response {
- emit_cert_status(&mut flight, ocsp_response);
- }
- let server_kx = emit_server_kx(
- &mut flight,
- sigschemes,
- selected_kxg,
- server_key.get_key(),
- &self.randoms,
- )?;
- let doing_client_auth = emit_certificate_req(&mut flight, &self.config)?;
- emit_server_hello_done(&mut flight);
-
- flight.finish(cx.common);
-
- if doing_client_auth {
- Ok(Box::new(ExpectCertificate {
- config: self.config,
- transcript: self.transcript,
- randoms: self.randoms,
- session_id: self.session_id,
- suite: self.suite,
- using_ems: self.using_ems,
- server_kx,
- send_ticket: self.send_ticket,
- }))
- } else {
- Ok(Box::new(ExpectClientKx {
- config: self.config,
- transcript: self.transcript,
- randoms: self.randoms,
- session_id: self.session_id,
- suite: self.suite,
- using_ems: self.using_ems,
- server_kx,
- client_cert: None,
- send_ticket: self.send_ticket,
- }))
- }
- }
-
- fn start_resumption(
- mut self,
- cx: &mut ServerContext<'_>,
- client_hello: &ClientHelloPayload,
- id: &SessionId,
- resumedata: persist::ServerSessionValue,
- ) -> hs::NextStateOrError<'static> {
- debug!("Resuming connection");
-
- if resumedata.extended_ms && !self.using_ems {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::ResumptionAttemptedWithVariedEms,
- ));
- }
-
- self.session_id = *id;
- let mut flight = HandshakeFlightTls12::new(&mut self.transcript);
- self.send_ticket = emit_server_hello(
- &mut flight,
- &self.config,
- cx,
- self.session_id,
- self.suite,
- self.using_ems,
- &mut None,
- client_hello,
- Some(&resumedata),
- &self.randoms,
- self.extra_exts,
- )?;
- flight.finish(cx.common);
-
- let secrets = ConnectionSecrets::new_resume(
- self.randoms,
- self.suite,
- &resumedata.master_secret.0,
- );
- self.config.key_log.log(
- "CLIENT_RANDOM",
- &secrets.randoms.client,
- &secrets.master_secret,
- );
- cx.common
- .start_encryption_tls12(&secrets, Side::Server);
- cx.common.peer_certificates = resumedata.client_cert_chain;
- cx.common.handshake_kind = Some(HandshakeKind::Resumed);
-
- if self.send_ticket {
- let now = self.config.current_time()?;
-
- emit_ticket(
- &secrets,
- &mut self.transcript,
- self.using_ems,
- cx,
- &*self.config.ticketer,
- now,
- )?;
- }
- emit_ccs(cx.common);
- cx.common
- .record_layer
- .start_encrypting();
- emit_finished(&secrets, &mut self.transcript, cx.common);
-
- Ok(Box::new(ExpectCcs {
- config: self.config,
- secrets,
- transcript: self.transcript,
- session_id: self.session_id,
- using_ems: self.using_ems,
- resuming: true,
- send_ticket: self.send_ticket,
- }))
- }
- }
-
- fn emit_server_hello(
- flight: &mut HandshakeFlightTls12<'_>,
- config: &ServerConfig,
- cx: &mut ServerContext<'_>,
- session_id: SessionId,
- suite: &'static Tls12CipherSuite,
- using_ems: bool,
- ocsp_response: &mut Option<&[u8]>,
- hello: &ClientHelloPayload,
- resumedata: Option<&persist::ServerSessionValue>,
- randoms: &ConnectionRandoms,
- extra_exts: ServerExtensionsInput<'static>,
- ) -> Result<bool, Error> {
- let mut ep = hs::ExtensionProcessing::new(extra_exts);
- ep.process_common(config, cx, ocsp_response, hello, resumedata)?;
- ep.process_tls12(config, hello, using_ems);
-
- let sh = HandshakeMessagePayload(HandshakePayload::ServerHello(ServerHelloPayload {
- legacy_version: ProtocolVersion::TLSv1_2,
- random: Random::from(randoms.server),
- session_id,
- cipher_suite: suite.common.suite,
- compression_method: Compression::Null,
- extensions: ep.extensions,
- }));
- trace!("sending server hello {sh:?}");
- flight.add(sh);
-
- Ok(ep.send_ticket)
- }
-
- fn emit_certificate(
- flight: &mut HandshakeFlightTls12<'_>,
- cert_chain: &[CertificateDer<'static>],
- ) {
- flight.add(HandshakeMessagePayload(HandshakePayload::Certificate(
- CertificateChain(cert_chain.to_vec()),
- )));
- }
-
- fn emit_cert_status(flight: &mut HandshakeFlightTls12<'_>, ocsp: &[u8]) {
- flight.add(HandshakeMessagePayload(
- HandshakePayload::CertificateStatus(CertificateStatus::new(ocsp)),
- ));
- }
-
- fn emit_server_kx(
- flight: &mut HandshakeFlightTls12<'_>,
- sigschemes: Vec<SignatureScheme>,
- selected_group: &'static dyn SupportedKxGroup,
- signing_key: &dyn sign::SigningKey,
- randoms: &ConnectionRandoms,
- ) -> Result<Box<dyn ActiveKeyExchange>, Error> {
- let kx = selected_group.start()?;
- let kx_params = ServerKeyExchangeParams::new(&*kx);
-
- let mut msg = Vec::new();
- msg.extend(randoms.client);
- msg.extend(randoms.server);
- kx_params.encode(&mut msg);
-
- let signer = signing_key
- .choose_scheme(&sigschemes)
- .ok_or_else(|| Error::General("incompatible signing key".to_string()))?;
- let sigscheme = signer.scheme();
- let sig = signer.sign(&msg)?;
-
- let skx = ServerKeyExchangePayload::from(ServerKeyExchange {
- params: kx_params,
- dss: DigitallySignedStruct::new(sigscheme, sig),
- });
-
- flight.add(HandshakeMessagePayload(
- HandshakePayload::ServerKeyExchange(skx),
- ));
- Ok(kx)
- }
-
- fn emit_certificate_req(
- flight: &mut HandshakeFlightTls12<'_>,
- config: &ServerConfig,
- ) -> Result<bool, Error> {
- let client_auth = &config.verifier;
-
- if !client_auth.offer_client_auth() {
- return Ok(false);
- }
-
- let verify_schemes = client_auth.supported_verify_schemes();
-
- let names = config
- .verifier
- .root_hint_subjects()
- .to_vec();
-
- let cr = CertificateRequestPayload {
- certtypes: vec![
- ClientCertificateType::RSASign,
- ClientCertificateType::ECDSASign,
- ],
- sigschemes: verify_schemes,
- canames: names,
- };
-
- let creq = HandshakeMessagePayload(HandshakePayload::CertificateRequest(cr));
-
- trace!("Sending CertificateRequest {creq:?}");
- flight.add(creq);
- Ok(true)
- }
-
- fn emit_server_hello_done(flight: &mut HandshakeFlightTls12<'_>) {
- flight.add(HandshakeMessagePayload(HandshakePayload::ServerHelloDone));
- }
-}
-
-// --- Process client's Certificate for client auth ---
-struct ExpectCertificate {
- config: Arc<ServerConfig>,
- transcript: HandshakeHash,
- randoms: ConnectionRandoms,
- session_id: SessionId,
- suite: &'static Tls12CipherSuite,
- using_ems: bool,
- server_kx: Box<dyn ActiveKeyExchange>,
- send_ticket: bool,
-}
-
-impl State<ServerConnectionData> for ExpectCertificate {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ServerContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- self.transcript.add_message(&m);
- let cert_chain = require_handshake_msg_move!(
- m,
- HandshakeType::Certificate,
- HandshakePayload::Certificate
- )?;
-
- // If we can't determine if the auth is mandatory, abort
- let mandatory = self
- .config
- .verifier
- .client_auth_mandatory();
-
- trace!("certs {cert_chain:?}");
-
- let client_cert = match cert_chain.split_first() {
- None if mandatory => {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::CertificateRequired,
- Error::NoCertificatesPresented,
- ));
- }
- None => {
- debug!("client auth requested but no certificate supplied");
- self.transcript.abandon_client_auth();
- None
- }
- Some((end_entity, intermediates)) => {
- let now = self.config.current_time()?;
-
- self.config
- .verifier
- .verify_client_cert(end_entity, intermediates, now)
- .map_err(|err| {
- cx.common
- .send_cert_verify_error_alert(err)
- })?;
-
- Some(cert_chain)
- }
- };
-
- Ok(Box::new(ExpectClientKx {
- config: self.config,
- transcript: self.transcript,
- randoms: self.randoms,
- session_id: self.session_id,
- suite: self.suite,
- using_ems: self.using_ems,
- server_kx: self.server_kx,
- client_cert,
- send_ticket: self.send_ticket,
- }))
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-// --- Process client's KeyExchange ---
-struct ExpectClientKx<'a> {
- config: Arc<ServerConfig>,
- transcript: HandshakeHash,
- randoms: ConnectionRandoms,
- session_id: SessionId,
- suite: &'static Tls12CipherSuite,
- using_ems: bool,
- server_kx: Box<dyn ActiveKeyExchange>,
- client_cert: Option<CertificateChain<'a>>,
- send_ticket: bool,
-}
-
-impl State<ServerConnectionData> for ExpectClientKx<'_> {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ServerContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- let client_kx = require_handshake_msg!(
- m,
- HandshakeType::ClientKeyExchange,
- HandshakePayload::ClientKeyExchange
- )?;
- self.transcript.add_message(&m);
- let ems_seed = self
- .using_ems
- .then(|| self.transcript.current_hash());
-
- // Complete key agreement, and set up encryption with the
- // resulting premaster secret.
- let peer_kx_params = tls12::decode_kx_params::<ClientKeyExchangeParams>(
- self.suite.kx,
- cx.common,
- client_kx.bytes(),
- )?;
- let secrets = ConnectionSecrets::from_key_exchange(
- self.server_kx,
- peer_kx_params.pub_key(),
- ems_seed,
- self.randoms,
- self.suite,
- )
- .map_err(|err| {
- cx.common
- .send_fatal_alert(AlertDescription::IllegalParameter, err)
- })?;
- cx.common.kx_state.complete();
-
- self.config.key_log.log(
- "CLIENT_RANDOM",
- &secrets.randoms.client,
- &secrets.master_secret,
- );
- cx.common
- .start_encryption_tls12(&secrets, Side::Server);
-
- match self.client_cert {
- Some(client_cert) => Ok(Box::new(ExpectCertificateVerify {
- config: self.config,
- secrets,
- transcript: self.transcript,
- session_id: self.session_id,
- using_ems: self.using_ems,
- client_cert,
- send_ticket: self.send_ticket,
- })),
- _ => Ok(Box::new(ExpectCcs {
- config: self.config,
- secrets,
- transcript: self.transcript,
- session_id: self.session_id,
- using_ems: self.using_ems,
- resuming: false,
- send_ticket: self.send_ticket,
- })),
- }
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- Box::new(ExpectClientKx {
- config: self.config,
- transcript: self.transcript,
- randoms: self.randoms,
- session_id: self.session_id,
- suite: self.suite,
- using_ems: self.using_ems,
- server_kx: self.server_kx,
- client_cert: self
- .client_cert
- .map(|cert| cert.into_owned()),
- send_ticket: self.send_ticket,
- })
- }
-}
-
-// --- Process client's certificate proof ---
-struct ExpectCertificateVerify<'a> {
- config: Arc<ServerConfig>,
- secrets: ConnectionSecrets,
- transcript: HandshakeHash,
- session_id: SessionId,
- using_ems: bool,
- client_cert: CertificateChain<'a>,
- send_ticket: bool,
-}
-
-impl State<ServerConnectionData> for ExpectCertificateVerify<'_> {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ServerContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- let rc = {
- let sig = require_handshake_msg!(
- m,
- HandshakeType::CertificateVerify,
- HandshakePayload::CertificateVerify
- )?;
-
- match self.transcript.take_handshake_buf() {
- Some(msgs) => {
- let certs = &self.client_cert;
- self.config
- .verifier
- .verify_tls12_signature(&msgs, &certs[0], sig)
- }
- None => {
- // This should be unreachable; the handshake buffer was initialized with
- // client authentication if the verifier wants to offer it.
- // `transcript.abandon_client_auth()` can extract it, but its only caller in
- // this flow will also set `ExpectClientKx::client_cert` to `None`, making it
- // impossible to reach this state.
- return Err(cx.common.send_fatal_alert(
- AlertDescription::AccessDenied,
- Error::General("client authentication not set up".into()),
- ));
- }
- }
- };
-
- if let Err(e) = rc {
- return Err(cx
- .common
- .send_cert_verify_error_alert(e));
- }
-
- trace!("client CertificateVerify OK");
- cx.common.peer_certificates = Some(self.client_cert.into_owned());
-
- self.transcript.add_message(&m);
- Ok(Box::new(ExpectCcs {
- config: self.config,
- secrets: self.secrets,
- transcript: self.transcript,
- session_id: self.session_id,
- using_ems: self.using_ems,
- resuming: false,
- send_ticket: self.send_ticket,
- }))
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- Box::new(ExpectCertificateVerify {
- config: self.config,
- secrets: self.secrets,
- transcript: self.transcript,
- session_id: self.session_id,
- using_ems: self.using_ems,
- client_cert: self.client_cert.into_owned(),
- send_ticket: self.send_ticket,
- })
- }
-}
-
-// --- Process client's ChangeCipherSpec ---
-struct ExpectCcs {
- config: Arc<ServerConfig>,
- secrets: ConnectionSecrets,
- transcript: HandshakeHash,
- session_id: SessionId,
- using_ems: bool,
- resuming: bool,
- send_ticket: bool,
-}
-
-impl State<ServerConnectionData> for ExpectCcs {
- fn handle<'m>(
- self: Box<Self>,
- cx: &mut ServerContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- match m.payload {
- MessagePayload::ChangeCipherSpec(..) => {}
- payload => {
- return Err(inappropriate_message(
- &payload,
- &[ContentType::ChangeCipherSpec],
- ));
- }
- }
-
- // CCS should not be received interleaved with fragmented handshake-level
- // message.
- cx.common.check_aligned_handshake()?;
-
- cx.common
- .record_layer
- .start_decrypting();
- Ok(Box::new(ExpectFinished {
- config: self.config,
- secrets: self.secrets,
- transcript: self.transcript,
- session_id: self.session_id,
- using_ems: self.using_ems,
- resuming: self.resuming,
- send_ticket: self.send_ticket,
- }))
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-// --- Process client's Finished ---
-fn get_server_connection_value_tls12(
- secrets: &ConnectionSecrets,
- using_ems: bool,
- cx: &ServerContext<'_>,
- time_now: UnixTime,
-) -> persist::ServerSessionValue {
- let version = ProtocolVersion::TLSv1_2;
-
- let mut v = persist::ServerSessionValue::new(
- cx.data.sni.as_ref(),
- version,
- secrets.suite().common.suite,
- secrets.master_secret(),
- cx.common.peer_certificates.clone(),
- cx.common.alpn_protocol.clone(),
- cx.data.resumption_data.clone(),
- time_now,
- 0,
- );
-
- if using_ems {
- v.set_extended_ms_used();
- }
-
- v
-}
-
-fn emit_ticket(
- secrets: &ConnectionSecrets,
- transcript: &mut HandshakeHash,
- using_ems: bool,
- cx: &mut ServerContext<'_>,
- ticketer: &dyn ProducesTickets,
- now: UnixTime,
-) -> Result<(), Error> {
- let plain = get_server_connection_value_tls12(secrets, using_ems, cx, now).get_encoding();
-
- // If we can't produce a ticket for some reason, we can't
- // report an error. Send an empty one.
- let ticket = ticketer
- .encrypt(&plain)
- .unwrap_or_default();
- let ticket_lifetime = ticketer.lifetime();
-
- let m = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::NewSessionTicket(NewSessionTicketPayload::new(
- ticket_lifetime,
- ticket,
- )),
- )),
- };
-
- transcript.add_message(&m);
- cx.common.send_msg(m, false);
- Ok(())
-}
-
-fn emit_ccs(common: &mut CommonState) {
- let m = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::ChangeCipherSpec(ChangeCipherSpecPayload {}),
- };
-
- common.send_msg(m, false);
-}
-
-fn emit_finished(
- secrets: &ConnectionSecrets,
- transcript: &mut HandshakeHash,
- common: &mut CommonState,
-) {
- let vh = transcript.current_hash();
- let verify_data = secrets.server_verify_data(&vh);
- let verify_data_payload = Payload::new(verify_data);
-
- let f = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::handshake(HandshakeMessagePayload(HandshakePayload::Finished(
- verify_data_payload,
- ))),
- };
-
- transcript.add_message(&f);
- common.send_msg(f, true);
-}
-
-struct ExpectFinished {
- config: Arc<ServerConfig>,
- secrets: ConnectionSecrets,
- transcript: HandshakeHash,
- session_id: SessionId,
- using_ems: bool,
- resuming: bool,
- send_ticket: bool,
-}
-
-impl State<ServerConnectionData> for ExpectFinished {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ServerContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- let finished =
- require_handshake_msg!(m, HandshakeType::Finished, HandshakePayload::Finished)?;
-
- cx.common.check_aligned_handshake()?;
-
- let vh = self.transcript.current_hash();
- let expect_verify_data = self.secrets.client_verify_data(&vh);
-
- let _fin_verified =
- match ConstantTimeEq::ct_eq(&expect_verify_data[..], finished.bytes()).into() {
- true => verify::FinishedMessageVerified::assertion(),
- false => {
- return Err(cx
- .common
- .send_fatal_alert(AlertDescription::DecryptError, Error::DecryptError));
- }
- };
-
- // Save connection, perhaps
- if !self.resuming && !self.session_id.is_empty() {
- let now = self.config.current_time()?;
-
- let value = get_server_connection_value_tls12(&self.secrets, self.using_ems, cx, now);
-
- let worked = self
- .config
- .session_storage
- .put(self.session_id.as_ref().to_vec(), value.get_encoding());
- #[cfg_attr(not(feature = "logging"), allow(clippy::if_same_then_else))]
- if worked {
- debug!("Session saved");
- } else {
- debug!("Session not saved");
- }
- }
-
- // Send our CCS and Finished.
- self.transcript.add_message(&m);
- if !self.resuming {
- if self.send_ticket {
- let now = self.config.current_time()?;
- emit_ticket(
- &self.secrets,
- &mut self.transcript,
- self.using_ems,
- cx,
- &*self.config.ticketer,
- now,
- )?;
- }
- emit_ccs(cx.common);
- cx.common
- .record_layer
- .start_encrypting();
- emit_finished(&self.secrets, &mut self.transcript, cx.common);
- }
-
- cx.common
- .start_traffic(&mut cx.sendable_plaintext);
- Ok(Box::new(ExpectTraffic {
- secrets: self.secrets,
- _fin_verified,
- }))
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-// --- Process traffic ---
-struct ExpectTraffic {
- secrets: ConnectionSecrets,
- _fin_verified: verify::FinishedMessageVerified,
-}
-
-impl ExpectTraffic {}
-
-impl State<ServerConnectionData> for ExpectTraffic {
- fn handle<'m>(
- self: Box<Self>,
- cx: &mut ServerContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- match m.payload {
- MessagePayload::ApplicationData(payload) => cx
- .common
- .take_received_plaintext(payload),
- payload => {
- return Err(inappropriate_message(
- &payload,
- &[ContentType::ApplicationData],
- ));
- }
- }
- Ok(self)
- }
-
- fn export_keying_material(
- &self,
- output: &mut [u8],
- label: &[u8],
- context: Option<&[u8]>,
- ) -> Result<(), Error> {
- self.secrets
- .export_keying_material(output, label, context);
- Ok(())
- }
-
- fn extract_secrets(&self) -> Result<PartiallyExtractedSecrets, Error> {
- self.secrets
- .extract_secrets(Side::Server)
- }
-
- fn into_external_state(self: Box<Self>) -> Result<Box<dyn KernelState + 'static>, Error> {
- Ok(self)
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-impl KernelState for ExpectTraffic {
- fn update_secrets(&mut self, _: Direction) -> Result<ConnectionTrafficSecrets, Error> {
- Err(Error::General(
- "TLS 1.2 connections do not support traffic secret updates".into(),
- ))
- }
-
- fn handle_new_session_ticket(
- &mut self,
- _cx: &mut KernelContext<'_>,
- _message: &NewSessionTicketPayloadTls13,
- ) -> Result<(), Error> {
- unreachable!(
- "server connections should never have handle_new_session_ticket called on them"
- )
- }
-}
diff --git a/vendor/rustls/src/server/tls13.rs b/vendor/rustls/src/server/tls13.rs
deleted file mode 100644
index b8b70e72..00000000
--- a/vendor/rustls/src/server/tls13.rs
+++ /dev/null
@@ -1,1535 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec;
-use alloc::vec::Vec;
-
-pub(super) use client_hello::CompleteClientHelloHandling;
-use pki_types::{CertificateDer, UnixTime};
-use subtle::ConstantTimeEq;
-
-use super::hs::{self, HandshakeHashOrBuffer, ServerContext};
-use super::server_conn::ServerConnectionData;
-use crate::check::{inappropriate_handshake_message, inappropriate_message};
-use crate::common_state::{
- CommonState, HandshakeFlightTls13, HandshakeKind, Protocol, Side, State,
-};
-use crate::conn::ConnectionRandoms;
-use crate::conn::kernel::{Direction, KernelContext, KernelState};
-use crate::enums::{AlertDescription, ContentType, HandshakeType, ProtocolVersion};
-use crate::error::{Error, InvalidMessage, PeerIncompatible, PeerMisbehaved};
-use crate::hash_hs::HandshakeHash;
-use crate::log::{debug, trace, warn};
-use crate::msgs::codec::{Codec, Reader};
-use crate::msgs::enums::KeyUpdateRequest;
-use crate::msgs::handshake::{
- CERTIFICATE_MAX_SIZE_LIMIT, CertificateChain, CertificatePayloadTls13, HandshakeMessagePayload,
- HandshakePayload, NewSessionTicketPayloadTls13,
-};
-use crate::msgs::message::{Message, MessagePayload};
-use crate::msgs::persist;
-use crate::server::ServerConfig;
-use crate::suites::PartiallyExtractedSecrets;
-use crate::sync::Arc;
-use crate::tls13::key_schedule::{
- KeyScheduleResumption, KeyScheduleTraffic, KeyScheduleTrafficWithClientFinishedPending,
-};
-use crate::tls13::{
- Tls13CipherSuite, construct_client_verify_message, construct_server_verify_message,
-};
-use crate::{ConnectionTrafficSecrets, compress, rand, verify};
-
-mod client_hello {
- use super::*;
- use crate::compress::CertCompressor;
- use crate::crypto::SupportedKxGroup;
- use crate::enums::SignatureScheme;
- use crate::msgs::base::{Payload, PayloadU8};
- use crate::msgs::ccs::ChangeCipherSpecPayload;
- use crate::msgs::enums::{Compression, NamedGroup};
- use crate::msgs::handshake::{
- CertificatePayloadTls13, CertificateRequestExtensions, CertificateRequestPayloadTls13,
- ClientHelloPayload, HelloRetryRequest, HelloRetryRequestExtensions, KeyShareEntry, Random,
- ServerExtensions, ServerExtensionsInput, ServerHelloPayload, SessionId,
- };
- use crate::server::common::ActiveCertifiedKey;
- use crate::sign;
- use crate::tls13::key_schedule::{
- KeyScheduleEarly, KeyScheduleHandshake, KeySchedulePreHandshake,
- };
- use crate::verify::DigitallySignedStruct;
-
- #[derive(PartialEq)]
- pub(super) enum EarlyDataDecision {
- Disabled,
- RequestedButRejected,
- Accepted,
- }
-
- pub(in crate::server) struct CompleteClientHelloHandling {
- pub(in crate::server) config: Arc<ServerConfig>,
- pub(in crate::server) transcript: HandshakeHash,
- pub(in crate::server) suite: &'static Tls13CipherSuite,
- pub(in crate::server) randoms: ConnectionRandoms,
- pub(in crate::server) done_retry: bool,
- pub(in crate::server) send_tickets: usize,
- pub(in crate::server) extra_exts: ServerExtensionsInput<'static>,
- }
-
- fn max_early_data_size(configured: u32) -> usize {
- if configured != 0 {
- configured as usize
- } else {
- // The relevant max_early_data_size may in fact be unknowable: if
- // we (the server) have turned off early_data but the client has
- // a stale ticket from when we allowed early_data: we'll naturally
- // reject early_data but need an upper bound on the amount of data
- // to drop.
- //
- // Use a single maximum-sized message.
- 16384
- }
- }
-
- impl CompleteClientHelloHandling {
- fn check_binder(
- &self,
- suite: &'static Tls13CipherSuite,
- client_hello: &Message<'_>,
- psk: &[u8],
- binder: &[u8],
- ) -> bool {
- let binder_plaintext = match &client_hello.payload {
- MessagePayload::Handshake { parsed, encoded } => {
- &encoded.bytes()[..encoded.bytes().len() - parsed.total_binder_length()]
- }
- _ => unreachable!(),
- };
-
- let handshake_hash = self
- .transcript
- .hash_given(binder_plaintext);
-
- let key_schedule = KeyScheduleEarly::new(suite, psk);
- let real_binder =
- key_schedule.resumption_psk_binder_key_and_sign_verify_data(&handshake_hash);
-
- ConstantTimeEq::ct_eq(real_binder.as_ref(), binder).into()
- }
-
- fn attempt_tls13_ticket_decryption(
- &mut self,
- ticket: &[u8],
- ) -> Option<persist::ServerSessionValue> {
- if self.config.ticketer.enabled() {
- self.config
- .ticketer
- .decrypt(ticket)
- .and_then(|plain| persist::ServerSessionValue::read_bytes(&plain).ok())
- } else {
- self.config
- .session_storage
- .take(ticket)
- .and_then(|plain| persist::ServerSessionValue::read_bytes(&plain).ok())
- }
- }
-
- pub(in crate::server) fn handle_client_hello(
- mut self,
- cx: &mut ServerContext<'_>,
- server_key: ActiveCertifiedKey<'_>,
- chm: &Message<'_>,
- client_hello: &ClientHelloPayload,
- selected_kxg: &'static dyn SupportedKxGroup,
- mut sigschemes_ext: Vec<SignatureScheme>,
- ) -> hs::NextStateOrError<'static> {
- if client_hello.compression_methods.len() != 1 {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::OfferedIncorrectCompressions,
- ));
- }
-
- sigschemes_ext.retain(SignatureScheme::supported_in_tls13);
-
- let shares_ext = client_hello
- .key_shares
- .as_ref()
- .ok_or_else(|| {
- cx.common.send_fatal_alert(
- AlertDescription::HandshakeFailure,
- PeerIncompatible::KeyShareExtensionRequired,
- )
- })?;
-
- if client_hello.has_keyshare_extension_with_duplicates() {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::OfferedDuplicateKeyShares,
- ));
- }
-
- if client_hello.has_certificate_compression_extension_with_duplicates() {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::OfferedDuplicateCertificateCompressions,
- ));
- }
-
- let cert_compressor = client_hello
- .certificate_compression_algorithms
- .as_ref()
- .and_then(|offered|
- // prefer server order when choosing a compression: the client's
- // extension here does not denote any preference.
- self.config
- .cert_compressors
- .iter()
- .find(|compressor| offered.contains(&compressor.algorithm()))
- .cloned());
-
- let early_data_requested = client_hello
- .early_data_request
- .is_some();
-
- // EarlyData extension is illegal in second ClientHello
- if self.done_retry && early_data_requested {
- return Err({
- cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::EarlyDataAttemptedInSecondClientHello,
- )
- });
- }
-
- // See if there is a KeyShare for the selected kx group.
- let chosen_share_and_kxg = shares_ext.iter().find_map(|share| {
- (share.group == selected_kxg.name()).then_some((share, selected_kxg))
- });
-
- let Some(chosen_share_and_kxg) = chosen_share_and_kxg else {
- // We don't have a suitable key share. Send a HelloRetryRequest
- // for the mutually_preferred_group.
- self.transcript.add_message(chm);
-
- if self.done_retry {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::RefusedToFollowHelloRetryRequest,
- ));
- }
-
- emit_hello_retry_request(
- &mut self.transcript,
- self.suite,
- client_hello.session_id,
- cx.common,
- selected_kxg.name(),
- );
- emit_fake_ccs(cx.common);
-
- let skip_early_data = max_early_data_size(self.config.max_early_data_size);
-
- let next = Box::new(hs::ExpectClientHello {
- config: self.config,
- transcript: HandshakeHashOrBuffer::Hash(self.transcript),
- #[cfg(feature = "tls12")]
- session_id: SessionId::empty(),
- #[cfg(feature = "tls12")]
- using_ems: false,
- done_retry: true,
- send_tickets: self.send_tickets,
- extra_exts: self.extra_exts,
- });
-
- return if early_data_requested {
- Ok(Box::new(ExpectAndSkipRejectedEarlyData {
- skip_data_left: skip_early_data,
- next,
- }))
- } else {
- Ok(next)
- };
- };
-
- let mut chosen_psk_index = None;
- let mut resumedata = None;
-
- if let Some(psk_offer) = &client_hello.preshared_key_offer {
- // "A client MUST provide a "psk_key_exchange_modes" extension if it
- // offers a "pre_shared_key" extension. If clients offer
- // "pre_shared_key" without a "psk_key_exchange_modes" extension,
- // servers MUST abort the handshake." - RFC8446 4.2.9
- if client_hello
- .preshared_key_modes
- .is_none()
- {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::MissingExtension,
- PeerMisbehaved::MissingPskModesExtension,
- ));
- }
-
- if psk_offer.binders.is_empty() {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::DecodeError,
- PeerMisbehaved::MissingBinderInPskExtension,
- ));
- }
-
- if psk_offer.binders.len() != psk_offer.identities.len() {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::IllegalParameter,
- PeerMisbehaved::PskExtensionWithMismatchedIdsAndBinders,
- ));
- }
-
- let now = self.config.current_time()?;
-
- for (i, psk_id) in psk_offer.identities.iter().enumerate() {
- let maybe_resume_data = self
- .attempt_tls13_ticket_decryption(&psk_id.identity.0)
- .map(|resumedata| {
- resumedata.set_freshness(psk_id.obfuscated_ticket_age, now)
- })
- .filter(|resumedata| {
- hs::can_resume(self.suite.into(), &cx.data.sni, false, resumedata)
- });
-
- let Some(resume) = maybe_resume_data else {
- continue;
- };
-
- if !self.check_binder(
- self.suite,
- chm,
- &resume.master_secret.0,
- psk_offer.binders[i].as_ref(),
- ) {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::DecryptError,
- PeerMisbehaved::IncorrectBinder,
- ));
- }
-
- chosen_psk_index = Some(i);
- resumedata = Some(resume);
- break;
- }
- }
-
- if !client_hello
- .preshared_key_modes
- .as_ref()
- .map(|offer| offer.psk_dhe)
- .unwrap_or_default()
- {
- debug!("Client unwilling to resume, PSK_DHE_KE not offered");
- self.send_tickets = 0;
- chosen_psk_index = None;
- resumedata = None;
- } else {
- self.send_tickets = self.config.send_tls13_tickets;
- }
-
- if let Some(resume) = &resumedata {
- cx.data.received_resumption_data = Some(resume.application_data.0.clone());
- cx.common
- .peer_certificates
- .clone_from(&resume.client_cert_chain);
- }
-
- let full_handshake = resumedata.is_none();
- self.transcript.add_message(chm);
- let key_schedule = emit_server_hello(
- &mut self.transcript,
- &self.randoms,
- self.suite,
- cx,
- &client_hello.session_id,
- chosen_share_and_kxg,
- chosen_psk_index,
- resumedata
- .as_ref()
- .map(|x| &x.master_secret.0[..]),
- &self.config,
- )?;
- if !self.done_retry {
- emit_fake_ccs(cx.common);
- }
-
- if full_handshake {
- cx.common
- .handshake_kind
- .get_or_insert(HandshakeKind::Full);
- } else {
- cx.common.handshake_kind = Some(HandshakeKind::Resumed);
- }
-
- let mut ocsp_response = server_key.get_ocsp();
- let mut flight = HandshakeFlightTls13::new(&mut self.transcript);
- let doing_early_data = emit_encrypted_extensions(
- &mut flight,
- self.suite,
- cx,
- &mut ocsp_response,
- client_hello,
- resumedata.as_ref(),
- self.extra_exts,
- &self.config,
- )?;
-
- let doing_client_auth = if full_handshake {
- let client_auth = emit_certificate_req_tls13(&mut flight, &self.config)?;
-
- if let Some(compressor) = cert_compressor {
- emit_compressed_certificate_tls13(
- &mut flight,
- &self.config,
- server_key.get_cert(),
- ocsp_response,
- compressor,
- );
- } else {
- emit_certificate_tls13(&mut flight, server_key.get_cert(), ocsp_response);
- }
- emit_certificate_verify_tls13(
- &mut flight,
- cx.common,
- server_key.get_key(),
- &sigschemes_ext,
- )?;
- client_auth
- } else {
- false
- };
-
- // If we're not doing early data, then the next messages we receive
- // are encrypted with the handshake keys.
- match doing_early_data {
- EarlyDataDecision::Disabled => {
- key_schedule.set_handshake_decrypter(None, cx.common);
- cx.data.early_data.reject();
- }
- EarlyDataDecision::RequestedButRejected => {
- debug!(
- "Client requested early_data, but not accepted: switching to handshake keys with trial decryption"
- );
- key_schedule.set_handshake_decrypter(
- Some(max_early_data_size(self.config.max_early_data_size)),
- cx.common,
- );
- cx.data.early_data.reject();
- }
- EarlyDataDecision::Accepted => {
- cx.data
- .early_data
- .accept(self.config.max_early_data_size as usize);
- }
- }
-
- cx.common.check_aligned_handshake()?;
- let key_schedule_traffic =
- emit_finished_tls13(flight, &self.randoms, cx, key_schedule, &self.config);
-
- if !doing_client_auth && self.config.send_half_rtt_data {
- // Application data can be sent immediately after Finished, in one
- // flight. However, if client auth is enabled, we don't want to send
- // application data to an unauthenticated peer.
- cx.common
- .start_outgoing_traffic(&mut cx.sendable_plaintext);
- }
-
- if doing_client_auth {
- if self
- .config
- .cert_decompressors
- .is_empty()
- {
- Ok(Box::new(ExpectCertificate {
- config: self.config,
- transcript: self.transcript,
- suite: self.suite,
- key_schedule: key_schedule_traffic,
- send_tickets: self.send_tickets,
- message_already_in_transcript: false,
- }))
- } else {
- Ok(Box::new(ExpectCertificateOrCompressedCertificate {
- config: self.config,
- transcript: self.transcript,
- suite: self.suite,
- key_schedule: key_schedule_traffic,
- send_tickets: self.send_tickets,
- }))
- }
- } else if doing_early_data == EarlyDataDecision::Accepted && !cx.common.is_quic() {
- // Not used for QUIC: RFC 9001 §8.3: Clients MUST NOT send the EndOfEarlyData
- // message. A server MUST treat receipt of a CRYPTO frame in a 0-RTT packet as a
- // connection error of type PROTOCOL_VIOLATION.
- Ok(Box::new(ExpectEarlyData {
- config: self.config,
- transcript: self.transcript,
- suite: self.suite,
- key_schedule: key_schedule_traffic,
- send_tickets: self.send_tickets,
- }))
- } else {
- Ok(Box::new(ExpectFinished {
- config: self.config,
- transcript: self.transcript,
- suite: self.suite,
- key_schedule: key_schedule_traffic,
- send_tickets: self.send_tickets,
- }))
- }
- }
- }
-
- fn emit_server_hello(
- transcript: &mut HandshakeHash,
- randoms: &ConnectionRandoms,
- suite: &'static Tls13CipherSuite,
- cx: &mut ServerContext<'_>,
- session_id: &SessionId,
- share_and_kxgroup: (&KeyShareEntry, &'static dyn SupportedKxGroup),
- chosen_psk_idx: Option<usize>,
- resuming_psk: Option<&[u8]>,
- config: &ServerConfig,
- ) -> Result<KeyScheduleHandshake, Error> {
- // Prepare key exchange; the caller already found the matching SupportedKxGroup
- let (share, kxgroup) = share_and_kxgroup;
- debug_assert_eq!(kxgroup.name(), share.group);
- let ckx = kxgroup
- .start_and_complete(&share.payload.0)
- .map_err(|err| {
- cx.common
- .send_fatal_alert(AlertDescription::IllegalParameter, err)
- })?;
- cx.common.kx_state.complete();
-
- let extensions = Box::new(ServerExtensions {
- key_share: Some(KeyShareEntry::new(ckx.group, ckx.pub_key)),
- selected_version: Some(ProtocolVersion::TLSv1_3),
- preshared_key: chosen_psk_idx.map(|idx| idx as u16),
- ..Default::default()
- });
-
- let sh = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::ServerHello(ServerHelloPayload {
- legacy_version: ProtocolVersion::TLSv1_2,
- random: Random::from(randoms.server),
- session_id: *session_id,
- cipher_suite: suite.common.suite,
- compression_method: Compression::Null,
- extensions,
- }),
- )),
- };
-
- cx.common.check_aligned_handshake()?;
-
- let client_hello_hash = transcript.hash_given(&[]);
-
- trace!("sending server hello {sh:?}");
- transcript.add_message(&sh);
- cx.common.send_msg(sh, false);
-
- // Start key schedule
- let key_schedule_pre_handshake = if let Some(psk) = resuming_psk {
- let early_key_schedule = KeyScheduleEarly::new(suite, psk);
- early_key_schedule.client_early_traffic_secret(
- &client_hello_hash,
- &*config.key_log,
- &randoms.client,
- cx.common,
- );
-
- KeySchedulePreHandshake::from(early_key_schedule)
- } else {
- KeySchedulePreHandshake::new(suite)
- };
-
- // Do key exchange
- let key_schedule = key_schedule_pre_handshake.into_handshake(ckx.secret);
-
- let handshake_hash = transcript.current_hash();
- let key_schedule = key_schedule.derive_server_handshake_secrets(
- handshake_hash,
- &*config.key_log,
- &randoms.client,
- cx.common,
- );
-
- Ok(key_schedule)
- }
-
- fn emit_fake_ccs(common: &mut CommonState) {
- if common.is_quic() {
- return;
- }
- let m = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::ChangeCipherSpec(ChangeCipherSpecPayload {}),
- };
- common.send_msg(m, false);
- }
-
- fn emit_hello_retry_request(
- transcript: &mut HandshakeHash,
- suite: &'static Tls13CipherSuite,
- session_id: SessionId,
- common: &mut CommonState,
- group: NamedGroup,
- ) {
- let req = HelloRetryRequest {
- legacy_version: ProtocolVersion::TLSv1_2,
- session_id,
- cipher_suite: suite.common.suite,
- extensions: HelloRetryRequestExtensions {
- key_share: Some(group),
- supported_versions: Some(ProtocolVersion::TLSv1_3),
- ..Default::default()
- },
- };
-
- let m = Message {
- version: ProtocolVersion::TLSv1_2,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::HelloRetryRequest(req),
- )),
- };
-
- trace!("Requesting retry {m:?}");
- transcript.rollup_for_hrr();
- transcript.add_message(&m);
- common.send_msg(m, false);
- common.handshake_kind = Some(HandshakeKind::FullWithHelloRetryRequest);
- }
-
- fn decide_if_early_data_allowed(
- cx: &mut ServerContext<'_>,
- client_hello: &ClientHelloPayload,
- resumedata: Option<&persist::ServerSessionValue>,
- suite: &'static Tls13CipherSuite,
- config: &ServerConfig,
- ) -> EarlyDataDecision {
- let early_data_requested = client_hello
- .early_data_request
- .is_some();
- let rejected_or_disabled = match early_data_requested {
- true => EarlyDataDecision::RequestedButRejected,
- false => EarlyDataDecision::Disabled,
- };
-
- let Some(resume) = resumedata else {
- // never any early data if not resuming.
- return rejected_or_disabled;
- };
-
- /* Non-zero max_early_data_size controls whether early_data is allowed at all.
- * We also require stateful resumption. */
- let early_data_configured = config.max_early_data_size > 0 && !config.ticketer.enabled();
-
- /* "For PSKs provisioned via NewSessionTicket, a server MUST validate
- * that the ticket age for the selected PSK identity (computed by
- * subtracting ticket_age_add from PskIdentity.obfuscated_ticket_age
- * modulo 2^32) is within a small tolerance of the time since the ticket
- * was issued (see Section 8)." -- this is implemented in ServerSessionValue::set_freshness()
- * and related.
- *
- * "In order to accept early data, the server [...] MUST verify that the
- * following values are the same as those associated with the
- * selected PSK:
- *
- * - The TLS version number
- * - The selected cipher suite
- * - The selected ALPN [RFC7301] protocol, if any"
- *
- * (RFC8446, 4.2.10) */
- let early_data_possible = early_data_requested
- && resume.is_fresh()
- && Some(resume.version) == cx.common.negotiated_version
- && resume.cipher_suite == suite.common.suite
- && resume.alpn.as_ref().map(|p| &p.0[..]) == cx.common.alpn_protocol.as_deref();
-
- if early_data_configured && early_data_possible && !cx.data.early_data.was_rejected() {
- EarlyDataDecision::Accepted
- } else {
- if cx.common.is_quic() {
- // Clobber value set in tls13::emit_server_hello
- cx.common.quic.early_secret = None;
- }
-
- rejected_or_disabled
- }
- }
-
- fn emit_encrypted_extensions(
- flight: &mut HandshakeFlightTls13<'_>,
- suite: &'static Tls13CipherSuite,
- cx: &mut ServerContext<'_>,
- ocsp_response: &mut Option<&[u8]>,
- hello: &ClientHelloPayload,
- resumedata: Option<&persist::ServerSessionValue>,
- extra_exts: ServerExtensionsInput<'static>,
- config: &ServerConfig,
- ) -> Result<EarlyDataDecision, Error> {
- let mut ep = hs::ExtensionProcessing::new(extra_exts);
- ep.process_common(config, cx, ocsp_response, hello, resumedata)?;
-
- let early_data = decide_if_early_data_allowed(cx, hello, resumedata, suite, config);
- if early_data == EarlyDataDecision::Accepted {
- ep.extensions.early_data_ack = Some(());
- }
-
- let ee = HandshakeMessagePayload(HandshakePayload::EncryptedExtensions(ep.extensions));
-
- trace!("sending encrypted extensions {ee:?}");
- flight.add(ee);
- Ok(early_data)
- }
-
- fn emit_certificate_req_tls13(
- flight: &mut HandshakeFlightTls13<'_>,
- config: &ServerConfig,
- ) -> Result<bool, Error> {
- if !config.verifier.offer_client_auth() {
- return Ok(false);
- }
-
- let cr = CertificateRequestPayloadTls13 {
- context: PayloadU8::empty(),
- extensions: CertificateRequestExtensions {
- signature_algorithms: Some(
- config
- .verifier
- .supported_verify_schemes(),
- ),
- certificate_compression_algorithms: match config.cert_decompressors.as_slice() {
- &[] => None,
- decomps => Some(
- decomps
- .iter()
- .map(|decomp| decomp.algorithm())
- .collect(),
- ),
- },
- authority_names: match config.verifier.root_hint_subjects() {
- &[] => None,
- authorities => Some(authorities.to_vec()),
- },
- },
- };
-
- let creq = HandshakeMessagePayload(HandshakePayload::CertificateRequestTls13(cr));
-
- trace!("Sending CertificateRequest {creq:?}");
- flight.add(creq);
- Ok(true)
- }
-
- fn emit_certificate_tls13(
- flight: &mut HandshakeFlightTls13<'_>,
- cert_chain: &[CertificateDer<'static>],
- ocsp_response: Option<&[u8]>,
- ) {
- let cert = HandshakeMessagePayload(HandshakePayload::CertificateTls13(
- CertificatePayloadTls13::new(cert_chain.iter(), ocsp_response),
- ));
-
- trace!("sending certificate {cert:?}");
- flight.add(cert);
- }
-
- fn emit_compressed_certificate_tls13(
- flight: &mut HandshakeFlightTls13<'_>,
- config: &ServerConfig,
- cert_chain: &[CertificateDer<'static>],
- ocsp_response: Option<&[u8]>,
- cert_compressor: &'static dyn CertCompressor,
- ) {
- let payload = CertificatePayloadTls13::new(cert_chain.iter(), ocsp_response);
-
- let Ok(entry) = config
- .cert_compression_cache
- .compression_for(cert_compressor, &payload)
- else {
- return emit_certificate_tls13(flight, cert_chain, ocsp_response);
- };
-
- let c = HandshakeMessagePayload(HandshakePayload::CompressedCertificate(
- entry.compressed_cert_payload(),
- ));
-
- trace!("sending compressed certificate {c:?}");
- flight.add(c);
- }
-
- fn emit_certificate_verify_tls13(
- flight: &mut HandshakeFlightTls13<'_>,
- common: &mut CommonState,
- signing_key: &dyn sign::SigningKey,
- schemes: &[SignatureScheme],
- ) -> Result<(), Error> {
- let message = construct_server_verify_message(&flight.transcript.current_hash());
-
- let signer = signing_key
- .choose_scheme(schemes)
- .ok_or_else(|| {
- common.send_fatal_alert(
- AlertDescription::HandshakeFailure,
- PeerIncompatible::NoSignatureSchemesInCommon,
- )
- })?;
-
- let scheme = signer.scheme();
- let sig = signer.sign(message.as_ref())?;
-
- let cv = DigitallySignedStruct::new(scheme, sig);
-
- let cv = HandshakeMessagePayload(HandshakePayload::CertificateVerify(cv));
-
- trace!("sending certificate-verify {cv:?}");
- flight.add(cv);
- Ok(())
- }
-
- fn emit_finished_tls13(
- mut flight: HandshakeFlightTls13<'_>,
- randoms: &ConnectionRandoms,
- cx: &mut ServerContext<'_>,
- key_schedule: KeyScheduleHandshake,
- config: &ServerConfig,
- ) -> KeyScheduleTrafficWithClientFinishedPending {
- let handshake_hash = flight.transcript.current_hash();
- let verify_data = key_schedule.sign_server_finish(&handshake_hash);
- let verify_data_payload = Payload::new(verify_data.as_ref());
-
- let fin = HandshakeMessagePayload(HandshakePayload::Finished(verify_data_payload));
-
- trace!("sending finished {fin:?}");
- flight.add(fin);
- let hash_at_server_fin = flight.transcript.current_hash();
- flight.finish(cx.common);
-
- // Now move to application data keys. Read key change is deferred until
- // the Finish message is received & validated.
- key_schedule.into_traffic_with_client_finished_pending(
- hash_at_server_fin,
- &*config.key_log,
- &randoms.client,
- cx.common,
- )
- }
-}
-
-struct ExpectAndSkipRejectedEarlyData {
- skip_data_left: usize,
- next: Box<hs::ExpectClientHello>,
-}
-
-impl State<ServerConnectionData> for ExpectAndSkipRejectedEarlyData {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ServerContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- /* "The server then ignores early data by skipping all records with an external
- * content type of "application_data" (indicating that they are encrypted),
- * up to the configured max_early_data_size."
- * (RFC8446, 14.2.10) */
- if let MessagePayload::ApplicationData(skip_data) = &m.payload {
- if skip_data.bytes().len() <= self.skip_data_left {
- self.skip_data_left -= skip_data.bytes().len();
- return Ok(self);
- }
- }
-
- self.next.handle(cx, m)
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-struct ExpectCertificateOrCompressedCertificate {
- config: Arc<ServerConfig>,
- transcript: HandshakeHash,
- suite: &'static Tls13CipherSuite,
- key_schedule: KeyScheduleTrafficWithClientFinishedPending,
- send_tickets: usize,
-}
-
-impl State<ServerConnectionData> for ExpectCertificateOrCompressedCertificate {
- fn handle<'m>(
- self: Box<Self>,
- cx: &mut ServerContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- match m.payload {
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::CertificateTls13(..)),
- ..
- } => Box::new(ExpectCertificate {
- config: self.config,
- transcript: self.transcript,
- suite: self.suite,
- key_schedule: self.key_schedule,
- send_tickets: self.send_tickets,
- message_already_in_transcript: false,
- })
- .handle(cx, m),
-
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::CompressedCertificate(..)),
- ..
- } => Box::new(ExpectCompressedCertificate {
- config: self.config,
- transcript: self.transcript,
- suite: self.suite,
- key_schedule: self.key_schedule,
- send_tickets: self.send_tickets,
- })
- .handle(cx, m),
-
- payload => Err(inappropriate_handshake_message(
- &payload,
- &[ContentType::Handshake],
- &[
- HandshakeType::Certificate,
- HandshakeType::CompressedCertificate,
- ],
- )),
- }
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-struct ExpectCompressedCertificate {
- config: Arc<ServerConfig>,
- transcript: HandshakeHash,
- suite: &'static Tls13CipherSuite,
- key_schedule: KeyScheduleTrafficWithClientFinishedPending,
- send_tickets: usize,
-}
-
-impl State<ServerConnectionData> for ExpectCompressedCertificate {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ServerContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- self.transcript.add_message(&m);
- let compressed_cert = require_handshake_msg_move!(
- m,
- HandshakeType::CompressedCertificate,
- HandshakePayload::CompressedCertificate
- )?;
-
- let selected_decompressor = self
- .config
- .cert_decompressors
- .iter()
- .find(|item| item.algorithm() == compressed_cert.alg);
-
- let Some(decompressor) = selected_decompressor else {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::BadCertificate,
- PeerMisbehaved::SelectedUnofferedCertCompression,
- ));
- };
-
- if compressed_cert.uncompressed_len as usize > CERTIFICATE_MAX_SIZE_LIMIT {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::BadCertificate,
- InvalidMessage::MessageTooLarge,
- ));
- }
-
- let mut decompress_buffer = vec![0u8; compressed_cert.uncompressed_len as usize];
- if let Err(compress::DecompressionFailed) =
- decompressor.decompress(compressed_cert.compressed.0.bytes(), &mut decompress_buffer)
- {
- return Err(cx.common.send_fatal_alert(
- AlertDescription::BadCertificate,
- PeerMisbehaved::InvalidCertCompression,
- ));
- }
-
- let cert_payload =
- match CertificatePayloadTls13::read(&mut Reader::init(&decompress_buffer)) {
- Ok(cm) => cm,
- Err(err) => {
- return Err(cx
- .common
- .send_fatal_alert(AlertDescription::BadCertificate, err));
- }
- };
- trace!(
- "Client certificate decompressed using {:?} ({} bytes -> {})",
- compressed_cert.alg,
- compressed_cert
- .compressed
- .0
- .bytes()
- .len(),
- compressed_cert.uncompressed_len,
- );
-
- let m = Message {
- version: ProtocolVersion::TLSv1_3,
- payload: MessagePayload::handshake(HandshakeMessagePayload(
- HandshakePayload::CertificateTls13(cert_payload.into_owned()),
- )),
- };
-
- Box::new(ExpectCertificate {
- config: self.config,
- transcript: self.transcript,
- suite: self.suite,
- key_schedule: self.key_schedule,
- send_tickets: self.send_tickets,
- message_already_in_transcript: true,
- })
- .handle(cx, m)
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-struct ExpectCertificate {
- config: Arc<ServerConfig>,
- transcript: HandshakeHash,
- suite: &'static Tls13CipherSuite,
- key_schedule: KeyScheduleTrafficWithClientFinishedPending,
- send_tickets: usize,
- message_already_in_transcript: bool,
-}
-
-impl State<ServerConnectionData> for ExpectCertificate {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ServerContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- if !self.message_already_in_transcript {
- self.transcript.add_message(&m);
- }
- let certp = require_handshake_msg_move!(
- m,
- HandshakeType::Certificate,
- HandshakePayload::CertificateTls13
- )?;
-
- // We don't send any CertificateRequest extensions, so any extensions
- // here are illegal.
- if certp
- .entries
- .iter()
- .any(|e| !e.extensions.only_contains(&[]))
- {
- return Err(PeerMisbehaved::UnsolicitedCertExtension.into());
- }
-
- let client_cert = certp.into_certificate_chain();
-
- let mandatory = self
- .config
- .verifier
- .client_auth_mandatory();
-
- let Some((end_entity, intermediates)) = client_cert.split_first() else {
- if !mandatory {
- debug!("client auth requested but no certificate supplied");
- self.transcript.abandon_client_auth();
- return Ok(Box::new(ExpectFinished {
- config: self.config,
- suite: self.suite,
- key_schedule: self.key_schedule,
- transcript: self.transcript,
- send_tickets: self.send_tickets,
- }));
- }
-
- return Err(cx.common.send_fatal_alert(
- AlertDescription::CertificateRequired,
- Error::NoCertificatesPresented,
- ));
- };
-
- let now = self.config.current_time()?;
-
- self.config
- .verifier
- .verify_client_cert(end_entity, intermediates, now)
- .map_err(|err| {
- cx.common
- .send_cert_verify_error_alert(err)
- })?;
-
- Ok(Box::new(ExpectCertificateVerify {
- config: self.config,
- suite: self.suite,
- transcript: self.transcript,
- key_schedule: self.key_schedule,
- client_cert: client_cert.into_owned(),
- send_tickets: self.send_tickets,
- }))
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-struct ExpectCertificateVerify {
- config: Arc<ServerConfig>,
- transcript: HandshakeHash,
- suite: &'static Tls13CipherSuite,
- key_schedule: KeyScheduleTrafficWithClientFinishedPending,
- client_cert: CertificateChain<'static>,
- send_tickets: usize,
-}
-
-impl State<ServerConnectionData> for ExpectCertificateVerify {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ServerContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- let rc = {
- let sig = require_handshake_msg!(
- m,
- HandshakeType::CertificateVerify,
- HandshakePayload::CertificateVerify
- )?;
- let handshake_hash = self.transcript.current_hash();
- self.transcript.abandon_client_auth();
- let certs = &self.client_cert;
- let msg = construct_client_verify_message(&handshake_hash);
-
- self.config
- .verifier
- .verify_tls13_signature(msg.as_ref(), &certs[0], sig)
- };
-
- if let Err(e) = rc {
- return Err(cx
- .common
- .send_cert_verify_error_alert(e));
- }
-
- trace!("client CertificateVerify OK");
- cx.common.peer_certificates = Some(self.client_cert);
-
- self.transcript.add_message(&m);
- Ok(Box::new(ExpectFinished {
- config: self.config,
- suite: self.suite,
- key_schedule: self.key_schedule,
- transcript: self.transcript,
- send_tickets: self.send_tickets,
- }))
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-// --- Process (any number of) early ApplicationData messages,
-// followed by a terminating handshake EndOfEarlyData message ---
-
-struct ExpectEarlyData {
- config: Arc<ServerConfig>,
- transcript: HandshakeHash,
- suite: &'static Tls13CipherSuite,
- key_schedule: KeyScheduleTrafficWithClientFinishedPending,
- send_tickets: usize,
-}
-
-impl State<ServerConnectionData> for ExpectEarlyData {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ServerContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- match m.payload {
- MessagePayload::ApplicationData(payload) => {
- match cx
- .data
- .early_data
- .take_received_plaintext(payload)
- {
- true => Ok(self),
- false => Err(cx.common.send_fatal_alert(
- AlertDescription::UnexpectedMessage,
- PeerMisbehaved::TooMuchEarlyDataReceived,
- )),
- }
- }
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::EndOfEarlyData),
- ..
- } => {
- self.key_schedule
- .update_decrypter(cx.common);
- self.transcript.add_message(&m);
- Ok(Box::new(ExpectFinished {
- config: self.config,
- suite: self.suite,
- key_schedule: self.key_schedule,
- transcript: self.transcript,
- send_tickets: self.send_tickets,
- }))
- }
- payload => Err(inappropriate_handshake_message(
- &payload,
- &[ContentType::ApplicationData, ContentType::Handshake],
- &[HandshakeType::EndOfEarlyData],
- )),
- }
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-// --- Process client's Finished ---
-fn get_server_session_value(
- suite: &'static Tls13CipherSuite,
- resumption: &KeyScheduleResumption,
- cx: &ServerContext<'_>,
- nonce: &[u8],
- time_now: UnixTime,
- age_obfuscation_offset: u32,
-) -> persist::ServerSessionValue {
- let version = ProtocolVersion::TLSv1_3;
-
- let secret = resumption.derive_ticket_psk(nonce);
-
- persist::ServerSessionValue::new(
- cx.data.sni.as_ref(),
- version,
- suite.common.suite,
- secret.as_ref(),
- cx.common.peer_certificates.clone(),
- cx.common.alpn_protocol.clone(),
- cx.data.resumption_data.clone(),
- time_now,
- age_obfuscation_offset,
- )
-}
-
-struct ExpectFinished {
- config: Arc<ServerConfig>,
- transcript: HandshakeHash,
- suite: &'static Tls13CipherSuite,
- key_schedule: KeyScheduleTrafficWithClientFinishedPending,
- send_tickets: usize,
-}
-
-impl ExpectFinished {
- fn emit_ticket(
- flight: &mut HandshakeFlightTls13<'_>,
- suite: &'static Tls13CipherSuite,
- cx: &ServerContext<'_>,
- resumption: &KeyScheduleResumption,
- config: &ServerConfig,
- ) -> Result<(), Error> {
- let secure_random = config.provider.secure_random;
- let nonce = rand::random_vec(secure_random, 32)?;
- let age_add = rand::random_u32(secure_random)?;
-
- let now = config.current_time()?;
-
- let plain =
- get_server_session_value(suite, resumption, cx, &nonce, now, age_add).get_encoding();
-
- let stateless = config.ticketer.enabled();
- let (ticket, lifetime) = if stateless {
- let Some(ticket) = config.ticketer.encrypt(&plain) else {
- return Ok(());
- };
- (ticket, config.ticketer.lifetime())
- } else {
- let id = rand::random_vec(secure_random, 32)?;
- let stored = config
- .session_storage
- .put(id.clone(), plain);
- if !stored {
- trace!("resumption not available; not issuing ticket");
- return Ok(());
- }
- let stateful_lifetime = 24 * 60 * 60; // this is a bit of a punt
- (id, stateful_lifetime)
- };
-
- let mut payload = NewSessionTicketPayloadTls13::new(lifetime, age_add, nonce, ticket);
-
- if config.max_early_data_size > 0 {
- if !stateless {
- payload.extensions.max_early_data_size = Some(config.max_early_data_size);
- } else {
- // We implement RFC8446 section 8.1: by enforcing that 0-RTT is
- // only possible if using stateful resumption
- warn!("early_data with stateless resumption is not allowed");
- }
- }
-
- let t = HandshakeMessagePayload(HandshakePayload::NewSessionTicketTls13(payload));
- trace!("sending new ticket {t:?} (stateless: {stateless})");
- flight.add(t);
-
- Ok(())
- }
-}
-
-impl State<ServerConnectionData> for ExpectFinished {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ServerContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- let finished =
- require_handshake_msg!(m, HandshakeType::Finished, HandshakePayload::Finished)?;
-
- let handshake_hash = self.transcript.current_hash();
- let (key_schedule_before_finished, expect_verify_data) = self
- .key_schedule
- .sign_client_finish(&handshake_hash, cx.common);
-
- let fin = match ConstantTimeEq::ct_eq(expect_verify_data.as_ref(), finished.bytes()).into()
- {
- true => verify::FinishedMessageVerified::assertion(),
- false => {
- return Err(cx
- .common
- .send_fatal_alert(AlertDescription::DecryptError, Error::DecryptError));
- }
- };
-
- // Note: future derivations include Client Finished, but not the
- // main application data keying.
- self.transcript.add_message(&m);
-
- cx.common.check_aligned_handshake()?;
-
- let (key_schedule_traffic, resumption) =
- key_schedule_before_finished.into_traffic(self.transcript.current_hash());
-
- let mut flight = HandshakeFlightTls13::new(&mut self.transcript);
- for _ in 0..self.send_tickets {
- Self::emit_ticket(&mut flight, self.suite, cx, &resumption, &self.config)?;
- }
- flight.finish(cx.common);
-
- // Application data may now flow, even if we have client auth enabled.
- cx.common
- .start_traffic(&mut cx.sendable_plaintext);
-
- Ok(match cx.common.is_quic() {
- true => Box::new(ExpectQuicTraffic {
- key_schedule: key_schedule_traffic,
- _fin_verified: fin,
- }),
- false => Box::new(ExpectTraffic {
- key_schedule: key_schedule_traffic,
- _fin_verified: fin,
- }),
- })
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-// --- Process traffic ---
-struct ExpectTraffic {
- key_schedule: KeyScheduleTraffic,
- _fin_verified: verify::FinishedMessageVerified,
-}
-
-impl ExpectTraffic {
- fn handle_key_update(
- &mut self,
- common: &mut CommonState,
- key_update_request: &KeyUpdateRequest,
- ) -> Result<(), Error> {
- if let Protocol::Quic = common.protocol {
- return Err(common.send_fatal_alert(
- AlertDescription::UnexpectedMessage,
- PeerMisbehaved::KeyUpdateReceivedInQuicConnection,
- ));
- }
-
- common.check_aligned_handshake()?;
-
- if common.should_update_key(key_update_request)? {
- self.key_schedule
- .update_encrypter_and_notify(common);
- }
-
- // Update our read-side keys.
- self.key_schedule
- .update_decrypter(common);
- Ok(())
- }
-}
-
-impl State<ServerConnectionData> for ExpectTraffic {
- fn handle<'m>(
- mut self: Box<Self>,
- cx: &mut ServerContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- match m.payload {
- MessagePayload::ApplicationData(payload) => cx
- .common
- .take_received_plaintext(payload),
- MessagePayload::Handshake {
- parsed: HandshakeMessagePayload(HandshakePayload::KeyUpdate(key_update)),
- ..
- } => self.handle_key_update(cx.common, &key_update)?,
- payload => {
- return Err(inappropriate_handshake_message(
- &payload,
- &[ContentType::ApplicationData, ContentType::Handshake],
- &[HandshakeType::KeyUpdate],
- ));
- }
- }
-
- Ok(self)
- }
-
- fn export_keying_material(
- &self,
- output: &mut [u8],
- label: &[u8],
- context: Option<&[u8]>,
- ) -> Result<(), Error> {
- self.key_schedule
- .export_keying_material(output, label, context)
- }
-
- fn extract_secrets(&self) -> Result<PartiallyExtractedSecrets, Error> {
- self.key_schedule
- .extract_secrets(Side::Server)
- }
-
- fn send_key_update_request(&mut self, common: &mut CommonState) -> Result<(), Error> {
- self.key_schedule
- .request_key_update_and_update_encrypter(common)
- }
-
- fn into_external_state(self: Box<Self>) -> Result<Box<dyn KernelState + 'static>, Error> {
- Ok(self)
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-impl KernelState for ExpectTraffic {
- fn update_secrets(&mut self, dir: Direction) -> Result<ConnectionTrafficSecrets, Error> {
- self.key_schedule
- .refresh_traffic_secret(match dir {
- Direction::Transmit => Side::Server,
- Direction::Receive => Side::Client,
- })
- }
-
- fn handle_new_session_ticket(
- &mut self,
- _cx: &mut KernelContext<'_>,
- _message: &NewSessionTicketPayloadTls13,
- ) -> Result<(), Error> {
- unreachable!(
- "server connections should never have handle_new_session_ticket called on them"
- )
- }
-}
-
-struct ExpectQuicTraffic {
- key_schedule: KeyScheduleTraffic,
- _fin_verified: verify::FinishedMessageVerified,
-}
-
-impl State<ServerConnectionData> for ExpectQuicTraffic {
- fn handle<'m>(
- self: Box<Self>,
- _cx: &mut ServerContext<'_>,
- m: Message<'m>,
- ) -> hs::NextStateOrError<'m>
- where
- Self: 'm,
- {
- // reject all messages
- Err(inappropriate_message(&m.payload, &[]))
- }
-
- fn export_keying_material(
- &self,
- output: &mut [u8],
- label: &[u8],
- context: Option<&[u8]>,
- ) -> Result<(), Error> {
- self.key_schedule
- .export_keying_material(output, label, context)
- }
-
- fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
- self
- }
-}
-
-impl KernelState for ExpectQuicTraffic {
- fn update_secrets(&mut self, _: Direction) -> Result<ConnectionTrafficSecrets, Error> {
- Err(Error::General(
- "QUIC connections do not support key updates".into(),
- ))
- }
-
- fn handle_new_session_ticket(
- &mut self,
- _cx: &mut KernelContext<'_>,
- _message: &NewSessionTicketPayloadTls13,
- ) -> Result<(), Error> {
- unreachable!("handle_new_session_ticket should not be called for server-side connections")
- }
-}
diff --git a/vendor/rustls/src/stream.rs b/vendor/rustls/src/stream.rs
deleted file mode 100644
index d92d05e3..00000000
--- a/vendor/rustls/src/stream.rs
+++ /dev/null
@@ -1,282 +0,0 @@
-use core::ops::{Deref, DerefMut};
-use std::io::{BufRead, IoSlice, Read, Result, Write};
-
-use crate::conn::{ConnectionCommon, SideData};
-
-/// This type implements `io::Read` and `io::Write`, encapsulating
-/// a Connection `C` and an underlying transport `T`, such as a socket.
-///
-/// This allows you to use a rustls Connection like a normal stream.
-#[derive(Debug)]
-pub struct Stream<'a, C: 'a + ?Sized, T: 'a + Read + Write + ?Sized> {
- /// Our TLS connection
- pub conn: &'a mut C,
-
- /// The underlying transport, like a socket
- pub sock: &'a mut T,
-}
-
-impl<'a, C, T, S> Stream<'a, C, T>
-where
- C: 'a + DerefMut + Deref<Target = ConnectionCommon<S>>,
- T: 'a + Read + Write,
- S: SideData,
-{
- /// Make a new Stream using the Connection `conn` and socket-like object
- /// `sock`. This does not fail and does no IO.
- pub fn new(conn: &'a mut C, sock: &'a mut T) -> Self {
- Self { conn, sock }
- }
-
- /// If we're handshaking, complete all the IO for that.
- /// If we have data to write, write it all.
- fn complete_prior_io(&mut self) -> Result<()> {
- if self.conn.is_handshaking() {
- self.conn.complete_io(self.sock)?;
- }
-
- if self.conn.wants_write() {
- self.conn.complete_io(self.sock)?;
- }
-
- Ok(())
- }
-
- fn prepare_read(&mut self) -> Result<()> {
- self.complete_prior_io()?;
-
- // We call complete_io() in a loop since a single call may read only
- // a partial packet from the underlying transport. A full packet is
- // needed to get more plaintext, which we must do if EOF has not been
- // hit.
- while self.conn.wants_read() {
- if self.conn.complete_io(self.sock)?.0 == 0 {
- break;
- }
- }
-
- Ok(())
- }
-
- // Implements `BufRead::fill_buf` but with more flexible lifetimes, so StreamOwned can reuse it
- fn fill_buf(mut self) -> Result<&'a [u8]>
- where
- S: 'a,
- {
- self.prepare_read()?;
- self.conn.reader().into_first_chunk()
- }
-}
-
-impl<'a, C, T, S> Read for Stream<'a, C, T>
-where
- C: 'a + DerefMut + Deref<Target = ConnectionCommon<S>>,
- T: 'a + Read + Write,
- S: SideData,
-{
- fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
- self.prepare_read()?;
- self.conn.reader().read(buf)
- }
-
- #[cfg(read_buf)]
- fn read_buf(&mut self, cursor: core::io::BorrowedCursor<'_>) -> Result<()> {
- self.prepare_read()?;
- self.conn.reader().read_buf(cursor)
- }
-}
-
-impl<'a, C, T, S> BufRead for Stream<'a, C, T>
-where
- C: 'a + DerefMut + Deref<Target = ConnectionCommon<S>>,
- T: 'a + Read + Write,
- S: 'a + SideData,
-{
- fn fill_buf(&mut self) -> Result<&[u8]> {
- // reborrow to get an owned `Stream`
- Stream {
- conn: self.conn,
- sock: self.sock,
- }
- .fill_buf()
- }
-
- fn consume(&mut self, amt: usize) {
- self.conn.reader().consume(amt)
- }
-}
-
-impl<'a, C, T, S> Write for Stream<'a, C, T>
-where
- C: 'a + DerefMut + Deref<Target = ConnectionCommon<S>>,
- T: 'a + Read + Write,
- S: SideData,
-{
- fn write(&mut self, buf: &[u8]) -> Result<usize> {
- self.complete_prior_io()?;
-
- let len = self.conn.writer().write(buf)?;
-
- // Try to write the underlying transport here, but don't let
- // any errors mask the fact we've consumed `len` bytes.
- // Callers will learn of permanent errors on the next call.
- let _ = self.conn.complete_io(self.sock);
-
- Ok(len)
- }
-
- fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> {
- self.complete_prior_io()?;
-
- let len = self
- .conn
- .writer()
- .write_vectored(bufs)?;
-
- // Try to write the underlying transport here, but don't let
- // any errors mask the fact we've consumed `len` bytes.
- // Callers will learn of permanent errors on the next call.
- let _ = self.conn.complete_io(self.sock);
-
- Ok(len)
- }
-
- fn flush(&mut self) -> Result<()> {
- self.complete_prior_io()?;
-
- self.conn.writer().flush()?;
- if self.conn.wants_write() {
- self.conn.complete_io(self.sock)?;
- }
- Ok(())
- }
-}
-
-/// This type implements `io::Read` and `io::Write`, encapsulating
-/// and owning a Connection `C` and an underlying blocking transport
-/// `T`, such as a socket.
-///
-/// This allows you to use a rustls Connection like a normal stream.
-#[derive(Debug)]
-pub struct StreamOwned<C: Sized, T: Read + Write + Sized> {
- /// Our connection
- pub conn: C,
-
- /// The underlying transport, like a socket
- pub sock: T,
-}
-
-impl<C, T, S> StreamOwned<C, T>
-where
- C: DerefMut + Deref<Target = ConnectionCommon<S>>,
- T: Read + Write,
- S: SideData,
-{
- /// Make a new StreamOwned taking the Connection `conn` and socket-like
- /// object `sock`. This does not fail and does no IO.
- ///
- /// This is the same as `Stream::new` except `conn` and `sock` are
- /// moved into the StreamOwned.
- pub fn new(conn: C, sock: T) -> Self {
- Self { conn, sock }
- }
-
- /// Get a reference to the underlying socket
- pub fn get_ref(&self) -> &T {
- &self.sock
- }
-
- /// Get a mutable reference to the underlying socket
- pub fn get_mut(&mut self) -> &mut T {
- &mut self.sock
- }
-
- /// Extract the `conn` and `sock` parts from the `StreamOwned`
- pub fn into_parts(self) -> (C, T) {
- (self.conn, self.sock)
- }
-}
-
-impl<'a, C, T, S> StreamOwned<C, T>
-where
- C: DerefMut + Deref<Target = ConnectionCommon<S>>,
- T: Read + Write,
- S: SideData,
-{
- fn as_stream(&'a mut self) -> Stream<'a, C, T> {
- Stream {
- conn: &mut self.conn,
- sock: &mut self.sock,
- }
- }
-}
-
-impl<C, T, S> Read for StreamOwned<C, T>
-where
- C: DerefMut + Deref<Target = ConnectionCommon<S>>,
- T: Read + Write,
- S: SideData,
-{
- fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
- self.as_stream().read(buf)
- }
-
- #[cfg(read_buf)]
- fn read_buf(&mut self, cursor: core::io::BorrowedCursor<'_>) -> Result<()> {
- self.as_stream().read_buf(cursor)
- }
-}
-
-impl<C, T, S> BufRead for StreamOwned<C, T>
-where
- C: DerefMut + Deref<Target = ConnectionCommon<S>>,
- T: Read + Write,
- S: 'static + SideData,
-{
- fn fill_buf(&mut self) -> Result<&[u8]> {
- self.as_stream().fill_buf()
- }
-
- fn consume(&mut self, amt: usize) {
- self.as_stream().consume(amt)
- }
-}
-
-impl<C, T, S> Write for StreamOwned<C, T>
-where
- C: DerefMut + Deref<Target = ConnectionCommon<S>>,
- T: Read + Write,
- S: SideData,
-{
- fn write(&mut self, buf: &[u8]) -> Result<usize> {
- self.as_stream().write(buf)
- }
-
- fn flush(&mut self) -> Result<()> {
- self.as_stream().flush()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use std::net::TcpStream;
-
- use super::{Stream, StreamOwned};
- use crate::client::ClientConnection;
- use crate::server::ServerConnection;
-
- #[test]
- fn stream_can_be_created_for_connection_and_tcpstream() {
- type _Test<'a> = Stream<'a, ClientConnection, TcpStream>;
- }
-
- #[test]
- fn streamowned_can_be_created_for_client_and_tcpstream() {
- type _Test = StreamOwned<ClientConnection, TcpStream>;
- }
-
- #[test]
- fn streamowned_can_be_created_for_server_and_tcpstream() {
- type _Test = StreamOwned<ServerConnection, TcpStream>;
- }
-}
diff --git a/vendor/rustls/src/suites.rs b/vendor/rustls/src/suites.rs
deleted file mode 100644
index c40b88df..00000000
--- a/vendor/rustls/src/suites.rs
+++ /dev/null
@@ -1,272 +0,0 @@
-use core::fmt;
-
-use crate::common_state::Protocol;
-use crate::crypto::cipher::{AeadKey, Iv};
-use crate::crypto::{self, KeyExchangeAlgorithm};
-use crate::enums::{CipherSuite, SignatureAlgorithm, SignatureScheme};
-use crate::msgs::handshake::ALL_KEY_EXCHANGE_ALGORITHMS;
-#[cfg(feature = "tls12")]
-use crate::tls12::Tls12CipherSuite;
-use crate::tls13::Tls13CipherSuite;
-#[cfg(feature = "tls12")]
-use crate::versions::TLS12;
-use crate::versions::{SupportedProtocolVersion, TLS13};
-
-/// Common state for cipher suites (both for TLS 1.2 and TLS 1.3)
-pub struct CipherSuiteCommon {
- /// The TLS enumeration naming this cipher suite.
- pub suite: CipherSuite,
-
- /// Which hash function the suite uses.
- pub hash_provider: &'static dyn crypto::hash::Hash,
-
- /// Number of TCP-TLS messages that can be safely encrypted with a single key of this type
- ///
- /// Once a `MessageEncrypter` produced for this suite has encrypted more than
- /// `confidentiality_limit` messages, an attacker gains an advantage in distinguishing it
- /// from an ideal pseudorandom permutation (PRP).
- ///
- /// This is to be set on the assumption that messages are maximally sized --
- /// each is 2<sup>14</sup> bytes. It **does not** consider confidentiality limits for
- /// QUIC connections - see the [`quic::KeyBuilder.confidentiality_limit`] field for
- /// this context.
- ///
- /// For AES-GCM implementations, this should be set to 2<sup>24</sup> to limit attack
- /// probability to one in 2<sup>60</sup>. See [AEBounds] (Table 1) and [draft-irtf-aead-limits-08]:
- ///
- /// ```python
- /// >>> p = 2 ** -60
- /// >>> L = (2 ** 14 // 16) + 1
- /// >>> qlim = (math.sqrt(p) * (2 ** (129 // 2)) - 1) / (L + 1)
- /// >>> print(int(qlim).bit_length())
- /// 24
- /// ```
- /// [AEBounds]: https://eprint.iacr.org/2024/051.pdf
- /// [draft-irtf-aead-limits-08]: https://www.ietf.org/archive/id/draft-irtf-cfrg-aead-limits-08.html#section-5.1.1
- ///
- /// For chacha20-poly1305 implementations, this should be set to `u64::MAX`:
- /// see <https://www.ietf.org/archive/id/draft-irtf-cfrg-aead-limits-08.html#section-5.2.1>
- pub confidentiality_limit: u64,
-}
-
-impl CipherSuiteCommon {
- /// Return `true` if this is backed by a FIPS-approved implementation.
- ///
- /// This means all the constituent parts that do cryptography return `true` for `fips()`.
- pub fn fips(&self) -> bool {
- self.hash_provider.fips()
- }
-}
-
-/// A cipher suite supported by rustls.
-///
-/// This type carries both configuration and implementation. Compare with
-/// [`CipherSuite`], which carries solely a cipher suite identifier.
-#[derive(Clone, Copy, PartialEq)]
-pub enum SupportedCipherSuite {
- /// A TLS 1.2 cipher suite
- #[cfg(feature = "tls12")]
- Tls12(&'static Tls12CipherSuite),
- /// A TLS 1.3 cipher suite
- Tls13(&'static Tls13CipherSuite),
-}
-
-impl SupportedCipherSuite {
- /// The cipher suite's identifier
- pub fn suite(&self) -> CipherSuite {
- self.common().suite
- }
-
- /// The hash function the ciphersuite uses.
- pub(crate) fn hash_provider(&self) -> &'static dyn crypto::hash::Hash {
- self.common().hash_provider
- }
-
- pub(crate) fn common(&self) -> &CipherSuiteCommon {
- match self {
- #[cfg(feature = "tls12")]
- Self::Tls12(inner) => &inner.common,
- Self::Tls13(inner) => &inner.common,
- }
- }
-
- /// Return the inner `Tls13CipherSuite` for this suite, if it is a TLS1.3 suite.
- pub fn tls13(&self) -> Option<&'static Tls13CipherSuite> {
- match self {
- #[cfg(feature = "tls12")]
- Self::Tls12(_) => None,
- Self::Tls13(inner) => Some(inner),
- }
- }
-
- /// Return supported protocol version for the cipher suite.
- pub fn version(&self) -> &'static SupportedProtocolVersion {
- match self {
- #[cfg(feature = "tls12")]
- Self::Tls12(_) => &TLS12,
- Self::Tls13(_) => &TLS13,
- }
- }
-
- /// Return true if this suite is usable for a key only offering `sig_alg`
- /// signatures. This resolves to true for all TLS1.3 suites.
- pub fn usable_for_signature_algorithm(&self, _sig_alg: SignatureAlgorithm) -> bool {
- match self {
- Self::Tls13(_) => true, // no constraint expressed by ciphersuite (e.g., TLS1.3)
- #[cfg(feature = "tls12")]
- Self::Tls12(inner) => inner
- .sign
- .iter()
- .any(|scheme| scheme.algorithm() == _sig_alg),
- }
- }
-
- /// Return true if this suite is usable for the given [`Protocol`].
- ///
- /// All cipher suites are usable for TCP-TLS. Only TLS1.3 suites
- /// with `Tls13CipherSuite::quic` provided are usable for QUIC.
- pub(crate) fn usable_for_protocol(&self, proto: Protocol) -> bool {
- match proto {
- Protocol::Tcp => true,
- Protocol::Quic => self
- .tls13()
- .and_then(|cs| cs.quic)
- .is_some(),
- }
- }
-
- /// Return `true` if this is backed by a FIPS-approved implementation.
- pub fn fips(&self) -> bool {
- match self {
- #[cfg(feature = "tls12")]
- Self::Tls12(cs) => cs.fips(),
- Self::Tls13(cs) => cs.fips(),
- }
- }
-
- /// Return the list of `KeyExchangeAlgorithm`s supported by this cipher suite.
- ///
- /// TLS 1.3 cipher suites support both ECDHE and DHE key exchange, but TLS 1.2 suites
- /// support one or the other.
- pub(crate) fn key_exchange_algorithms(&self) -> &[KeyExchangeAlgorithm] {
- match self {
- #[cfg(feature = "tls12")]
- Self::Tls12(tls12) => core::slice::from_ref(&tls12.kx),
- Self::Tls13(_) => ALL_KEY_EXCHANGE_ALGORITHMS,
- }
- }
-
- /// Say if the given `KeyExchangeAlgorithm` is supported by this cipher suite.
- ///
- /// TLS 1.3 cipher suites support all key exchange types, but TLS 1.2 suites
- /// support only one.
- pub(crate) fn usable_for_kx_algorithm(&self, _kxa: KeyExchangeAlgorithm) -> bool {
- match self {
- #[cfg(feature = "tls12")]
- Self::Tls12(tls12) => tls12.kx == _kxa,
- Self::Tls13(_) => true,
- }
- }
-}
-
-impl fmt::Debug for SupportedCipherSuite {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.suite().fmt(f)
- }
-}
-
-/// Return true if `sigscheme` is usable by any of the given suites.
-pub(crate) fn compatible_sigscheme_for_suites(
- sigscheme: SignatureScheme,
- common_suites: &[SupportedCipherSuite],
-) -> bool {
- let sigalg = sigscheme.algorithm();
- common_suites
- .iter()
- .any(|&suite| suite.usable_for_signature_algorithm(sigalg))
-}
-
-/// Secrets for transmitting/receiving data over a TLS session.
-///
-/// After performing a handshake with rustls, these secrets can be extracted
-/// to configure kTLS for a socket, and have the kernel take over encryption
-/// and/or decryption.
-pub struct ExtractedSecrets {
- /// sequence number and secrets for the "tx" (transmit) direction
- pub tx: (u64, ConnectionTrafficSecrets),
-
- /// sequence number and secrets for the "rx" (receive) direction
- pub rx: (u64, ConnectionTrafficSecrets),
-}
-
-/// [ExtractedSecrets] minus the sequence numbers
-pub(crate) struct PartiallyExtractedSecrets {
- /// secrets for the "tx" (transmit) direction
- pub(crate) tx: ConnectionTrafficSecrets,
-
- /// secrets for the "rx" (receive) direction
- pub(crate) rx: ConnectionTrafficSecrets,
-}
-
-/// Secrets used to encrypt/decrypt data in a TLS session.
-///
-/// These can be used to configure kTLS for a socket in one direction.
-/// The only other piece of information needed is the sequence number,
-/// which is in [ExtractedSecrets].
-#[non_exhaustive]
-pub enum ConnectionTrafficSecrets {
- /// Secrets for the AES_128_GCM AEAD algorithm
- Aes128Gcm {
- /// AEAD Key
- key: AeadKey,
- /// Initialization vector
- iv: Iv,
- },
-
- /// Secrets for the AES_256_GCM AEAD algorithm
- Aes256Gcm {
- /// AEAD Key
- key: AeadKey,
- /// Initialization vector
- iv: Iv,
- },
-
- /// Secrets for the CHACHA20_POLY1305 AEAD algorithm
- Chacha20Poly1305 {
- /// AEAD Key
- key: AeadKey,
- /// Initialization vector
- iv: Iv,
- },
-}
-
-#[cfg(test)]
-#[macro_rules_attribute::apply(test_for_each_provider)]
-mod tests {
- use std::println;
-
- use super::provider::tls13::*;
-
- #[test]
- fn test_scs_is_debug() {
- println!("{:?}", super::provider::ALL_CIPHER_SUITES);
- }
-
- #[test]
- fn test_can_resume_to() {
- assert!(
- TLS13_AES_128_GCM_SHA256
- .tls13()
- .unwrap()
- .can_resume_from(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL)
- .is_some()
- );
- assert!(
- TLS13_AES_256_GCM_SHA384
- .tls13()
- .unwrap()
- .can_resume_from(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL)
- .is_none()
- );
- }
-}
diff --git a/vendor/rustls/src/test_macros.rs b/vendor/rustls/src/test_macros.rs
deleted file mode 100644
index 237578e0..00000000
--- a/vendor/rustls/src/test_macros.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-//! Macros used for unit testing.
-
-/// Instantiate the given test functions once for each built-in provider.
-///
-/// The selected provider module is bound as `provider`; you can rely on this
-/// having the union of the items common to the `crypto::ring` and
-/// `crypto::aws_lc_rs` modules.
-#[cfg(test)]
-macro_rules! test_for_each_provider {
- ($($tt:tt)+) => {
- #[cfg(feature = "ring")]
- mod test_with_ring {
- use crate::crypto::ring as provider;
- #[allow(unused_imports)]
- use super::*;
- $($tt)+
- }
-
- #[cfg(feature = "aws_lc_rs")]
- mod test_with_aws_lc_rs {
- use crate::crypto::aws_lc_rs as provider;
- #[allow(unused_imports)]
- use super::*;
- $($tt)+
- }
- };
-}
-
-/// Instantiate the given benchmark functions once for each built-in provider.
-///
-/// The selected provider module is bound as `provider`; you can rely on this
-/// having the union of the items common to the `crypto::ring` and
-/// `crypto::aws_lc_rs` modules.
-#[cfg(bench)]
-macro_rules! bench_for_each_provider {
- ($($tt:tt)+) => {
- #[cfg(feature = "ring")]
- mod bench_with_ring {
- use crate::crypto::ring as provider;
- #[allow(unused_imports)]
- use super::*;
- $($tt)+
- }
-
- #[cfg(feature = "aws_lc_rs")]
- mod bench_with_aws_lc_rs {
- use crate::crypto::aws_lc_rs as provider;
- #[allow(unused_imports)]
- use super::*;
- $($tt)+
- }
- };
-}
-
-#[cfg(test)]
-#[macro_rules_attribute::apply(test_for_each_provider)]
-mod tests {
- #[test]
- fn test_each_provider() {
- std::println!("provider is {:?}", super::provider::default_provider());
- }
-}
-
-#[cfg(all(test, bench))]
-#[macro_rules_attribute::apply(bench_for_each_provider)]
-mod benchmarks {
- #[bench]
- fn bench_each_provider(b: &mut test::Bencher) {
- b.iter(|| super::provider::default_provider());
- }
-}
diff --git a/vendor/rustls/src/ticketer.rs b/vendor/rustls/src/ticketer.rs
deleted file mode 100644
index d1b5e143..00000000
--- a/vendor/rustls/src/ticketer.rs
+++ /dev/null
@@ -1,365 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec::Vec;
-use core::mem;
-#[cfg(feature = "std")]
-use std::sync::{RwLock, RwLockReadGuard};
-
-use pki_types::UnixTime;
-
-use crate::lock::{Mutex, MutexGuard};
-use crate::server::ProducesTickets;
-#[cfg(not(feature = "std"))]
-use crate::time_provider::TimeProvider;
-use crate::{Error, rand};
-
-#[derive(Debug)]
-pub(crate) struct TicketSwitcherState {
- next: Option<Box<dyn ProducesTickets>>,
- current: Box<dyn ProducesTickets>,
- previous: Option<Box<dyn ProducesTickets>>,
- next_switch_time: u64,
-}
-
-/// A ticketer that has a 'current' sub-ticketer and a single
-/// 'previous' ticketer. It creates a new ticketer every so
-/// often, demoting the current ticketer.
-#[cfg_attr(feature = "std", derive(Debug))]
-pub struct TicketSwitcher {
- pub(crate) generator: fn() -> Result<Box<dyn ProducesTickets>, rand::GetRandomFailed>,
- lifetime: u32,
- state: Mutex<TicketSwitcherState>,
- #[cfg(not(feature = "std"))]
- time_provider: &'static dyn TimeProvider,
-}
-
-impl TicketSwitcher {
- /// Creates a new `TicketSwitcher`, which rotates through sub-ticketers
- /// based on the passage of time.
- ///
- /// `lifetime` is in seconds, and is how long the current ticketer
- /// is used to generate new tickets. Tickets are accepted for no
- /// longer than twice this duration. `generator` produces a new
- /// `ProducesTickets` implementation.
- #[cfg(feature = "std")]
- #[deprecated(note = "use TicketRotator instead")]
- pub fn new(
- lifetime: u32,
- generator: fn() -> Result<Box<dyn ProducesTickets>, rand::GetRandomFailed>,
- ) -> Result<Self, Error> {
- Ok(Self {
- generator,
- lifetime,
- state: Mutex::new(TicketSwitcherState {
- next: Some(generator()?),
- current: generator()?,
- previous: None,
- next_switch_time: UnixTime::now()
- .as_secs()
- .saturating_add(u64::from(lifetime)),
- }),
- })
- }
-
- /// Creates a new `TicketSwitcher`, which rotates through sub-ticketers
- /// based on the passage of time.
- ///
- /// `lifetime` is in seconds, and is how long the current ticketer
- /// is used to generate new tickets. Tickets are accepted for no
- /// longer than twice this duration. `generator` produces a new
- /// `ProducesTickets` implementation.
- #[cfg(not(feature = "std"))]
- pub fn new<M: crate::lock::MakeMutex>(
- lifetime: u32,
- generator: fn() -> Result<Box<dyn ProducesTickets>, rand::GetRandomFailed>,
- time_provider: &'static dyn TimeProvider,
- ) -> Result<Self, Error> {
- Ok(Self {
- generator,
- lifetime,
- state: Mutex::new::<M>(TicketSwitcherState {
- next: Some(generator()?),
- current: generator()?,
- previous: None,
- next_switch_time: time_provider
- .current_time()
- .unwrap()
- .as_secs()
- .saturating_add(u64::from(lifetime)),
- }),
- time_provider,
- })
- }
-
- /// If it's time, demote the `current` ticketer to `previous` (so it
- /// does no new encryptions but can do decryption) and use next for a
- /// new `current` ticketer.
- ///
- /// Calling this regularly will ensure timely key erasure. Otherwise,
- /// key erasure will be delayed until the next encrypt/decrypt call.
- ///
- /// For efficiency, this is also responsible for locking the state mutex
- /// and returning the mutexguard.
- pub(crate) fn maybe_roll(&self, now: UnixTime) -> Option<MutexGuard<'_, TicketSwitcherState>> {
- // The code below aims to make switching as efficient as possible
- // in the common case that the generator never fails. To achieve this
- // we run the following steps:
- // 1. If no switch is necessary, just return the mutexguard
- // 2. Shift over all of the ticketers (so current becomes previous,
- // and next becomes current). After this, other threads can
- // start using the new current ticketer.
- // 3. unlock mutex and generate new ticketer.
- // 4. Place new ticketer in next and return current
- //
- // There are a few things to note here. First, we don't check whether
- // a new switch might be needed in step 4, even though, due to locking
- // and entropy collection, significant amounts of time may have passed.
- // This is to guarantee that the thread doing the switch will eventually
- // make progress.
- //
- // Second, because next may be None, step 2 can fail. In that case
- // we enter a recovery mode where we generate 2 new ticketers, one for
- // next and one for the current ticketer. We then take the mutex a
- // second time and redo the time check to see if a switch is still
- // necessary.
- //
- // This somewhat convoluted approach ensures good availability of the
- // mutex, by ensuring that the state is usable and the mutex not held
- // during generation. It also ensures that, so long as the inner
- // ticketer never generates panics during encryption/decryption,
- // we are guaranteed to never panic when holding the mutex.
-
- let now = now.as_secs();
- let mut are_recovering = false; // Are we recovering from previous failure?
- {
- // Scope the mutex so we only take it for as long as needed
- let mut state = self.state.lock()?;
-
- // Fast path in case we do not need to switch to the next ticketer yet
- if now <= state.next_switch_time {
- return Some(state);
- }
-
- // Make the switch, or mark for recovery if not possible
- match state.next.take() {
- Some(next) => {
- state.previous = Some(mem::replace(&mut state.current, next));
- state.next_switch_time = now.saturating_add(u64::from(self.lifetime));
- }
- _ => are_recovering = true,
- }
- }
-
- // We always need a next, so generate it now
- let next = (self.generator)().ok()?;
- if !are_recovering {
- // Normal path, generate new next and place it in the state
- let mut state = self.state.lock()?;
- state.next = Some(next);
- Some(state)
- } else {
- // Recovering, generate also a new current ticketer, and modify state
- // as needed. (we need to redo the time check, otherwise this might
- // result in very rapid switching of ticketers)
- let new_current = (self.generator)().ok()?;
- let mut state = self.state.lock()?;
- state.next = Some(next);
- if now > state.next_switch_time {
- state.previous = Some(mem::replace(&mut state.current, new_current));
- state.next_switch_time = now.saturating_add(u64::from(self.lifetime));
- }
- Some(state)
- }
- }
-}
-
-impl ProducesTickets for TicketSwitcher {
- fn lifetime(&self) -> u32 {
- self.lifetime * 2
- }
-
- fn enabled(&self) -> bool {
- true
- }
-
- fn encrypt(&self, message: &[u8]) -> Option<Vec<u8>> {
- #[cfg(feature = "std")]
- let now = UnixTime::now();
- #[cfg(not(feature = "std"))]
- let now = self
- .time_provider
- .current_time()
- .unwrap();
-
- self.maybe_roll(now)?
- .current
- .encrypt(message)
- }
-
- fn decrypt(&self, ciphertext: &[u8]) -> Option<Vec<u8>> {
- #[cfg(feature = "std")]
- let now = UnixTime::now();
- #[cfg(not(feature = "std"))]
- let now = self
- .time_provider
- .current_time()
- .unwrap();
-
- let state = self.maybe_roll(now)?;
-
- // Decrypt with the current key; if that fails, try with the previous.
- state
- .current
- .decrypt(ciphertext)
- .or_else(|| {
- state
- .previous
- .as_ref()
- .and_then(|previous| previous.decrypt(ciphertext))
- })
- }
-}
-
-#[cfg(not(feature = "std"))]
-impl core::fmt::Debug for TicketSwitcher {
- fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
- f.debug_struct("TicketSwitcher")
- .field("generator", &self.generator)
- .field("lifetime", &self.lifetime)
- .field("state", &**self.state.lock().unwrap())
- .finish()
- }
-}
-
-#[cfg(feature = "std")]
-#[derive(Debug)]
-pub(crate) struct TicketRotatorState {
- current: Box<dyn ProducesTickets>,
- previous: Option<Box<dyn ProducesTickets>>,
- next_switch_time: u64,
-}
-
-/// A ticketer that has a 'current' sub-ticketer and a single
-/// 'previous' ticketer. It creates a new ticketer every so
-/// often, demoting the current ticketer.
-#[cfg(feature = "std")]
-pub struct TicketRotator {
- pub(crate) generator: fn() -> Result<Box<dyn ProducesTickets>, rand::GetRandomFailed>,
- lifetime: u32,
- state: RwLock<TicketRotatorState>,
-}
-
-#[cfg(feature = "std")]
-impl TicketRotator {
- /// Creates a new `TicketRotator`, which rotates through sub-ticketers
- /// based on the passage of time.
- ///
- /// `lifetime` is in seconds, and is how long the current ticketer
- /// is used to generate new tickets. Tickets are accepted for no
- /// longer than twice this duration. `generator` produces a new
- /// `ProducesTickets` implementation.
- pub fn new(
- lifetime: u32,
- generator: fn() -> Result<Box<dyn ProducesTickets>, rand::GetRandomFailed>,
- ) -> Result<Self, Error> {
- Ok(Self {
- generator,
- lifetime,
- state: RwLock::new(TicketRotatorState {
- current: generator()?,
- previous: None,
- next_switch_time: UnixTime::now()
- .as_secs()
- .saturating_add(u64::from(lifetime)),
- }),
- })
- }
-
- /// If it's time, demote the `current` ticketer to `previous` (so it
- /// does no new encryptions but can do decryption) and replace it
- /// with a new one.
- ///
- /// Calling this regularly will ensure timely key erasure. Otherwise,
- /// key erasure will be delayed until the next encrypt/decrypt call.
- ///
- /// For efficiency, this is also responsible for locking the state rwlock
- /// and returning it for read.
- pub(crate) fn maybe_roll(
- &self,
- now: UnixTime,
- ) -> Option<RwLockReadGuard<'_, TicketRotatorState>> {
- let now = now.as_secs();
-
- // Fast, common, & read-only path in case we do not need to switch
- // to the next ticketer yet
- {
- let read = self.state.read().ok()?;
-
- if now <= read.next_switch_time {
- return Some(read);
- }
- }
-
- // We need to switch ticketers, and make a new one.
- // Generate a potential "next" ticketer outside the lock.
- let next = (self.generator)().ok()?;
-
- let mut write = self.state.write().ok()?;
-
- if now <= write.next_switch_time {
- // Another thread beat us to it. Nothing to do.
- drop(write);
-
- return self.state.read().ok();
- }
-
- // Now we have:
- // - confirmed we need rotation
- // - confirmed we are the thread that will do it
- // - successfully made the replacement ticketer
- write.previous = Some(mem::replace(&mut write.current, next));
- write.next_switch_time = now.saturating_add(u64::from(self.lifetime));
- drop(write);
-
- self.state.read().ok()
- }
-}
-
-#[cfg(feature = "std")]
-impl ProducesTickets for TicketRotator {
- fn lifetime(&self) -> u32 {
- self.lifetime * 2
- }
-
- fn enabled(&self) -> bool {
- true
- }
-
- fn encrypt(&self, message: &[u8]) -> Option<Vec<u8>> {
- self.maybe_roll(UnixTime::now())?
- .current
- .encrypt(message)
- }
-
- fn decrypt(&self, ciphertext: &[u8]) -> Option<Vec<u8>> {
- let state = self.maybe_roll(UnixTime::now())?;
-
- // Decrypt with the current key; if that fails, try with the previous.
- state
- .current
- .decrypt(ciphertext)
- .or_else(|| {
- state
- .previous
- .as_ref()
- .and_then(|previous| previous.decrypt(ciphertext))
- })
- }
-}
-
-#[cfg(feature = "std")]
-impl core::fmt::Debug for TicketRotator {
- fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
- f.debug_struct("TicketRotator")
- .finish_non_exhaustive()
- }
-}
diff --git a/vendor/rustls/src/time_provider.rs b/vendor/rustls/src/time_provider.rs
deleted file mode 100644
index e43f4d6d..00000000
--- a/vendor/rustls/src/time_provider.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-//! The library's source of time.
-
-use core::fmt::Debug;
-
-use pki_types::UnixTime;
-
-/// An object that provides the current time.
-///
-/// This is used to, for example, check if a certificate has expired during
-/// certificate validation, or to check the age of a ticket.
-pub trait TimeProvider: Debug + Send + Sync {
- /// Returns the current wall time.
- ///
- /// This is not required to be monotonic.
- ///
- /// Return `None` if unable to retrieve the time.
- fn current_time(&self) -> Option<UnixTime>;
-}
-
-#[derive(Debug)]
-#[cfg(feature = "std")]
-/// Default `TimeProvider` implementation that uses `std`
-pub struct DefaultTimeProvider;
-
-#[cfg(feature = "std")]
-impl TimeProvider for DefaultTimeProvider {
- fn current_time(&self) -> Option<UnixTime> {
- Some(UnixTime::now())
- }
-}
diff --git a/vendor/rustls/src/tls12/mod.rs b/vendor/rustls/src/tls12/mod.rs
deleted file mode 100644
index c9271850..00000000
--- a/vendor/rustls/src/tls12/mod.rs
+++ /dev/null
@@ -1,380 +0,0 @@
-use alloc::boxed::Box;
-use alloc::vec;
-use alloc::vec::Vec;
-use core::fmt;
-
-use zeroize::Zeroize;
-
-use crate::common_state::{CommonState, Side};
-use crate::conn::ConnectionRandoms;
-use crate::crypto;
-use crate::crypto::cipher::{AeadKey, MessageDecrypter, MessageEncrypter, Tls12AeadAlgorithm};
-use crate::crypto::hash;
-use crate::enums::{AlertDescription, SignatureScheme};
-use crate::error::{Error, InvalidMessage};
-use crate::msgs::codec::{Codec, Reader};
-use crate::msgs::handshake::{KeyExchangeAlgorithm, KxDecode};
-use crate::suites::{CipherSuiteCommon, PartiallyExtractedSecrets, SupportedCipherSuite};
-
-/// A TLS 1.2 cipher suite supported by rustls.
-pub struct Tls12CipherSuite {
- /// Common cipher suite fields.
- pub common: CipherSuiteCommon,
-
- /// How to compute the TLS1.2 PRF for the suite's hash function.
- ///
- /// If you have a TLS1.2 PRF implementation, you should directly implement the [`crypto::tls12::Prf`] trait.
- ///
- /// If not, you can implement the [`crypto::hmac::Hmac`] trait (and associated), and then use
- /// [`crypto::tls12::PrfUsingHmac`].
- pub prf_provider: &'static dyn crypto::tls12::Prf,
-
- /// How to exchange/agree keys.
- ///
- /// In TLS1.2, the key exchange method (eg, Elliptic Curve Diffie-Hellman with Ephemeral keys -- ECDHE)
- /// is baked into the cipher suite, but the details to achieve it are negotiated separately.
- ///
- /// This controls how protocol messages (like the `ClientKeyExchange` message) are interpreted
- /// once this cipher suite has been negotiated.
- pub kx: KeyExchangeAlgorithm,
-
- /// How to sign messages for authentication.
- ///
- /// This is a set of [`SignatureScheme`]s that are usable once this cipher suite has been
- /// negotiated.
- ///
- /// The precise scheme used is then chosen from this set by the selected authentication key.
- pub sign: &'static [SignatureScheme],
-
- /// How to produce a [`MessageDecrypter`] or [`MessageEncrypter`]
- /// from raw key material.
- pub aead_alg: &'static dyn Tls12AeadAlgorithm,
-}
-
-impl Tls12CipherSuite {
- /// Resolve the set of supported [`SignatureScheme`]s from the
- /// offered signature schemes. If we return an empty
- /// set, the handshake terminates.
- pub fn resolve_sig_schemes(&self, offered: &[SignatureScheme]) -> Vec<SignatureScheme> {
- self.sign
- .iter()
- .filter(|pref| offered.contains(pref))
- .cloned()
- .collect()
- }
-
- /// Return `true` if this is backed by a FIPS-approved implementation.
- ///
- /// This means all the constituent parts that do cryptography return `true` for `fips()`.
- pub fn fips(&self) -> bool {
- self.common.fips() && self.prf_provider.fips() && self.aead_alg.fips()
- }
-}
-
-impl From<&'static Tls12CipherSuite> for SupportedCipherSuite {
- fn from(s: &'static Tls12CipherSuite) -> Self {
- Self::Tls12(s)
- }
-}
-
-impl PartialEq for Tls12CipherSuite {
- fn eq(&self, other: &Self) -> bool {
- self.common.suite == other.common.suite
- }
-}
-
-impl fmt::Debug for Tls12CipherSuite {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("Tls12CipherSuite")
- .field("suite", &self.common.suite)
- .finish()
- }
-}
-
-/// TLS1.2 per-connection keying material
-pub(crate) struct ConnectionSecrets {
- pub(crate) randoms: ConnectionRandoms,
- suite: &'static Tls12CipherSuite,
- pub(crate) master_secret: [u8; 48],
-}
-
-impl ConnectionSecrets {
- pub(crate) fn from_key_exchange(
- kx: Box<dyn crypto::ActiveKeyExchange>,
- peer_pub_key: &[u8],
- ems_seed: Option<hash::Output>,
- randoms: ConnectionRandoms,
- suite: &'static Tls12CipherSuite,
- ) -> Result<Self, Error> {
- let mut ret = Self {
- randoms,
- suite,
- master_secret: [0u8; 48],
- };
-
- let (label, seed) = match ems_seed {
- Some(seed) => ("extended master secret", Seed::Ems(seed)),
- None => (
- "master secret",
- Seed::Randoms(join_randoms(&ret.randoms.client, &ret.randoms.server)),
- ),
- };
-
- // The API contract for for_key_exchange is that the caller guarantees `label` and `seed`
- // slice parameters are non-empty.
- // `label` is guaranteed non-empty because it's assigned from a `&str` above.
- // `seed.as_ref()` is guaranteed non-empty by documentation on the AsRef impl.
- ret.suite
- .prf_provider
- .for_key_exchange(
- &mut ret.master_secret,
- kx,
- peer_pub_key,
- label.as_bytes(),
- seed.as_ref(),
- )?;
-
- Ok(ret)
- }
-
- pub(crate) fn new_resume(
- randoms: ConnectionRandoms,
- suite: &'static Tls12CipherSuite,
- master_secret: &[u8],
- ) -> Self {
- let mut ret = Self {
- randoms,
- suite,
- master_secret: [0u8; 48],
- };
- ret.master_secret
- .copy_from_slice(master_secret);
- ret
- }
-
- /// Make a `MessageCipherPair` based on the given supported ciphersuite `self.suite`,
- /// and the session's `secrets`.
- pub(crate) fn make_cipher_pair(&self, side: Side) -> MessageCipherPair {
- // Make a key block, and chop it up.
- // Note: we don't implement any ciphersuites with nonzero mac_key_len.
- let key_block = self.make_key_block();
- let shape = self.suite.aead_alg.key_block_shape();
-
- let (client_write_key, key_block) = key_block.split_at(shape.enc_key_len);
- let (server_write_key, key_block) = key_block.split_at(shape.enc_key_len);
- let (client_write_iv, key_block) = key_block.split_at(shape.fixed_iv_len);
- let (server_write_iv, extra) = key_block.split_at(shape.fixed_iv_len);
-
- let (write_key, write_iv, read_key, read_iv) = match side {
- Side::Client => (
- client_write_key,
- client_write_iv,
- server_write_key,
- server_write_iv,
- ),
- Side::Server => (
- server_write_key,
- server_write_iv,
- client_write_key,
- client_write_iv,
- ),
- };
-
- (
- self.suite
- .aead_alg
- .decrypter(AeadKey::new(read_key), read_iv),
- self.suite
- .aead_alg
- .encrypter(AeadKey::new(write_key), write_iv, extra),
- )
- }
-
- fn make_key_block(&self) -> Vec<u8> {
- let shape = self.suite.aead_alg.key_block_shape();
-
- let len = (shape.enc_key_len + shape.fixed_iv_len) * 2 + shape.explicit_nonce_len;
-
- let mut out = vec![0u8; len];
-
- // NOTE: opposite order to above for no good reason.
- // Don't design security protocols on drugs, kids.
- let randoms = join_randoms(&self.randoms.server, &self.randoms.client);
- self.suite.prf_provider.for_secret(
- &mut out,
- &self.master_secret,
- b"key expansion",
- &randoms,
- );
-
- out
- }
-
- pub(crate) fn suite(&self) -> &'static Tls12CipherSuite {
- self.suite
- }
-
- pub(crate) fn master_secret(&self) -> &[u8] {
- &self.master_secret[..]
- }
-
- fn make_verify_data(&self, handshake_hash: &hash::Output, label: &[u8]) -> Vec<u8> {
- let mut out = vec![0u8; 12];
-
- self.suite.prf_provider.for_secret(
- &mut out,
- &self.master_secret,
- label,
- handshake_hash.as_ref(),
- );
-
- out
- }
-
- pub(crate) fn client_verify_data(&self, handshake_hash: &hash::Output) -> Vec<u8> {
- self.make_verify_data(handshake_hash, b"client finished")
- }
-
- pub(crate) fn server_verify_data(&self, handshake_hash: &hash::Output) -> Vec<u8> {
- self.make_verify_data(handshake_hash, b"server finished")
- }
-
- pub(crate) fn export_keying_material(
- &self,
- output: &mut [u8],
- label: &[u8],
- context: Option<&[u8]>,
- ) {
- let mut randoms = Vec::new();
- randoms.extend_from_slice(&self.randoms.client);
- randoms.extend_from_slice(&self.randoms.server);
- if let Some(context) = context {
- assert!(context.len() <= 0xffff);
- (context.len() as u16).encode(&mut randoms);
- randoms.extend_from_slice(context);
- }
-
- self.suite
- .prf_provider
- .for_secret(output, &self.master_secret, label, &randoms);
- }
-
- pub(crate) fn extract_secrets(&self, side: Side) -> Result<PartiallyExtractedSecrets, Error> {
- // Make a key block, and chop it up
- let key_block = self.make_key_block();
- let shape = self.suite.aead_alg.key_block_shape();
-
- let (client_key, key_block) = key_block.split_at(shape.enc_key_len);
- let (server_key, key_block) = key_block.split_at(shape.enc_key_len);
- let (client_iv, key_block) = key_block.split_at(shape.fixed_iv_len);
- let (server_iv, explicit_nonce) = key_block.split_at(shape.fixed_iv_len);
-
- let client_secrets = self.suite.aead_alg.extract_keys(
- AeadKey::new(client_key),
- client_iv,
- explicit_nonce,
- )?;
- let server_secrets = self.suite.aead_alg.extract_keys(
- AeadKey::new(server_key),
- server_iv,
- explicit_nonce,
- )?;
-
- let (tx, rx) = match side {
- Side::Client => (client_secrets, server_secrets),
- Side::Server => (server_secrets, client_secrets),
- };
- Ok(PartiallyExtractedSecrets { tx, rx })
- }
-}
-
-impl Drop for ConnectionSecrets {
- fn drop(&mut self) {
- self.master_secret.zeroize();
- }
-}
-
-enum Seed {
- Ems(hash::Output),
- Randoms([u8; 64]),
-}
-
-impl AsRef<[u8]> for Seed {
- /// This is guaranteed to return a non-empty slice.
- fn as_ref(&self) -> &[u8] {
- match self {
- // seed is a hash::Output, which is a fixed, non-zero length array.
- Self::Ems(seed) => seed.as_ref(),
- // randoms is a fixed, non-zero length array.
- Self::Randoms(randoms) => randoms.as_ref(),
- }
- }
-}
-
-fn join_randoms(first: &[u8; 32], second: &[u8; 32]) -> [u8; 64] {
- let mut randoms = [0u8; 64];
- randoms[..32].copy_from_slice(first);
- randoms[32..].copy_from_slice(second);
- randoms
-}
-
-type MessageCipherPair = (Box<dyn MessageDecrypter>, Box<dyn MessageEncrypter>);
-
-pub(crate) fn decode_kx_params<'a, T: KxDecode<'a>>(
- kx_algorithm: KeyExchangeAlgorithm,
- common: &mut CommonState,
- kx_params: &'a [u8],
-) -> Result<T, Error> {
- let mut rd = Reader::init(kx_params);
- let kx_params = T::decode(&mut rd, kx_algorithm)?;
- match rd.any_left() {
- false => Ok(kx_params),
- true => Err(common.send_fatal_alert(
- AlertDescription::DecodeError,
- InvalidMessage::InvalidDhParams,
- )),
- }
-}
-
-pub(crate) const DOWNGRADE_SENTINEL: [u8; 8] = [0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x01];
-
-#[cfg(test)]
-#[macro_rules_attribute::apply(test_for_each_provider)]
-mod tests {
- use super::provider::kx_group::X25519;
- use super::*;
- use crate::common_state::{CommonState, Side};
- use crate::msgs::handshake::{ServerEcdhParams, ServerKeyExchangeParams};
-
- #[test]
- fn server_ecdhe_remaining_bytes() {
- let key = X25519.start().unwrap();
- let server_params = ServerEcdhParams::new(&*key);
- let mut server_buf = Vec::new();
- server_params.encode(&mut server_buf);
- server_buf.push(34);
-
- let mut common = CommonState::new(Side::Client);
- assert!(
- decode_kx_params::<ServerKeyExchangeParams>(
- KeyExchangeAlgorithm::ECDHE,
- &mut common,
- &server_buf
- )
- .is_err()
- );
- }
-
- #[test]
- fn client_ecdhe_invalid() {
- let mut common = CommonState::new(Side::Server);
- assert!(
- decode_kx_params::<ServerKeyExchangeParams>(
- KeyExchangeAlgorithm::ECDHE,
- &mut common,
- &[34],
- )
- .is_err()
- );
- }
-}
diff --git a/vendor/rustls/src/tls13/key_schedule.rs b/vendor/rustls/src/tls13/key_schedule.rs
deleted file mode 100644
index 4bf04214..00000000
--- a/vendor/rustls/src/tls13/key_schedule.rs
+++ /dev/null
@@ -1,1308 +0,0 @@
-//! Key schedule maintenance for TLS1.3
-
-use alloc::boxed::Box;
-use alloc::string::ToString;
-use core::ops::Deref;
-
-use crate::common_state::{CommonState, Side};
-use crate::crypto::cipher::{AeadKey, Iv, MessageDecrypter, Tls13AeadAlgorithm};
-use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock, OutputLengthError, expand};
-use crate::crypto::{SharedSecret, hash, hmac};
-use crate::error::Error;
-use crate::msgs::message::Message;
-use crate::suites::PartiallyExtractedSecrets;
-use crate::{ConnectionTrafficSecrets, KeyLog, Tls13CipherSuite, quic};
-
-// We express the state of a contained KeySchedule using these
-// typestates. This means we can write code that cannot accidentally
-// (e.g.) encrypt application data using a KeySchedule solely constructed
-// with an empty or trivial secret, or extract the wrong kind of secrets
-// at a given point.
-
-/// The "early secret" stage of the key schedule WITH a PSK.
-///
-/// This is only useful when you need to use one of the binder
-/// keys, the "client_early_traffic_secret", or
-/// "early_exporter_master_secret".
-///
-/// See [`KeySchedulePreHandshake`] for more information.
-pub(crate) struct KeyScheduleEarly {
- ks: KeySchedule,
-}
-
-impl KeyScheduleEarly {
- pub(crate) fn new(suite: &'static Tls13CipherSuite, secret: &[u8]) -> Self {
- Self {
- ks: KeySchedule::new(suite, secret),
- }
- }
-
- /// Computes the `client_early_traffic_secret` and writes it
- /// to `common`.
- ///
- /// `hs_hash` is `Transcript-Hash(ClientHello)`.
- ///
- /// ```text
- /// Derive-Secret(., "c e traffic", ClientHello)
- /// = client_early_traffic_secret
- /// ```
- pub(crate) fn client_early_traffic_secret(
- &self,
- hs_hash: &hash::Output,
- key_log: &dyn KeyLog,
- client_random: &[u8; 32],
- common: &mut CommonState,
- ) {
- let client_early_traffic_secret = self.ks.derive_logged_secret(
- SecretKind::ClientEarlyTrafficSecret,
- hs_hash.as_ref(),
- key_log,
- client_random,
- );
-
- match common.side {
- Side::Client => self
- .ks
- .set_encrypter(&client_early_traffic_secret, common),
- Side::Server => self
- .ks
- .set_decrypter(&client_early_traffic_secret, common),
- }
-
- if common.is_quic() {
- // If 0-RTT should be rejected, this will be clobbered by ExtensionProcessing
- // before the application can see.
- common.quic.early_secret = Some(client_early_traffic_secret);
- }
- }
-
- pub(crate) fn resumption_psk_binder_key_and_sign_verify_data(
- &self,
- hs_hash: &hash::Output,
- ) -> hmac::Tag {
- let resumption_psk_binder_key = self
- .ks
- .derive_for_empty_hash(SecretKind::ResumptionPskBinderKey);
- self.ks
- .sign_verify_data(&resumption_psk_binder_key, hs_hash)
- }
-}
-
-/// The "early secret" stage of the key schedule.
-///
-/// Call [`KeySchedulePreHandshake::new`] to create it without
-/// a PSK, or use [`From<KeyScheduleEarly>`] to create it with
-/// a PSK.
-///
-/// ```text
-/// 0
-/// |
-/// v
-/// PSK -> HKDF-Extract = Early Secret
-/// |
-/// +-----> Derive-Secret(., "ext binder" | "res binder", "")
-/// | = binder_key
-/// |
-/// +-----> Derive-Secret(., "c e traffic", ClientHello)
-/// | = client_early_traffic_secret
-/// |
-/// +-----> Derive-Secret(., "e exp master", ClientHello)
-/// | = early_exporter_master_secret
-/// v
-/// Derive-Secret(., "derived", "")
-/// ```
-pub(crate) struct KeySchedulePreHandshake {
- ks: KeySchedule,
-}
-
-impl KeySchedulePreHandshake {
- /// Creates a key schedule without a PSK.
- pub(crate) fn new(suite: &'static Tls13CipherSuite) -> Self {
- Self {
- ks: KeySchedule::new_with_empty_secret(suite),
- }
- }
-
- /// `shared_secret` is the "(EC)DHE" secret input to
- /// "HKDF-Extract":
- ///
- /// ```text
- /// (EC)DHE -> HKDF-Extract = Handshake Secret
- /// ```
- pub(crate) fn into_handshake(
- mut self,
- shared_secret: SharedSecret,
- ) -> KeyScheduleHandshakeStart {
- self.ks
- .input_secret(shared_secret.secret_bytes());
- KeyScheduleHandshakeStart { ks: self.ks }
- }
-}
-
-/// Creates a key schedule with a PSK.
-impl From<KeyScheduleEarly> for KeySchedulePreHandshake {
- fn from(KeyScheduleEarly { ks }: KeyScheduleEarly) -> Self {
- Self { ks }
- }
-}
-
-/// KeySchedule during handshake.
-///
-/// Created by [`KeySchedulePreHandshake`].
-pub(crate) struct KeyScheduleHandshakeStart {
- ks: KeySchedule,
-}
-
-impl KeyScheduleHandshakeStart {
- pub(crate) fn derive_client_handshake_secrets(
- mut self,
- early_data_enabled: bool,
- hs_hash: hash::Output,
- suite: &'static Tls13CipherSuite,
- key_log: &dyn KeyLog,
- client_random: &[u8; 32],
- common: &mut CommonState,
- ) -> KeyScheduleHandshake {
- debug_assert_eq!(common.side, Side::Client);
- // Suite might have changed due to resumption
- self.ks.inner = suite.into();
- let new = self.into_handshake(hs_hash, key_log, client_random, common);
-
- // Decrypt with the peer's key, encrypt with our own key
- new.ks
- .set_decrypter(&new.server_handshake_traffic_secret, common);
-
- if !early_data_enabled {
- // Set the client encryption key for handshakes if early data is not used
- new.ks
- .set_encrypter(&new.client_handshake_traffic_secret, common);
- }
-
- new
- }
-
- pub(crate) fn derive_server_handshake_secrets(
- self,
- hs_hash: hash::Output,
- key_log: &dyn KeyLog,
- client_random: &[u8; 32],
- common: &mut CommonState,
- ) -> KeyScheduleHandshake {
- debug_assert_eq!(common.side, Side::Server);
- let new = self.into_handshake(hs_hash, key_log, client_random, common);
-
- // Set up to encrypt with handshake secrets, but decrypt with early_data keys.
- // If not doing early_data after all, this is corrected later to the handshake
- // keys (now stored in key_schedule).
- new.ks
- .set_encrypter(&new.server_handshake_traffic_secret, common);
- new
- }
-
- pub(crate) fn server_ech_confirmation_secret(
- &mut self,
- client_hello_inner_random: &[u8],
- hs_hash: hash::Output,
- ) -> [u8; 8] {
- /*
- Per ietf-tls-esni-17 section 7.2:
- <https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-17#section-7.2>
- accept_confirmation = HKDF-Expand-Label(
- HKDF-Extract(0, ClientHelloInner.random),
- "ech accept confirmation",
- transcript_ech_conf,8)
- */
- hkdf_expand_label(
- self.ks
- .suite
- .hkdf_provider
- .extract_from_secret(None, client_hello_inner_random)
- .as_ref(),
- SecretKind::ServerEchConfirmationSecret.to_bytes(),
- hs_hash.as_ref(),
- )
- }
-
- fn into_handshake(
- self,
- hs_hash: hash::Output,
- key_log: &dyn KeyLog,
- client_random: &[u8; 32],
- common: &mut CommonState,
- ) -> KeyScheduleHandshake {
- // Use an empty handshake hash for the initial handshake.
- let client_secret = self.ks.derive_logged_secret(
- SecretKind::ClientHandshakeTrafficSecret,
- hs_hash.as_ref(),
- key_log,
- client_random,
- );
-
- let server_secret = self.ks.derive_logged_secret(
- SecretKind::ServerHandshakeTrafficSecret,
- hs_hash.as_ref(),
- key_log,
- client_random,
- );
-
- if common.is_quic() {
- common.quic.hs_secrets = Some(quic::Secrets::new(
- client_secret.clone(),
- server_secret.clone(),
- self.ks.suite,
- self.ks.suite.quic.unwrap(),
- common.side,
- common.quic.version,
- ));
- }
-
- KeyScheduleHandshake {
- ks: self.ks,
- client_handshake_traffic_secret: client_secret,
- server_handshake_traffic_secret: server_secret,
- }
- }
-}
-
-pub(crate) struct KeyScheduleHandshake {
- ks: KeySchedule,
- client_handshake_traffic_secret: OkmBlock,
- server_handshake_traffic_secret: OkmBlock,
-}
-
-impl KeyScheduleHandshake {
- pub(crate) fn sign_server_finish(&self, hs_hash: &hash::Output) -> hmac::Tag {
- self.ks
- .sign_finish(&self.server_handshake_traffic_secret, hs_hash)
- }
-
- pub(crate) fn set_handshake_encrypter(&self, common: &mut CommonState) {
- debug_assert_eq!(common.side, Side::Client);
- self.ks
- .set_encrypter(&self.client_handshake_traffic_secret, common);
- }
-
- pub(crate) fn set_handshake_decrypter(
- &self,
- skip_requested: Option<usize>,
- common: &mut CommonState,
- ) {
- debug_assert_eq!(common.side, Side::Server);
- let secret = &self.client_handshake_traffic_secret;
- match skip_requested {
- None => self.ks.set_decrypter(secret, common),
- Some(max_early_data_size) => common
- .record_layer
- .set_message_decrypter_with_trial_decryption(
- self.ks
- .derive_decrypter(&self.client_handshake_traffic_secret),
- max_early_data_size,
- ),
- }
- }
-
- pub(crate) fn into_traffic_with_client_finished_pending(
- self,
- hs_hash: hash::Output,
- key_log: &dyn KeyLog,
- client_random: &[u8; 32],
- common: &mut CommonState,
- ) -> KeyScheduleTrafficWithClientFinishedPending {
- debug_assert_eq!(common.side, Side::Server);
-
- let before_finished =
- KeyScheduleBeforeFinished::new(self.ks, hs_hash, key_log, client_random);
- let (_client_secret, server_secret) = (
- &before_finished.current_client_traffic_secret,
- &before_finished.current_server_traffic_secret,
- );
-
- before_finished
- .ks
- .set_encrypter(server_secret, common);
-
- if common.is_quic() {
- common.quic.traffic_secrets = Some(quic::Secrets::new(
- _client_secret.clone(),
- server_secret.clone(),
- before_finished.ks.suite,
- before_finished.ks.suite.quic.unwrap(),
- common.side,
- common.quic.version,
- ));
- }
-
- KeyScheduleTrafficWithClientFinishedPending {
- handshake_client_traffic_secret: self.client_handshake_traffic_secret,
- before_finished,
- }
- }
-
- pub(crate) fn into_pre_finished_client_traffic(
- self,
- pre_finished_hash: hash::Output,
- handshake_hash: hash::Output,
- key_log: &dyn KeyLog,
- client_random: &[u8; 32],
- ) -> (KeyScheduleClientBeforeFinished, hmac::Tag) {
- let before_finished =
- KeyScheduleBeforeFinished::new(self.ks, pre_finished_hash, key_log, client_random);
- let tag = before_finished
- .ks
- .sign_finish(&self.client_handshake_traffic_secret, &handshake_hash);
- (KeyScheduleClientBeforeFinished(before_finished), tag)
- }
-}
-
-/// Keys derived (but not installed) before client's Finished message.
-pub(crate) struct KeyScheduleBeforeFinished {
- ks: KeySchedule,
- current_client_traffic_secret: OkmBlock,
- current_server_traffic_secret: OkmBlock,
- current_exporter_secret: OkmBlock,
-}
-
-impl KeyScheduleBeforeFinished {
- fn new(
- mut ks: KeySchedule,
- hs_hash: hash::Output,
- key_log: &dyn KeyLog,
- client_random: &[u8; 32],
- ) -> Self {
- ks.input_empty();
-
- let current_client_traffic_secret = ks.derive_logged_secret(
- SecretKind::ClientApplicationTrafficSecret,
- hs_hash.as_ref(),
- key_log,
- client_random,
- );
-
- let current_server_traffic_secret = ks.derive_logged_secret(
- SecretKind::ServerApplicationTrafficSecret,
- hs_hash.as_ref(),
- key_log,
- client_random,
- );
-
- let current_exporter_secret = ks.derive_logged_secret(
- SecretKind::ExporterMasterSecret,
- hs_hash.as_ref(),
- key_log,
- client_random,
- );
-
- Self {
- ks,
- current_client_traffic_secret,
- current_server_traffic_secret,
- current_exporter_secret,
- }
- }
-
- pub(crate) fn into_traffic(
- self,
- hs_hash: hash::Output,
- ) -> (KeyScheduleTraffic, KeyScheduleResumption) {
- let Self {
- ks,
- current_client_traffic_secret,
- current_server_traffic_secret,
- current_exporter_secret,
- } = self;
-
- let resumption_master_secret =
- ks.derive(SecretKind::ResumptionMasterSecret, hs_hash.as_ref());
-
- (
- KeyScheduleTraffic {
- ks: ks.inner,
- current_client_traffic_secret,
- current_server_traffic_secret,
- current_exporter_secret,
- },
- KeyScheduleResumption {
- ks: ks.inner,
- resumption_master_secret,
- },
- )
- }
-}
-
-/// Client-side key schedule before the finished message is sent.
-///
-/// This differs from `KeyScheduleTrafficWithClientFinishedPending` because
-/// none of the final traffic secrets are installed yet. After the finished
-/// message is sent, `into_traffic()` does that.
-pub(crate) struct KeyScheduleClientBeforeFinished(KeyScheduleBeforeFinished);
-
-impl KeyScheduleClientBeforeFinished {
- pub(crate) fn into_traffic(
- self,
- common: &mut CommonState,
- hs_hash: hash::Output,
- ) -> (KeyScheduleTraffic, KeyScheduleResumption) {
- let next = self.0;
-
- debug_assert_eq!(common.side, Side::Client);
- let (client_secret, server_secret) = (
- &next.current_client_traffic_secret,
- &next.current_server_traffic_secret,
- );
-
- next.ks
- .set_decrypter(server_secret, common);
- next.ks
- .set_encrypter(client_secret, common);
-
- if common.is_quic() {
- common.quic.traffic_secrets = Some(quic::Secrets::new(
- client_secret.clone(),
- server_secret.clone(),
- next.ks.suite,
- next.ks.suite.quic.unwrap(),
- common.side,
- common.quic.version,
- ));
- }
-
- next.into_traffic(hs_hash)
- }
-}
-
-/// KeySchedule during traffic stage, retaining the ability to calculate the client's
-/// finished verify_data. The traffic stage key schedule can be extracted from it
-/// through signing the client finished hash.
-pub(crate) struct KeyScheduleTrafficWithClientFinishedPending {
- handshake_client_traffic_secret: OkmBlock,
- before_finished: KeyScheduleBeforeFinished,
-}
-
-impl KeyScheduleTrafficWithClientFinishedPending {
- pub(crate) fn update_decrypter(&self, common: &mut CommonState) {
- debug_assert_eq!(common.side, Side::Server);
- self.before_finished
- .ks
- .set_decrypter(&self.handshake_client_traffic_secret, common);
- }
-
- pub(crate) fn sign_client_finish(
- self,
- hs_hash: &hash::Output,
- common: &mut CommonState,
- ) -> (KeyScheduleBeforeFinished, hmac::Tag) {
- debug_assert_eq!(common.side, Side::Server);
- let tag = self
- .before_finished
- .ks
- .sign_finish(&self.handshake_client_traffic_secret, hs_hash);
-
- // Install keying to read future messages.
- self.before_finished.ks.set_decrypter(
- &self
- .before_finished
- .current_client_traffic_secret,
- common,
- );
-
- (self.before_finished, tag)
- }
-}
-
-/// KeySchedule during traffic stage. All traffic & exporter keys are guaranteed
-/// to be available.
-pub(crate) struct KeyScheduleTraffic {
- ks: KeyScheduleSuite,
- current_client_traffic_secret: OkmBlock,
- current_server_traffic_secret: OkmBlock,
- current_exporter_secret: OkmBlock,
-}
-
-impl KeyScheduleTraffic {
- pub(crate) fn update_encrypter_and_notify(&mut self, common: &mut CommonState) {
- let secret = self.next_application_traffic_secret(common.side);
- common.enqueue_key_update_notification();
- self.ks.set_encrypter(&secret, common);
- }
-
- pub(crate) fn request_key_update_and_update_encrypter(
- &mut self,
- common: &mut CommonState,
- ) -> Result<(), Error> {
- common.check_aligned_handshake()?;
- common.send_msg_encrypt(Message::build_key_update_request().into());
- let secret = self.next_application_traffic_secret(common.side);
- self.ks.set_encrypter(&secret, common);
- Ok(())
- }
-
- pub(crate) fn update_decrypter(&mut self, common: &mut CommonState) {
- let secret = self.next_application_traffic_secret(common.side.peer());
- self.ks.set_decrypter(&secret, common);
- }
-
- pub(crate) fn next_application_traffic_secret(&mut self, side: Side) -> OkmBlock {
- let current = match side {
- Side::Client => &mut self.current_client_traffic_secret,
- Side::Server => &mut self.current_server_traffic_secret,
- };
-
- let secret = self.ks.derive_next(current);
- *current = secret.clone();
- secret
- }
-
- pub(crate) fn export_keying_material(
- &self,
- out: &mut [u8],
- label: &[u8],
- context: Option<&[u8]>,
- ) -> Result<(), Error> {
- self.ks
- .export_keying_material(&self.current_exporter_secret, out, label, context)
- }
-
- pub(crate) fn refresh_traffic_secret(
- &mut self,
- side: Side,
- ) -> Result<ConnectionTrafficSecrets, Error> {
- let secret = self.next_application_traffic_secret(side);
- let (key, iv) = expand_secret(
- &secret,
- self.ks.suite.hkdf_provider,
- self.ks.suite.aead_alg.key_len(),
- );
- Ok(self
- .ks
- .suite
- .aead_alg
- .extract_keys(key, iv)?)
- }
-
- pub(crate) fn extract_secrets(&self, side: Side) -> Result<PartiallyExtractedSecrets, Error> {
- let (client_key, client_iv) = expand_secret(
- &self.current_client_traffic_secret,
- self.ks.suite.hkdf_provider,
- self.ks.suite.aead_alg.key_len(),
- );
- let (server_key, server_iv) = expand_secret(
- &self.current_server_traffic_secret,
- self.ks.suite.hkdf_provider,
- self.ks.suite.aead_alg.key_len(),
- );
- let client_secrets = self
- .ks
- .suite
- .aead_alg
- .extract_keys(client_key, client_iv)?;
- let server_secrets = self
- .ks
- .suite
- .aead_alg
- .extract_keys(server_key, server_iv)?;
-
- let (tx, rx) = match side {
- Side::Client => (client_secrets, server_secrets),
- Side::Server => (server_secrets, client_secrets),
- };
- Ok(PartiallyExtractedSecrets { tx, rx })
- }
-}
-
-pub(crate) struct KeyScheduleResumption {
- ks: KeyScheduleSuite,
- resumption_master_secret: OkmBlock,
-}
-
-impl KeyScheduleResumption {
- pub(crate) fn derive_ticket_psk(&self, nonce: &[u8]) -> OkmBlock {
- self.ks
- .derive_ticket_psk(&self.resumption_master_secret, nonce)
- }
-}
-
-fn expand_secret(secret: &OkmBlock, hkdf: &'static dyn Hkdf, aead_key_len: usize) -> (AeadKey, Iv) {
- let expander = hkdf.expander_for_okm(secret);
-
- (
- hkdf_expand_label_aead_key(expander.as_ref(), aead_key_len, b"key", &[]),
- hkdf_expand_label(expander.as_ref(), b"iv", &[]),
- )
-}
-
-/// This is the TLS1.3 key schedule. It stores the current secret and
-/// the type of hash. This isn't used directly; but only through the
-/// typestates.
-struct KeySchedule {
- current: Box<dyn HkdfExpander>,
- inner: KeyScheduleSuite,
-}
-
-impl KeySchedule {
- fn new(suite: &'static Tls13CipherSuite, secret: &[u8]) -> Self {
- Self {
- current: suite
- .hkdf_provider
- .extract_from_secret(None, secret),
- inner: suite.into(),
- }
- }
-
- /// Creates a key schedule without a PSK.
- fn new_with_empty_secret(suite: &'static Tls13CipherSuite) -> Self {
- Self {
- current: suite
- .hkdf_provider
- .extract_from_zero_ikm(None),
- inner: suite.into(),
- }
- }
-
- /// Input the empty secret.
- ///
- /// RFC 8446: "If a given secret is not available, then the
- /// 0-value consisting of a string of Hash.length bytes set
- /// to zeros is used."
- fn input_empty(&mut self) {
- let salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
- self.current = self
- .suite
- .hkdf_provider
- .extract_from_zero_ikm(Some(salt.as_ref()));
- }
-
- /// Input the given secret.
- fn input_secret(&mut self, secret: &[u8]) {
- let salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
- self.current = self
- .suite
- .hkdf_provider
- .extract_from_secret(Some(salt.as_ref()), secret);
- }
-
- /// Derive a secret of given `kind`, using current handshake hash `hs_hash`.
- ///
- /// More specifically
- /// ```text
- /// Derive-Secret(., "derived", Messages)
- /// ```
- /// where `hs_hash` is `Messages`.
- fn derive(&self, kind: SecretKind, hs_hash: &[u8]) -> OkmBlock {
- hkdf_expand_label_block(self.current.as_ref(), kind.to_bytes(), hs_hash)
- }
-
- fn derive_logged_secret(
- &self,
- kind: SecretKind,
- hs_hash: &[u8],
- key_log: &dyn KeyLog,
- client_random: &[u8; 32],
- ) -> OkmBlock {
- let output = self.derive(kind, hs_hash);
-
- let log_label = kind
- .log_label()
- .expect("not a loggable secret");
- if key_log.will_log(log_label) {
- key_log.log(log_label, client_random, output.as_ref());
- }
- output
- }
-
- /// Derive a secret of given `kind` using the hash of the empty string
- /// for the handshake hash.
- ///
- /// More specifically:
- /// ```text
- /// Derive-Secret(., Label, "")
- /// ```
- /// where `kind` is `Label`.
- ///
- /// Useful only for the following `SecretKind`s:
- /// - `SecretKind::ExternalPskBinderKey`
- /// - `SecretKind::ResumptionPSKBinderKey`
- /// - `SecretKind::DerivedSecret`
- fn derive_for_empty_hash(&self, kind: SecretKind) -> OkmBlock {
- let hp = self.suite.common.hash_provider;
- let empty_hash = hp
- .algorithm()
- .hash_for_empty_input()
- .unwrap_or_else(|| hp.start().finish());
- self.derive(kind, empty_hash.as_ref())
- }
-}
-
-impl Deref for KeySchedule {
- type Target = KeyScheduleSuite;
-
- fn deref(&self) -> &Self::Target {
- &self.inner
- }
-}
-
-/// This is a component part of `KeySchedule`, and groups operations
-/// that do not depend on the root key schedule secret.
-#[derive(Clone, Copy)]
-struct KeyScheduleSuite {
- suite: &'static Tls13CipherSuite,
-}
-
-impl KeyScheduleSuite {
- fn set_encrypter(&self, secret: &OkmBlock, common: &mut CommonState) {
- let expander = self
- .suite
- .hkdf_provider
- .expander_for_okm(secret);
- let key = derive_traffic_key(expander.as_ref(), self.suite.aead_alg);
- let iv = derive_traffic_iv(expander.as_ref());
-
- common
- .record_layer
- .set_message_encrypter(
- self.suite.aead_alg.encrypter(key, iv),
- self.suite.common.confidentiality_limit,
- );
- }
-
- fn set_decrypter(&self, secret: &OkmBlock, common: &mut CommonState) {
- common
- .record_layer
- .set_message_decrypter(self.derive_decrypter(secret));
- }
-
- fn derive_decrypter(&self, secret: &OkmBlock) -> Box<dyn MessageDecrypter> {
- let expander = self
- .suite
- .hkdf_provider
- .expander_for_okm(secret);
- let key = derive_traffic_key(expander.as_ref(), self.suite.aead_alg);
- let iv = derive_traffic_iv(expander.as_ref());
- self.suite.aead_alg.decrypter(key, iv)
- }
-
- /// Sign the finished message consisting of `hs_hash` using a current
- /// traffic secret.
- ///
- /// See RFC 8446 section 4.4.4.
- fn sign_finish(&self, base_key: &OkmBlock, hs_hash: &hash::Output) -> hmac::Tag {
- self.sign_verify_data(base_key, hs_hash)
- }
-
- /// Sign the finished message consisting of `hs_hash` using the key material
- /// `base_key`.
- ///
- /// See RFC 8446 section 4.4.4.
- fn sign_verify_data(&self, base_key: &OkmBlock, hs_hash: &hash::Output) -> hmac::Tag {
- let expander = self
- .suite
- .hkdf_provider
- .expander_for_okm(base_key);
- let hmac_key = hkdf_expand_label_block(expander.as_ref(), b"finished", &[]);
-
- self.suite
- .hkdf_provider
- .hmac_sign(&hmac_key, hs_hash.as_ref())
- }
-
- /// Derive the next application traffic secret, returning it.
- fn derive_next(&self, base_key: &OkmBlock) -> OkmBlock {
- let expander = self
- .suite
- .hkdf_provider
- .expander_for_okm(base_key);
- hkdf_expand_label_block(expander.as_ref(), b"traffic upd", &[])
- }
-
- /// Derive the PSK to use given a resumption_master_secret and
- /// ticket_nonce.
- fn derive_ticket_psk(&self, rms: &OkmBlock, nonce: &[u8]) -> OkmBlock {
- let expander = self
- .suite
- .hkdf_provider
- .expander_for_okm(rms);
- hkdf_expand_label_block(expander.as_ref(), b"resumption", nonce)
- }
-
- fn export_keying_material(
- &self,
- current_exporter_secret: &OkmBlock,
- out: &mut [u8],
- label: &[u8],
- context: Option<&[u8]>,
- ) -> Result<(), Error> {
- let secret = {
- let h_empty = self
- .suite
- .common
- .hash_provider
- .hash(&[]);
-
- let expander = self
- .suite
- .hkdf_provider
- .expander_for_okm(current_exporter_secret);
- hkdf_expand_label_block(expander.as_ref(), label, h_empty.as_ref())
- };
-
- let h_context = self
- .suite
- .common
- .hash_provider
- .hash(context.unwrap_or(&[]));
-
- let expander = self
- .suite
- .hkdf_provider
- .expander_for_okm(&secret);
- hkdf_expand_label_slice(expander.as_ref(), b"exporter", h_context.as_ref(), out)
- .map_err(|_| Error::General("exporting too much".to_string()))
- }
-}
-
-impl From<&'static Tls13CipherSuite> for KeyScheduleSuite {
- fn from(suite: &'static Tls13CipherSuite) -> Self {
- Self { suite }
- }
-}
-
-/// [HKDF-Expand-Label] where the output is an AEAD key.
-///
-/// [HKDF-Expand-Label]: <https://www.rfc-editor.org/rfc/rfc8446#section-7.1>
-pub fn derive_traffic_key(
- expander: &dyn HkdfExpander,
- aead_alg: &dyn Tls13AeadAlgorithm,
-) -> AeadKey {
- hkdf_expand_label_aead_key(expander, aead_alg.key_len(), b"key", &[])
-}
-
-/// [HKDF-Expand-Label] where the output is an IV.
-///
-/// [HKDF-Expand-Label]: <https://www.rfc-editor.org/rfc/rfc8446#section-7.1>
-pub fn derive_traffic_iv(expander: &dyn HkdfExpander) -> Iv {
- hkdf_expand_label(expander, b"iv", &[])
-}
-
-/// [HKDF-Expand-Label] where the output length is a compile-time constant, and therefore
-/// it is infallible.
-///
-/// [HKDF-Expand-Label]: <https://www.rfc-editor.org/rfc/rfc8446#section-7.1>
-pub(crate) fn hkdf_expand_label<T: From<[u8; N]>, const N: usize>(
- expander: &dyn HkdfExpander,
- label: &[u8],
- context: &[u8],
-) -> T {
- hkdf_expand_label_inner(expander, label, context, N, |e, info| expand(e, info))
-}
-
-/// [HKDF-Expand-Label] where the output is one block in size.
-pub(crate) fn hkdf_expand_label_block(
- expander: &dyn HkdfExpander,
- label: &[u8],
- context: &[u8],
-) -> OkmBlock {
- hkdf_expand_label_inner(expander, label, context, expander.hash_len(), |e, info| {
- e.expand_block(info)
- })
-}
-
-/// [HKDF-Expand-Label] where the output is an AEAD key.
-pub(crate) fn hkdf_expand_label_aead_key(
- expander: &dyn HkdfExpander,
- key_len: usize,
- label: &[u8],
- context: &[u8],
-) -> AeadKey {
- hkdf_expand_label_inner(expander, label, context, key_len, |e, info| {
- let key: AeadKey = expand(e, info);
- key.with_length(key_len)
- })
-}
-
-/// [HKDF-Expand-Label] where the output is a slice.
-///
-/// This can fail because HKDF-Expand is limited in its maximum output length.
-fn hkdf_expand_label_slice(
- expander: &dyn HkdfExpander,
- label: &[u8],
- context: &[u8],
- output: &mut [u8],
-) -> Result<(), OutputLengthError> {
- hkdf_expand_label_inner(expander, label, context, output.len(), |e, info| {
- e.expand_slice(info, output)
- })
-}
-
-pub(crate) fn server_ech_hrr_confirmation_secret(
- hkdf_provider: &'static dyn Hkdf,
- client_hello_inner_random: &[u8],
- hs_hash: hash::Output,
-) -> [u8; 8] {
- /*
- Per ietf-tls-esni-17 section 7.2.1:
- <https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-17#section-7.2.1>
- hrr_accept_confirmation = HKDF-Expand-Label(
- HKDF-Extract(0, ClientHelloInner1.random),
- "hrr ech accept confirmation",
- transcript_hrr_ech_conf,
- 8)
- */
- hkdf_expand_label(
- hkdf_provider
- .extract_from_secret(None, client_hello_inner_random)
- .as_ref(),
- SecretKind::ServerEchHrrConfirmationSecret.to_bytes(),
- hs_hash.as_ref(),
- )
-}
-
-fn hkdf_expand_label_inner<F, T>(
- expander: &dyn HkdfExpander,
- label: &[u8],
- context: &[u8],
- n: usize,
- f: F,
-) -> T
-where
- F: FnOnce(&dyn HkdfExpander, &[&[u8]]) -> T,
-{
- const LABEL_PREFIX: &[u8] = b"tls13 ";
-
- let output_len = u16::to_be_bytes(n as u16);
- let label_len = u8::to_be_bytes((LABEL_PREFIX.len() + label.len()) as u8);
- let context_len = u8::to_be_bytes(context.len() as u8);
-
- let info = &[
- &output_len[..],
- &label_len[..],
- LABEL_PREFIX,
- label,
- &context_len[..],
- context,
- ];
-
- f(expander, info)
-}
-
-/// The kinds of secret we can extract from `KeySchedule`.
-#[derive(Debug, Clone, Copy, PartialEq)]
-enum SecretKind {
- ResumptionPskBinderKey,
- ClientEarlyTrafficSecret,
- ClientHandshakeTrafficSecret,
- ServerHandshakeTrafficSecret,
- ClientApplicationTrafficSecret,
- ServerApplicationTrafficSecret,
- ExporterMasterSecret,
- ResumptionMasterSecret,
- DerivedSecret,
- ServerEchConfirmationSecret,
- ServerEchHrrConfirmationSecret,
-}
-
-impl SecretKind {
- fn to_bytes(self) -> &'static [u8] {
- use self::SecretKind::*;
- match self {
- ResumptionPskBinderKey => b"res binder",
- ClientEarlyTrafficSecret => b"c e traffic",
- ClientHandshakeTrafficSecret => b"c hs traffic",
- ServerHandshakeTrafficSecret => b"s hs traffic",
- ClientApplicationTrafficSecret => b"c ap traffic",
- ServerApplicationTrafficSecret => b"s ap traffic",
- ExporterMasterSecret => b"exp master",
- ResumptionMasterSecret => b"res master",
- DerivedSecret => b"derived",
- // https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#section-7.2
- ServerEchConfirmationSecret => b"ech accept confirmation",
- // https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#section-7.2.1
- ServerEchHrrConfirmationSecret => b"hrr ech accept confirmation",
- }
- }
-
- fn log_label(self) -> Option<&'static str> {
- use self::SecretKind::*;
- Some(match self {
- ClientEarlyTrafficSecret => "CLIENT_EARLY_TRAFFIC_SECRET",
- ClientHandshakeTrafficSecret => "CLIENT_HANDSHAKE_TRAFFIC_SECRET",
- ServerHandshakeTrafficSecret => "SERVER_HANDSHAKE_TRAFFIC_SECRET",
- ClientApplicationTrafficSecret => "CLIENT_TRAFFIC_SECRET_0",
- ServerApplicationTrafficSecret => "SERVER_TRAFFIC_SECRET_0",
- ExporterMasterSecret => "EXPORTER_SECRET",
- _ => {
- return None;
- }
- })
- }
-}
-
-#[cfg(test)]
-#[macro_rules_attribute::apply(test_for_each_provider)]
-mod tests {
- use core::fmt::Debug;
- use std::prelude::v1::*;
- use std::vec;
-
- use super::provider::ring_like::aead;
- use super::provider::tls13::{
- TLS13_AES_128_GCM_SHA256_INTERNAL, TLS13_CHACHA20_POLY1305_SHA256_INTERNAL,
- };
- use super::{KeySchedule, SecretKind, derive_traffic_iv, derive_traffic_key};
- use crate::KeyLog;
- use crate::msgs::enums::HashAlgorithm;
-
- #[test]
- fn empty_hash() {
- let sha256 = super::provider::tls13::TLS13_AES_128_GCM_SHA256
- .tls13()
- .unwrap()
- .common
- .hash_provider;
- let sha384 = super::provider::tls13::TLS13_AES_256_GCM_SHA384
- .tls13()
- .unwrap()
- .common
- .hash_provider;
-
- assert!(
- sha256.start().finish().as_ref()
- == HashAlgorithm::SHA256
- .hash_for_empty_input()
- .unwrap()
- .as_ref()
- );
- assert!(
- sha384.start().finish().as_ref()
- == HashAlgorithm::SHA384
- .hash_for_empty_input()
- .unwrap()
- .as_ref()
- );
-
- // a theoretical example of unsupported hash
- assert!(
- HashAlgorithm::SHA1
- .hash_for_empty_input()
- .is_none()
- );
- }
-
- #[test]
- fn test_vectors() {
- /* These test vectors generated with OpenSSL. */
- let hs_start_hash = [
- 0xec, 0x14, 0x7a, 0x06, 0xde, 0xa3, 0xc8, 0x84, 0x6c, 0x02, 0xb2, 0x23, 0x8e, 0x41,
- 0xbd, 0xdc, 0x9d, 0x89, 0xf9, 0xae, 0xa1, 0x7b, 0x5e, 0xfd, 0x4d, 0x74, 0x82, 0xaf,
- 0x75, 0x88, 0x1c, 0x0a,
- ];
-
- let hs_full_hash = [
- 0x75, 0x1a, 0x3d, 0x4a, 0x14, 0xdf, 0xab, 0xeb, 0x68, 0xe9, 0x2c, 0xa5, 0x91, 0x8e,
- 0x24, 0x08, 0xb9, 0xbc, 0xb0, 0x74, 0x89, 0x82, 0xec, 0x9c, 0x32, 0x30, 0xac, 0x30,
- 0xbb, 0xeb, 0x23, 0xe2,
- ];
-
- let ecdhe_secret = [
- 0xe7, 0xb8, 0xfe, 0xf8, 0x90, 0x3b, 0x52, 0x0c, 0xb9, 0xa1, 0x89, 0x71, 0xb6, 0x9d,
- 0xd4, 0x5d, 0xca, 0x53, 0xce, 0x2f, 0x12, 0xbf, 0x3b, 0xef, 0x93, 0x15, 0xe3, 0x12,
- 0x71, 0xdf, 0x4b, 0x40,
- ];
-
- let client_hts = [
- 0x61, 0x7b, 0x35, 0x07, 0x6b, 0x9d, 0x0e, 0x08, 0xcf, 0x73, 0x1d, 0x94, 0xa8, 0x66,
- 0x14, 0x78, 0x41, 0x09, 0xef, 0x25, 0x55, 0x51, 0x92, 0x1d, 0xd4, 0x6e, 0x04, 0x01,
- 0x35, 0xcf, 0x46, 0xab,
- ];
-
- let client_hts_key = [
- 0x62, 0xd0, 0xdd, 0x00, 0xf6, 0x96, 0x19, 0xd3, 0xb8, 0x19, 0x3a, 0xb4, 0xa0, 0x95,
- 0x85, 0xa7,
- ];
-
- let client_hts_iv = [
- 0xff, 0xf7, 0x5d, 0xf5, 0xad, 0x35, 0xd5, 0xcb, 0x3c, 0x53, 0xf3, 0xa9,
- ];
-
- let server_hts = [
- 0xfc, 0xf7, 0xdf, 0xe6, 0x4f, 0xa2, 0xc0, 0x4f, 0x62, 0x35, 0x38, 0x7f, 0x43, 0x4e,
- 0x01, 0x42, 0x23, 0x36, 0xd9, 0xc0, 0x39, 0xde, 0x68, 0x47, 0xa0, 0xb9, 0xdd, 0xcf,
- 0x29, 0xa8, 0x87, 0x59,
- ];
-
- let server_hts_key = [
- 0x04, 0x67, 0xf3, 0x16, 0xa8, 0x05, 0xb8, 0xc4, 0x97, 0xee, 0x67, 0x04, 0x7b, 0xbc,
- 0xbc, 0x54,
- ];
-
- let server_hts_iv = [
- 0xde, 0x83, 0xa7, 0x3e, 0x9d, 0x81, 0x4b, 0x04, 0xc4, 0x8b, 0x78, 0x09,
- ];
-
- let client_ats = [
- 0xc1, 0x4a, 0x6d, 0x79, 0x76, 0xd8, 0x10, 0x2b, 0x5a, 0x0c, 0x99, 0x51, 0x49, 0x3f,
- 0xee, 0x87, 0xdc, 0xaf, 0xf8, 0x2c, 0x24, 0xca, 0xb2, 0x14, 0xe8, 0xbe, 0x71, 0xa8,
- 0x20, 0x6d, 0xbd, 0xa5,
- ];
-
- let client_ats_key = [
- 0xcc, 0x9f, 0x5f, 0x98, 0x0b, 0x5f, 0x10, 0x30, 0x6c, 0xba, 0xd7, 0xbe, 0x98, 0xd7,
- 0x57, 0x2e,
- ];
-
- let client_ats_iv = [
- 0xb8, 0x09, 0x29, 0xe8, 0xd0, 0x2c, 0x70, 0xf6, 0x11, 0x62, 0xed, 0x6b,
- ];
-
- let server_ats = [
- 0x2c, 0x90, 0x77, 0x38, 0xd3, 0xf8, 0x37, 0x02, 0xd1, 0xe4, 0x59, 0x8f, 0x48, 0x48,
- 0x53, 0x1d, 0x9f, 0x93, 0x65, 0x49, 0x1b, 0x9f, 0x7f, 0x52, 0xc8, 0x22, 0x29, 0x0d,
- 0x4c, 0x23, 0x21, 0x92,
- ];
-
- let server_ats_key = [
- 0x0c, 0xb2, 0x95, 0x62, 0xd8, 0xd8, 0x8f, 0x48, 0xb0, 0x2c, 0xbf, 0xbe, 0xd7, 0xe6,
- 0x2b, 0xb3,
- ];
-
- let server_ats_iv = [
- 0x0d, 0xb2, 0x8f, 0x98, 0x85, 0x86, 0xa1, 0xb7, 0xe4, 0xd5, 0xc6, 0x9c,
- ];
-
- let mut ks = KeySchedule::new_with_empty_secret(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
- ks.input_secret(&ecdhe_secret);
-
- assert_traffic_secret(
- &ks,
- SecretKind::ClientHandshakeTrafficSecret,
- &hs_start_hash,
- &client_hts,
- &client_hts_key,
- &client_hts_iv,
- );
-
- assert_traffic_secret(
- &ks,
- SecretKind::ServerHandshakeTrafficSecret,
- &hs_start_hash,
- &server_hts,
- &server_hts_key,
- &server_hts_iv,
- );
-
- ks.input_empty();
-
- assert_traffic_secret(
- &ks,
- SecretKind::ClientApplicationTrafficSecret,
- &hs_full_hash,
- &client_ats,
- &client_ats_key,
- &client_ats_iv,
- );
-
- assert_traffic_secret(
- &ks,
- SecretKind::ServerApplicationTrafficSecret,
- &hs_full_hash,
- &server_ats,
- &server_ats_key,
- &server_ats_iv,
- );
- }
-
- fn assert_traffic_secret(
- ks: &KeySchedule,
- kind: SecretKind,
- hash: &[u8],
- expected_traffic_secret: &[u8],
- expected_key: &[u8],
- expected_iv: &[u8],
- ) {
- #[derive(Debug)]
- struct Log<'a>(&'a [u8]);
- impl KeyLog for Log<'_> {
- fn log(&self, _label: &str, _client_random: &[u8], secret: &[u8]) {
- assert_eq!(self.0, secret);
- }
- }
- let log = Log(expected_traffic_secret);
- let traffic_secret = ks.derive_logged_secret(kind, hash, &log, &[0; 32]);
-
- // Since we can't test key equality, we test the output of sealing with the key instead.
- let aead_alg = &aead::AES_128_GCM;
- let expander = TLS13_AES_128_GCM_SHA256_INTERNAL
- .hkdf_provider
- .expander_for_okm(&traffic_secret);
- let key = derive_traffic_key(
- expander.as_ref(),
- TLS13_AES_128_GCM_SHA256_INTERNAL.aead_alg,
- );
- let key = aead::UnboundKey::new(aead_alg, key.as_ref()).unwrap();
- let seal_output = seal_zeroes(key);
- let expected_key = aead::UnboundKey::new(aead_alg, expected_key).unwrap();
- let expected_seal_output = seal_zeroes(expected_key);
- assert_eq!(seal_output, expected_seal_output);
- assert!(seal_output.len() >= 48); // Sanity check.
-
- let iv = derive_traffic_iv(expander.as_ref());
- assert_eq!(iv.as_ref(), expected_iv);
- }
-
- fn seal_zeroes(key: aead::UnboundKey) -> Vec<u8> {
- let key = aead::LessSafeKey::new(key);
- let mut seal_output = vec![0; 32];
- key.seal_in_place_append_tag(
- aead::Nonce::assume_unique_for_key([0; aead::NONCE_LEN]),
- aead::Aad::empty(),
- &mut seal_output,
- )
- .unwrap();
- seal_output
- }
-}
-
-#[cfg(all(test, bench))]
-#[macro_rules_attribute::apply(bench_for_each_provider)]
-mod benchmarks {
- #[bench]
- fn bench_sha256(b: &mut test::Bencher) {
- use core::fmt::Debug;
-
- use super::provider::tls13::TLS13_CHACHA20_POLY1305_SHA256_INTERNAL;
- use super::{KeySchedule, SecretKind, derive_traffic_iv, derive_traffic_key};
- use crate::KeyLog;
-
- fn extract_traffic_secret(ks: &KeySchedule, kind: SecretKind) {
- #[derive(Debug)]
- struct Log;
-
- impl KeyLog for Log {
- fn log(&self, _label: &str, _client_random: &[u8], _secret: &[u8]) {}
- }
-
- let hash = [0u8; 32];
- let traffic_secret = ks.derive_logged_secret(kind, &hash, &Log, &[0u8; 32]);
- let traffic_secret_expander = TLS13_CHACHA20_POLY1305_SHA256_INTERNAL
- .hkdf_provider
- .expander_for_okm(&traffic_secret);
- test::black_box(derive_traffic_key(
- traffic_secret_expander.as_ref(),
- TLS13_CHACHA20_POLY1305_SHA256_INTERNAL.aead_alg,
- ));
- test::black_box(derive_traffic_iv(traffic_secret_expander.as_ref()));
- }
-
- b.iter(|| {
- let mut ks =
- KeySchedule::new_with_empty_secret(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
- ks.input_secret(&[0u8; 32]);
-
- extract_traffic_secret(&ks, SecretKind::ClientHandshakeTrafficSecret);
- extract_traffic_secret(&ks, SecretKind::ServerHandshakeTrafficSecret);
-
- ks.input_empty();
-
- extract_traffic_secret(&ks, SecretKind::ClientApplicationTrafficSecret);
- extract_traffic_secret(&ks, SecretKind::ServerApplicationTrafficSecret);
- });
- }
-}
diff --git a/vendor/rustls/src/tls13/mod.rs b/vendor/rustls/src/tls13/mod.rs
deleted file mode 100644
index ab55c889..00000000
--- a/vendor/rustls/src/tls13/mod.rs
+++ /dev/null
@@ -1,125 +0,0 @@
-use core::fmt;
-
-use crate::crypto;
-use crate::crypto::hash;
-use crate::suites::{CipherSuiteCommon, SupportedCipherSuite};
-
-pub(crate) mod key_schedule;
-
-/// A TLS 1.3 cipher suite supported by rustls.
-pub struct Tls13CipherSuite {
- /// Common cipher suite fields.
- pub common: CipherSuiteCommon,
-
- /// How to complete HKDF with the suite's hash function.
- ///
- /// If you have a HKDF implementation, you should directly implement the `crypto::tls13::Hkdf`
- /// trait (and associated).
- ///
- /// If not, you can implement the [`crypto::hmac::Hmac`] trait (and associated), and then use
- /// [`crypto::tls13::HkdfUsingHmac`].
- pub hkdf_provider: &'static dyn crypto::tls13::Hkdf,
-
- /// How to produce a [MessageDecrypter] or [MessageEncrypter]
- /// from raw key material.
- ///
- /// [MessageDecrypter]: crate::crypto::cipher::MessageDecrypter
- /// [MessageEncrypter]: crate::crypto::cipher::MessageEncrypter
- pub aead_alg: &'static dyn crypto::cipher::Tls13AeadAlgorithm,
-
- /// How to create QUIC header and record protection algorithms
- /// for this suite.
- ///
- /// Provide `None` to opt out of QUIC support for this suite. It will
- /// not be offered in QUIC handshakes.
- pub quic: Option<&'static dyn crate::quic::Algorithm>,
-}
-
-impl Tls13CipherSuite {
- /// Can a session using suite self resume from suite prev?
- pub fn can_resume_from(&self, prev: &'static Self) -> Option<&'static Self> {
- (prev.common.hash_provider.algorithm() == self.common.hash_provider.algorithm())
- .then_some(prev)
- }
-
- /// Return `true` if this is backed by a FIPS-approved implementation.
- ///
- /// This means all the constituent parts that do cryptography return `true` for `fips()`.
- pub fn fips(&self) -> bool {
- let Self {
- common,
- hkdf_provider,
- aead_alg,
- quic,
- } = self;
- common.fips()
- && hkdf_provider.fips()
- && aead_alg.fips()
- && quic.map(|q| q.fips()).unwrap_or(true)
- }
-
- /// Returns a `quic::Suite` for the ciphersuite, if supported.
- pub fn quic_suite(&'static self) -> Option<crate::quic::Suite> {
- self.quic
- .map(|quic| crate::quic::Suite { quic, suite: self })
- }
-}
-
-impl From<&'static Tls13CipherSuite> for SupportedCipherSuite {
- fn from(s: &'static Tls13CipherSuite) -> Self {
- Self::Tls13(s)
- }
-}
-
-impl PartialEq for Tls13CipherSuite {
- fn eq(&self, other: &Self) -> bool {
- self.common.suite == other.common.suite
- }
-}
-
-impl fmt::Debug for Tls13CipherSuite {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("Tls13CipherSuite")
- .field("suite", &self.common.suite)
- .finish()
- }
-}
-
-/// Constructs the signature message specified in section 4.4.3 of RFC8446.
-pub(crate) fn construct_client_verify_message(handshake_hash: &hash::Output) -> VerifyMessage {
- VerifyMessage::new(handshake_hash, CLIENT_CONSTANT)
-}
-
-/// Constructs the signature message specified in section 4.4.3 of RFC8446.
-pub(crate) fn construct_server_verify_message(handshake_hash: &hash::Output) -> VerifyMessage {
- VerifyMessage::new(handshake_hash, SERVER_CONSTANT)
-}
-
-pub(crate) struct VerifyMessage {
- buf: [u8; MAX_VERIFY_MSG],
- used: usize,
-}
-
-impl VerifyMessage {
- fn new(handshake_hash: &hash::Output, context_string_with_0: &[u8; 34]) -> Self {
- let used = 64 + context_string_with_0.len() + handshake_hash.as_ref().len();
- let mut buf = [0x20u8; MAX_VERIFY_MSG];
-
- let (_spaces, context) = buf.split_at_mut(64);
- let (context, hash) = context.split_at_mut(34);
- context.copy_from_slice(context_string_with_0);
- hash[..handshake_hash.as_ref().len()].copy_from_slice(handshake_hash.as_ref());
-
- Self { buf, used }
- }
-}
-
-impl AsRef<[u8]> for VerifyMessage {
- fn as_ref(&self) -> &[u8] {
- &self.buf[..self.used]
- }
-}
-
-const SERVER_CONSTANT: &[u8; 34] = b"TLS 1.3, server CertificateVerify\x00";
-const CLIENT_CONSTANT: &[u8; 34] = b"TLS 1.3, client CertificateVerify\x00";
-const MAX_VERIFY_MSG: usize = 64 + CLIENT_CONSTANT.len() + hash::Output::MAX_LEN;
diff --git a/vendor/rustls/src/vecbuf.rs b/vendor/rustls/src/vecbuf.rs
deleted file mode 100644
index 8a4a1f3e..00000000
--- a/vendor/rustls/src/vecbuf.rs
+++ /dev/null
@@ -1,374 +0,0 @@
-use alloc::collections::VecDeque;
-use alloc::vec::Vec;
-use core::{cmp, mem};
-#[cfg(feature = "std")]
-use std::io;
-#[cfg(feature = "std")]
-use std::io::Read;
-
-#[cfg(feature = "std")]
-use crate::msgs::message::OutboundChunks;
-
-/// This is a byte buffer that is built from a deque of byte vectors.
-///
-/// This avoids extra copies when appending a new byte vector,
-/// at the expense of more complexity when reading out.
-pub(crate) struct ChunkVecBuffer {
- /// How many bytes have been consumed in the first chunk.
- ///
- /// Invariant: zero if `chunks.is_empty()`
- /// Invariant: 0 <= `prefix_used` < `chunks[0].len()`
- prefix_used: usize,
-
- chunks: VecDeque<Vec<u8>>,
-
- /// The total upper limit (in bytes) of this object.
- limit: Option<usize>,
-}
-
-impl ChunkVecBuffer {
- pub(crate) fn new(limit: Option<usize>) -> Self {
- Self {
- prefix_used: 0,
- chunks: VecDeque::new(),
- limit,
- }
- }
-
- /// Sets the upper limit on how many bytes this
- /// object can store.
- ///
- /// Setting a lower limit than the currently stored
- /// data is not an error.
- ///
- /// A [`None`] limit is interpreted as no limit.
- pub(crate) fn set_limit(&mut self, new_limit: Option<usize>) {
- self.limit = new_limit;
- }
-
- /// If we're empty
- pub(crate) fn is_empty(&self) -> bool {
- self.chunks.is_empty()
- }
-
- /// How many bytes we're storing
- pub(crate) fn len(&self) -> usize {
- self.chunks
- .iter()
- .fold(0usize, |acc, chunk| acc + chunk.len())
- - self.prefix_used
- }
-
- /// For a proposed append of `len` bytes, how many
- /// bytes should we actually append to adhere to the
- /// currently set `limit`?
- pub(crate) fn apply_limit(&self, len: usize) -> usize {
- if let Some(limit) = self.limit {
- let space = limit.saturating_sub(self.len());
- cmp::min(len, space)
- } else {
- len
- }
- }
-
- /// Take and append the given `bytes`.
- pub(crate) fn append(&mut self, bytes: Vec<u8>) -> usize {
- let len = bytes.len();
-
- if !bytes.is_empty() {
- if self.chunks.is_empty() {
- debug_assert_eq!(self.prefix_used, 0);
- }
-
- self.chunks.push_back(bytes);
- }
-
- len
- }
-
- /// Take one of the chunks from this object.
- ///
- /// This function returns `None` if the object `is_empty`.
- pub(crate) fn pop(&mut self) -> Option<Vec<u8>> {
- let mut first = self.chunks.pop_front();
-
- if let Some(first) = &mut first {
- // slice off `prefix_used` if needed (uncommon)
- let prefix = mem::take(&mut self.prefix_used);
- first.drain(0..prefix);
- }
-
- first
- }
-
- #[cfg(read_buf)]
- /// Read data out of this object, writing it into `cursor`.
- pub(crate) fn read_buf(&mut self, mut cursor: core::io::BorrowedCursor<'_>) -> io::Result<()> {
- while !self.is_empty() && cursor.capacity() > 0 {
- let chunk = &self.chunks[0][self.prefix_used..];
- let used = cmp::min(chunk.len(), cursor.capacity());
- cursor.append(&chunk[..used]);
- self.consume(used);
- }
-
- Ok(())
- }
-
- /// Inspect the first chunk from this object.
- pub(crate) fn peek(&self) -> Option<&[u8]> {
- self.chunks
- .front()
- .map(|ch| ch.as_slice())
- }
-}
-
-#[cfg(feature = "std")]
-impl ChunkVecBuffer {
- pub(crate) fn is_full(&self) -> bool {
- self.limit
- .map(|limit| self.len() > limit)
- .unwrap_or_default()
- }
-
- /// Append a copy of `bytes`, perhaps a prefix if
- /// we're near the limit.
- pub(crate) fn append_limited_copy(&mut self, payload: OutboundChunks<'_>) -> usize {
- let take = self.apply_limit(payload.len());
- self.append(payload.split_at(take).0.to_vec());
- take
- }
-
- /// Read data out of this object, writing it into `buf`
- /// and returning how many bytes were written there.
- pub(crate) fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- let mut offs = 0;
-
- while offs < buf.len() && !self.is_empty() {
- let used = (&self.chunks[0][self.prefix_used..]).read(&mut buf[offs..])?;
-
- self.consume(used);
- offs += used;
- }
-
- Ok(offs)
- }
-
- pub(crate) fn consume_first_chunk(&mut self, used: usize) {
- // this backs (infallible) `BufRead::consume`, where `used` is
- // user-supplied.
- assert!(
- used <= self
- .chunk()
- .map(|ch| ch.len())
- .unwrap_or_default(),
- "illegal `BufRead::consume` usage",
- );
- self.consume(used);
- }
-
- fn consume(&mut self, used: usize) {
- // first, mark the rightmost extent of the used buffer
- self.prefix_used += used;
-
- // then reduce `prefix_used` by discarding wholly-covered
- // buffers
- while let Some(buf) = self.chunks.front() {
- if self.prefix_used < buf.len() {
- return;
- } else {
- self.prefix_used -= buf.len();
- self.chunks.pop_front();
- }
- }
-
- debug_assert_eq!(
- self.prefix_used, 0,
- "attempted to `ChunkVecBuffer::consume` more than available"
- );
- }
-
- /// Read data out of this object, passing it `wr`
- pub(crate) fn write_to(&mut self, wr: &mut dyn io::Write) -> io::Result<usize> {
- if self.is_empty() {
- return Ok(0);
- }
-
- let mut prefix = self.prefix_used;
- let mut bufs = [io::IoSlice::new(&[]); 64];
- for (iov, chunk) in bufs.iter_mut().zip(self.chunks.iter()) {
- *iov = io::IoSlice::new(&chunk[prefix..]);
- prefix = 0;
- }
- let len = cmp::min(bufs.len(), self.chunks.len());
- let bufs = &bufs[..len];
- let used = wr.write_vectored(bufs)?;
- let available_bytes = bufs.iter().map(|ch| ch.len()).sum();
-
- if used > available_bytes {
- // This is really unrecoverable, since the amount of data written
- // is now unknown. Consume all the potentially-written data in
- // case the caller ignores the error.
- // See <https://github.com/rustls/rustls/issues/2316> for background.
- self.consume(available_bytes);
- return Err(io::Error::new(
- io::ErrorKind::Other,
- std::format!("illegal write_vectored return value ({used} > {available_bytes})"),
- ));
- }
- self.consume(used);
- Ok(used)
- }
-
- /// Returns the first contiguous chunk of data, or None if empty.
- pub(crate) fn chunk(&self) -> Option<&[u8]> {
- self.chunks
- .front()
- .map(|chunk| &chunk[self.prefix_used..])
- }
-}
-
-#[cfg(all(test, feature = "std"))]
-mod tests {
- use alloc::vec;
- use alloc::vec::Vec;
-
- use super::ChunkVecBuffer;
-
- #[test]
- fn short_append_copy_with_limit() {
- let mut cvb = ChunkVecBuffer::new(Some(12));
- assert_eq!(cvb.append_limited_copy(b"hello"[..].into()), 5);
- assert_eq!(cvb.append_limited_copy(b"world"[..].into()), 5);
- assert_eq!(cvb.append_limited_copy(b"hello"[..].into()), 2);
- assert_eq!(cvb.append_limited_copy(b"world"[..].into()), 0);
-
- let mut buf = [0u8; 12];
- assert_eq!(cvb.read(&mut buf).unwrap(), 12);
- assert_eq!(buf.to_vec(), b"helloworldhe".to_vec());
- }
-
- #[test]
- fn read_byte_by_byte() {
- let mut cvb = ChunkVecBuffer::new(None);
- cvb.append(b"test fixture data".to_vec());
- assert!(!cvb.is_empty());
- for expect in b"test fixture data" {
- let mut byte = [0];
- assert_eq!(cvb.read(&mut byte).unwrap(), 1);
- assert_eq!(byte[0], *expect);
- }
-
- assert_eq!(cvb.read(&mut [0]).unwrap(), 0);
- }
-
- #[test]
- fn every_possible_chunk_interleaving() {
- let input = (0..=0xffu8)
- .cycle()
- .take(4096)
- .collect::<Vec<u8>>();
-
- for input_chunk_len in 1..64usize {
- for output_chunk_len in 1..65usize {
- std::println!("check input={input_chunk_len} output={output_chunk_len}");
- let mut cvb = ChunkVecBuffer::new(None);
- for chunk in input.chunks(input_chunk_len) {
- cvb.append(chunk.to_vec());
- }
-
- assert_eq!(cvb.len(), input.len());
- let mut buf = vec![0u8; output_chunk_len];
-
- for expect in input.chunks(output_chunk_len) {
- assert_eq!(expect.len(), cvb.read(&mut buf).unwrap());
- assert_eq!(expect, &buf[..expect.len()]);
- }
-
- assert_eq!(cvb.read(&mut [0]).unwrap(), 0);
- }
- }
- }
-
- #[cfg(read_buf)]
- #[test]
- fn read_buf() {
- use core::io::BorrowedBuf;
- use core::mem::MaybeUninit;
-
- {
- let mut cvb = ChunkVecBuffer::new(None);
- cvb.append(b"test ".to_vec());
- cvb.append(b"fixture ".to_vec());
- cvb.append(b"data".to_vec());
-
- let mut buf = [MaybeUninit::<u8>::uninit(); 8];
- let mut buf: BorrowedBuf<'_> = buf.as_mut_slice().into();
- cvb.read_buf(buf.unfilled()).unwrap();
- assert_eq!(buf.filled(), b"test fix");
- buf.clear();
- cvb.read_buf(buf.unfilled()).unwrap();
- assert_eq!(buf.filled(), b"ture dat");
- buf.clear();
- cvb.read_buf(buf.unfilled()).unwrap();
- assert_eq!(buf.filled(), b"a");
- }
-
- {
- let mut cvb = ChunkVecBuffer::new(None);
- cvb.append(b"short message".to_vec());
-
- let mut buf = [MaybeUninit::<u8>::uninit(); 1024];
- let mut buf: BorrowedBuf<'_> = buf.as_mut_slice().into();
- cvb.read_buf(buf.unfilled()).unwrap();
- assert_eq!(buf.filled(), b"short message");
- }
- }
-}
-
-#[cfg(bench)]
-mod benchmarks {
- use alloc::vec;
-
- use super::ChunkVecBuffer;
-
- #[bench]
- fn read_one_byte_from_large_message(b: &mut test::Bencher) {
- b.iter(|| {
- let mut cvb = ChunkVecBuffer::new(None);
- cvb.append(vec![0u8; 16_384]);
- assert_eq!(1, cvb.read(&mut [0u8]).unwrap());
- });
- }
-
- #[bench]
- fn read_all_individual_from_large_message(b: &mut test::Bencher) {
- b.iter(|| {
- let mut cvb = ChunkVecBuffer::new(None);
- cvb.append(vec![0u8; 16_384]);
- loop {
- if let Ok(0) = cvb.read(&mut [0u8]) {
- break;
- }
- }
- });
- }
-
- #[bench]
- fn read_half_bytes_from_large_message(b: &mut test::Bencher) {
- b.iter(|| {
- let mut cvb = ChunkVecBuffer::new(None);
- cvb.append(vec![0u8; 16_384]);
- assert_eq!(8192, cvb.read(&mut [0u8; 8192]).unwrap());
- assert_eq!(8192, cvb.read(&mut [0u8; 8192]).unwrap());
- });
- }
-
- #[bench]
- fn read_entire_large_message(b: &mut test::Bencher) {
- b.iter(|| {
- let mut cvb = ChunkVecBuffer::new(None);
- cvb.append(vec![0u8; 16_384]);
- assert_eq!(16_384, cvb.read(&mut [0u8; 16_384]).unwrap());
- });
- }
-}
diff --git a/vendor/rustls/src/verify.rs b/vendor/rustls/src/verify.rs
deleted file mode 100644
index ce07e3a0..00000000
--- a/vendor/rustls/src/verify.rs
+++ /dev/null
@@ -1,382 +0,0 @@
-use alloc::vec::Vec;
-use core::fmt::Debug;
-
-use pki_types::{CertificateDer, ServerName, UnixTime};
-
-use crate::enums::SignatureScheme;
-use crate::error::{Error, InvalidMessage};
-use crate::msgs::base::PayloadU16;
-use crate::msgs::codec::{Codec, Reader};
-use crate::msgs::handshake::DistinguishedName;
-
-// Marker types. These are used to bind the fact some verification
-// (certificate chain or handshake signature) has taken place into
-// protocol states. We use this to have the compiler check that there
-// are no 'goto fail'-style elisions of important checks before we
-// reach the traffic stage.
-//
-// These types are public, but cannot be directly constructed. This
-// means their origins can be precisely determined by looking
-// for their `assertion` constructors.
-
-/// Zero-sized marker type representing verification of a signature.
-#[derive(Debug)]
-pub struct HandshakeSignatureValid(());
-
-impl HandshakeSignatureValid {
- /// Make a `HandshakeSignatureValid`
- pub fn assertion() -> Self {
- Self(())
- }
-}
-
-#[derive(Debug)]
-pub(crate) struct FinishedMessageVerified(());
-
-impl FinishedMessageVerified {
- pub(crate) fn assertion() -> Self {
- Self(())
- }
-}
-
-/// Zero-sized marker type representing verification of a server cert chain.
-#[allow(unreachable_pub)]
-#[derive(Debug)]
-pub struct ServerCertVerified(());
-
-#[allow(unreachable_pub)]
-impl ServerCertVerified {
- /// Make a `ServerCertVerified`
- pub fn assertion() -> Self {
- Self(())
- }
-}
-
-/// Zero-sized marker type representing verification of a client cert chain.
-#[derive(Debug)]
-pub struct ClientCertVerified(());
-
-impl ClientCertVerified {
- /// Make a `ClientCertVerified`
- pub fn assertion() -> Self {
- Self(())
- }
-}
-
-/// Something that can verify a server certificate chain, and verify
-/// signatures made by certificates.
-#[allow(unreachable_pub)]
-pub trait ServerCertVerifier: Debug + Send + Sync {
- /// Verify the end-entity certificate `end_entity` is valid for the
- /// hostname `dns_name` and chains to at least one trust anchor.
- ///
- /// `intermediates` contains all certificates other than `end_entity` that
- /// were sent as part of the server's [Certificate] message. It is in the
- /// same order that the server sent them and may be empty.
- ///
- /// Note that none of the certificates have been parsed yet, so it is the responsibility of
- /// the implementer to handle invalid data. It is recommended that the implementer returns
- /// [`Error::InvalidCertificate(CertificateError::BadEncoding)`] when these cases are encountered.
- ///
- /// [Certificate]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.4.2
- fn verify_server_cert(
- &self,
- end_entity: &CertificateDer<'_>,
- intermediates: &[CertificateDer<'_>],
- server_name: &ServerName<'_>,
- ocsp_response: &[u8],
- now: UnixTime,
- ) -> Result<ServerCertVerified, Error>;
-
- /// Verify a signature allegedly by the given server certificate.
- ///
- /// `message` is not hashed, and needs hashing during the verification.
- /// The signature and algorithm are within `dss`. `cert` contains the
- /// public key to use.
- ///
- /// `cert` has already been validated by [`ServerCertVerifier::verify_server_cert`].
- ///
- /// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`.
- /// Otherwise, return an error -- rustls will send an alert and abort the
- /// connection.
- ///
- /// This method is only called for TLS1.2 handshakes. Note that, in TLS1.2,
- /// SignatureSchemes such as `SignatureScheme::ECDSA_NISTP256_SHA256` are not
- /// in fact bound to the specific curve implied in their name.
- fn verify_tls12_signature(
- &self,
- message: &[u8],
- cert: &CertificateDer<'_>,
- dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error>;
-
- /// Verify a signature allegedly by the given server certificate.
- ///
- /// This method is only called for TLS1.3 handshakes.
- ///
- /// This method is very similar to `verify_tls12_signature`: but note the
- /// tighter ECDSA SignatureScheme semantics -- e.g. `SignatureScheme::ECDSA_NISTP256_SHA256`
- /// must only validate signatures using public keys on the right curve --
- /// rustls does not enforce this requirement for you.
- ///
- /// `cert` has already been validated by [`ServerCertVerifier::verify_server_cert`].
- ///
- /// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`.
- /// Otherwise, return an error -- rustls will send an alert and abort the
- /// connection.
- fn verify_tls13_signature(
- &self,
- message: &[u8],
- cert: &CertificateDer<'_>,
- dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error>;
-
- /// Return the list of SignatureSchemes that this verifier will handle,
- /// in `verify_tls12_signature` and `verify_tls13_signature` calls.
- ///
- /// This should be in priority order, with the most preferred first.
- fn supported_verify_schemes(&self) -> Vec<SignatureScheme>;
-
- /// Returns whether this verifier requires raw public keys as defined
- /// in [RFC 7250](https://tools.ietf.org/html/rfc7250).
- fn requires_raw_public_keys(&self) -> bool {
- false
- }
-
- /// Return the [`DistinguishedName`]s of certificate authorities that this verifier trusts.
- ///
- /// If specified, will be sent as the [`certificate_authorities`] extension in ClientHello.
- /// Note that this is only applicable to TLS 1.3.
- ///
- /// [`certificate_authorities`]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.4
- fn root_hint_subjects(&self) -> Option<&[DistinguishedName]> {
- None
- }
-}
-
-/// Something that can verify a client certificate chain
-#[allow(unreachable_pub)]
-pub trait ClientCertVerifier: Debug + Send + Sync {
- /// Returns `true` to enable the server to request a client certificate and
- /// `false` to skip requesting a client certificate. Defaults to `true`.
- fn offer_client_auth(&self) -> bool {
- true
- }
-
- /// Return `true` to require a client certificate and `false` to make
- /// client authentication optional.
- /// Defaults to `self.offer_client_auth()`.
- fn client_auth_mandatory(&self) -> bool {
- self.offer_client_auth()
- }
-
- /// Returns the [`DistinguishedName`] [subjects] that the server will hint to clients to
- /// identify acceptable authentication trust anchors.
- ///
- /// These hint values help the client pick a client certificate it believes the server will
- /// accept. The hints must be DER-encoded X.500 distinguished names, per [RFC 5280 A.1]. They
- /// are sent in the [`certificate_authorities`] extension of a [`CertificateRequest`] message
- /// when [ClientCertVerifier::offer_client_auth] is true. When an empty list is sent the client
- /// should always provide a client certificate if it has one.
- ///
- /// Generally this list should contain the [`DistinguishedName`] of each root trust
- /// anchor in the root cert store that the server is configured to use for authenticating
- /// presented client certificates.
- ///
- /// In some circumstances this list may be customized to include [`DistinguishedName`] entries
- /// that do not correspond to a trust anchor in the server's root cert store. For example,
- /// the server may be configured to trust a root CA that cross-signed an issuer certificate
- /// that the client considers a trust anchor. From the server's perspective the cross-signed
- /// certificate is an intermediate, and not present in the server's root cert store. The client
- /// may have the cross-signed certificate configured as a trust anchor, and be unaware of the
- /// root CA that cross-signed it. If the server's hints list only contained the subjects of the
- /// server's root store the client would consider a client certificate issued by the cross-signed
- /// issuer unacceptable, since its subject was not hinted. To avoid this circumstance the server
- /// should customize the hints list to include the subject of the cross-signed issuer in addition
- /// to the subjects from the root cert store.
- ///
- /// [subjects]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6
- /// [RFC 5280 A.1]: https://www.rfc-editor.org/rfc/rfc5280#appendix-A.1
- /// [`CertificateRequest`]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.3.2
- /// [`certificate_authorities`]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.4
- fn root_hint_subjects(&self) -> &[DistinguishedName];
-
- /// Verify the end-entity certificate `end_entity` is valid, acceptable,
- /// and chains to at least one of the trust anchors trusted by
- /// this verifier.
- ///
- /// `intermediates` contains the intermediate certificates the
- /// client sent along with the end-entity certificate; it is in the same
- /// order that the peer sent them and may be empty.
- ///
- /// Note that none of the certificates have been parsed yet, so it is the responsibility of
- /// the implementer to handle invalid data. It is recommended that the implementer returns
- /// an [InvalidCertificate] error with the [BadEncoding] variant when these cases are encountered.
- ///
- /// [InvalidCertificate]: Error#variant.InvalidCertificate
- /// [BadEncoding]: crate::CertificateError#variant.BadEncoding
- fn verify_client_cert(
- &self,
- end_entity: &CertificateDer<'_>,
- intermediates: &[CertificateDer<'_>],
- now: UnixTime,
- ) -> Result<ClientCertVerified, Error>;
-
- /// Verify a signature allegedly by the given client certificate.
- ///
- /// `message` is not hashed, and needs hashing during the verification.
- /// The signature and algorithm are within `dss`. `cert` contains the
- /// public key to use.
- ///
- /// `cert` has already been validated by [`ClientCertVerifier::verify_client_cert`].
- ///
- /// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`.
- /// Otherwise, return an error -- rustls will send an alert and abort the
- /// connection.
- ///
- /// This method is only called for TLS1.2 handshakes. Note that, in TLS1.2,
- /// SignatureSchemes such as `SignatureScheme::ECDSA_NISTP256_SHA256` are not
- /// in fact bound to the specific curve implied in their name.
- fn verify_tls12_signature(
- &self,
- message: &[u8],
- cert: &CertificateDer<'_>,
- dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error>;
-
- /// Verify a signature allegedly by the given client certificate.
- ///
- /// This method is only called for TLS1.3 handshakes.
- ///
- /// This method is very similar to `verify_tls12_signature`, but note the
- /// tighter ECDSA SignatureScheme semantics in TLS 1.3. For example,
- /// `SignatureScheme::ECDSA_NISTP256_SHA256`
- /// must only validate signatures using public keys on the right curve --
- /// rustls does not enforce this requirement for you.
- fn verify_tls13_signature(
- &self,
- message: &[u8],
- cert: &CertificateDer<'_>,
- dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error>;
-
- /// Return the list of SignatureSchemes that this verifier will handle,
- /// in `verify_tls12_signature` and `verify_tls13_signature` calls.
- ///
- /// This should be in priority order, with the most preferred first.
- fn supported_verify_schemes(&self) -> Vec<SignatureScheme>;
-
- /// Returns whether this verifier requires raw public keys as defined
- /// in [RFC 7250](https://tools.ietf.org/html/rfc7250).
- fn requires_raw_public_keys(&self) -> bool {
- false
- }
-}
-
-/// Turns off client authentication.
-///
-/// In contrast to using
-/// `WebPkiClientVerifier::builder(roots).allow_unauthenticated().build()`, the `NoClientAuth`
-/// `ClientCertVerifier` will not offer client authentication at all, vs offering but not
-/// requiring it.
-#[derive(Debug)]
-pub struct NoClientAuth;
-
-impl ClientCertVerifier for NoClientAuth {
- fn offer_client_auth(&self) -> bool {
- false
- }
-
- fn root_hint_subjects(&self) -> &[DistinguishedName] {
- unimplemented!();
- }
-
- fn verify_client_cert(
- &self,
- _end_entity: &CertificateDer<'_>,
- _intermediates: &[CertificateDer<'_>],
- _now: UnixTime,
- ) -> Result<ClientCertVerified, Error> {
- unimplemented!();
- }
-
- fn verify_tls12_signature(
- &self,
- _message: &[u8],
- _cert: &CertificateDer<'_>,
- _dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error> {
- unimplemented!();
- }
-
- fn verify_tls13_signature(
- &self,
- _message: &[u8],
- _cert: &CertificateDer<'_>,
- _dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error> {
- unimplemented!();
- }
-
- fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
- unimplemented!();
- }
-}
-
-/// This type combines a [`SignatureScheme`] and a signature payload produced with that scheme.
-#[derive(Debug, Clone)]
-pub struct DigitallySignedStruct {
- /// The [`SignatureScheme`] used to produce the signature.
- pub scheme: SignatureScheme,
- sig: PayloadU16,
-}
-
-impl DigitallySignedStruct {
- pub(crate) fn new(scheme: SignatureScheme, sig: Vec<u8>) -> Self {
- Self {
- scheme,
- sig: PayloadU16::new(sig),
- }
- }
-
- /// Get the signature.
- pub fn signature(&self) -> &[u8] {
- &self.sig.0
- }
-}
-
-impl Codec<'_> for DigitallySignedStruct {
- fn encode(&self, bytes: &mut Vec<u8>) {
- self.scheme.encode(bytes);
- self.sig.encode(bytes);
- }
-
- fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
- let scheme = SignatureScheme::read(r)?;
- let sig = PayloadU16::read(r)?;
-
- Ok(Self { scheme, sig })
- }
-}
-
-#[test]
-fn assertions_are_debug() {
- use std::format;
-
- assert_eq!(
- format!("{:?}", ClientCertVerified::assertion()),
- "ClientCertVerified(())"
- );
- assert_eq!(
- format!("{:?}", HandshakeSignatureValid::assertion()),
- "HandshakeSignatureValid(())"
- );
- assert_eq!(
- format!("{:?}", FinishedMessageVerified::assertion()),
- "FinishedMessageVerified(())"
- );
- assert_eq!(
- format!("{:?}", ServerCertVerified::assertion()),
- "ServerCertVerified(())"
- );
-}
diff --git a/vendor/rustls/src/verifybench.rs b/vendor/rustls/src/verifybench.rs
deleted file mode 100644
index 06213e7b..00000000
--- a/vendor/rustls/src/verifybench.rs
+++ /dev/null
@@ -1,244 +0,0 @@
-//! This program does benchmarking of the functions in verify.rs,
-//! that do certificate chain validation and signature verification.
-//!
-//! This uses captured certificate chains for a selection of websites,
-//! saved in `testdata/cert-{SITE}.{I}.der`.
-//!
-//! To update that data:
-//!
-//! - delete all `testdata/cert-*.der`.
-//! - run the `admin/capture-certdata` script.
-//! - update the verification timestamp near the bottom of this file
-//! to the current time.
-//! - where a website's chain length changed, reflect that in the list
-//! of certificate files below.
-//!
-//! This does not need to be done regularly; because the verification
-//! time is fixed, it only needs doing if a root certificate is
-//! distrusted.
-
-#![cfg(bench)]
-
-use core::time::Duration;
-use std::prelude::v1::*;
-
-use pki_types::{CertificateDer, ServerName, UnixTime};
-use webpki_roots;
-
-use crate::crypto::CryptoProvider;
-use crate::verify::ServerCertVerifier;
-use crate::webpki::{RootCertStore, WebPkiServerVerifier};
-
-#[macro_rules_attribute::apply(bench_for_each_provider)]
-mod benchmarks {
- use super::{Context, provider};
-
- #[bench]
- fn reddit_cert(b: &mut test::Bencher) {
- let ctx = Context::new(
- provider::default_provider(),
- "reddit.com",
- &[
- include_bytes!("testdata/cert-reddit.0.der"),
- include_bytes!("testdata/cert-reddit.1.der"),
- ],
- );
- b.iter(|| ctx.verify_once());
- }
-
- #[bench]
- fn github_cert(b: &mut test::Bencher) {
- let ctx = Context::new(
- provider::default_provider(),
- "github.com",
- &[
- include_bytes!("testdata/cert-github.0.der"),
- include_bytes!("testdata/cert-github.1.der"),
- include_bytes!("testdata/cert-github.2.der"),
- ],
- );
- b.iter(|| ctx.verify_once());
- }
-
- #[bench]
- fn arstechnica_cert(b: &mut test::Bencher) {
- let ctx = Context::new(
- provider::default_provider(),
- "arstechnica.com",
- &[
- include_bytes!("testdata/cert-arstechnica.0.der"),
- include_bytes!("testdata/cert-arstechnica.1.der"),
- include_bytes!("testdata/cert-arstechnica.2.der"),
- ],
- );
- b.iter(|| ctx.verify_once());
- }
-
- #[bench]
- fn servo_cert(b: &mut test::Bencher) {
- let ctx = Context::new(
- provider::default_provider(),
- "servo.org",
- &[
- include_bytes!("testdata/cert-servo.0.der"),
- include_bytes!("testdata/cert-servo.1.der"),
- include_bytes!("testdata/cert-servo.2.der"),
- ],
- );
- b.iter(|| ctx.verify_once());
- }
-
- #[bench]
- fn twitter_cert(b: &mut test::Bencher) {
- let ctx = Context::new(
- provider::default_provider(),
- "twitter.com",
- &[
- include_bytes!("testdata/cert-twitter.0.der"),
- include_bytes!("testdata/cert-twitter.1.der"),
- ],
- );
- b.iter(|| ctx.verify_once());
- }
-
- #[bench]
- fn wikipedia_cert(b: &mut test::Bencher) {
- let ctx = Context::new(
- provider::default_provider(),
- "wikipedia.org",
- &[
- include_bytes!("testdata/cert-wikipedia.0.der"),
- include_bytes!("testdata/cert-wikipedia.1.der"),
- ],
- );
- b.iter(|| ctx.verify_once());
- }
-
- #[bench]
- fn google_cert(b: &mut test::Bencher) {
- let ctx = Context::new(
- provider::default_provider(),
- "www.google.com",
- &[
- include_bytes!("testdata/cert-google.0.der"),
- include_bytes!("testdata/cert-google.1.der"),
- include_bytes!("testdata/cert-google.2.der"),
- ],
- );
- b.iter(|| ctx.verify_once());
- }
-
- #[bench]
- fn hn_cert(b: &mut test::Bencher) {
- let ctx = Context::new(
- provider::default_provider(),
- "news.ycombinator.com",
- &[
- include_bytes!("testdata/cert-hn.0.der"),
- include_bytes!("testdata/cert-hn.1.der"),
- ],
- );
- b.iter(|| ctx.verify_once());
- }
-
- #[bench]
- fn stackoverflow_cert(b: &mut test::Bencher) {
- let ctx = Context::new(
- provider::default_provider(),
- "stackoverflow.com",
- &[
- include_bytes!("testdata/cert-stackoverflow.0.der"),
- include_bytes!("testdata/cert-stackoverflow.1.der"),
- ],
- );
- b.iter(|| ctx.verify_once());
- }
-
- #[bench]
- fn duckduckgo_cert(b: &mut test::Bencher) {
- let ctx = Context::new(
- provider::default_provider(),
- "duckduckgo.com",
- &[
- include_bytes!("testdata/cert-duckduckgo.0.der"),
- include_bytes!("testdata/cert-duckduckgo.1.der"),
- include_bytes!("testdata/cert-duckduckgo.2.der"),
- ],
- );
- b.iter(|| ctx.verify_once());
- }
-
- #[bench]
- fn rustlang_cert(b: &mut test::Bencher) {
- let ctx = Context::new(
- provider::default_provider(),
- "www.rust-lang.org",
- &[
- include_bytes!("testdata/cert-rustlang.0.der"),
- include_bytes!("testdata/cert-rustlang.1.der"),
- include_bytes!("testdata/cert-rustlang.2.der"),
- include_bytes!("testdata/cert-rustlang.3.der"),
- ],
- );
- b.iter(|| ctx.verify_once());
- }
-
- #[bench]
- fn wapo_cert(b: &mut test::Bencher) {
- let ctx = Context::new(
- provider::default_provider(),
- "www.washingtonpost.com",
- &[
- include_bytes!("testdata/cert-wapo.0.der"),
- include_bytes!("testdata/cert-wapo.1.der"),
- ],
- );
- b.iter(|| ctx.verify_once());
- }
-}
-
-struct Context {
- server_name: ServerName<'static>,
- chain: Vec<CertificateDer<'static>>,
- now: UnixTime,
- verifier: WebPkiServerVerifier,
-}
-
-impl Context {
- fn new(provider: CryptoProvider, domain: &'static str, certs: &[&'static [u8]]) -> Self {
- let mut roots = RootCertStore::empty();
- roots.extend(
- webpki_roots::TLS_SERVER_ROOTS
- .iter()
- .cloned(),
- );
- Self {
- server_name: domain.try_into().unwrap(),
- chain: certs
- .iter()
- .copied()
- .map(|bytes| CertificateDer::from(bytes.to_vec()))
- .collect(),
- now: UnixTime::since_unix_epoch(Duration::from_secs(1_746_605_469)),
- verifier: WebPkiServerVerifier::new_without_revocation(
- roots,
- provider.signature_verification_algorithms,
- ),
- }
- }
-
- fn verify_once(&self) {
- const OCSP_RESPONSE: &[u8] = &[];
-
- let (end_entity, intermediates) = self.chain.split_first().unwrap();
- self.verifier
- .verify_server_cert(
- end_entity,
- intermediates,
- &self.server_name,
- OCSP_RESPONSE,
- self.now,
- )
- .unwrap();
- }
-}
diff --git a/vendor/rustls/src/versions.rs b/vendor/rustls/src/versions.rs
deleted file mode 100644
index 4acdf99a..00000000
--- a/vendor/rustls/src/versions.rs
+++ /dev/null
@@ -1,97 +0,0 @@
-use core::fmt;
-
-use crate::enums::ProtocolVersion;
-
-/// A TLS protocol version supported by rustls.
-///
-/// All possible instances of this class are provided by the library in
-/// the [`ALL_VERSIONS`] array, as well as individually as [`TLS12`]
-/// and [`TLS13`].
-#[non_exhaustive]
-#[derive(Eq, PartialEq)]
-pub struct SupportedProtocolVersion {
- /// The TLS enumeration naming this version.
- pub version: ProtocolVersion,
-}
-
-impl fmt::Debug for SupportedProtocolVersion {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.version.fmt(f)
- }
-}
-
-/// TLS1.2
-#[cfg(feature = "tls12")]
-pub static TLS12: SupportedProtocolVersion = SupportedProtocolVersion {
- version: ProtocolVersion::TLSv1_2,
-};
-
-/// TLS1.3
-pub static TLS13: SupportedProtocolVersion = SupportedProtocolVersion {
- version: ProtocolVersion::TLSv1_3,
-};
-
-/// A list of all the protocol versions supported by rustls.
-pub static ALL_VERSIONS: &[&SupportedProtocolVersion] = &[
- &TLS13,
- #[cfg(feature = "tls12")]
- &TLS12,
-];
-
-/// The version configuration that an application should use by default.
-///
-/// This will be [`ALL_VERSIONS`] for now, but gives space in the future
-/// to remove a version from here and require users to opt-in to older
-/// versions.
-pub static DEFAULT_VERSIONS: &[&SupportedProtocolVersion] = ALL_VERSIONS;
-
-#[derive(Clone, Copy)]
-pub(crate) struct EnabledVersions {
- #[cfg(feature = "tls12")]
- tls12: Option<&'static SupportedProtocolVersion>,
- tls13: Option<&'static SupportedProtocolVersion>,
-}
-
-impl fmt::Debug for EnabledVersions {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let mut list = &mut f.debug_list();
- #[cfg(feature = "tls12")]
- if let Some(v) = self.tls12 {
- list = list.entry(v);
- }
- if let Some(v) = self.tls13 {
- list = list.entry(v);
- }
- list.finish()
- }
-}
-
-impl EnabledVersions {
- pub(crate) fn new(versions: &[&'static SupportedProtocolVersion]) -> Self {
- let mut ev = Self {
- #[cfg(feature = "tls12")]
- tls12: None,
- tls13: None,
- };
-
- for v in versions {
- match v.version {
- #[cfg(feature = "tls12")]
- ProtocolVersion::TLSv1_2 => ev.tls12 = Some(v),
- ProtocolVersion::TLSv1_3 => ev.tls13 = Some(v),
- _ => {}
- }
- }
-
- ev
- }
-
- pub(crate) fn contains(&self, version: ProtocolVersion) -> bool {
- match version {
- #[cfg(feature = "tls12")]
- ProtocolVersion::TLSv1_2 => self.tls12.is_some(),
- ProtocolVersion::TLSv1_3 => self.tls13.is_some(),
- _ => false,
- }
- }
-}
diff --git a/vendor/rustls/src/webpki/anchors.rs b/vendor/rustls/src/webpki/anchors.rs
deleted file mode 100644
index b526ed25..00000000
--- a/vendor/rustls/src/webpki/anchors.rs
+++ /dev/null
@@ -1,143 +0,0 @@
-use alloc::vec::Vec;
-use alloc::{fmt, format};
-
-use pki_types::{CertificateDer, TrustAnchor};
-use webpki::anchor_from_trusted_cert;
-
-use super::pki_error;
-use crate::log::{debug, trace};
-use crate::{DistinguishedName, Error};
-
-/// A container for root certificates able to provide a root-of-trust
-/// for connection authentication.
-#[derive(Clone)]
-pub struct RootCertStore {
- /// The list of roots.
- pub roots: Vec<TrustAnchor<'static>>,
-}
-
-impl RootCertStore {
- /// Make a new, empty `RootCertStore`.
- pub fn empty() -> Self {
- Self { roots: Vec::new() }
- }
-
- /// Parse the given DER-encoded certificates and add all that can be parsed
- /// in a best-effort fashion.
- ///
- /// This is because large collections of root certificates often
- /// include ancient or syntactically invalid certificates.
- ///
- /// Returns the number of certificates added, and the number that were ignored.
- pub fn add_parsable_certificates<'a>(
- &mut self,
- der_certs: impl IntoIterator<Item = CertificateDer<'a>>,
- ) -> (usize, usize) {
- let mut valid_count = 0;
- let mut invalid_count = 0;
-
- for der_cert in der_certs {
- #[cfg_attr(not(feature = "logging"), allow(unused_variables))]
- match anchor_from_trusted_cert(&der_cert) {
- Ok(anchor) => {
- self.roots.push(anchor.to_owned());
- valid_count += 1;
- }
- Err(err) => {
- trace!("invalid cert der {:?}", der_cert.as_ref());
- debug!("certificate parsing failed: {err:?}");
- invalid_count += 1;
- }
- };
- }
-
- debug!(
- "add_parsable_certificates processed {valid_count} valid and {invalid_count} invalid certs"
- );
-
- (valid_count, invalid_count)
- }
-
- /// Add a single DER-encoded certificate to the store.
- ///
- /// This is suitable for a small set of root certificates that are expected to parse
- /// successfully. For large collections of roots (for example from a system store) it
- /// is expected that some of them might not be valid according to the rules rustls
- /// implements. As long as a relatively limited number of certificates are affected,
- /// this should not be a cause for concern. Use [`RootCertStore::add_parsable_certificates`]
- /// in order to add as many valid roots as possible and to understand how many certificates
- /// have been diagnosed as malformed.
- pub fn add(&mut self, der: CertificateDer<'_>) -> Result<(), Error> {
- self.roots.push(
- anchor_from_trusted_cert(&der)
- .map_err(pki_error)?
- .to_owned(),
- );
- Ok(())
- }
-
- /// Return the DER encoded [`DistinguishedName`] of each trust anchor subject in the root
- /// cert store.
- ///
- /// Each [`DistinguishedName`] will be a DER-encoded X.500 distinguished name, per
- /// [RFC 5280 A.1], including the outer `SEQUENCE`.
- ///
- /// [RFC 5280 A.1]: https://www.rfc-editor.org/rfc/rfc5280#appendix-A.1
- pub fn subjects(&self) -> Vec<DistinguishedName> {
- self.roots
- .iter()
- .map(|ta| DistinguishedName::in_sequence(ta.subject.as_ref()))
- .collect()
- }
-
- /// Return true if there are no certificates.
- pub fn is_empty(&self) -> bool {
- self.len() == 0
- }
-
- /// Say how many certificates are in the container.
- pub fn len(&self) -> usize {
- self.roots.len()
- }
-}
-
-impl FromIterator<TrustAnchor<'static>> for RootCertStore {
- fn from_iter<T: IntoIterator<Item = TrustAnchor<'static>>>(iter: T) -> Self {
- Self {
- roots: iter.into_iter().collect(),
- }
- }
-}
-
-impl Extend<TrustAnchor<'static>> for RootCertStore {
- fn extend<T: IntoIterator<Item = TrustAnchor<'static>>>(&mut self, iter: T) {
- self.roots.extend(iter);
- }
-}
-
-impl fmt::Debug for RootCertStore {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("RootCertStore")
- .field("roots", &format!("({} roots)", &self.roots.len()))
- .finish()
- }
-}
-
-#[test]
-fn root_cert_store_debug() {
- use core::iter;
-
- use pki_types::Der;
-
- let ta = TrustAnchor {
- subject: Der::from_slice(&[]),
- subject_public_key_info: Der::from_slice(&[]),
- name_constraints: None,
- };
- let store = RootCertStore::from_iter(iter::repeat(ta).take(138));
-
- assert_eq!(
- format!("{store:?}"),
- "RootCertStore { roots: \"(138 roots)\" }"
- );
-}
diff --git a/vendor/rustls/src/webpki/client_verifier.rs b/vendor/rustls/src/webpki/client_verifier.rs
deleted file mode 100644
index 060f0f77..00000000
--- a/vendor/rustls/src/webpki/client_verifier.rs
+++ /dev/null
@@ -1,665 +0,0 @@
-use alloc::vec::Vec;
-
-use pki_types::{CertificateDer, CertificateRevocationListDer, UnixTime};
-use webpki::{CertRevocationList, ExpirationPolicy, RevocationCheckDepth, UnknownStatusPolicy};
-
-use super::{VerifierBuilderError, pki_error};
-#[cfg(doc)]
-use crate::ConfigBuilder;
-#[cfg(doc)]
-use crate::crypto;
-use crate::crypto::{CryptoProvider, WebPkiSupportedAlgorithms};
-#[cfg(doc)]
-use crate::server::ServerConfig;
-use crate::sync::Arc;
-use crate::verify::{
- ClientCertVerified, ClientCertVerifier, DigitallySignedStruct, HandshakeSignatureValid,
- NoClientAuth,
-};
-use crate::webpki::parse_crls;
-use crate::webpki::verify::{ParsedCertificate, verify_tls12_signature, verify_tls13_signature};
-use crate::{DistinguishedName, Error, RootCertStore, SignatureScheme};
-
-/// A builder for configuring a `webpki` client certificate verifier.
-///
-/// For more information, see the [`WebPkiClientVerifier`] documentation.
-#[derive(Debug, Clone)]
-pub struct ClientCertVerifierBuilder {
- roots: Arc<RootCertStore>,
- root_hint_subjects: Vec<DistinguishedName>,
- crls: Vec<CertificateRevocationListDer<'static>>,
- revocation_check_depth: RevocationCheckDepth,
- unknown_revocation_policy: UnknownStatusPolicy,
- revocation_expiration_policy: ExpirationPolicy,
- anon_policy: AnonymousClientPolicy,
- supported_algs: WebPkiSupportedAlgorithms,
-}
-
-impl ClientCertVerifierBuilder {
- pub(crate) fn new(
- roots: Arc<RootCertStore>,
- supported_algs: WebPkiSupportedAlgorithms,
- ) -> Self {
- Self {
- root_hint_subjects: roots.subjects(),
- roots,
- crls: Vec::new(),
- anon_policy: AnonymousClientPolicy::Deny,
- revocation_check_depth: RevocationCheckDepth::Chain,
- unknown_revocation_policy: UnknownStatusPolicy::Deny,
- revocation_expiration_policy: ExpirationPolicy::Ignore,
- supported_algs,
- }
- }
-
- /// Clear the list of trust anchor hint subjects.
- ///
- /// By default, the client cert verifier will use the subjects provided by the root cert
- /// store configured for client authentication. Calling this function will remove these
- /// hint subjects, indicating the client should make a free choice of which certificate
- /// to send.
- ///
- /// See [`ClientCertVerifier::root_hint_subjects`] for more information on
- /// circumstances where you may want to clear the default hint subjects.
- pub fn clear_root_hint_subjects(mut self) -> Self {
- self.root_hint_subjects = Vec::default();
- self
- }
-
- /// Add additional [`DistinguishedName`]s to the list of trust anchor hint subjects.
- ///
- /// By default, the client cert verifier will use the subjects provided by the root cert
- /// store configured for client authentication. Calling this function will add to these
- /// existing hint subjects. Calling this function with empty `subjects` will have no
- /// effect.
- ///
- /// See [`ClientCertVerifier::root_hint_subjects`] for more information on
- /// circumstances where you may want to override the default hint subjects.
- pub fn add_root_hint_subjects(
- mut self,
- subjects: impl IntoIterator<Item = DistinguishedName>,
- ) -> Self {
- self.root_hint_subjects.extend(subjects);
- self
- }
-
- /// Verify the revocation state of presented client certificates against the provided
- /// certificate revocation lists (CRLs). Calling `with_crls` multiple times appends the
- /// given CRLs to the existing collection.
- ///
- /// By default all certificates in the verified chain built from the presented client
- /// certificate to a trust anchor will have their revocation status checked. Calling
- /// [`only_check_end_entity_revocation`][Self::only_check_end_entity_revocation] will
- /// change this behavior to only check the end entity client certificate.
- ///
- /// By default if a certificate's revocation status can not be determined using the
- /// configured CRLs, it will be treated as an error. Calling
- /// [`allow_unknown_revocation_status`][Self::allow_unknown_revocation_status] will change
- /// this behavior to allow unknown revocation status.
- pub fn with_crls(
- mut self,
- crls: impl IntoIterator<Item = CertificateRevocationListDer<'static>>,
- ) -> Self {
- self.crls.extend(crls);
- self
- }
-
- /// Only check the end entity certificate revocation status when using CRLs.
- ///
- /// If CRLs are provided using [`with_crls`][Self::with_crls] only check the end entity
- /// certificate's revocation status. Overrides the default behavior of checking revocation
- /// status for each certificate in the verified chain built to a trust anchor
- /// (excluding the trust anchor itself).
- ///
- /// If no CRLs are provided then this setting has no effect. Neither the end entity certificate
- /// or any intermediates will have revocation status checked.
- pub fn only_check_end_entity_revocation(mut self) -> Self {
- self.revocation_check_depth = RevocationCheckDepth::EndEntity;
- self
- }
-
- /// Allow unauthenticated clients to connect.
- ///
- /// Clients that offer a client certificate issued by a trusted root, and clients that offer no
- /// client certificate will be allowed to connect.
- pub fn allow_unauthenticated(mut self) -> Self {
- self.anon_policy = AnonymousClientPolicy::Allow;
- self
- }
-
- /// Allow unknown certificate revocation status when using CRLs.
- ///
- /// If CRLs are provided with [`with_crls`][Self::with_crls] and it isn't possible to
- /// determine the revocation status of a certificate, do not treat it as an error condition.
- /// Overrides the default behavior where unknown revocation status is considered an error.
- ///
- /// If no CRLs are provided then this setting has no effect as revocation status checks
- /// are not performed.
- pub fn allow_unknown_revocation_status(mut self) -> Self {
- self.unknown_revocation_policy = UnknownStatusPolicy::Allow;
- self
- }
-
- /// Enforce the CRL nextUpdate field (i.e. expiration)
- ///
- /// If CRLs are provided with [`with_crls`][Self::with_crls] and the verification time is
- /// beyond the time in the CRL nextUpdate field, it is expired and treated as an error condition.
- /// Overrides the default behavior where expired CRLs are not treated as an error condition.
- ///
- /// If no CRLs are provided then this setting has no effect as revocation status checks
- /// are not performed.
- pub fn enforce_revocation_expiration(mut self) -> Self {
- self.revocation_expiration_policy = ExpirationPolicy::Enforce;
- self
- }
-
- /// Build a client certificate verifier. The built verifier will be used for the server to offer
- /// client certificate authentication, to control how offered client certificates are validated,
- /// and to determine what to do with anonymous clients that do not respond to the client
- /// certificate authentication offer with a client certificate.
- ///
- /// If `with_signature_verification_algorithms` was not called on the builder, a default set of
- /// signature verification algorithms is used, controlled by the selected [`CryptoProvider`].
- ///
- /// Once built, the provided `Arc<dyn ClientCertVerifier>` can be used with a Rustls
- /// [`ServerConfig`] to configure client certificate validation using
- /// [`with_client_cert_verifier`][ConfigBuilder<ClientConfig, WantsVerifier>::with_client_cert_verifier].
- ///
- /// # Errors
- /// This function will return a [`VerifierBuilderError`] if:
- /// 1. No trust anchors have been provided.
- /// 2. DER encoded CRLs have been provided that can not be parsed successfully.
- pub fn build(self) -> Result<Arc<dyn ClientCertVerifier>, VerifierBuilderError> {
- if self.roots.is_empty() {
- return Err(VerifierBuilderError::NoRootAnchors);
- }
-
- Ok(Arc::new(WebPkiClientVerifier::new(
- self.roots,
- self.root_hint_subjects,
- parse_crls(self.crls)?,
- self.revocation_check_depth,
- self.unknown_revocation_policy,
- self.revocation_expiration_policy,
- self.anon_policy,
- self.supported_algs,
- )))
- }
-}
-
-/// A client certificate verifier that uses the `webpki` crate[^1] to perform client certificate
-/// validation.
-///
-/// It must be created via the [`WebPkiClientVerifier::builder()`] or
-/// [`WebPkiClientVerifier::builder_with_provider()`] functions.
-///
-/// Once built, the provided `Arc<dyn ClientCertVerifier>` can be used with a Rustls [`ServerConfig`]
-/// to configure client certificate validation using [`with_client_cert_verifier`][ConfigBuilder<ClientConfig, WantsVerifier>::with_client_cert_verifier].
-///
-/// Example:
-///
-/// To require all clients present a client certificate issued by a trusted CA:
-/// ```no_run
-/// # #[cfg(any(feature = "ring", feature = "aws_lc_rs"))] {
-/// # use rustls::RootCertStore;
-/// # use rustls::server::WebPkiClientVerifier;
-/// # let roots = RootCertStore::empty();
-/// let client_verifier = WebPkiClientVerifier::builder(roots.into())
-/// .build()
-/// .unwrap();
-/// # }
-/// ```
-///
-/// Or, to allow clients presenting a client certificate authenticated by a trusted CA, or
-/// anonymous clients that present no client certificate:
-/// ```no_run
-/// # #[cfg(any(feature = "ring", feature = "aws_lc_rs"))] {
-/// # use rustls::RootCertStore;
-/// # use rustls::server::WebPkiClientVerifier;
-/// # let roots = RootCertStore::empty();
-/// let client_verifier = WebPkiClientVerifier::builder(roots.into())
-/// .allow_unauthenticated()
-/// .build()
-/// .unwrap();
-/// # }
-/// ```
-///
-/// If you wish to disable advertising client authentication:
-/// ```no_run
-/// # use rustls::RootCertStore;
-/// # use rustls::server::WebPkiClientVerifier;
-/// # let roots = RootCertStore::empty();
-/// let client_verifier = WebPkiClientVerifier::no_client_auth();
-/// ```
-///
-/// You can also configure the client verifier to check for certificate revocation with
-/// client certificate revocation lists (CRLs):
-/// ```no_run
-/// # #[cfg(any(feature = "ring", feature = "aws_lc_rs"))] {
-/// # use rustls::RootCertStore;
-/// # use rustls::server::{WebPkiClientVerifier};
-/// # let roots = RootCertStore::empty();
-/// # let crls = Vec::new();
-/// let client_verifier = WebPkiClientVerifier::builder(roots.into())
-/// .with_crls(crls)
-/// .build()
-/// .unwrap();
-/// # }
-/// ```
-///
-/// [^1]: <https://github.com/rustls/webpki>
-#[derive(Debug)]
-pub struct WebPkiClientVerifier {
- roots: Arc<RootCertStore>,
- root_hint_subjects: Vec<DistinguishedName>,
- crls: Vec<CertRevocationList<'static>>,
- revocation_check_depth: RevocationCheckDepth,
- unknown_revocation_policy: UnknownStatusPolicy,
- revocation_expiration_policy: ExpirationPolicy,
- anonymous_policy: AnonymousClientPolicy,
- supported_algs: WebPkiSupportedAlgorithms,
-}
-
-impl WebPkiClientVerifier {
- /// Create a builder for the `webpki` client certificate verifier configuration using
- /// the [process-default `CryptoProvider`][CryptoProvider#using-the-per-process-default-cryptoprovider].
- ///
- /// Client certificate authentication will be offered by the server, and client certificates
- /// will be verified using the trust anchors found in the provided `roots`. If you
- /// wish to disable client authentication use [`WebPkiClientVerifier::no_client_auth()`] instead.
- ///
- /// Use [`Self::builder_with_provider`] if you wish to specify an explicit provider.
- ///
- /// For more information, see the [`ClientCertVerifierBuilder`] documentation.
- pub fn builder(roots: Arc<RootCertStore>) -> ClientCertVerifierBuilder {
- Self::builder_with_provider(
- roots,
- CryptoProvider::get_default_or_install_from_crate_features().clone(),
- )
- }
-
- /// Create a builder for the `webpki` client certificate verifier configuration using
- /// a specified [`CryptoProvider`].
- ///
- /// Client certificate authentication will be offered by the server, and client certificates
- /// will be verified using the trust anchors found in the provided `roots`. If you
- /// wish to disable client authentication use [WebPkiClientVerifier::no_client_auth()] instead.
- ///
- /// The cryptography used comes from the specified [`CryptoProvider`].
- ///
- /// For more information, see the [`ClientCertVerifierBuilder`] documentation.
- pub fn builder_with_provider(
- roots: Arc<RootCertStore>,
- provider: Arc<CryptoProvider>,
- ) -> ClientCertVerifierBuilder {
- ClientCertVerifierBuilder::new(roots, provider.signature_verification_algorithms)
- }
-
- /// Create a new `WebPkiClientVerifier` that disables client authentication. The server will
- /// not offer client authentication and anonymous clients will be accepted.
- ///
- /// This is in contrast to using `WebPkiClientVerifier::builder().allow_unauthenticated().build()`,
- /// which will produce a verifier that will offer client authentication, but not require it.
- pub fn no_client_auth() -> Arc<dyn ClientCertVerifier> {
- Arc::new(NoClientAuth {})
- }
-
- /// Construct a new `WebpkiClientVerifier`.
- ///
- /// * `roots` is a list of trust anchors to use for certificate validation.
- /// * `root_hint_subjects` is a list of distinguished names to use for hinting acceptable
- /// certificate authority subjects to a client.
- /// * `crls` is a `Vec` of owned certificate revocation lists (CRLs) to use for
- /// client certificate validation.
- /// * `revocation_check_depth` controls which certificates have their revocation status checked
- /// when `crls` are provided.
- /// * `unknown_revocation_policy` controls how certificates with an unknown revocation status
- /// are handled when `crls` are provided.
- /// * `anonymous_policy` controls whether client authentication is required, or if anonymous
- /// clients can connect.
- /// * `supported_algs` specifies which signature verification algorithms should be used.
- pub(crate) fn new(
- roots: Arc<RootCertStore>,
- root_hint_subjects: Vec<DistinguishedName>,
- crls: Vec<CertRevocationList<'static>>,
- revocation_check_depth: RevocationCheckDepth,
- unknown_revocation_policy: UnknownStatusPolicy,
- revocation_expiration_policy: ExpirationPolicy,
- anonymous_policy: AnonymousClientPolicy,
- supported_algs: WebPkiSupportedAlgorithms,
- ) -> Self {
- Self {
- roots,
- root_hint_subjects,
- crls,
- revocation_check_depth,
- unknown_revocation_policy,
- revocation_expiration_policy,
- anonymous_policy,
- supported_algs,
- }
- }
-}
-
-impl ClientCertVerifier for WebPkiClientVerifier {
- fn offer_client_auth(&self) -> bool {
- true
- }
-
- fn client_auth_mandatory(&self) -> bool {
- match self.anonymous_policy {
- AnonymousClientPolicy::Allow => false,
- AnonymousClientPolicy::Deny => true,
- }
- }
-
- fn root_hint_subjects(&self) -> &[DistinguishedName] {
- &self.root_hint_subjects
- }
-
- fn verify_client_cert(
- &self,
- end_entity: &CertificateDer<'_>,
- intermediates: &[CertificateDer<'_>],
- now: UnixTime,
- ) -> Result<ClientCertVerified, Error> {
- let cert = ParsedCertificate::try_from(end_entity)?;
-
- let crl_refs = self.crls.iter().collect::<Vec<_>>();
-
- let revocation = if self.crls.is_empty() {
- None
- } else {
- Some(
- webpki::RevocationOptionsBuilder::new(&crl_refs)
- // Note: safe to unwrap here - new is only fallible if no CRLs are provided
- // and we verify this above.
- .unwrap()
- .with_depth(self.revocation_check_depth)
- .with_status_policy(self.unknown_revocation_policy)
- .with_expiration_policy(self.revocation_expiration_policy)
- .build(),
- )
- };
-
- cert.0
- .verify_for_usage(
- self.supported_algs.all,
- &self.roots.roots,
- intermediates,
- now,
- webpki::KeyUsage::client_auth(),
- revocation,
- None,
- )
- .map_err(pki_error)
- .map(|_| ClientCertVerified::assertion())
- }
-
- fn verify_tls12_signature(
- &self,
- message: &[u8],
- cert: &CertificateDer<'_>,
- dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error> {
- verify_tls12_signature(message, cert, dss, &self.supported_algs)
- }
-
- fn verify_tls13_signature(
- &self,
- message: &[u8],
- cert: &CertificateDer<'_>,
- dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error> {
- verify_tls13_signature(message, cert, dss, &self.supported_algs)
- }
-
- fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
- self.supported_algs.supported_schemes()
- }
-}
-
-/// Controls how the [WebPkiClientVerifier] handles anonymous clients.
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub(crate) enum AnonymousClientPolicy {
- /// Clients that do not present a client certificate are allowed.
- Allow,
- /// Clients that do not present a client certificate are denied.
- Deny,
-}
-
-#[cfg(test)]
-#[macro_rules_attribute::apply(test_for_each_provider)]
-mod tests {
- use std::prelude::v1::*;
- use std::{format, println, vec};
-
- use pki_types::pem::PemObject;
- use pki_types::{CertificateDer, CertificateRevocationListDer};
-
- use super::{WebPkiClientVerifier, provider};
- use crate::RootCertStore;
- use crate::server::VerifierBuilderError;
- use crate::sync::Arc;
-
- fn load_crls(crls_der: &[&[u8]]) -> Vec<CertificateRevocationListDer<'static>> {
- crls_der
- .iter()
- .map(|pem_bytes| CertificateRevocationListDer::from_pem_slice(pem_bytes).unwrap())
- .collect()
- }
-
- fn test_crls() -> Vec<CertificateRevocationListDer<'static>> {
- load_crls(&[
- include_bytes!("../../../test-ca/ecdsa-p256/client.revoked.crl.pem").as_slice(),
- include_bytes!("../../../test-ca/rsa-2048/client.revoked.crl.pem").as_slice(),
- ])
- }
-
- fn load_roots(roots_der: &[&[u8]]) -> Arc<RootCertStore> {
- let mut roots = RootCertStore::empty();
- roots_der.iter().for_each(|der| {
- roots
- .add(CertificateDer::from(der.to_vec()))
- .unwrap()
- });
- roots.into()
- }
-
- fn test_roots() -> Arc<RootCertStore> {
- load_roots(&[
- include_bytes!("../../../test-ca/ecdsa-p256/ca.der").as_slice(),
- include_bytes!("../../../test-ca/rsa-2048/ca.der").as_slice(),
- ])
- }
-
- #[test]
- fn test_client_verifier_no_auth() {
- // We should be able to build a verifier that turns off client authentication.
- WebPkiClientVerifier::no_client_auth();
- }
-
- #[test]
- fn test_client_verifier_required_auth() {
- // We should be able to build a verifier that requires client authentication, and does
- // no revocation checking.
- let builder = WebPkiClientVerifier::builder_with_provider(
- test_roots(),
- provider::default_provider().into(),
- );
- // The builder should be Debug.
- println!("{builder:?}");
- builder.build().unwrap();
- }
-
- #[test]
- fn test_client_verifier_optional_auth() {
- // We should be able to build a verifier that allows client authentication, and anonymous
- // access, and does no revocation checking.
- let builder = WebPkiClientVerifier::builder_with_provider(
- test_roots(),
- provider::default_provider().into(),
- )
- .allow_unauthenticated();
- // The builder should be Debug.
- println!("{builder:?}");
- builder.build().unwrap();
- }
-
- #[test]
- fn test_client_verifier_without_crls_required_auth() {
- // We should be able to build a verifier that requires client authentication, and does
- // no revocation checking, that hasn't been configured to determine how to handle
- // unauthenticated clients yet.
- let builder = WebPkiClientVerifier::builder_with_provider(
- test_roots(),
- provider::default_provider().into(),
- );
- // The builder should be Debug.
- println!("{builder:?}");
- builder.build().unwrap();
- }
-
- #[test]
- fn test_client_verifier_without_crls_opptional_auth() {
- // We should be able to build a verifier that allows client authentication,
- // and anonymous access, that does no revocation checking.
- let builder = WebPkiClientVerifier::builder_with_provider(
- test_roots(),
- provider::default_provider().into(),
- )
- .allow_unauthenticated();
- // The builder should be Debug.
- println!("{builder:?}");
- builder.build().unwrap();
- }
-
- #[test]
- fn test_with_invalid_crls() {
- // Trying to build a client verifier with invalid CRLs should error at build time.
- let result = WebPkiClientVerifier::builder_with_provider(
- test_roots(),
- provider::default_provider().into(),
- )
- .with_crls(vec![CertificateRevocationListDer::from(vec![0xFF])])
- .build();
- assert!(matches!(result, Err(VerifierBuilderError::InvalidCrl(_))));
- }
-
- #[test]
- fn test_with_crls_multiple_calls() {
- // We should be able to call `with_crls` on a client verifier multiple times.
- let initial_crls = test_crls();
- let extra_crls =
- load_crls(&[
- include_bytes!("../../../test-ca/eddsa/client.revoked.crl.pem").as_slice(),
- ]);
- let builder = WebPkiClientVerifier::builder_with_provider(
- test_roots(),
- provider::default_provider().into(),
- )
- .with_crls(initial_crls.clone())
- .with_crls(extra_crls.clone());
-
- // There should be the expected number of crls.
- assert_eq!(builder.crls.len(), initial_crls.len() + extra_crls.len());
- // The builder should be Debug.
- println!("{builder:?}");
- builder.build().unwrap();
- }
-
- #[test]
- fn test_client_verifier_with_crls_required_auth_implicit() {
- // We should be able to build a verifier that requires client authentication, and that does
- // revocation checking with CRLs, and that does not allow any anonymous access.
- let builder = WebPkiClientVerifier::builder_with_provider(
- test_roots(),
- provider::default_provider().into(),
- )
- .with_crls(test_crls());
- // The builder should be Debug.
- println!("{builder:?}");
- builder.build().unwrap();
- }
-
- #[test]
- fn test_client_verifier_with_crls_optional_auth() {
- // We should be able to build a verifier that supports client authentication, that does
- // revocation checking with CRLs, and that allows anonymous access.
- let builder = WebPkiClientVerifier::builder_with_provider(
- test_roots(),
- provider::default_provider().into(),
- )
- .with_crls(test_crls())
- .allow_unauthenticated();
- // The builder should be Debug.
- println!("{builder:?}");
- builder.build().unwrap();
- }
-
- #[test]
- fn test_client_verifier_ee_only() {
- // We should be able to build a client verifier that only checks EE revocation status.
- let builder = WebPkiClientVerifier::builder_with_provider(
- test_roots(),
- provider::default_provider().into(),
- )
- .with_crls(test_crls())
- .only_check_end_entity_revocation();
- // The builder should be Debug.
- println!("{builder:?}");
- builder.build().unwrap();
- }
-
- #[test]
- fn test_client_verifier_allow_unknown() {
- // We should be able to build a client verifier that allows unknown revocation status
- let builder = WebPkiClientVerifier::builder_with_provider(
- test_roots(),
- provider::default_provider().into(),
- )
- .with_crls(test_crls())
- .allow_unknown_revocation_status();
- // The builder should be Debug.
- println!("{builder:?}");
- builder.build().unwrap();
- }
-
- #[test]
- fn test_client_verifier_enforce_expiration() {
- // We should be able to build a client verifier that allows unknown revocation status
- let builder = WebPkiClientVerifier::builder_with_provider(
- test_roots(),
- provider::default_provider().into(),
- )
- .with_crls(test_crls())
- .enforce_revocation_expiration();
- // The builder should be Debug.
- println!("{builder:?}");
- builder.build().unwrap();
- }
-
- #[test]
- fn test_builder_no_roots() {
- // Trying to create a client verifier builder with no trust anchors should fail at build time
- let result = WebPkiClientVerifier::builder_with_provider(
- RootCertStore::empty().into(),
- provider::default_provider().into(),
- )
- .build();
- assert!(matches!(result, Err(VerifierBuilderError::NoRootAnchors)));
- }
-
- #[test]
- fn smoke() {
- let all = vec![
- VerifierBuilderError::NoRootAnchors,
- VerifierBuilderError::InvalidCrl(crate::CertRevocationListError::ParseError),
- ];
-
- for err in all {
- let _ = format!("{err:?}");
- let _ = format!("{err}");
- }
- }
-}
diff --git a/vendor/rustls/src/webpki/mod.rs b/vendor/rustls/src/webpki/mod.rs
deleted file mode 100644
index 24960a1e..00000000
--- a/vendor/rustls/src/webpki/mod.rs
+++ /dev/null
@@ -1,313 +0,0 @@
-use alloc::vec::Vec;
-use core::fmt;
-
-use pki_types::CertificateRevocationListDer;
-use webpki::{CertRevocationList, InvalidNameContext, OwnedCertRevocationList};
-
-use crate::error::{
- CertRevocationListError, CertificateError, Error, ExtendedKeyPurpose, OtherError,
-};
-#[cfg(feature = "std")]
-use crate::sync::Arc;
-
-mod anchors;
-mod client_verifier;
-mod server_verifier;
-mod verify;
-
-pub use anchors::RootCertStore;
-pub use client_verifier::{ClientCertVerifierBuilder, WebPkiClientVerifier};
-pub use server_verifier::{ServerCertVerifierBuilder, WebPkiServerVerifier};
-// Conditionally exported from crate.
-#[allow(unreachable_pub)]
-pub use verify::{
- ParsedCertificate, verify_server_cert_signed_by_trust_anchor, verify_server_name,
-};
-pub use verify::{
- WebPkiSupportedAlgorithms, verify_tls12_signature, verify_tls13_signature,
- verify_tls13_signature_with_raw_key,
-};
-
-/// An error that can occur when building a certificate verifier.
-#[derive(Debug, Clone)]
-#[non_exhaustive]
-pub enum VerifierBuilderError {
- /// No root trust anchors were provided.
- NoRootAnchors,
- /// A provided CRL could not be parsed.
- InvalidCrl(CertRevocationListError),
-}
-
-impl From<CertRevocationListError> for VerifierBuilderError {
- fn from(value: CertRevocationListError) -> Self {
- Self::InvalidCrl(value)
- }
-}
-
-impl fmt::Display for VerifierBuilderError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::NoRootAnchors => write!(f, "no root trust anchors were provided"),
- Self::InvalidCrl(e) => write!(f, "provided CRL could not be parsed: {e:?}"),
- }
- }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for VerifierBuilderError {}
-
-fn pki_error(error: webpki::Error) -> Error {
- use webpki::Error::*;
- match error {
- BadDer | BadDerTime | TrailingData(_) => CertificateError::BadEncoding.into(),
- CertNotValidYet { time, not_before } => {
- CertificateError::NotValidYetContext { time, not_before }.into()
- }
- CertExpired { time, not_after } => {
- CertificateError::ExpiredContext { time, not_after }.into()
- }
- InvalidCertValidity => CertificateError::Expired.into(),
- UnknownIssuer => CertificateError::UnknownIssuer.into(),
- CertNotValidForName(InvalidNameContext {
- expected,
- presented,
- }) => CertificateError::NotValidForNameContext {
- expected,
- presented,
- }
- .into(),
- CertRevoked => CertificateError::Revoked.into(),
- UnknownRevocationStatus => CertificateError::UnknownRevocationStatus.into(),
- CrlExpired { time, next_update } => {
- CertificateError::ExpiredRevocationListContext { time, next_update }.into()
- }
- IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl.into(),
-
- InvalidSignatureForPublicKey => CertificateError::BadSignature.into(),
- #[allow(deprecated)]
- UnsupportedSignatureAlgorithm | UnsupportedSignatureAlgorithmForPublicKey => {
- CertificateError::UnsupportedSignatureAlgorithm.into()
- }
- UnsupportedSignatureAlgorithmContext(cx) => {
- CertificateError::UnsupportedSignatureAlgorithmContext {
- signature_algorithm_id: cx.signature_algorithm_id,
- supported_algorithms: cx.supported_algorithms,
- }
- .into()
- }
- UnsupportedSignatureAlgorithmForPublicKeyContext(cx) => {
- CertificateError::UnsupportedSignatureAlgorithmForPublicKeyContext {
- signature_algorithm_id: cx.signature_algorithm_id,
- public_key_algorithm_id: cx.public_key_algorithm_id,
- }
- .into()
- }
-
- InvalidCrlSignatureForPublicKey => CertRevocationListError::BadSignature.into(),
- #[allow(deprecated)]
- UnsupportedCrlSignatureAlgorithm | UnsupportedCrlSignatureAlgorithmForPublicKey => {
- CertRevocationListError::UnsupportedSignatureAlgorithm.into()
- }
- UnsupportedCrlSignatureAlgorithmContext(cx) => {
- CertRevocationListError::UnsupportedSignatureAlgorithmContext {
- signature_algorithm_id: cx.signature_algorithm_id,
- supported_algorithms: cx.supported_algorithms,
- }
- .into()
- }
- UnsupportedCrlSignatureAlgorithmForPublicKeyContext(cx) => {
- CertRevocationListError::UnsupportedSignatureAlgorithmForPublicKeyContext {
- signature_algorithm_id: cx.signature_algorithm_id,
- public_key_algorithm_id: cx.public_key_algorithm_id,
- }
- .into()
- }
-
- #[allow(deprecated)]
- RequiredEkuNotFound => CertificateError::InvalidPurpose.into(),
- RequiredEkuNotFoundContext(webpki::RequiredEkuNotFoundContext { required, present }) => {
- CertificateError::InvalidPurposeContext {
- required: ExtendedKeyPurpose::for_values(required.oid_values()),
- presented: present
- .into_iter()
- .map(|eku| ExtendedKeyPurpose::for_values(eku.into_iter()))
- .collect(),
- }
- .into()
- }
-
- _ => CertificateError::Other(OtherError(
- #[cfg(feature = "std")]
- Arc::new(error),
- ))
- .into(),
- }
-}
-
-fn crl_error(e: webpki::Error) -> CertRevocationListError {
- use webpki::Error::*;
- match e {
- InvalidCrlSignatureForPublicKey => CertRevocationListError::BadSignature,
- #[allow(deprecated)]
- UnsupportedCrlSignatureAlgorithm | UnsupportedCrlSignatureAlgorithmForPublicKey => {
- CertRevocationListError::UnsupportedSignatureAlgorithm
- }
- UnsupportedCrlSignatureAlgorithmContext(cx) => {
- CertRevocationListError::UnsupportedSignatureAlgorithmContext {
- signature_algorithm_id: cx.signature_algorithm_id,
- supported_algorithms: cx.supported_algorithms,
- }
- }
- UnsupportedSignatureAlgorithmForPublicKeyContext(cx) => {
- CertRevocationListError::UnsupportedSignatureAlgorithmForPublicKeyContext {
- signature_algorithm_id: cx.signature_algorithm_id,
- public_key_algorithm_id: cx.public_key_algorithm_id,
- }
- }
- InvalidCrlNumber => CertRevocationListError::InvalidCrlNumber,
- InvalidSerialNumber => CertRevocationListError::InvalidRevokedCertSerialNumber,
- IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl,
- MalformedExtensions | BadDer | BadDerTime => CertRevocationListError::ParseError,
- UnsupportedCriticalExtension => CertRevocationListError::UnsupportedCriticalExtension,
- UnsupportedCrlVersion => CertRevocationListError::UnsupportedCrlVersion,
- UnsupportedDeltaCrl => CertRevocationListError::UnsupportedDeltaCrl,
- UnsupportedIndirectCrl => CertRevocationListError::UnsupportedIndirectCrl,
- UnsupportedRevocationReason => CertRevocationListError::UnsupportedRevocationReason,
-
- _ => CertRevocationListError::Other(OtherError(
- #[cfg(feature = "std")]
- Arc::new(e),
- )),
- }
-}
-
-fn parse_crls(
- crls: Vec<CertificateRevocationListDer<'_>>,
-) -> Result<Vec<CertRevocationList<'_>>, CertRevocationListError> {
- crls.iter()
- .map(|der| OwnedCertRevocationList::from_der(der.as_ref()).map(Into::into))
- .collect::<Result<Vec<_>, _>>()
- .map_err(crl_error)
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use alloc::vec;
-
- #[test]
- fn pki_crl_errors() {
- // CRL signature errors should be turned into BadSignature.
- assert_eq!(
- pki_error(webpki::Error::InvalidCrlSignatureForPublicKey),
- Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
- );
-
- #[allow(deprecated)]
- {
- assert_eq!(
- pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithm),
- Error::InvalidCertRevocationList(
- CertRevocationListError::UnsupportedSignatureAlgorithm
- ),
- );
- assert_eq!(
- pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey),
- Error::InvalidCertRevocationList(
- CertRevocationListError::UnsupportedSignatureAlgorithm
- ),
- );
- }
-
- assert_eq!(
- pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmContext(
- webpki::UnsupportedSignatureAlgorithmContext {
- signature_algorithm_id: vec![],
- supported_algorithms: vec![],
- }
- )),
- Error::InvalidCertRevocationList(
- CertRevocationListError::UnsupportedSignatureAlgorithmContext {
- signature_algorithm_id: vec![],
- supported_algorithms: vec![],
- }
- )
- );
- assert_eq!(
- pki_error(
- webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKeyContext(
- webpki::UnsupportedSignatureAlgorithmForPublicKeyContext {
- signature_algorithm_id: vec![],
- public_key_algorithm_id: vec![],
- }
- )
- ),
- Error::InvalidCertRevocationList(
- CertRevocationListError::UnsupportedSignatureAlgorithmForPublicKeyContext {
- signature_algorithm_id: vec![],
- public_key_algorithm_id: vec![],
- }
- )
- );
-
- // Revoked cert errors should be turned into Revoked.
- assert_eq!(
- pki_error(webpki::Error::CertRevoked),
- Error::InvalidCertificate(CertificateError::Revoked),
- );
-
- // Issuer not CRL signer errors should be turned into IssuerInvalidForCrl
- assert_eq!(
- pki_error(webpki::Error::IssuerNotCrlSigner),
- Error::InvalidCertRevocationList(CertRevocationListError::IssuerInvalidForCrl)
- );
- }
-
- #[test]
- fn crl_error_from_webpki() {
- use CertRevocationListError::*;
- #[allow(deprecated)]
- let testcases = &[
- (webpki::Error::InvalidCrlSignatureForPublicKey, BadSignature),
- (
- webpki::Error::UnsupportedCrlSignatureAlgorithm,
- UnsupportedSignatureAlgorithm,
- ),
- (
- webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey,
- UnsupportedSignatureAlgorithm,
- ),
- (webpki::Error::InvalidCrlNumber, InvalidCrlNumber),
- (
- webpki::Error::InvalidSerialNumber,
- InvalidRevokedCertSerialNumber,
- ),
- (webpki::Error::IssuerNotCrlSigner, IssuerInvalidForCrl),
- (webpki::Error::MalformedExtensions, ParseError),
- (webpki::Error::BadDer, ParseError),
- (webpki::Error::BadDerTime, ParseError),
- (
- webpki::Error::UnsupportedCriticalExtension,
- UnsupportedCriticalExtension,
- ),
- (webpki::Error::UnsupportedCrlVersion, UnsupportedCrlVersion),
- (webpki::Error::UnsupportedDeltaCrl, UnsupportedDeltaCrl),
- (
- webpki::Error::UnsupportedIndirectCrl,
- UnsupportedIndirectCrl,
- ),
- (
- webpki::Error::UnsupportedRevocationReason,
- UnsupportedRevocationReason,
- ),
- ];
- for t in testcases {
- assert_eq!(crl_error(t.0.clone()), t.1);
- }
-
- assert!(matches!(
- crl_error(webpki::Error::NameConstraintViolation),
- Other(..)
- ));
- }
-}
diff --git a/vendor/rustls/src/webpki/server_verifier.rs b/vendor/rustls/src/webpki/server_verifier.rs
deleted file mode 100644
index 5aa92350..00000000
--- a/vendor/rustls/src/webpki/server_verifier.rs
+++ /dev/null
@@ -1,448 +0,0 @@
-use alloc::vec::Vec;
-
-use pki_types::{CertificateDer, CertificateRevocationListDer, ServerName, UnixTime};
-use webpki::{CertRevocationList, ExpirationPolicy, RevocationCheckDepth, UnknownStatusPolicy};
-
-use crate::crypto::{CryptoProvider, WebPkiSupportedAlgorithms};
-use crate::log::trace;
-use crate::sync::Arc;
-use crate::verify::{
- DigitallySignedStruct, HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier,
-};
-use crate::webpki::verify::{
- ParsedCertificate, verify_server_cert_signed_by_trust_anchor_impl, verify_tls12_signature,
- verify_tls13_signature,
-};
-use crate::webpki::{VerifierBuilderError, parse_crls, verify_server_name};
-#[cfg(doc)]
-use crate::{ConfigBuilder, ServerConfig, crypto};
-use crate::{Error, RootCertStore, SignatureScheme};
-
-/// A builder for configuring a `webpki` server certificate verifier.
-///
-/// For more information, see the [`WebPkiServerVerifier`] documentation.
-#[derive(Debug, Clone)]
-pub struct ServerCertVerifierBuilder {
- roots: Arc<RootCertStore>,
- crls: Vec<CertificateRevocationListDer<'static>>,
- revocation_check_depth: RevocationCheckDepth,
- unknown_revocation_policy: UnknownStatusPolicy,
- revocation_expiration_policy: ExpirationPolicy,
- supported_algs: WebPkiSupportedAlgorithms,
-}
-
-impl ServerCertVerifierBuilder {
- pub(crate) fn new(
- roots: Arc<RootCertStore>,
- supported_algs: WebPkiSupportedAlgorithms,
- ) -> Self {
- Self {
- roots,
- crls: Vec::new(),
- revocation_check_depth: RevocationCheckDepth::Chain,
- unknown_revocation_policy: UnknownStatusPolicy::Deny,
- revocation_expiration_policy: ExpirationPolicy::Ignore,
- supported_algs,
- }
- }
-
- /// Verify the revocation state of presented client certificates against the provided
- /// certificate revocation lists (CRLs). Calling `with_crls` multiple times appends the
- /// given CRLs to the existing collection.
- pub fn with_crls(
- mut self,
- crls: impl IntoIterator<Item = CertificateRevocationListDer<'static>>,
- ) -> Self {
- self.crls.extend(crls);
- self
- }
-
- /// Only check the end entity certificate revocation status when using CRLs.
- ///
- /// If CRLs are provided using [`with_crls`][Self::with_crls] only check the end entity
- /// certificate's revocation status. Overrides the default behavior of checking revocation
- /// status for each certificate in the verified chain built to a trust anchor
- /// (excluding the trust anchor itself).
- ///
- /// If no CRLs are provided then this setting has no effect. Neither the end entity certificate
- /// or any intermediates will have revocation status checked.
- pub fn only_check_end_entity_revocation(mut self) -> Self {
- self.revocation_check_depth = RevocationCheckDepth::EndEntity;
- self
- }
-
- /// Allow unknown certificate revocation status when using CRLs.
- ///
- /// If CRLs are provided with [`with_crls`][Self::with_crls] and it isn't possible to
- /// determine the revocation status of a certificate, do not treat it as an error condition.
- /// Overrides the default behavior where unknown revocation status is considered an error.
- ///
- /// If no CRLs are provided then this setting has no effect as revocation status checks
- /// are not performed.
- pub fn allow_unknown_revocation_status(mut self) -> Self {
- self.unknown_revocation_policy = UnknownStatusPolicy::Allow;
- self
- }
-
- /// Enforce the CRL nextUpdate field (i.e. expiration)
- ///
- /// If CRLs are provided with [`with_crls`][Self::with_crls] and the verification time is
- /// beyond the time in the CRL nextUpdate field, it is expired and treated as an error condition.
- /// Overrides the default behavior where expired CRLs are not treated as an error condition.
- ///
- /// If no CRLs are provided then this setting has no effect as revocation status checks
- /// are not performed.
- pub fn enforce_revocation_expiration(mut self) -> Self {
- self.revocation_expiration_policy = ExpirationPolicy::Enforce;
- self
- }
-
- /// Build a server certificate verifier, allowing control over the root certificates to use as
- /// trust anchors, and to control how server certificate revocation checking is performed.
- ///
- /// If `with_signature_verification_algorithms` was not called on the builder, a default set of
- /// signature verification algorithms is used, controlled by the selected [`crypto::CryptoProvider`].
- ///
- /// Once built, the provided `Arc<dyn ServerCertVerifier>` can be used with a Rustls
- /// [`ServerConfig`] to configure client certificate validation using
- /// [`with_client_cert_verifier`][ConfigBuilder<ClientConfig, WantsVerifier>::with_client_cert_verifier].
- ///
- /// # Errors
- /// This function will return a [`VerifierBuilderError`] if:
- /// 1. No trust anchors have been provided.
- /// 2. DER encoded CRLs have been provided that can not be parsed successfully.
- pub fn build(self) -> Result<Arc<WebPkiServerVerifier>, VerifierBuilderError> {
- if self.roots.is_empty() {
- return Err(VerifierBuilderError::NoRootAnchors);
- }
-
- Ok(WebPkiServerVerifier::new(
- self.roots,
- parse_crls(self.crls)?,
- self.revocation_check_depth,
- self.unknown_revocation_policy,
- self.revocation_expiration_policy,
- self.supported_algs,
- )
- .into())
- }
-}
-
-/// Default `ServerCertVerifier`, see the trait impl for more information.
-#[allow(unreachable_pub)]
-#[derive(Debug)]
-pub struct WebPkiServerVerifier {
- roots: Arc<RootCertStore>,
- crls: Vec<CertRevocationList<'static>>,
- revocation_check_depth: RevocationCheckDepth,
- unknown_revocation_policy: UnknownStatusPolicy,
- revocation_expiration_policy: ExpirationPolicy,
- supported: WebPkiSupportedAlgorithms,
-}
-
-#[allow(unreachable_pub)]
-impl WebPkiServerVerifier {
- /// Create a builder for the `webpki` server certificate verifier configuration using
- /// the [process-default `CryptoProvider`][CryptoProvider#using-the-per-process-default-cryptoprovider].
- ///
- /// Server certificates will be verified using the trust anchors found in the provided `roots`.
- ///
- /// Use [`Self::builder_with_provider`] if you wish to specify an explicit provider.
- ///
- /// For more information, see the [`ServerCertVerifierBuilder`] documentation.
- pub fn builder(roots: Arc<RootCertStore>) -> ServerCertVerifierBuilder {
- Self::builder_with_provider(
- roots,
- CryptoProvider::get_default_or_install_from_crate_features().clone(),
- )
- }
-
- /// Create a builder for the `webpki` server certificate verifier configuration using
- /// a specified [`CryptoProvider`].
- ///
- /// Server certificates will be verified using the trust anchors found in the provided `roots`.
- ///
- /// The cryptography used comes from the specified [`CryptoProvider`].
- ///
- /// For more information, see the [`ServerCertVerifierBuilder`] documentation.
- pub fn builder_with_provider(
- roots: Arc<RootCertStore>,
- provider: Arc<CryptoProvider>,
- ) -> ServerCertVerifierBuilder {
- ServerCertVerifierBuilder::new(roots, provider.signature_verification_algorithms)
- }
-
- /// Short-cut for creating a `WebPkiServerVerifier` that does not perform certificate revocation
- /// checking, avoiding the need to use a builder.
- pub(crate) fn new_without_revocation(
- roots: impl Into<Arc<RootCertStore>>,
- supported_algs: WebPkiSupportedAlgorithms,
- ) -> Self {
- Self::new(
- roots,
- Vec::default(),
- RevocationCheckDepth::Chain,
- UnknownStatusPolicy::Allow,
- ExpirationPolicy::Ignore,
- supported_algs,
- )
- }
-
- /// Constructs a new `WebPkiServerVerifier`.
- ///
- /// * `roots` is the set of trust anchors to trust for issuing server certs.
- /// * `crls` are a vec of owned certificate revocation lists (CRLs) to use for
- /// client certificate validation.
- /// * `revocation_check_depth` controls which certificates have their revocation status checked
- /// when `crls` are provided.
- /// * `unknown_revocation_policy` controls how certificates with an unknown revocation status
- /// are handled when `crls` are provided.
- /// * `supported` is the set of supported algorithms that will be used for
- /// certificate verification and TLS handshake signature verification.
- pub(crate) fn new(
- roots: impl Into<Arc<RootCertStore>>,
- crls: Vec<CertRevocationList<'static>>,
- revocation_check_depth: RevocationCheckDepth,
- unknown_revocation_policy: UnknownStatusPolicy,
- revocation_expiration_policy: ExpirationPolicy,
- supported: WebPkiSupportedAlgorithms,
- ) -> Self {
- Self {
- roots: roots.into(),
- crls,
- revocation_check_depth,
- unknown_revocation_policy,
- revocation_expiration_policy,
- supported,
- }
- }
-}
-
-impl ServerCertVerifier for WebPkiServerVerifier {
- /// Will verify the certificate is valid in the following ways:
- /// - Signed by a trusted `RootCertStore` CA
- /// - Not Expired
- /// - Valid for DNS entry
- /// - Valid revocation status (if applicable).
- ///
- /// Depending on the verifier's configuration revocation status checking may be performed for
- /// each certificate in the chain to a root CA (excluding the root itself), or only the
- /// end entity certificate. Similarly, unknown revocation status may be treated as an error
- /// or allowed based on configuration.
- fn verify_server_cert(
- &self,
- end_entity: &CertificateDer<'_>,
- intermediates: &[CertificateDer<'_>],
- server_name: &ServerName<'_>,
- ocsp_response: &[u8],
- now: UnixTime,
- ) -> Result<ServerCertVerified, Error> {
- let cert = ParsedCertificate::try_from(end_entity)?;
-
- let crl_refs = self.crls.iter().collect::<Vec<_>>();
-
- let revocation = if self.crls.is_empty() {
- None
- } else {
- // Note: unwrap here is safe because RevocationOptionsBuilder only errors when given
- // empty CRLs.
- Some(
- webpki::RevocationOptionsBuilder::new(crl_refs.as_slice())
- // Note: safe to unwrap here - new is only fallible if no CRLs are provided
- // and we verify this above.
- .unwrap()
- .with_depth(self.revocation_check_depth)
- .with_status_policy(self.unknown_revocation_policy)
- .with_expiration_policy(self.revocation_expiration_policy)
- .build(),
- )
- };
-
- // Note: we use the crate-internal `_impl` fn here in order to provide revocation
- // checking information, if applicable.
- verify_server_cert_signed_by_trust_anchor_impl(
- &cert,
- &self.roots,
- intermediates,
- revocation,
- now,
- self.supported.all,
- )?;
-
- if !ocsp_response.is_empty() {
- trace!("Unvalidated OCSP response: {:?}", ocsp_response.to_vec());
- }
-
- verify_server_name(&cert, server_name)?;
- Ok(ServerCertVerified::assertion())
- }
-
- fn verify_tls12_signature(
- &self,
- message: &[u8],
- cert: &CertificateDer<'_>,
- dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error> {
- verify_tls12_signature(message, cert, dss, &self.supported)
- }
-
- fn verify_tls13_signature(
- &self,
- message: &[u8],
- cert: &CertificateDer<'_>,
- dss: &DigitallySignedStruct,
- ) -> Result<HandshakeSignatureValid, Error> {
- verify_tls13_signature(message, cert, dss, &self.supported)
- }
-
- fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
- self.supported.supported_schemes()
- }
-}
-
-#[cfg(test)]
-#[macro_rules_attribute::apply(test_for_each_provider)]
-mod tests {
- use std::prelude::v1::*;
- use std::{println, vec};
-
- use pki_types::pem::PemObject;
- use pki_types::{CertificateDer, CertificateRevocationListDer};
-
- use super::{VerifierBuilderError, WebPkiServerVerifier, provider};
- use crate::RootCertStore;
- use crate::sync::Arc;
-
- fn load_crls(crls_der: &[&[u8]]) -> Vec<CertificateRevocationListDer<'static>> {
- crls_der
- .iter()
- .map(|pem_bytes| CertificateRevocationListDer::from_pem_slice(pem_bytes).unwrap())
- .collect()
- }
-
- fn test_crls() -> Vec<CertificateRevocationListDer<'static>> {
- load_crls(&[
- include_bytes!("../../../test-ca/ecdsa-p256/client.revoked.crl.pem").as_slice(),
- include_bytes!("../../../test-ca/rsa-2048/client.revoked.crl.pem").as_slice(),
- ])
- }
-
- fn load_roots(roots_der: &[&[u8]]) -> Arc<RootCertStore> {
- let mut roots = RootCertStore::empty();
- roots_der.iter().for_each(|der| {
- roots
- .add(CertificateDer::from(der.to_vec()))
- .unwrap()
- });
- roots.into()
- }
-
- fn test_roots() -> Arc<RootCertStore> {
- load_roots(&[
- include_bytes!("../../../test-ca/ecdsa-p256/ca.der").as_slice(),
- include_bytes!("../../../test-ca/rsa-2048/ca.der").as_slice(),
- ])
- }
-
- #[test]
- fn test_with_invalid_crls() {
- // Trying to build a server verifier with invalid CRLs should error at build time.
- let result = WebPkiServerVerifier::builder_with_provider(
- test_roots(),
- provider::default_provider().into(),
- )
- .with_crls(vec![CertificateRevocationListDer::from(vec![0xFF])])
- .build();
- assert!(matches!(result, Err(VerifierBuilderError::InvalidCrl(_))));
- }
-
- #[test]
- fn test_with_crls_multiple_calls() {
- // We should be able to call `with_crls` on a server verifier multiple times.
- let initial_crls = test_crls();
- let extra_crls =
- load_crls(&[
- include_bytes!("../../../test-ca/eddsa/client.revoked.crl.pem").as_slice(),
- ]);
-
- let builder = WebPkiServerVerifier::builder_with_provider(
- test_roots(),
- provider::default_provider().into(),
- )
- .with_crls(initial_crls.clone())
- .with_crls(extra_crls.clone());
-
- // There should be the expected number of crls.
- assert_eq!(builder.crls.len(), initial_crls.len() + extra_crls.len());
- // The builder should be Debug.
- println!("{builder:?}");
- builder.build().unwrap();
- }
-
- #[test]
- fn test_builder_no_roots() {
- // Trying to create a server verifier builder with no trust anchors should fail at build time
- let result = WebPkiServerVerifier::builder_with_provider(
- RootCertStore::empty().into(),
- provider::default_provider().into(),
- )
- .build();
- assert!(matches!(result, Err(VerifierBuilderError::NoRootAnchors)));
- }
-
- #[test]
- fn test_server_verifier_ee_only() {
- // We should be able to build a server cert. verifier that only checks the EE cert.
- let builder = WebPkiServerVerifier::builder_with_provider(
- test_roots(),
- provider::default_provider().into(),
- )
- .only_check_end_entity_revocation();
- // The builder should be Debug.
- println!("{builder:?}");
- builder.build().unwrap();
- }
-
- #[test]
- fn test_server_verifier_allow_unknown() {
- // We should be able to build a server cert. verifier that allows unknown revocation
- // status.
- let builder = WebPkiServerVerifier::builder_with_provider(
- test_roots(),
- provider::default_provider().into(),
- )
- .allow_unknown_revocation_status();
- // The builder should be Debug.
- println!("{builder:?}");
- builder.build().unwrap();
- }
-
- #[test]
- fn test_server_verifier_allow_unknown_ee_only() {
- // We should be able to build a server cert. verifier that allows unknown revocation
- // status and only checks the EE cert.
- let builder = WebPkiServerVerifier::builder_with_provider(
- test_roots(),
- provider::default_provider().into(),
- )
- .allow_unknown_revocation_status()
- .only_check_end_entity_revocation();
- // The builder should be Debug.
- println!("{builder:?}");
- builder.build().unwrap();
- }
-
- #[test]
- fn test_server_verifier_enforce_expiration() {
- // We should be able to build a server cert. verifier that allows unknown revocation
- // status.
- let builder = WebPkiServerVerifier::builder_with_provider(
- test_roots(),
- provider::default_provider().into(),
- )
- .enforce_revocation_expiration();
- // The builder should be Debug.
- println!("{builder:?}");
- builder.build().unwrap();
- }
-}
diff --git a/vendor/rustls/src/webpki/verify.rs b/vendor/rustls/src/webpki/verify.rs
deleted file mode 100644
index 5c3e79be..00000000
--- a/vendor/rustls/src/webpki/verify.rs
+++ /dev/null
@@ -1,289 +0,0 @@
-use alloc::vec::Vec;
-use core::fmt;
-
-use pki_types::{
- CertificateDer, ServerName, SignatureVerificationAlgorithm, SubjectPublicKeyInfoDer, UnixTime,
-};
-
-use super::anchors::RootCertStore;
-use super::pki_error;
-use crate::enums::SignatureScheme;
-use crate::error::{Error, PeerMisbehaved};
-use crate::verify::{DigitallySignedStruct, HandshakeSignatureValid};
-
-/// Verify that the end-entity certificate `end_entity` is a valid server cert
-/// and chains to at least one of the trust anchors in the `roots` [RootCertStore].
-///
-/// This function is primarily useful when building a custom certificate verifier. It
-/// performs **no revocation checking**. Implementers must handle this themselves,
-/// along with checking that the server certificate is valid for the subject name
-/// being used (see [`verify_server_name`]).
-///
-/// `intermediates` contains all certificates other than `end_entity` that
-/// were sent as part of the server's `Certificate` message. It is in the
-/// same order that the server sent them and may be empty.
-#[allow(dead_code)]
-pub fn verify_server_cert_signed_by_trust_anchor(
- cert: &ParsedCertificate<'_>,
- roots: &RootCertStore,
- intermediates: &[CertificateDer<'_>],
- now: UnixTime,
- supported_algs: &[&dyn SignatureVerificationAlgorithm],
-) -> Result<(), Error> {
- verify_server_cert_signed_by_trust_anchor_impl(
- cert,
- roots,
- intermediates,
- None, // No revocation checking supported with this API.
- now,
- supported_algs,
- )
-}
-
-/// Verify that the `end_entity` has an alternative name matching the `server_name`.
-///
-/// Note: this only verifies the name and should be used in conjunction with more verification
-/// like [verify_server_cert_signed_by_trust_anchor]
-pub fn verify_server_name(
- cert: &ParsedCertificate<'_>,
- server_name: &ServerName<'_>,
-) -> Result<(), Error> {
- cert.0
- .verify_is_valid_for_subject_name(server_name)
- .map_err(pki_error)
-}
-
-/// Describes which `webpki` signature verification algorithms are supported and
-/// how they map to TLS [`SignatureScheme`]s.
-#[derive(Clone, Copy)]
-#[allow(unreachable_pub)]
-pub struct WebPkiSupportedAlgorithms {
- /// A list of all supported signature verification algorithms.
- ///
- /// Used for verifying certificate chains.
- ///
- /// The order of this list is not significant.
- pub all: &'static [&'static dyn SignatureVerificationAlgorithm],
-
- /// A mapping from TLS `SignatureScheme`s to matching webpki signature verification algorithms.
- ///
- /// This is one (`SignatureScheme`) to many ([`SignatureVerificationAlgorithm`]) because
- /// (depending on the protocol version) there is not necessary a 1-to-1 mapping.
- ///
- /// For TLS1.2, all `SignatureVerificationAlgorithm`s are tried in sequence.
- ///
- /// For TLS1.3, only the first is tried.
- ///
- /// The supported schemes in this mapping is communicated to the peer and the order is significant.
- /// The first mapping is our highest preference.
- pub mapping: &'static [(
- SignatureScheme,
- &'static [&'static dyn SignatureVerificationAlgorithm],
- )],
-}
-
-impl WebPkiSupportedAlgorithms {
- /// Return all the `scheme` items in `mapping`, maintaining order.
- pub fn supported_schemes(&self) -> Vec<SignatureScheme> {
- self.mapping
- .iter()
- .map(|item| item.0)
- .collect()
- }
-
- /// Return the first item in `mapping` that matches `scheme`.
- fn convert_scheme(
- &self,
- scheme: SignatureScheme,
- ) -> Result<&[&'static dyn SignatureVerificationAlgorithm], Error> {
- self.mapping
- .iter()
- .filter_map(|item| if item.0 == scheme { Some(item.1) } else { None })
- .next()
- .ok_or_else(|| PeerMisbehaved::SignedHandshakeWithUnadvertisedSigScheme.into())
- }
-
- /// Return `true` if all cryptography is FIPS-approved.
- pub fn fips(&self) -> bool {
- self.all.iter().all(|alg| alg.fips())
- && self
- .mapping
- .iter()
- .all(|item| item.1.iter().all(|alg| alg.fips()))
- }
-}
-
-impl fmt::Debug for WebPkiSupportedAlgorithms {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "WebPkiSupportedAlgorithms {{ all: [ .. ], mapping: ")?;
- f.debug_list()
- .entries(self.mapping.iter().map(|item| item.0))
- .finish()?;
- write!(f, " }}")
- }
-}
-
-/// Wrapper around internal representation of a parsed certificate.
-///
-/// This is used in order to avoid parsing twice when specifying custom verification
-pub struct ParsedCertificate<'a>(pub(crate) webpki::EndEntityCert<'a>);
-
-impl ParsedCertificate<'_> {
- /// Get the parsed certificate's SubjectPublicKeyInfo (SPKI)
- pub fn subject_public_key_info(&self) -> SubjectPublicKeyInfoDer<'static> {
- self.0.subject_public_key_info()
- }
-}
-
-impl<'a> TryFrom<&'a CertificateDer<'a>> for ParsedCertificate<'a> {
- type Error = Error;
- fn try_from(value: &'a CertificateDer<'a>) -> Result<Self, Self::Error> {
- webpki::EndEntityCert::try_from(value)
- .map_err(pki_error)
- .map(ParsedCertificate)
- }
-}
-
-/// Verify a message signature using the `cert` public key and any supported scheme.
-///
-/// This function verifies the `dss` signature over `message` using the subject public key from
-/// `cert`. Since TLS 1.2 doesn't provide enough information to map the `dss.scheme` into a single
-/// [`SignatureVerificationAlgorithm`], this function will map to several candidates and try each in
-/// succession until one succeeds or we exhaust all candidates.
-///
-/// See [WebPkiSupportedAlgorithms::mapping] for more information.
-pub fn verify_tls12_signature(
- message: &[u8],
- cert: &CertificateDer<'_>,
- dss: &DigitallySignedStruct,
- supported_schemes: &WebPkiSupportedAlgorithms,
-) -> Result<HandshakeSignatureValid, Error> {
- let possible_algs = supported_schemes.convert_scheme(dss.scheme)?;
- let cert = webpki::EndEntityCert::try_from(cert).map_err(pki_error)?;
-
- let mut error = None;
- for alg in possible_algs {
- match cert.verify_signature(*alg, message, dss.signature()) {
- Err(err @ webpki::Error::UnsupportedSignatureAlgorithmForPublicKeyContext(_)) => {
- error = Some(err);
- continue;
- }
- Err(e) => return Err(pki_error(e)),
- Ok(()) => return Ok(HandshakeSignatureValid::assertion()),
- }
- }
-
- #[allow(deprecated)] // The `unwrap_or()` should be statically unreachable
- Err(pki_error(error.unwrap_or(
- webpki::Error::UnsupportedSignatureAlgorithmForPublicKey,
- )))
-}
-
-/// Verify a message signature using the `cert` public key and the first TLS 1.3 compatible
-/// supported scheme.
-///
-/// This function verifies the `dss` signature over `message` using the subject public key from
-/// `cert`. Unlike [verify_tls12_signature], this function only tries the first matching scheme. See
-/// [WebPkiSupportedAlgorithms::mapping] for more information.
-pub fn verify_tls13_signature(
- msg: &[u8],
- cert: &CertificateDer<'_>,
- dss: &DigitallySignedStruct,
- supported_schemes: &WebPkiSupportedAlgorithms,
-) -> Result<HandshakeSignatureValid, Error> {
- if !dss.scheme.supported_in_tls13() {
- return Err(PeerMisbehaved::SignedHandshakeWithUnadvertisedSigScheme.into());
- }
-
- let alg = supported_schemes.convert_scheme(dss.scheme)?[0];
-
- let cert = webpki::EndEntityCert::try_from(cert).map_err(pki_error)?;
-
- cert.verify_signature(alg, msg, dss.signature())
- .map_err(pki_error)
- .map(|_| HandshakeSignatureValid::assertion())
-}
-
-/// Verify a message signature using a raw public key and the first TLS 1.3 compatible
-/// supported scheme.
-pub fn verify_tls13_signature_with_raw_key(
- msg: &[u8],
- spki: &SubjectPublicKeyInfoDer<'_>,
- dss: &DigitallySignedStruct,
- supported_schemes: &WebPkiSupportedAlgorithms,
-) -> Result<HandshakeSignatureValid, Error> {
- if !dss.scheme.supported_in_tls13() {
- return Err(PeerMisbehaved::SignedHandshakeWithUnadvertisedSigScheme.into());
- }
-
- let raw_key = webpki::RawPublicKeyEntity::try_from(spki).map_err(pki_error)?;
- let alg = supported_schemes.convert_scheme(dss.scheme)?[0];
-
- raw_key
- .verify_signature(alg, msg, dss.signature())
- .map_err(pki_error)
- .map(|_| HandshakeSignatureValid::assertion())
-}
-
-/// Verify that the end-entity certificate `end_entity` is a valid server cert
-/// and chains to at least one of the trust anchors in the `roots` [RootCertStore].
-///
-/// `intermediates` contains all certificates other than `end_entity` that
-/// were sent as part of the server's `Certificate` message. It is in the
-/// same order that the server sent them and may be empty.
-///
-/// `revocation` controls how revocation checking is performed, if at all.
-///
-/// This function exists to be used by [`verify_server_cert_signed_by_trust_anchor`],
-/// and differs only in providing a `Option<webpki::RevocationOptions>` argument. We
-/// can't include this argument in `verify_server_cert_signed_by_trust_anchor` because
-/// it will leak the webpki types into Rustls' public API.
-pub(crate) fn verify_server_cert_signed_by_trust_anchor_impl(
- cert: &ParsedCertificate<'_>,
- roots: &RootCertStore,
- intermediates: &[CertificateDer<'_>],
- revocation: Option<webpki::RevocationOptions<'_>>,
- now: UnixTime,
- supported_algs: &[&dyn SignatureVerificationAlgorithm],
-) -> Result<(), Error> {
- let result = cert.0.verify_for_usage(
- supported_algs,
- &roots.roots,
- intermediates,
- now,
- webpki::KeyUsage::server_auth(),
- revocation,
- None,
- );
- match result {
- Ok(_) => Ok(()),
- Err(e) => Err(pki_error(e)),
- }
-}
-
-#[cfg(test)]
-mod tests {
- use std::format;
-
- use super::*;
-
- #[test]
- fn certificate_debug() {
- assert_eq!(
- "CertificateDer(0x6162)",
- format!("{:?}", CertificateDer::from(b"ab".to_vec()))
- );
- }
-
- #[cfg(feature = "ring")]
- #[test]
- fn webpki_supported_algorithms_is_debug() {
- assert_eq!(
- "WebPkiSupportedAlgorithms { all: [ .. ], mapping: [ECDSA_NISTP384_SHA384, ECDSA_NISTP256_SHA256, ED25519, RSA_PSS_SHA512, RSA_PSS_SHA384, RSA_PSS_SHA256, RSA_PKCS1_SHA512, RSA_PKCS1_SHA384, RSA_PKCS1_SHA256] }",
- format!(
- "{:?}",
- crate::crypto::ring::default_provider().signature_verification_algorithms
- )
- );
- }
-}
diff --git a/vendor/rustls/src/x509.rs b/vendor/rustls/src/x509.rs
deleted file mode 100644
index 2620fe8a..00000000
--- a/vendor/rustls/src/x509.rs
+++ /dev/null
@@ -1,147 +0,0 @@
-// Additional x509/asn1 functions to those provided in webpki/ring.
-
-use alloc::vec::Vec;
-
-/// Prepend stuff to `bytes` to put it in a DER SEQUENCE.
-pub(crate) fn wrap_in_sequence(bytes: &[u8]) -> Vec<u8> {
- asn1_wrap(DER_SEQUENCE_TAG, bytes, &[])
-}
-
-/// Prepend stuff to `bytes_a` + `bytes_b` to put it in a DER SEQUENCE.
-#[cfg_attr(not(feature = "ring"), allow(dead_code))]
-pub(crate) fn wrap_concat_in_sequence(bytes_a: &[u8], bytes_b: &[u8]) -> Vec<u8> {
- asn1_wrap(DER_SEQUENCE_TAG, bytes_a, bytes_b)
-}
-
-/// Prepend stuff to `bytes` to put it in a DER BIT STRING.
-pub(crate) fn wrap_in_bit_string(bytes: &[u8]) -> Vec<u8> {
- asn1_wrap(DER_BIT_STRING_TAG, &[0u8], bytes)
-}
-
-/// Prepend stuff to `bytes` to put it in a DER OCTET STRING.
-#[cfg_attr(not(feature = "ring"), allow(dead_code))]
-pub(crate) fn wrap_in_octet_string(bytes: &[u8]) -> Vec<u8> {
- asn1_wrap(DER_OCTET_STRING_TAG, bytes, &[])
-}
-
-fn asn1_wrap(tag: u8, bytes_a: &[u8], bytes_b: &[u8]) -> Vec<u8> {
- let len = bytes_a.len() + bytes_b.len();
-
- if len <= 0x7f {
- // Short form
- let mut ret = Vec::with_capacity(2 + len);
- ret.push(tag);
- ret.push(len as u8);
- ret.extend_from_slice(bytes_a);
- ret.extend_from_slice(bytes_b);
- ret
- } else {
- // Long form
- let size = len.to_be_bytes();
- let leading_zero_bytes = size
- .iter()
- .position(|&x| x != 0)
- .unwrap_or(size.len());
- assert!(leading_zero_bytes < size.len());
- let encoded_bytes = size.len() - leading_zero_bytes;
-
- let mut ret = Vec::with_capacity(2 + encoded_bytes + len);
- ret.push(tag);
-
- ret.push(0x80 + encoded_bytes as u8);
- ret.extend_from_slice(&size[leading_zero_bytes..]);
-
- ret.extend_from_slice(bytes_a);
- ret.extend_from_slice(bytes_b);
- ret
- }
-}
-
-const DER_SEQUENCE_TAG: u8 = 0x30;
-const DER_BIT_STRING_TAG: u8 = 0x03;
-const DER_OCTET_STRING_TAG: u8 = 0x04;
-
-#[cfg(test)]
-mod tests {
- use std::vec;
-
- use super::*;
-
- #[test]
- fn test_empty() {
- assert_eq!(vec![0x30, 0x00], wrap_in_sequence(&[]));
- }
-
- #[test]
- fn test_small() {
- assert_eq!(
- vec![0x30, 0x04, 0x00, 0x11, 0x22, 0x33],
- wrap_in_sequence(&[0x00, 0x11, 0x22, 0x33])
- );
- }
-
- #[test]
- fn test_medium() {
- let mut val = Vec::new();
- val.resize(255, 0x12);
- assert_eq!(
- vec![0x30, 0x81, 0xff, 0x12, 0x12, 0x12],
- wrap_in_sequence(&val)[..6]
- );
- }
-
- #[test]
- fn test_large() {
- let mut val = Vec::new();
- val.resize(4660, 0x12);
- wrap_in_sequence(&val);
- assert_eq!(
- vec![0x30, 0x82, 0x12, 0x34, 0x12, 0x12],
- wrap_in_sequence(&val)[..6]
- );
- }
-
- #[test]
- fn test_huge() {
- let mut val = Vec::new();
- val.resize(0xffff, 0x12);
- let result = wrap_in_sequence(&val);
- assert_eq!(vec![0x30, 0x82, 0xff, 0xff, 0x12, 0x12], result[..6]);
- assert_eq!(result.len(), 0xffff + 4);
- }
-
- #[test]
- fn test_gigantic() {
- let mut val = Vec::new();
- val.resize(0x100000, 0x12);
- let result = wrap_in_sequence(&val);
- assert_eq!(vec![0x30, 0x83, 0x10, 0x00, 0x00, 0x12, 0x12], result[..7]);
- assert_eq!(result.len(), 0x100000 + 5);
- }
-
- #[test]
- fn test_ludicrous() {
- let mut val = Vec::new();
- val.resize(0x1000000, 0x12);
- let result = wrap_in_sequence(&val);
- assert_eq!(
- vec![0x30, 0x84, 0x01, 0x00, 0x00, 0x00, 0x12, 0x12],
- result[..8]
- );
- assert_eq!(result.len(), 0x1000000 + 6);
- }
-
- #[test]
- fn test_wrap_in_bit_string() {
- // The BIT STRING encoding starts with a single octet on
- // the front saying how many bits to disregard from the
- // last octet. So this zero means "no bits" unused, which
- // is correct because our input is an string of octets.
- //
- // So if we encode &[0x55u8] with this function, we should get:
- //
- // 0x03 0x02 0x00 0x55
- // ^ tag ^ len ^ no unused bits ^ value
- assert_eq!(wrap_in_bit_string(&[0x55u8]), vec![0x03, 0x02, 0x00, 0x55]);
- }
-}