From 4c81a162c7caf98037819159ae0cfae19dab26ce Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 13 Jan 2025 00:59:19 +0000 Subject: [PATCH 001/403] chore(deps): lock file maintenance --- Cargo.lock | 160 +++++++++++++++++++++++++----------------------- fuzz/Cargo.lock | 4 +- 2 files changed, 84 insertions(+), 80 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 04db29f222e..3c6c62c6d23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -171,7 +171,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", "synstructure", ] @@ -183,7 +183,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -194,7 +194,7 @@ checksum = "a200809d0138620b3dba989f1d08d0620e76248bc1e62a2ec1b2df5eb1ee08ad" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -296,7 +296,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -340,7 +340,7 @@ checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -455,15 +455,15 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.95", + "syn 2.0.96", "which", ] [[package]] name = "bitflags" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" [[package]] name = "block-buffer" @@ -544,9 +544,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.7" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" +checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" dependencies = [ "jobserver", "libc", @@ -672,7 +672,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -850,7 +850,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -912,7 +912,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -970,7 +970,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -1126,9 +1126,9 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" +checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" dependencies = [ "fastrand", "futures-core", @@ -1315,8 +1315,8 @@ dependencies = [ "ipnet", "once_cell", "rand", - "rustls 0.23.20", - "thiserror 2.0.10", + "rustls 0.23.21 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 2.0.11", "tinyvec", "tokio", "tokio-rustls", @@ -1340,7 +1340,7 @@ dependencies = [ "parking_lot", "rand", "resolv-conf", - "rustls 0.23.20", + "rustls 0.23.21 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec", "thiserror 1.0.69", "tokio", @@ -1557,7 +1557,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -1679,9 +1679,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", @@ -1966,7 +1966,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2187,12 +2187,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.27" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "483f8c21f64f3ea09fe0f30f5d48c3e8eefe5dac9129f0075f76593b4c1da705" +checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" dependencies = [ "proc-macro2", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2206,9 +2206,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -2428,21 +2428,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "rustls" -version = "0.23.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" -dependencies = [ - "log", - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - [[package]] name = "rustls" version = "0.23.21" @@ -2474,6 +2459,21 @@ dependencies = [ "zlib-rs", ] +[[package]] +name = "rustls" +version = "0.23.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-bench" version = "0.1.0" @@ -2678,7 +2678,7 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2792,9 +2792,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.95" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", @@ -2809,7 +2809,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2823,11 +2823,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.10" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ac7f54ca534db81081ef1c1e7f6ea8a3ef428d2fc069097c079443d24124d3" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" dependencies = [ - "thiserror-impl 2.0.10", + "thiserror-impl 2.0.11", ] [[package]] @@ -2838,18 +2838,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] name = "thiserror-impl" -version = "2.0.10" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e9465d30713b56a37ede7185763c3492a91be2f5fa68d958c44e41ab9248beb" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2962,7 +2962,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2971,7 +2971,7 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ - "rustls 0.23.20", + "rustls 0.23.21 (registry+https://github.com/rust-lang/crates.io-index)", "tokio", ] @@ -3007,7 +3007,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -3112,34 +3112,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.49" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", @@ -3150,9 +3151,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3160,28 +3161,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -3473,7 +3477,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", "synstructure", ] @@ -3495,7 +3499,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -3515,7 +3519,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", "synstructure", ] @@ -3536,7 +3540,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -3558,7 +3562,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index dc437fcf8b8..8a010650d8d 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -68,9 +68,9 @@ checksum = "64cf76cb6e2222ed0ea86b2b0ee2f71c96ec6edd5af42e84d59160e91b836ec4" [[package]] name = "cc" -version = "1.2.7" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" +checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" dependencies = [ "shlex", ] From fc57e7311554248d3d8dcbc5bc6f83607fbe159d Mon Sep 17 00:00:00 2001 From: Daniel Roethlisberger Date: Tue, 21 Jan 2025 00:18:11 +0100 Subject: [PATCH 002/403] Fix SSL 2 version constant to 0x0002 SSL 2 uses a version field of 0x0002, not 0x0200. This is confirmed not only in the original Netscape spec [1] and RFC draft of the time [2], but also in major implementations such as OpenSSL [3] and Wireshark [4] as well as packet captures of SSL 2 traffic [5]. [1] https://www-archive.mozilla.org/projects/security/pki/nss/ssl/draft02.html [2] https://datatracker.ietf.org/doc/html/draft-hickman-netscape-ssl-00 [3] https://github.com/openssl/openssl/blob/OpenSSL_0_9_6m/ssl/ssl2.h#L66-L71 [4] https://github.com/wireshark/wireshark/blob/release-4.4/epan/dissectors/packet-tls-utils.h#L266-L277 [5] https://github.com/Lekensteyn/wireshark-notes/blob/master/ssl3/sslv2.pcapng --- rustls/src/enums.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustls/src/enums.rs b/rustls/src/enums.rs index 4b48a03bec9..298989ff763 100644 --- a/rustls/src/enums.rs +++ b/rustls/src/enums.rs @@ -95,7 +95,7 @@ enum_builder! { /// The `Unknown` item is used when processing unrecognised ordinals. #[repr(u16)] pub enum ProtocolVersion { - SSLv2 => 0x0200, + SSLv2 => 0x0002, SSLv3 => 0x0300, TLSv1_0 => 0x0301, TLSv1_1 => 0x0302, From 77bbde68d24722f81675615145f87c8f91b133e1 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 30 Dec 2024 12:40:28 +0000 Subject: [PATCH 003/403] tests/api: extract expected key exchange algorithm --- rustls/tests/api.rs | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index a9bc0f3de51..48d7da9106a 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -36,7 +36,7 @@ use rustls::{ ConnectionCommon, ConnectionTrafficSecrets, ContentType, DistinguishedName, Error, HandshakeKind, HandshakeType, InconsistentKeys, InvalidMessage, KeyLog, NamedGroup, PeerIncompatible, PeerMisbehaved, ProtocolVersion, ServerConfig, ServerConnection, SideData, - SignatureScheme, Stream, StreamOwned, SupportedCipherSuite, + SignatureScheme, Stream, StreamOwned, SupportedCipherSuite, SupportedProtocolVersion, }; use super::*; @@ -904,10 +904,6 @@ fn server_can_get_client_cert_after_resumption() { #[test] fn resumption_combinations() { - let expected_kx = match provider_is_fips() { - true => NamedGroup::secp256r1, - false => NamedGroup::X25519, - }; for kt in ALL_KEY_TYPES { let server_config = make_server_config(*kt); for version in rustls::ALL_VERSIONS { @@ -916,6 +912,8 @@ fn resumption_combinations() { make_pair_for_configs(client_config.clone(), server_config.clone()); do_handshake(&mut client, &mut server); + let expected_kx = expected_kx_for_version(version); + assert_eq!(client.handshake_kind(), Some(HandshakeKind::Full)); assert_eq!(server.handshake_kind(), Some(HandshakeKind::Full)); assert_eq!( @@ -3710,16 +3708,12 @@ fn test_ciphersuites() -> Vec<( #[test] fn negotiated_ciphersuite_default() { - let expected_kx = match provider_is_fips() { - true => NamedGroup::secp256r1, - false => NamedGroup::X25519, - }; for kt in ALL_KEY_TYPES { do_suite_and_kx_test( make_client_config(*kt), make_server_config(*kt), find_suite(CipherSuite::TLS13_AES_256_GCM_SHA384), - expected_kx, + expected_kx_for_version(&rustls::version::TLS13), ProtocolVersion::TLSv1_3, ); } @@ -3735,10 +3729,6 @@ fn all_suites_covered() { #[test] fn negotiated_ciphersuite_client() { - let expected_kx = match provider_is_fips() { - true => NamedGroup::secp256r1, - false => NamedGroup::X25519, - }; for (version, kt, suite) in test_ciphersuites() { let scs = find_suite(suite); let client_config = finish_client_config( @@ -3758,7 +3748,7 @@ fn negotiated_ciphersuite_client() { client_config, make_server_config(kt), scs, - expected_kx, + expected_kx_for_version(version), version.version, ); } @@ -3766,10 +3756,6 @@ fn negotiated_ciphersuite_client() { #[test] fn negotiated_ciphersuite_server() { - let expected_kx = match provider_is_fips() { - true => NamedGroup::secp256r1, - false => NamedGroup::X25519, - }; for (version, kt, suite) in test_ciphersuites() { let scs = find_suite(suite); let server_config = finish_server_config( @@ -3789,7 +3775,7 @@ fn negotiated_ciphersuite_server() { make_client_config(kt), server_config, scs, - expected_kx, + expected_kx_for_version(version), version.version, ); } @@ -3797,10 +3783,6 @@ fn negotiated_ciphersuite_server() { #[test] fn negotiated_ciphersuite_server_ignoring_client_preference() { - let expected_kx = match provider_is_fips() { - true => NamedGroup::secp256r1, - false => NamedGroup::X25519, - }; for (version, kt, suite) in test_ciphersuites() { let scs = find_suite(suite); let scs_other = if scs.suite() == CipherSuite::TLS13_AES_256_GCM_SHA384 { @@ -3839,12 +3821,19 @@ fn negotiated_ciphersuite_server_ignoring_client_preference() { client_config, server_config, scs, - expected_kx, + expected_kx_for_version(version), version.version, ); } } +fn expected_kx_for_version(_version: &SupportedProtocolVersion) -> NamedGroup { + match provider_is_fips() { + true => NamedGroup::secp256r1, + false => NamedGroup::X25519, + } +} + #[derive(Debug, PartialEq)] struct KeyLogItem { label: String, From 06e20d4af2b9c942139e37a8ada74c84320fbe92 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 21 Jan 2025 15:30:17 +0000 Subject: [PATCH 004/403] tests/unbuffered.rs: unwrap transcript states --- rustls/tests/unbuffered.rs | 238 +++++++++++++++++++------------------ 1 file changed, 120 insertions(+), 118 deletions(-) diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index 81311b2540c..7fc60e701d8 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -27,32 +27,32 @@ fn tls12_handshake() { assert_eq!( outcome.client_transcript, vec![ - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(BlockedHandshake)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(BlockedHandshake)", - "Ok(BlockedHandshake)", - "Ok(WriteTraffic)" + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "BlockedHandshake", + "WriteTraffic" ], "client transcript mismatch" ); assert_eq!( outcome.server_transcript, vec![ - "Ok(BlockedHandshake)", - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(BlockedHandshake)", - "Ok(BlockedHandshake)", - "Ok(BlockedHandshake)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(WriteTraffic)" + "BlockedHandshake", + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "EncodeTlsData", + "EncodeTlsData", + "TransmitTlsData", + "WriteTraffic" ], "server transcript mismatch" ); @@ -68,42 +68,42 @@ fn tls12_handshake_fragmented() { assert_eq!( outcome.client_transcript, vec![ - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(BlockedHandshake)", - "Ok(BlockedHandshake)", - "Ok(BlockedHandshake)", - "Ok(BlockedHandshake)", - "Ok(BlockedHandshake)", - "Ok(BlockedHandshake)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(BlockedHandshake)", - "Ok(BlockedHandshake)", - "Ok(WriteTraffic)" + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "BlockedHandshake", + "WriteTraffic" ], "client transcript mismatch" ); assert_eq!( outcome.server_transcript, vec![ - "Ok(BlockedHandshake)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(BlockedHandshake)", - "Ok(BlockedHandshake)", - "Ok(BlockedHandshake)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(WriteTraffic)" + "BlockedHandshake", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "EncodeTlsData", + "EncodeTlsData", + "TransmitTlsData", + "WriteTraffic" ], "server transcript mismatch" ); @@ -115,30 +115,30 @@ fn tls13_handshake() { assert_eq!( outcome.client_transcript, vec![ - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(BlockedHandshake)", - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(WriteTraffic)", - "Ok(WriteTraffic)" + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "EncodeTlsData", + "TransmitTlsData", + "EncodeTlsData", + "TransmitTlsData", + "WriteTraffic", + "WriteTraffic" ], "client transcript mismatch" ); assert_eq!( outcome.server_transcript, vec![ - "Ok(BlockedHandshake)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(BlockedHandshake)", - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(WriteTraffic)" + "BlockedHandshake", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "EncodeTlsData", + "TransmitTlsData", + "WriteTraffic" ], "server transcript mismatch" ); @@ -154,40 +154,40 @@ fn tls13_handshake_fragmented() { assert_eq!( outcome.client_transcript, vec![ - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(BlockedHandshake)", - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(BlockedHandshake)", - "Ok(BlockedHandshake)", - "Ok(BlockedHandshake)", - "Ok(BlockedHandshake)", - "Ok(BlockedHandshake)", - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(WriteTraffic)", - "Ok(WriteTraffic)" + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "EncodeTlsData", + "TransmitTlsData", + "WriteTraffic", + "WriteTraffic" ], "client transcript mismatch" ); assert_eq!( outcome.server_transcript, vec![ - "Ok(BlockedHandshake)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(BlockedHandshake)", - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(WriteTraffic)" + "BlockedHandshake", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "EncodeTlsData", + "TransmitTlsData", + "WriteTraffic" ], "server transcript mismatch" ); @@ -312,31 +312,31 @@ fn early_data() { assert_eq!( outcome.client_transcript, vec![ - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(BlockedHandshake)", - "Ok(BlockedHandshake)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(WriteTraffic)", - "Ok(WriteTraffic)" + "EncodeTlsData", + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "BlockedHandshake", + "EncodeTlsData", + "EncodeTlsData", + "TransmitTlsData", + "WriteTraffic", + "WriteTraffic" ] ); assert_eq!( outcome.server_transcript, vec![ - "Ok(BlockedHandshake)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(EncodeTlsData)", - "Ok(ReadEarlyData)", - "Ok(TransmitTlsData)", - "Ok(BlockedHandshake)", - "Ok(EncodeTlsData)", - "Ok(TransmitTlsData)", - "Ok(WriteTraffic)" + "BlockedHandshake", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "ReadEarlyData", + "TransmitTlsData", + "BlockedHandshake", + "EncodeTlsData", + "TransmitTlsData", + "WriteTraffic" ] ); assert!(client_actions @@ -1058,10 +1058,11 @@ fn advance_client( transcript: &mut Vec, ) -> State { let UnbufferedStatus { discard, state } = conn.process_tls_records(buffers.incoming.filled()); + let state = state.unwrap(); transcript.push(format!("{:?}", state)); - let state = match state.unwrap() { + let state = match state { ConnectionState::TransmitTlsData(mut state) => { let mut sent_early_data = false; if let Some(early_data) = actions.early_data_to_send { @@ -1104,10 +1105,11 @@ fn advance_server( transcript: &mut Vec, ) -> State { let UnbufferedStatus { discard, state } = conn.process_tls_records(buffers.incoming.filled()); + let state = state.unwrap(); transcript.push(format!("{:?}", state)); - let state = match state.unwrap() { + let state = match state { ConnectionState::ReadEarlyData(mut state) => { let mut records = vec![]; let mut peeked_len = state.peek_len(); From 4d903707196cb177854da00e64215e6de68cd83f Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 20 Jan 2025 17:14:43 +0000 Subject: [PATCH 005/403] tests/unbuffered.rs: extract expected API transcripts --- rustls/tests/unbuffered.rs | 252 +++++++++++++++++++------------------ 1 file changed, 132 insertions(+), 120 deletions(-) diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index 7fc60e701d8..318dc97bb08 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -24,36 +24,13 @@ const MAX_ITERATIONS: usize = 100; #[test] fn tls12_handshake() { let outcome = handshake(&rustls::version::TLS12); + assert_eq!( - outcome.client_transcript, - vec![ - "EncodeTlsData", - "TransmitTlsData", - "BlockedHandshake", - "EncodeTlsData", - "EncodeTlsData", - "EncodeTlsData", - "TransmitTlsData", - "BlockedHandshake", - "BlockedHandshake", - "WriteTraffic" - ], + outcome.client_transcript, TLS12_CLIENT_TRANSCRIPT, "client transcript mismatch" ); assert_eq!( - outcome.server_transcript, - vec![ - "BlockedHandshake", - "EncodeTlsData", - "TransmitTlsData", - "BlockedHandshake", - "BlockedHandshake", - "BlockedHandshake", - "EncodeTlsData", - "EncodeTlsData", - "TransmitTlsData", - "WriteTraffic" - ], + outcome.server_transcript, TLS12_SERVER_TRANSCRIPT, "server transcript mismatch" ); } @@ -65,46 +42,13 @@ fn tls12_handshake_fragmented() { client.cert_decompressors = vec![]; server.max_fragment_size = Some(512); }); + assert_eq!( - outcome.client_transcript, - vec![ - "EncodeTlsData", - "TransmitTlsData", - "BlockedHandshake", - "BlockedHandshake", - "BlockedHandshake", - "BlockedHandshake", - "BlockedHandshake", - "BlockedHandshake", - "EncodeTlsData", - "EncodeTlsData", - "EncodeTlsData", - "TransmitTlsData", - "BlockedHandshake", - "BlockedHandshake", - "WriteTraffic" - ], + outcome.client_transcript, TLS12_CLIENT_TRANSCRIPT_FRAGMENTED, "client transcript mismatch" ); assert_eq!( - outcome.server_transcript, - vec![ - "BlockedHandshake", - "EncodeTlsData", - "EncodeTlsData", - "EncodeTlsData", - "EncodeTlsData", - "EncodeTlsData", - "EncodeTlsData", - "TransmitTlsData", - "BlockedHandshake", - "BlockedHandshake", - "BlockedHandshake", - "EncodeTlsData", - "EncodeTlsData", - "TransmitTlsData", - "WriteTraffic" - ], + outcome.server_transcript, TLS12_SERVER_TRANSCRIPT_FRAGMENTED, "server transcript mismatch" ); } @@ -112,34 +56,13 @@ fn tls12_handshake_fragmented() { #[test] fn tls13_handshake() { let outcome = handshake(&rustls::version::TLS13); + assert_eq!( - outcome.client_transcript, - vec![ - "EncodeTlsData", - "TransmitTlsData", - "BlockedHandshake", - "EncodeTlsData", - "TransmitTlsData", - "EncodeTlsData", - "TransmitTlsData", - "WriteTraffic", - "WriteTraffic" - ], + outcome.client_transcript, TLS13_CLIENT_TRANSCRIPT, "client transcript mismatch" ); assert_eq!( - outcome.server_transcript, - vec![ - "BlockedHandshake", - "EncodeTlsData", - "EncodeTlsData", - "EncodeTlsData", - "TransmitTlsData", - "BlockedHandshake", - "EncodeTlsData", - "TransmitTlsData", - "WriteTraffic" - ], + outcome.server_transcript, TLS13_SERVER_TRANSCRIPT, "server transcript mismatch" ); } @@ -151,44 +74,13 @@ fn tls13_handshake_fragmented() { client.cert_decompressors = vec![]; server.max_fragment_size = Some(512); }); + assert_eq!( - outcome.client_transcript, - vec![ - "EncodeTlsData", - "TransmitTlsData", - "BlockedHandshake", - "EncodeTlsData", - "TransmitTlsData", - "BlockedHandshake", - "BlockedHandshake", - "BlockedHandshake", - "BlockedHandshake", - "BlockedHandshake", - "EncodeTlsData", - "TransmitTlsData", - "WriteTraffic", - "WriteTraffic" - ], + outcome.client_transcript, TLS13_CLIENT_TRANSCRIPT_FRAGMENTED, "client transcript mismatch" ); assert_eq!( - outcome.server_transcript, - vec![ - "BlockedHandshake", - "EncodeTlsData", - "EncodeTlsData", - "EncodeTlsData", - "EncodeTlsData", - "EncodeTlsData", - "EncodeTlsData", - "EncodeTlsData", - "EncodeTlsData", - "TransmitTlsData", - "BlockedHandshake", - "EncodeTlsData", - "TransmitTlsData", - "WriteTraffic" - ], + outcome.server_transcript, TLS13_SERVER_TRANSCRIPT_FRAGMENTED, "server transcript mismatch" ); } @@ -1424,3 +1316,123 @@ fn server_receives_incorrect_first_handshake_message() { _ => panic!("unexpected alert sending state"), }; } + +const TLS12_CLIENT_TRANSCRIPT: &[&str] = &[ + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "BlockedHandshake", + "WriteTraffic", +]; + +const TLS12_SERVER_TRANSCRIPT: &[&str] = &[ + "BlockedHandshake", + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "EncodeTlsData", + "EncodeTlsData", + "TransmitTlsData", + "WriteTraffic", +]; + +const TLS12_CLIENT_TRANSCRIPT_FRAGMENTED: &[&str] = &[ + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "BlockedHandshake", + "WriteTraffic", +]; + +const TLS12_SERVER_TRANSCRIPT_FRAGMENTED: &[&str] = &[ + "BlockedHandshake", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "EncodeTlsData", + "EncodeTlsData", + "TransmitTlsData", + "WriteTraffic", +]; + +const TLS13_CLIENT_TRANSCRIPT: &[&str] = &[ + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "EncodeTlsData", + "TransmitTlsData", + "EncodeTlsData", + "TransmitTlsData", + "WriteTraffic", + "WriteTraffic", +]; + +const TLS13_SERVER_TRANSCRIPT: &[&str] = &[ + "BlockedHandshake", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "EncodeTlsData", + "TransmitTlsData", + "WriteTraffic", +]; + +const TLS13_CLIENT_TRANSCRIPT_FRAGMENTED: &[&str] = &[ + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "BlockedHandshake", + "EncodeTlsData", + "TransmitTlsData", + "WriteTraffic", + "WriteTraffic", +]; + +const TLS13_SERVER_TRANSCRIPT_FRAGMENTED: &[&str] = &[ + "BlockedHandshake", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "EncodeTlsData", + "TransmitTlsData", + "BlockedHandshake", + "EncodeTlsData", + "TransmitTlsData", + "WriteTraffic", +]; From 48ba6542cb06c30b78ac873f3a0c5411ee8be0ef Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 21 Jan 2025 15:47:04 +0000 Subject: [PATCH 006/403] Hoist `ALL_KX_GROUPS` up a level To allow these to diverge in later changes. --- rustls/src/crypto/aws_lc_rs/mod.rs | 9 +++++---- rustls/src/crypto/ring/kx.rs | 6 ------ rustls/src/crypto/ring/mod.rs | 7 +++++-- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/rustls/src/crypto/aws_lc_rs/mod.rs b/rustls/src/crypto/aws_lc_rs/mod.rs index c31874aa92d..6b1bae86912 100644 --- a/rustls/src/crypto/aws_lc_rs/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/mod.rs @@ -9,7 +9,7 @@ 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}; +use crate::crypto::{CryptoProvider, KeyProvider, SecureRandom, SupportedKxGroup}; use crate::enums::SignatureScheme; use crate::rand::GetRandomFailed; use crate::sign::SigningKey; @@ -228,12 +228,13 @@ pub mod kx_group { pub use super::kx::{SECP256R1, SECP384R1, X25519}; } -pub use kx::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(any(feature = "std", feature = "hashbrown"))] pub use ticketer::Ticketer; -use super::SupportedKxGroup; - /// Compatibility shims between ring 0.16.x and 0.17.x API mod ring_shim { use super::ring_like; diff --git a/rustls/src/crypto/ring/kx.rs b/rustls/src/crypto/ring/kx.rs index 8c019d2ef25..6e0da22773c 100644 --- a/rustls/src/crypto/ring/kx.rs +++ b/rustls/src/crypto/ring/kx.rs @@ -11,9 +11,6 @@ use crate::msgs::enums::NamedGroup; use crate::rand::GetRandomFailed; /// A key-exchange group supported by *ring*. -/// -/// All possible instances of this class are provided by the library in -/// the [`ALL_KX_GROUPS`] array. struct KxGroup { /// The IANA "TLS Supported Groups" name of the group name: NamedGroup, @@ -118,9 +115,6 @@ fn uncompressed_point(point: &[u8]) -> bool { matches!(point.first(), Some(0x04)) } -/// A list of all the key exchange groups supported by rustls. -pub static ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[X25519, SECP256R1, SECP384R1]; - /// An in-progress key exchange. This has the algorithm, /// our private key, and our public key. struct KeyExchange { diff --git a/rustls/src/crypto/ring/mod.rs b/rustls/src/crypto/ring/mod.rs index 8f8ffc0053d..091e09bc6f4 100644 --- a/rustls/src/crypto/ring/mod.rs +++ b/rustls/src/crypto/ring/mod.rs @@ -4,7 +4,7 @@ use pki_types::PrivateKeyDer; pub(crate) use ring as ring_like; use webpki::ring as webpki_algs; -use crate::crypto::{CryptoProvider, KeyProvider, SecureRandom}; +use crate::crypto::{CryptoProvider, KeyProvider, SecureRandom, SupportedKxGroup}; use crate::enums::SignatureScheme; use crate::rand::GetRandomFailed; use crate::sign::SigningKey; @@ -170,7 +170,10 @@ pub mod kx_group { pub use super::kx::{SECP256R1, SECP384R1, X25519}; } -pub use kx::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(any(feature = "std", feature = "hashbrown"))] pub use ticketer::Ticketer; From 60318c232aec28edd408815488162967c636607b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 30 Dec 2024 11:49:55 +0000 Subject: [PATCH 007/403] Introduce `DEFAULT_KX_GROUPS` Similar to `DEFAULT_CIPHER_SUITES` and `ALL_CIPHER_SUITES` This commit makes no changes to the actual defaults. --- rustls/src/crypto/aws_lc_rs/mod.rs | 8 ++++++-- rustls/src/crypto/ring/mod.rs | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/rustls/src/crypto/aws_lc_rs/mod.rs b/rustls/src/crypto/aws_lc_rs/mod.rs index 6b1bae86912..73749a28f09 100644 --- a/rustls/src/crypto/aws_lc_rs/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/mod.rs @@ -50,7 +50,7 @@ pub fn default_provider() -> CryptoProvider { fn default_kx_groups() -> Vec<&'static dyn SupportedKxGroup> { #[cfg(feature = "fips")] { - ALL_KX_GROUPS + DEFAULT_KX_GROUPS .iter() .filter(|cs| cs.fips()) .copied() @@ -58,7 +58,7 @@ fn default_kx_groups() -> Vec<&'static dyn SupportedKxGroup> { } #[cfg(not(feature = "fips"))] { - ALL_KX_GROUPS.to_vec() + DEFAULT_KX_GROUPS.to_vec() } } @@ -224,10 +224,14 @@ static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms /// 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}; } +/// 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]; diff --git a/rustls/src/crypto/ring/mod.rs b/rustls/src/crypto/ring/mod.rs index 091e09bc6f4..84b7c945b86 100644 --- a/rustls/src/crypto/ring/mod.rs +++ b/rustls/src/crypto/ring/mod.rs @@ -32,7 +32,7 @@ pub(crate) mod tls13; pub fn default_provider() -> CryptoProvider { CryptoProvider { cipher_suites: DEFAULT_CIPHER_SUITES.to_vec(), - kx_groups: ALL_KX_GROUPS.to_vec(), + kx_groups: DEFAULT_KX_GROUPS.to_vec(), signature_verification_algorithms: SUPPORTED_SIG_ALGS, secure_random: &Ring, key_provider: &Ring, @@ -166,10 +166,14 @@ static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms /// 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]; From 5930dcbad28fed7428e464a04da4e3380f7e2a10 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 7 Jan 2025 14:01:08 +0000 Subject: [PATCH 008/403] Cargo.toml: sort features --- rustls/Cargo.toml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 55541050bea..a92fd636ce8 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -34,16 +34,17 @@ zlib-rs = { workspace = true, optional = true } [features] default = ["aws_lc_rs", "logging", "std", "tls12"] -std = ["webpki/std", "pki-types/std", "once_cell/std"] -logging = ["log"] -aws_lc_rs = ["dep:aws-lc-rs", "webpki/aws_lc_rs"] + aws-lc-rs = ["aws_lc_rs"] # Alias because Cargo features commonly use `-` +aws_lc_rs = ["dep:aws-lc-rs", "webpki/aws_lc_rs"] brotli = ["dep:brotli", "dep:brotli-decompressor", "std"] -ring = ["dep:ring", "webpki/ring"] custom-provider = [] -tls12 = [] -read_buf = ["rustversion", "std"] fips = ["aws_lc_rs", "aws-lc-rs?/fips"] +logging = ["log"] +read_buf = ["rustversion", "std"] +ring = ["dep:ring", "webpki/ring"] +std = ["webpki/std", "pki-types/std", "once_cell/std"] +tls12 = [] zlib = ["dep:zlib-rs"] [dev-dependencies] From 069e0339d82bb381fc9b7f3866b2d81ffc83e83c Mon Sep 17 00:00:00 2001 From: "@brody4hire - C. Jonathan Brody" Date: Tue, 21 Jan 2025 14:43:42 -0500 Subject: [PATCH 009/403] chore: enforce taplo toml formatting --- .github/workflows/build.yml | 14 ++++++++++++++ .rustfmt.toml | 2 +- .taplo.toml | 3 +++ Cargo.toml | 3 ++- connect-tests/Cargo.toml | 2 +- examples/Cargo.toml | 2 +- fuzz/Cargo.toml | 2 +- rustls/Cargo.toml | 5 +++-- 8 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 .taplo.toml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aa6dca058b3..37f4879a281 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -506,6 +506,20 @@ jobs: working-directory: rustls/ run: cargo check-external-types + taplo: + name: Taplo + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Install rust toolchain + uses: dtolnay/rust-toolchain@stable + - run: cargo install taplo-cli --locked + - run: taplo format --check + openssl-tests: name: Run openssl-tests runs-on: ubuntu-latest diff --git a/.rustfmt.toml b/.rustfmt.toml index e70b64a4ae9..745d2dc30f6 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1 +1 @@ -chain_width=40 +chain_width = 40 diff --git a/.taplo.toml b/.taplo.toml new file mode 100644 index 00000000000..f819ac88b10 --- /dev/null +++ b/.taplo.toml @@ -0,0 +1,3 @@ +[formatting] +align_comments = false +column_width = 110 diff --git a/Cargo.toml b/Cargo.toml index 88fdcb74976..b45909d5cc8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ exclude = [ ] default-members = [ + # --- "examples", "rustls", ] @@ -84,7 +85,7 @@ signature = "2" subtle = { version = "2.5.0", default-features = false } time = { version = "0.3.6", default-features = false } tikv-jemallocator = "0.6" -tokio = { version = "1.34", features = ["io-util", "macros", "net", "rt"]} +tokio = { version = "1.34", features = ["io-util", "macros", "net", "rt"] } webpki = { package = "rustls-webpki", version = "0.102.8", features = ["alloc"], default-features = false } webpki-roots = "0.26" x25519-dalek = "2" diff --git a/connect-tests/Cargo.toml b/connect-tests/Cargo.toml index 5b61033caab..548c70d946d 100644 --- a/connect-tests/Cargo.toml +++ b/connect-tests/Cargo.toml @@ -7,7 +7,7 @@ description = "Rustls connectivity based integration tests." publish = false [dependencies] -rustls = { path = "../rustls", features = [ "logging" ]} +rustls = { path = "../rustls", features = ["logging"] } [dev-dependencies] hickory-resolver = { workspace = true } diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 24e3acd9fe4..cd0bad26bf5 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -14,7 +14,7 @@ hickory-resolver = { workspace = true } log = { workspace = true } mio = { workspace = true } rcgen = { workspace = true } -rustls = { path = "../rustls", features = [ "logging" ]} +rustls = { path = "../rustls", features = ["logging"] } serde = { workspace = true } tokio = { workspace = true } webpki-roots = { workspace = true } diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 89e0b338698..89637ad7963 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -11,7 +11,7 @@ cargo-fuzz = true [dependencies] env_logger = "0.11" libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer-sys.git" } -rustls = { path = "../rustls", default-features = false, features = ["std", "tls12", "custom-provider"]} +rustls = { path = "../rustls", default-features = false, features = ["std", "tls12", "custom-provider"] } rustls-fuzzing-provider = { path = "../rustls-fuzzing-provider" } # Prevent this from interfering with workspaces diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index a92fd636ce8..30ec42cb3e5 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -116,6 +116,7 @@ rustdoc-args = ["--cfg", "docsrs"] [package.metadata.cargo_check_external_types] allowed_external_types = [ - "rustls_pki_types", - "rustls_pki_types::*", + # --- + "rustls_pki_types", + "rustls_pki_types::*", ] From eb28df3fd099bb27a20404af148a6440b4207f03 Mon Sep 17 00:00:00 2001 From: "@brody4hire - C. Jonathan Brody" Date: Wed, 22 Jan 2025 15:11:03 -0500 Subject: [PATCH 010/403] CI: deny all Clippy warnings including clippy::incompatible_msrv --- .github/workflows/build.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 37f4879a281..8cc8fab36a4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -463,10 +463,8 @@ jobs: uses: dtolnay/rust-toolchain@stable with: components: clippy - # - we want to be free of any warnings, so deny them - # - disable incompatible_msrv as it does not understand that we apply our - # MSRV to the just the core crate. - - run: ./admin/clippy -- --deny warnings --allow clippy::incompatible_msrv + # We want to be free of any warnings, so deny them. + - run: ./admin/clippy -- --deny warnings clippy-nightly: name: Clippy (Nightly) From 554473736fb9246bd6c48ee1a9f789d73f8b2fa7 Mon Sep 17 00:00:00 2001 From: "@brody4hire - C. Jonathan Brody" Date: Fri, 24 Jan 2025 05:19:21 +0000 Subject: [PATCH 011/403] chore: list rustls features near top of rustls/Cargo.toml --- rustls/Cargo.toml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 30ec42cb3e5..ecf2a664ed5 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -14,6 +14,21 @@ autotests = false exclude = ["src/testdata", "tests/**"] build = "build.rs" +[features] +default = ["aws_lc_rs", "logging", "std", "tls12"] + +aws-lc-rs = ["aws_lc_rs"] # Alias because Cargo features commonly use `-` +aws_lc_rs = ["dep:aws-lc-rs", "webpki/aws_lc_rs"] +brotli = ["dep:brotli", "dep:brotli-decompressor", "std"] +custom-provider = [] +fips = ["aws_lc_rs", "aws-lc-rs?/fips"] +logging = ["log"] +read_buf = ["rustversion", "std"] +ring = ["dep:ring", "webpki/ring"] +std = ["webpki/std", "pki-types/std", "once_cell/std"] +tls12 = [] +zlib = ["dep:zlib-rs"] + [build-dependencies] rustversion = { version = "1.0.6", optional = true } @@ -32,21 +47,6 @@ pki-types = { workspace = true } zeroize = { workspace = true } zlib-rs = { workspace = true, optional = true } -[features] -default = ["aws_lc_rs", "logging", "std", "tls12"] - -aws-lc-rs = ["aws_lc_rs"] # Alias because Cargo features commonly use `-` -aws_lc_rs = ["dep:aws-lc-rs", "webpki/aws_lc_rs"] -brotli = ["dep:brotli", "dep:brotli-decompressor", "std"] -custom-provider = [] -fips = ["aws_lc_rs", "aws-lc-rs?/fips"] -logging = ["log"] -read_buf = ["rustversion", "std"] -ring = ["dep:ring", "webpki/ring"] -std = ["webpki/std", "pki-types/std", "once_cell/std"] -tls12 = [] -zlib = ["dep:zlib-rs"] - [dev-dependencies] base64 = { workspace = true } bencher = { workspace = true } From 9697e6310733d09624711499f42dc5f59673ba78 Mon Sep 17 00:00:00 2001 From: "@brody4hire - C. Jonathan Brody" Date: Thu, 23 Jan 2025 15:07:52 -0500 Subject: [PATCH 012/403] top-level `sync::Arc` alias to support fork for targets with no atomic ptr Adds an internal `sync` module aliasing the `Arc` implementation to allow downstream forks of rustls targetting architectures without atomic pointers to replace the implementation with another implementation such as `portable_atomic_util::Arc` in one central location. This update should make it more straightforward for a fork of rustls to overwrite the top-level import of `alloc::sync::Arc` in `rustls/src/lib.rs` with another implementation such as `portable_atomic_util::Arc`. (A fork would also need to update single test import of `Arc` in `rustls/tests/common/mod.rs`.) To prevent accidental use of the non-aliased `Arc` the project `.clippy.toml` is upated to add `std::sync::Arc` to the `disallowed-types`. Since we only want this to apply to the main crate the CI clippy invocations targetting auxiliary crates are updated to ignore `disallowed-types` findings. We can improve this in the future with more targetted lint configuration from `Cargo.toml` settings. --- Resolves #2068 (ref: https://github.com/rustls/rustls/issues/2068) --- Co-authored-by: Daniel McCarney --- .clippy.toml | 5 +++++ .github/workflows/build.yml | 14 +++++++++++--- rustls/src/builder.rs | 2 +- rustls/src/client/builder.rs | 4 ++-- rustls/src/client/client_conn.rs | 7 +++---- rustls/src/client/common.rs | 2 +- rustls/src/client/handy.rs | 5 ++--- rustls/src/client/hs.rs | 2 +- rustls/src/client/tls12.rs | 2 +- rustls/src/client/tls13.rs | 2 +- rustls/src/compress.rs | 2 +- rustls/src/crypto/aws_lc_rs/hpke.rs | 4 ++-- rustls/src/crypto/aws_lc_rs/mod.rs | 2 +- rustls/src/crypto/aws_lc_rs/sign.rs | 2 +- rustls/src/crypto/aws_lc_rs/ticketer.rs | 2 +- rustls/src/crypto/mod.rs | 4 ++-- rustls/src/crypto/ring/mod.rs | 3 +-- rustls/src/crypto/ring/sign.rs | 2 +- rustls/src/crypto/ring/ticketer.rs | 2 +- rustls/src/crypto/signer.rs | 2 +- rustls/src/error.rs | 14 ++++++++------ rustls/src/lib.rs | 8 ++++++++ rustls/src/lock.rs | 3 ++- rustls/src/msgs/handshake.rs | 2 +- rustls/src/msgs/handshake_test.rs | 2 +- rustls/src/msgs/persist.rs | 2 +- rustls/src/quic.rs | 2 +- rustls/src/server/builder.rs | 2 +- rustls/src/server/handy.rs | 6 +++--- rustls/src/server/hs.rs | 2 +- rustls/src/server/server_conn.rs | 4 ++-- rustls/src/server/tls12.rs | 2 +- rustls/src/server/tls13.rs | 2 +- rustls/src/webpki/client_verifier.rs | 4 ++-- rustls/src/webpki/mod.rs | 4 ++-- rustls/src/webpki/server_verifier.rs | 4 ++-- rustls/tests/api.rs | 3 ++- rustls/tests/client_cert_verifier.rs | 4 ++-- rustls/tests/common/mod.rs | 7 ++++++- rustls/tests/key_log_file_env.rs | 3 +-- rustls/tests/server_cert_verifier.rs | 6 ++++-- rustls/tests/unbuffered.rs | 1 - 42 files changed, 92 insertions(+), 65 deletions(-) diff --git a/.clippy.toml b/.clippy.toml index cc94ec53e13..1d849dc657e 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -1 +1,6 @@ upper-case-acronyms-aggressive = true + +# only intended to affect main rustls crate - need to allow disallowed-types in all other crates in Clippy CI job +disallowed-types = [ + { path = "std::sync::Arc", reason = "must use Arc from sync module to support downstream forks targetting architectures without atomic ptrs" }, +] diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8cc8fab36a4..39ba757762a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -464,7 +464,11 @@ jobs: with: components: clippy # We want to be free of any warnings, so deny them. - - run: ./admin/clippy -- --deny warnings + # - Allow `clippy::disallowed_types` as a workaround since `disallowed_types` configured in `.clippy.toml` + # is only intended for the main `rustls` crate. + - run: ./admin/clippy -- --deny warnings --allow clippy::disallowed_types + # - Keep the main crate free of all warnings. + - run: cargo clippy -p rustls -- --deny warnings clippy-nightly: name: Clippy (Nightly) @@ -483,8 +487,12 @@ jobs: uses: dtolnay/rust-toolchain@nightly with: components: clippy - # do not deny warnings, as nightly clippy sometimes has false negatives - - run: ./admin/clippy + # Do not deny warnings, as nightly clippy sometimes has false negatives. + # - Ignore `clippy::disallowed_types` as a workaround since `disallowed_types` configured in `.clippy.toml` + # is only intended for main `rustls` crate. + - run: ./admin/clippy -- --allow clippy::disallowed_types + # Check the main crate for any Clippy nightly warnings, but do not deny them. + - run: cargo clippy -p rustls check-external-types: name: Validate external types appearing in public API diff --git a/rustls/src/builder.rs b/rustls/src/builder.rs index 85f95bdf436..342e3633600 100644 --- a/rustls/src/builder.rs +++ b/rustls/src/builder.rs @@ -1,5 +1,4 @@ use alloc::format; -use alloc::sync::Arc; use alloc::vec::Vec; use core::fmt; use core::marker::PhantomData; @@ -8,6 +7,7 @@ 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)] diff --git a/rustls/src/client/builder.rs b/rustls/src/client/builder.rs index bb2a7d66ecc..9c0316f3013 100644 --- a/rustls/src/client/builder.rs +++ b/rustls/src/client/builder.rs @@ -1,4 +1,3 @@ -use alloc::sync::Arc; use alloc::vec::Vec; use core::marker::PhantomData; @@ -10,6 +9,7 @@ use crate::client::{handy, ClientConfig, EchMode, ResolvesClientCert}; use crate::error::Error; use crate::key_log::NoKeyLog; use crate::msgs::handshake::CertificateChain; +use crate::sync::Arc; use crate::versions::TLS13; use crate::webpki::{self, WebPkiServerVerifier}; use crate::{compress, verify, versions, WantsVersions}; @@ -89,10 +89,10 @@ impl ConfigBuilder { /// Container for unsafe APIs pub(super) mod danger { - use alloc::sync::Arc; use core::marker::PhantomData; use crate::client::WantsClientCert; + use crate::sync::Arc; use crate::{verify, ClientConfig, ConfigBuilder, WantsVerifier}; /// Accessor for dangerous configuration options. diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index 854c6b65b67..c2540be6308 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -1,4 +1,3 @@ -use alloc::sync::Arc; use alloc::vec::Vec; use core::marker::PhantomData; use core::ops::{Deref, DerefMut}; @@ -20,6 +19,7 @@ use crate::msgs::enums::NamedGroup; use crate::msgs::handshake::ClientExtension; use crate::msgs::persist; use crate::suites::SupportedCipherSuite; +use crate::sync::Arc; #[cfg(feature = "std")] use crate::time_provider::DefaultTimeProvider; use crate::time_provider::TimeProvider; @@ -511,10 +511,9 @@ pub enum Tls12Resumption { /// Container for unsafe APIs pub(super) mod danger { - use alloc::sync::Arc; - use super::verify::ServerCertVerifier; use super::ClientConfig; + use crate::sync::Arc; /// Accessor for dangerous configuration options. #[derive(Debug)] @@ -611,7 +610,6 @@ impl EarlyData { #[cfg(feature = "std")] mod connection { - use alloc::sync::Arc; use alloc::vec::Vec; use core::fmt; use core::ops::{Deref, DerefMut}; @@ -625,6 +623,7 @@ mod connection { use crate::conn::{ConnectionCommon, ConnectionCore}; use crate::error::Error; use crate::suites::ExtractedSecrets; + use crate::sync::Arc; use crate::ClientConfig; /// Stub that implements io::Write and dispatches to `write_early_data`. diff --git a/rustls/src/client/common.rs b/rustls/src/client/common.rs index ad5e82b0f70..a468af93839 100644 --- a/rustls/src/client/common.rs +++ b/rustls/src/client/common.rs @@ -1,11 +1,11 @@ use alloc::boxed::Box; -use alloc::sync::Arc; use alloc::vec::Vec; use super::ResolvesClientCert; use crate::log::{debug, trace}; use crate::msgs::enums::ExtensionType; use crate::msgs::handshake::{CertificateChain, DistinguishedName, ServerExtension}; +use crate::sync::Arc; use crate::{compress, sign, SignatureScheme}; #[derive(Debug)] diff --git a/rustls/src/client/handy.rs b/rustls/src/client/handy.rs index 78d9326d355..911894f2bbe 100644 --- a/rustls/src/client/handy.rs +++ b/rustls/src/client/handy.rs @@ -1,11 +1,10 @@ -use alloc::sync::Arc; - use pki_types::ServerName; use crate::enums::SignatureScheme; use crate::error::Error; use crate::msgs::handshake::CertificateChain; use crate::msgs::persist; +use crate::sync::Arc; use crate::{client, sign, NamedGroup}; /// An implementer of `ClientSessionStore` which does nothing. @@ -279,7 +278,6 @@ impl client::ResolvesClientCert for AlwaysResolvesClientRawPublicKeys { #[cfg(test)] #[macro_rules_attribute::apply(test_for_each_provider)] mod tests { - use alloc::sync::Arc; use std::prelude::v1::*; use pki_types::{ServerName, UnixTime}; @@ -294,6 +292,7 @@ mod tests { use crate::msgs::handshake::SessionId; use crate::msgs::persist::Tls13ClientSessionValue; use crate::suites::SupportedCipherSuite; + use crate::sync::Arc; #[test] fn test_noclientsessionstorage_does_nothing() { diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 3a2aee48055..44c7dee361d 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -1,6 +1,5 @@ use alloc::borrow::ToOwned; use alloc::boxed::Box; -use alloc::sync::Arc; use alloc::vec; use alloc::vec::Vec; use core::ops::Deref; @@ -37,6 +36,7 @@ use crate::msgs::handshake::{ }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; +use crate::sync::Arc; use crate::tls13::key_schedule::KeyScheduleEarly; use crate::SupportedCipherSuite; diff --git a/rustls/src/client/tls12.rs b/rustls/src/client/tls12.rs index 0f098d3d5e2..c0af6f2e59d 100644 --- a/rustls/src/client/tls12.rs +++ b/rustls/src/client/tls12.rs @@ -1,6 +1,5 @@ use alloc::borrow::ToOwned; use alloc::boxed::Box; -use alloc::sync::Arc; use alloc::vec; use alloc::vec::Vec; @@ -31,6 +30,7 @@ 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}; diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index 6794579ab8e..94d904f0ee0 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -1,5 +1,4 @@ use alloc::boxed::Box; -use alloc::sync::Arc; use alloc::vec; use alloc::vec::Vec; @@ -37,6 +36,7 @@ use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; use crate::sign::{CertifiedKey, Signer}; use crate::suites::PartiallyExtractedSecrets; +use crate::sync::Arc; use crate::tls13::key_schedule::{ KeyScheduleEarly, KeyScheduleHandshake, KeySchedulePreHandshake, KeyScheduleTraffic, ResumptionSecret, diff --git a/rustls/src/compress.rs b/rustls/src/compress.rs index e6a2f028d96..e7b07d1db09 100644 --- a/rustls/src/compress.rs +++ b/rustls/src/compress.rs @@ -34,7 +34,6 @@ #[cfg(feature = "std")] use alloc::collections::VecDeque; -use alloc::sync::Arc; use alloc::vec::Vec; use core::fmt::Debug; #[cfg(feature = "std")] @@ -44,6 +43,7 @@ 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. diff --git a/rustls/src/crypto/aws_lc_rs/hpke.rs b/rustls/src/crypto/aws_lc_rs/hpke.rs index 80514de19c3..e7b1a949d4d 100644 --- a/rustls/src/crypto/aws_lc_rs/hpke.rs +++ b/rustls/src/crypto/aws_lc_rs/hpke.rs @@ -1,6 +1,4 @@ use alloc::boxed::Box; -#[cfg(feature = "std")] -use alloc::sync::Arc; use alloc::vec::Vec; use core::fmt::{self, Debug, Formatter}; @@ -21,6 +19,8 @@ use crate::crypto::hpke::{ use crate::crypto::tls13::{expand, HkdfExpander, HkdfPrkExtract, HkdfUsingHmac}; 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. diff --git a/rustls/src/crypto/aws_lc_rs/mod.rs b/rustls/src/crypto/aws_lc_rs/mod.rs index 73749a28f09..8b2390c6583 100644 --- a/rustls/src/crypto/aws_lc_rs/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/mod.rs @@ -1,4 +1,3 @@ -use alloc::sync::Arc; use alloc::vec::Vec; // aws-lc-rs has a -- roughly -- ring-compatible API, so we just reuse all that @@ -14,6 +13,7 @@ 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}; diff --git a/rustls/src/crypto/aws_lc_rs/sign.rs b/rustls/src/crypto/aws_lc_rs/sign.rs index 91d9110e982..e251c4a7c64 100644 --- a/rustls/src/crypto/aws_lc_rs/sign.rs +++ b/rustls/src/crypto/aws_lc_rs/sign.rs @@ -2,7 +2,6 @@ use alloc::boxed::Box; use alloc::string::ToString; -use alloc::sync::Arc; use alloc::vec::Vec; use alloc::{format, vec}; use core::fmt::{self, Debug, Formatter}; @@ -15,6 +14,7 @@ use super::ring_like::signature::{self, EcdsaKeyPair, Ed25519KeyPair, KeyPair, R use crate::crypto::signer::{public_key_to_spki, Signer, SigningKey}; 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. diff --git a/rustls/src/crypto/aws_lc_rs/ticketer.rs b/rustls/src/crypto/aws_lc_rs/ticketer.rs index dfed6b743be..3157a65f673 100644 --- a/rustls/src/crypto/aws_lc_rs/ticketer.rs +++ b/rustls/src/crypto/aws_lc_rs/ticketer.rs @@ -1,5 +1,4 @@ use alloc::boxed::Box; -use alloc::sync::Arc; use alloc::vec::Vec; use core::fmt; use core::fmt::{Debug, Formatter}; @@ -19,6 +18,7 @@ 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 {} diff --git a/rustls/src/crypto/mod.rs b/rustls/src/crypto/mod.rs index c0b83995bda..6a7db7a4009 100644 --- a/rustls/src/crypto/mod.rs +++ b/rustls/src/crypto/mod.rs @@ -1,5 +1,4 @@ use alloc::boxed::Box; -use alloc::sync::Arc; use alloc::vec::Vec; use core::fmt::Debug; @@ -8,6 +7,7 @@ use zeroize::Zeroize; use crate::msgs::ffdhe_groups::FfdheGroup; use crate::sign::SigningKey; +use crate::sync::Arc; pub use crate::webpki::{ verify_tls12_signature, verify_tls13_signature, verify_tls13_signature_with_raw_key, WebPkiSupportedAlgorithms, @@ -695,7 +695,6 @@ pub fn default_fips_provider() -> CryptoProvider { mod static_default { #[cfg(not(feature = "std"))] use alloc::boxed::Box; - use alloc::sync::Arc; #[cfg(feature = "std")] use std::sync::OnceLock; @@ -703,6 +702,7 @@ mod static_default { use once_cell::race::OnceBox; use super::CryptoProvider; + use crate::sync::Arc; #[cfg(feature = "std")] pub(crate) fn install_default( diff --git a/rustls/src/crypto/ring/mod.rs b/rustls/src/crypto/ring/mod.rs index 84b7c945b86..5ddc87e20ac 100644 --- a/rustls/src/crypto/ring/mod.rs +++ b/rustls/src/crypto/ring/mod.rs @@ -1,5 +1,3 @@ -use alloc::sync::Arc; - use pki_types::PrivateKeyDer; pub(crate) use ring as ring_like; use webpki::ring as webpki_algs; @@ -9,6 +7,7 @@ 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; diff --git a/rustls/src/crypto/ring/sign.rs b/rustls/src/crypto/ring/sign.rs index 0ddfe2d41c2..63496766a48 100644 --- a/rustls/src/crypto/ring/sign.rs +++ b/rustls/src/crypto/ring/sign.rs @@ -2,7 +2,6 @@ use alloc::boxed::Box; use alloc::string::ToString; -use alloc::sync::Arc; use alloc::vec::Vec; use alloc::{format, vec}; use core::fmt::{self, Debug, Formatter}; @@ -15,6 +14,7 @@ use super::ring_like::signature::{self, EcdsaKeyPair, Ed25519KeyPair, KeyPair, R use crate::crypto::signer::{public_key_to_spki, Signer, SigningKey}; 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 diff --git a/rustls/src/crypto/ring/ticketer.rs b/rustls/src/crypto/ring/ticketer.rs index 556293cad34..95793f6223d 100644 --- a/rustls/src/crypto/ring/ticketer.rs +++ b/rustls/src/crypto/ring/ticketer.rs @@ -1,5 +1,4 @@ use alloc::boxed::Box; -use alloc::sync::Arc; use alloc::vec::Vec; use core::fmt; use core::fmt::{Debug, Formatter}; @@ -15,6 +14,7 @@ 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 {} diff --git a/rustls/src/crypto/signer.rs b/rustls/src/crypto/signer.rs index 1ee932d8c40..9f4edbb2546 100644 --- a/rustls/src/crypto/signer.rs +++ b/rustls/src/crypto/signer.rs @@ -1,5 +1,4 @@ use alloc::boxed::Box; -use alloc::sync::Arc; use alloc::vec::Vec; use core::fmt::Debug; @@ -8,6 +7,7 @@ use pki_types::{AlgorithmIdentifier, CertificateDer, SubjectPublicKeyInfoDer}; use crate::enums::{SignatureAlgorithm, SignatureScheme}; use crate::error::{Error, InconsistentKeys}; use crate::server::ParsedCertificate; +use crate::sync::Arc; use crate::x509; /// An abstract signing key. diff --git a/rustls/src/error.rs b/rustls/src/error.rs index d7dc6549f43..7453880daae 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -621,13 +621,13 @@ impl From for Error { } mod other_error { - #[cfg(feature = "std")] - use alloc::sync::Arc; 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. /// @@ -679,6 +679,8 @@ mod tests { use std::{println, vec}; use super::{CertRevocationListError, Error, InconsistentKeys, InvalidMessage, OtherError}; + #[cfg(feature = "std")] + use crate::sync::Arc; #[test] fn certificate_error_equality() { @@ -698,7 +700,7 @@ mod tests { ); let other = Other(OtherError( #[cfg(feature = "std")] - alloc::sync::Arc::from(Box::from("")), + Arc::from(Box::from("")), )); assert_ne!(other, other); assert_ne!(BadEncoding, Expired); @@ -722,7 +724,7 @@ mod tests { assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason); let other = Other(OtherError( #[cfg(feature = "std")] - alloc::sync::Arc::from(Box::from("")), + Arc::from(Box::from("")), )); assert_ne!(other, other); assert_ne!(BadSignature, InvalidCrlNumber); @@ -731,7 +733,7 @@ mod tests { #[test] #[cfg(feature = "std")] fn other_error_equality() { - let other_error = OtherError(alloc::sync::Arc::from(Box::from(""))); + let other_error = OtherError(Arc::from(Box::from(""))); assert_ne!(other_error, other_error); let other: Error = other_error.into(); assert_ne!(other, other); @@ -769,7 +771,7 @@ mod tests { Error::InvalidCertRevocationList(CertRevocationListError::BadSignature), Error::Other(OtherError( #[cfg(feature = "std")] - alloc::sync::Arc::from(Box::from("")), + Arc::from(Box::from("")), )), ]; diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index d8562932ba3..a3b77623bab 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -401,6 +401,14 @@ mod log { #[macro_use] mod test_macros; +/// This internal `sync` module aliases the `Arc` implementation to allow downstream forks +/// of rustls targetting 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 = alloc::sync::Arc; +} + #[macro_use] mod msgs; mod common_state; diff --git a/rustls/src/lock.rs b/rustls/src/lock.rs index 4a261b2eb75..b632b2c54b5 100644 --- a/rustls/src/lock.rs +++ b/rustls/src/lock.rs @@ -35,10 +35,11 @@ mod std_lock { #[cfg(not(feature = "std"))] mod no_std_lock { use alloc::boxed::Box; - use alloc::sync::Arc; use core::fmt::Debug; use core::ops::DerefMut; + use crate::sync::Arc; + /// A no-std compatible wrapper around [`Lock`]. #[derive(Debug)] pub struct Mutex { diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 38e211016ec..101f73d1c61 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -1,7 +1,6 @@ use alloc::collections::BTreeSet; #[cfg(feature = "logging")] use alloc::string::String; -use alloc::sync::Arc; use alloc::vec; use alloc::vec::Vec; use core::ops::Deref; @@ -28,6 +27,7 @@ use crate::msgs::enums::{ NamedGroup, PSKKeyExchangeMode, ServerNameType, }; use crate::rand; +use crate::sync::Arc; use crate::verify::DigitallySignedStruct; use crate::x509::wrap_in_sequence; diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index c6b2861eb5f..dc77e7f6020 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -1,4 +1,3 @@ -use alloc::sync::Arc; use std::prelude::v1::*; use std::{format, println, vec}; @@ -26,6 +25,7 @@ use crate::enums::{ CertificateCompressionAlgorithm, CipherSuite, HandshakeType, ProtocolVersion, SignatureScheme, }; use crate::error::InvalidMessage; +use crate::sync::Arc; use crate::verify::DigitallySignedStruct; #[test] diff --git a/rustls/src/msgs/persist.rs b/rustls/src/msgs/persist.rs index 33e7b66f9cc..1867e021eab 100644 --- a/rustls/src/msgs/persist.rs +++ b/rustls/src/msgs/persist.rs @@ -1,4 +1,3 @@ -use alloc::sync::Arc; use alloc::vec::Vec; use core::cmp; @@ -12,6 +11,7 @@ use crate::msgs::codec::{Codec, Reader}; use crate::msgs::handshake::CertificateChain; #[cfg(feature = "tls12")] use crate::msgs::handshake::SessionId; +use crate::sync::Arc; #[cfg(feature = "tls12")] use crate::tls12::Tls12CipherSuite; use crate::tls13::Tls13CipherSuite; diff --git a/rustls/src/quic.rs b/rustls/src/quic.rs index adfe168669f..ab2c28bd410 100644 --- a/rustls/src/quic.rs +++ b/rustls/src/quic.rs @@ -17,7 +17,6 @@ use crate::tls13::Tls13CipherSuite; #[cfg(feature = "std")] mod connection { - use alloc::sync::Arc; use alloc::vec; use alloc::vec::Vec; use core::fmt::{self, Debug}; @@ -35,6 +34,7 @@ mod connection { use crate::msgs::handshake::{ClientExtension, ServerExtension}; use crate::msgs::message::InboundPlainMessage; use crate::server::{ServerConfig, ServerConnectionData}; + use crate::sync::Arc; use crate::vecbuf::ChunkVecBuffer; /// A QUIC client or server connection. diff --git a/rustls/src/server/builder.rs b/rustls/src/server/builder.rs index 196dd3fcd06..fb15e807e7b 100644 --- a/rustls/src/server/builder.rs +++ b/rustls/src/server/builder.rs @@ -1,4 +1,3 @@ -use alloc::sync::Arc; use alloc::vec::Vec; use core::marker::PhantomData; @@ -8,6 +7,7 @@ use crate::builder::{ConfigBuilder, WantsVerifier}; use crate::error::Error; use crate::server::{handy, ResolvesServerCert, ServerConfig}; use crate::sign::CertifiedKey; +use crate::sync::Arc; use crate::verify::{ClientCertVerifier, NoClientAuth}; use crate::{compress, versions, InconsistentKeys, NoKeyLog}; diff --git a/rustls/src/server/handy.rs b/rustls/src/server/handy.rs index ba2570abfdd..be26b06537a 100644 --- a/rustls/src/server/handy.rs +++ b/rustls/src/server/handy.rs @@ -1,8 +1,8 @@ -use alloc::sync::Arc; 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. @@ -26,11 +26,11 @@ impl server::StoresServerSessions for NoServerSessionStorage { #[cfg(any(feature = "std", feature = "hashbrown"))] mod cache { - use alloc::sync::Arc; 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 @@ -226,7 +226,6 @@ impl server::ResolvesServerCert for AlwaysResolvesServerRawPublicKeys { #[cfg(any(feature = "std", feature = "hashbrown"))] mod sni_resolver { use alloc::string::{String, ToString}; - use alloc::sync::Arc; use core::fmt::Debug; use pki_types::{DnsName, ServerName}; @@ -234,6 +233,7 @@ mod sni_resolver { use crate::error::Error; use crate::hash_map::HashMap; use crate::server::ClientHello; + use crate::sync::Arc; use crate::webpki::{verify_server_name, ParsedCertificate}; use crate::{server, sign}; diff --git a/rustls/src/server/hs.rs b/rustls/src/server/hs.rs index 2d2a45cc575..b50f00f3e44 100644 --- a/rustls/src/server/hs.rs +++ b/rustls/src/server/hs.rs @@ -1,6 +1,5 @@ use alloc::borrow::ToOwned; use alloc::boxed::Box; -use alloc::sync::Arc; use alloc::vec::Vec; use pki_types::DnsName; @@ -31,6 +30,7 @@ use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; use crate::server::common::ActiveCertifiedKey; use crate::server::{tls13, ClientHello, ServerConfig}; +use crate::sync::Arc; use crate::{suites, SupportedCipherSuite}; pub(super) type NextState<'a> = Box + 'a>; diff --git a/rustls/src/server/server_conn.rs b/rustls/src/server/server_conn.rs index ad46cdf28f2..bb790da83fc 100644 --- a/rustls/src/server/server_conn.rs +++ b/rustls/src/server/server_conn.rs @@ -1,5 +1,4 @@ use alloc::boxed::Box; -use alloc::sync::Arc; use alloc::vec::Vec; use core::fmt; use core::fmt::{Debug, Formatter}; @@ -26,6 +25,7 @@ use crate::msgs::base::Payload; use crate::msgs::enums::CertificateType; use crate::msgs::handshake::{ClientHelloPayload, ProtocolName, ServerExtension}; use crate::msgs::message::Message; +use crate::sync::Arc; #[cfg(feature = "std")] use crate::time_provider::DefaultTimeProvider; use crate::time_provider::TimeProvider; @@ -528,7 +528,6 @@ impl ServerConfig { #[cfg(feature = "std")] mod connection { use alloc::boxed::Box; - use alloc::sync::Arc; use alloc::vec::Vec; use core::fmt; use core::fmt::{Debug, Formatter}; @@ -541,6 +540,7 @@ mod connection { 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. diff --git a/rustls/src/server/tls12.rs b/rustls/src/server/tls12.rs index 3313216998c..12b8d4da780 100644 --- a/rustls/src/server/tls12.rs +++ b/rustls/src/server/tls12.rs @@ -1,6 +1,5 @@ use alloc::boxed::Box; use alloc::string::ToString; -use alloc::sync::Arc; use alloc::vec; use alloc::vec::Vec; @@ -29,6 +28,7 @@ use crate::msgs::handshake::{ 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::verify; diff --git a/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index e90de2fba3a..8dde9260e76 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -1,5 +1,4 @@ use alloc::boxed::Box; -use alloc::sync::Arc; use alloc::vec; use alloc::vec::Vec; @@ -28,6 +27,7 @@ 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::{ KeyScheduleTraffic, KeyScheduleTrafficWithClientFinishedPending, ResumptionSecret, }; diff --git a/rustls/src/webpki/client_verifier.rs b/rustls/src/webpki/client_verifier.rs index bbe9db36be0..90b6f325f2e 100644 --- a/rustls/src/webpki/client_verifier.rs +++ b/rustls/src/webpki/client_verifier.rs @@ -1,4 +1,3 @@ -use alloc::sync::Arc; use alloc::vec::Vec; use pki_types::{CertificateDer, CertificateRevocationListDer, UnixTime}; @@ -10,6 +9,7 @@ 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, @@ -432,7 +432,6 @@ pub(crate) enum AnonymousClientPolicy { #[macro_rules_attribute::apply(test_for_each_provider)] mod tests { use std::prelude::v1::*; - use std::sync::Arc; use std::{format, println, vec}; use pki_types::pem::PemObject; @@ -440,6 +439,7 @@ mod tests { use super::{provider, WebPkiClientVerifier}; use crate::server::VerifierBuilderError; + use crate::sync::Arc; use crate::RootCertStore; fn load_crls(crls_der: &[&[u8]]) -> Vec> { diff --git a/rustls/src/webpki/mod.rs b/rustls/src/webpki/mod.rs index 3b890fa8a3a..77c83751858 100644 --- a/rustls/src/webpki/mod.rs +++ b/rustls/src/webpki/mod.rs @@ -1,5 +1,3 @@ -#[cfg(feature = "std")] -use alloc::sync::Arc; use alloc::vec::Vec; use core::fmt; @@ -7,6 +5,8 @@ use pki_types::CertificateRevocationListDer; use webpki::{CertRevocationList, OwnedCertRevocationList}; use crate::error::{CertRevocationListError, CertificateError, Error, OtherError}; +#[cfg(feature = "std")] +use crate::sync::Arc; mod anchors; mod client_verifier; diff --git a/rustls/src/webpki/server_verifier.rs b/rustls/src/webpki/server_verifier.rs index 40ccfcd371f..50a56fd4081 100644 --- a/rustls/src/webpki/server_verifier.rs +++ b/rustls/src/webpki/server_verifier.rs @@ -1,4 +1,3 @@ -use alloc::sync::Arc; use alloc::vec::Vec; use pki_types::{CertificateDer, CertificateRevocationListDer, ServerName, UnixTime}; @@ -6,6 +5,7 @@ use webpki::{CertRevocationList, ExpirationPolicy, RevocationCheckDepth, Unknown use crate::crypto::{CryptoProvider, WebPkiSupportedAlgorithms}; use crate::log::trace; +use crate::sync::Arc; use crate::verify::{ DigitallySignedStruct, HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier, }; @@ -304,13 +304,13 @@ impl ServerCertVerifier for WebPkiServerVerifier { #[macro_rules_attribute::apply(test_for_each_provider)] mod tests { use std::prelude::v1::*; - use std::sync::Arc; use std::{println, vec}; use pki_types::pem::PemObject; use pki_types::{CertificateDer, CertificateRevocationListDer}; use super::{provider, VerifierBuilderError, WebPkiServerVerifier}; + use crate::sync::Arc; use crate::RootCertStore; fn load_crls(crls_der: &[&[u8]]) -> Vec> { diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 48d7da9106a..e9adaae5794 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -6,10 +6,11 @@ use std::fmt::Debug; use std::io::{self, IoSlice, Read, Write}; use std::ops::{Deref, DerefMut}; use std::sync::atomic::{AtomicUsize, Ordering}; -use std::sync::{Arc, Mutex}; +use std::sync::Mutex; use std::{fmt, mem}; use pki_types::{CertificateDer, IpAddr, ServerName, UnixTime}; + use rustls::client::{verify_server_cert_signed_by_trust_anchor, ResolvesClientCert, Resumption}; use rustls::crypto::{ActiveKeyExchange, CryptoProvider, SharedSecret, SupportedKxGroup}; use rustls::internal::msgs::base::Payload; diff --git a/rustls/tests/client_cert_verifier.rs b/rustls/tests/client_cert_verifier.rs index 5f001a64331..9069680f667 100644 --- a/rustls/tests/client_cert_verifier.rs +++ b/rustls/tests/client_cert_verifier.rs @@ -5,13 +5,13 @@ use super::*; mod common; -use std::sync::Arc; use common::{ do_handshake_until_both_error, do_handshake_until_error, make_client_config_with_versions, make_client_config_with_versions_with_auth, make_pair_for_arc_configs, server_config_builder, - server_name, ErrorFromPeer, KeyType, MockClientVerifier, ALL_KEY_TYPES, + server_name, Arc, ErrorFromPeer, KeyType, MockClientVerifier, ALL_KEY_TYPES, }; + use rustls::server::danger::ClientCertVerified; use rustls::{ AlertDescription, ClientConnection, Error, InvalidMessage, ServerConfig, ServerConnection, diff --git a/rustls/tests/common/mod.rs b/rustls/tests/common/mod.rs index 21cf4e53524..a66812d19d7 100644 --- a/rustls/tests/common/mod.rs +++ b/rustls/tests/common/mod.rs @@ -3,13 +3,14 @@ use std::io; use std::ops::DerefMut; -use std::sync::{Arc, OnceLock}; +use std::sync::OnceLock; use pki_types::pem::PemObject; use pki_types::{ CertificateDer, CertificateRevocationListDer, PrivateKeyDer, PrivatePkcs8KeyDer, ServerName, SubjectPublicKeyInfoDer, UnixTime, }; + use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; use rustls::client::{ AlwaysResolvesClientRawPublicKeys, ServerCertVerifierBuilder, WebPkiServerVerifier, @@ -28,10 +29,14 @@ use rustls::{ DigitallySignedStruct, DistinguishedName, Error, InconsistentKeys, NamedGroup, ProtocolVersion, RootCertStore, ServerConfig, ServerConnection, SideData, SignatureScheme, SupportedCipherSuite, }; + use webpki::anchor_from_trusted_cert; use super::provider; +// Import `Arc` here for tests - can be overwritten to test with another `Arc` such as `portable_atomic_util::Arc` +pub use std::sync::Arc; + macro_rules! embed_files { ( $( diff --git a/rustls/tests/key_log_file_env.rs b/rustls/tests/key_log_file_env.rs index 1d00f0b2aa4..81f517c5143 100644 --- a/rustls/tests/key_log_file_env.rs +++ b/rustls/tests/key_log_file_env.rs @@ -25,14 +25,13 @@ use std::env; use std::io::Write; -use std::sync::Arc; use super::*; mod common; use common::{ do_handshake, make_client_config_with_versions, make_pair_for_arc_configs, make_server_config, - transfer, KeyType, + transfer, Arc, KeyType, }; #[test] diff --git a/rustls/tests/server_cert_verifier.rs b/rustls/tests/server_cert_verifier.rs index 8b5b03a9783..6a3ecad7042 100644 --- a/rustls/tests/server_cert_verifier.rs +++ b/rustls/tests/server_cert_verifier.rs @@ -5,15 +5,16 @@ use super::*; mod common; -use std::sync::Arc; use common::{ client_config_builder, client_config_builder_with_versions, do_handshake, do_handshake_until_both_error, do_handshake_until_error, make_client_config_with_versions, make_pair_for_arc_configs, make_server_config, server_config_builder, transfer_altered, - Altered, ErrorFromPeer, KeyType, MockServerVerifier, ALL_KEY_TYPES, + Altered, Arc, ErrorFromPeer, KeyType, MockServerVerifier, ALL_KEY_TYPES, }; + use pki_types::{CertificateDer, ServerName}; + use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; use rustls::client::WebPkiServerVerifier; use rustls::internal::msgs::handshake::{ClientExtension, HandshakePayload}; @@ -25,6 +26,7 @@ use rustls::{ AlertDescription, CertificateError, DigitallySignedStruct, DistinguishedName, Error, InvalidMessage, RootCertStore, }; + use x509_parser::prelude::FromDer; use x509_parser::x509::X509Name; diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index 318dc97bb08..e979940ee98 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -1,7 +1,6 @@ #![allow(clippy::duplicate_mod)] use std::num::NonZeroUsize; -use std::sync::Arc; use rustls::client::{ClientConnectionData, EarlyDataError, UnbufferedClientConnection}; use rustls::server::{ServerConnectionData, UnbufferedServerConnection}; From ba2a50f563d5dcabbc0d2f285d748f59195dd95a Mon Sep 17 00:00:00 2001 From: "@brody4hire - C. Jonathan Brody" Date: Fri, 24 Jan 2025 15:25:39 +0000 Subject: [PATCH 013/403] add missing doc for default `std` feature Co-authored-by: Dirkjan Ochtman Co-authored-by: Joe Birr-Pixton --- rustls/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index a3b77623bab..2f9086d0cf8 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -273,6 +273,9 @@ //! 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 From 7c40d213c764d357ba096b6bbebb910ae0d2f522 Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Thu, 23 Jan 2025 10:50:13 -0800 Subject: [PATCH 014/403] Add Reader::into_first_chunk to access the read buffer --- rustls/src/conn.rs | 16 +++++++++++++++- rustls/src/vecbuf.rs | 9 ++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/rustls/src/conn.rs b/rustls/src/conn.rs index f69f6408e96..e20ab825b2b 100644 --- a/rustls/src/conn.rs +++ b/rustls/src/conn.rs @@ -173,7 +173,7 @@ mod connection { pub(super) has_seen_eof: bool, } - impl Reader<'_> { + 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) { @@ -189,6 +189,20 @@ mod connection { (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 io::Read for Reader<'_> { diff --git a/rustls/src/vecbuf.rs b/rustls/src/vecbuf.rs index 813b99f4dce..59bd8e99cf6 100644 --- a/rustls/src/vecbuf.rs +++ b/rustls/src/vecbuf.rs @@ -142,7 +142,7 @@ impl ChunkVecBuffer { Ok(offs) } - fn consume(&mut self, used: usize) { + pub(crate) fn consume(&mut self, used: usize) { // first, mark the rightmost extent of the used buffer self.prefix_used += used; @@ -175,6 +175,13 @@ impl ChunkVecBuffer { 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"))] From f128131607d6a1b3dc7a84c86675e38d16b5eb76 Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Thu, 23 Jan 2025 10:50:27 -0800 Subject: [PATCH 015/403] Implement BufRead for Reader --- rustls/src/conn.rs | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/rustls/src/conn.rs b/rustls/src/conn.rs index e20ab825b2b..1e4e755e5a2 100644 --- a/rustls/src/conn.rs +++ b/rustls/src/conn.rs @@ -25,7 +25,7 @@ mod connection { use alloc::vec::Vec; use core::fmt::Debug; use core::ops::{Deref, DerefMut}; - use std::io; + use std::io::{self, BufRead, Read}; use crate::common_state::{CommonState, IoState}; use crate::error::Error; @@ -47,7 +47,7 @@ mod connection { /// Read TLS content from `rd`. /// /// See [`ConnectionCommon::read_tls()`] for more information. - pub fn read_tls(&mut self, rd: &mut dyn io::Read) -> Result { + pub fn read_tls(&mut self, rd: &mut dyn Read) -> Result { match self { Self::Client(conn) => conn.read_tls(rd), Self::Server(conn) => conn.read_tls(rd), @@ -108,7 +108,7 @@ mod connection { pub fn complete_io(&mut self, io: &mut T) -> Result<(usize, usize), io::Error> where Self: Sized, - T: io::Read + io::Write, + T: Read + io::Write, { match self { Self::Client(conn) => conn.complete_io(io), @@ -205,7 +205,7 @@ mod connection { } } - impl io::Read for Reader<'_> { + 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 @@ -271,6 +271,29 @@ mod connection { } } + 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(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"; From fed7e38b7986540490dc93cc4a4f1fa7eebe6cb1 Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Thu, 23 Jan 2025 10:42:10 -0800 Subject: [PATCH 016/403] Factor prepare_read out of Stream::read/read_buf --- rustls/src/stream.rs | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/rustls/src/stream.rs b/rustls/src/stream.rs index a6a394a9123..56374d144f0 100644 --- a/rustls/src/stream.rs +++ b/rustls/src/stream.rs @@ -41,15 +41,8 @@ where Ok(()) } -} -impl<'a, C, T, S> Read for Stream<'a, C, T> -where - C: 'a + DerefMut + Deref>, - T: 'a + Read + Write, - S: SideData, -{ - fn read(&mut self, buf: &mut [u8]) -> Result { + fn prepare_read(&mut self) -> Result<()> { self.complete_prior_io()?; // We call complete_io() in a loop since a single call may read only @@ -62,23 +55,24 @@ where } } + Ok(()) + } +} + +impl<'a, C, T, S> Read for Stream<'a, C, T> +where + C: 'a + DerefMut + Deref>, + T: 'a + Read + Write, + S: SideData, +{ + fn read(&mut self, buf: &mut [u8]) -> Result { + self.prepare_read()?; self.conn.reader().read(buf) } #[cfg(read_buf)] fn read_buf(&mut self, cursor: core::io::BorrowedCursor<'_>) -> 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; - } - } - + self.prepare_read()?; self.conn.reader().read_buf(cursor) } } From 8cb021bb1b32baa214663af1c4bd133079e9c61e Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Thu, 23 Jan 2025 10:54:21 -0800 Subject: [PATCH 017/403] Implement BufRead for Stream --- rustls/src/stream.rs | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/rustls/src/stream.rs b/rustls/src/stream.rs index 56374d144f0..16e13c4ceb2 100644 --- a/rustls/src/stream.rs +++ b/rustls/src/stream.rs @@ -1,5 +1,5 @@ use core::ops::{Deref, DerefMut}; -use std::io::{IoSlice, Read, Result, Write}; +use std::io::{BufRead, IoSlice, Read, Result, Write}; use crate::conn::{ConnectionCommon, SideData}; @@ -57,6 +57,15 @@ where 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> @@ -77,6 +86,26 @@ where } } +impl<'a, C, T, S> BufRead for Stream<'a, C, T> +where + C: 'a + DerefMut + Deref>, + 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>, From 53f1f16340f0e6df9d5735a7386514a076358157 Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Thu, 23 Jan 2025 10:54:27 -0800 Subject: [PATCH 018/403] Implement BufRead for StreamOwned --- rustls/src/stream.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/rustls/src/stream.rs b/rustls/src/stream.rs index 16e13c4ceb2..d92d05e3db7 100644 --- a/rustls/src/stream.rs +++ b/rustls/src/stream.rs @@ -227,6 +227,21 @@ where } } +impl BufRead for StreamOwned +where + C: DerefMut + Deref>, + 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 Write for StreamOwned where C: DerefMut + Deref>, From 4d79ed005928039f54f643e399fae49d788a910a Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Tue, 21 Jan 2025 14:50:26 -0800 Subject: [PATCH 019/403] Add basic tests for Stream/StreamOwned BufRead impls --- rustls/tests/api.rs | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index e9adaae5794..49009bf4a53 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -3,7 +3,7 @@ #![allow(clippy::duplicate_mod)] use std::fmt::Debug; -use std::io::{self, IoSlice, Read, Write}; +use std::io::{self, BufRead, IoSlice, Read, Write}; use std::ops::{Deref, DerefMut}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Mutex; @@ -610,6 +610,18 @@ fn check_read_err(reader: &mut dyn io::Read, err_kind: io::ErrorKind) { assert!(matches!(err, err if err.kind() == err_kind)) } +fn check_fill_buf(reader: &mut dyn io::BufRead, bytes: &[u8]) { + let b = reader.fill_buf().unwrap(); + assert_eq!(b, bytes); + let len = b.len(); + reader.consume(len); +} + +fn check_fill_buf_err(reader: &mut dyn io::BufRead, err_kind: io::ErrorKind) { + let err = reader.fill_buf().unwrap_err(); + assert!(matches!(err, err if err.kind() == err_kind)) +} + #[cfg(read_buf)] fn check_read_buf(reader: &mut dyn io::Read, bytes: &[u8]) { use core::io::BorrowedBuf; @@ -2910,6 +2922,8 @@ fn client_stream_read() { test_client_stream_read(StreamKind::Ref, ReadKind::BorrowedBuf); test_client_stream_read(StreamKind::Owned, ReadKind::BorrowedBuf); } + test_client_stream_read(StreamKind::Ref, ReadKind::BufRead); + test_client_stream_read(StreamKind::Owned, ReadKind::BufRead); } #[test] @@ -2921,6 +2935,8 @@ fn server_stream_read() { test_server_stream_read(StreamKind::Ref, ReadKind::BorrowedBuf); test_server_stream_read(StreamKind::Owned, ReadKind::BorrowedBuf); } + test_server_stream_read(StreamKind::Ref, ReadKind::BufRead); + test_server_stream_read(StreamKind::Owned, ReadKind::BufRead); } #[derive(Debug, Copy, Clone)] @@ -2928,9 +2944,10 @@ enum ReadKind { Buf, #[cfg(read_buf)] BorrowedBuf, + BufRead, } -fn test_stream_read(read_kind: ReadKind, mut stream: impl Read, data: &[u8]) { +fn test_stream_read(read_kind: ReadKind, mut stream: impl BufRead, data: &[u8]) { match read_kind { ReadKind::Buf => { check_read(&mut stream, data); @@ -2941,6 +2958,10 @@ fn test_stream_read(read_kind: ReadKind, mut stream: impl Read, data: &[u8]) { check_read_buf(&mut stream, data); check_read_buf_err(&mut stream, io::ErrorKind::UnexpectedEof) } + ReadKind::BufRead => { + check_fill_buf(&mut stream, data); + check_fill_buf_err(&mut stream, io::ErrorKind::UnexpectedEof) + } } } @@ -2954,7 +2975,7 @@ fn test_client_stream_read(stream_kind: StreamKind, read_kind: ReadKind) { let mut pipe = OtherSession::new(&mut server); transfer_eof(&mut client); - let stream: Box = match stream_kind { + let stream: Box = match stream_kind { StreamKind::Ref => Box::new(Stream::new(&mut client, &mut pipe)), StreamKind::Owned => Box::new(StreamOwned::new(client, pipe)), }; @@ -2974,7 +2995,7 @@ fn test_server_stream_read(stream_kind: StreamKind, read_kind: ReadKind) { let mut pipe = OtherSession::new(&mut client); transfer_eof(&mut server); - let stream: Box = match stream_kind { + let stream: Box = match stream_kind { StreamKind::Ref => Box::new(Stream::new(&mut server, &mut pipe)), StreamKind::Owned => Box::new(StreamOwned::new(server, pipe)), }; From f9d3c53d6e51ce8b1afcef9adf6e9430325e9a59 Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Tue, 21 Jan 2025 15:12:00 -0800 Subject: [PATCH 020/403] Add more tests for BufRead directly --- rustls/tests/api.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 49009bf4a53..95c8e00dd74 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -2457,6 +2457,37 @@ fn client_respects_buffer_limit_post_handshake() { check_read(&mut server.reader(), b"01234567890123456789012345"); } +#[test] +fn buf_read() { + let (mut client, mut server) = make_pair(KeyType::Rsa2048); + + do_handshake(&mut client, &mut server); + + // Write two separate messages + assert_eq!(client.writer().write(b"hello").unwrap(), 5); + transfer(&mut client, &mut server); + assert_eq!(client.writer().write(b"world").unwrap(), 5); + transfer(&mut client, &mut server); + server.process_new_packets().unwrap(); + + let mut reader = server.reader(); + // fill_buf() returns each record separately (this is an implementation detail) + assert_eq!(reader.fill_buf().unwrap(), b"hello"); + // partially consuming the buffer is OK + reader.consume(1); + assert_eq!(reader.fill_buf().unwrap(), b"ello"); + // Read::read is compatible with BufRead + let mut b = [0u8; 2]; + reader.read_exact(&mut b).unwrap(); + assert_eq!(b, *b"el"); + assert_eq!(reader.fill_buf().unwrap(), b"lo"); + reader.consume(2); + // once the first packet is consumed, the next one is available + assert_eq!(reader.fill_buf().unwrap(), b"world"); + reader.consume(5); + check_fill_buf_err(&mut reader, io::ErrorKind::WouldBlock); +} + struct OtherSession<'a, C, S> where C: DerefMut + Deref>, @@ -2594,6 +2625,20 @@ fn client_read_returns_wouldblock_when_no_data() { Err(err) if err.kind() == io::ErrorKind::WouldBlock)); } +#[test] +fn server_fill_buf_returns_wouldblock_when_no_data() { + let (_, mut server) = make_pair(KeyType::Rsa2048); + assert!(matches!(server.reader().fill_buf(), + Err(err) if err.kind() == io::ErrorKind::WouldBlock)); +} + +#[test] +fn client_fill_buf_returns_wouldblock_when_no_data() { + let (mut client, _) = make_pair(KeyType::Rsa2048); + assert!(matches!(client.reader().fill_buf(), + Err(err) if err.kind() == io::ErrorKind::WouldBlock)); +} + #[test] fn new_server_returns_initial_io_state() { let (_, mut server) = make_pair(KeyType::Rsa2048); From 6f83d9e0e4a463e552d2a9f646fb256caccf920e Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 18 Dec 2024 15:09:10 +0000 Subject: [PATCH 021/403] subsume rustls-post-quantum into core crate --- rustls/src/crypto/aws_lc_rs/mod.rs | 3 + .../src/crypto/aws_lc_rs/pq}/hybrid.rs | 10 ++-- .../src/crypto/aws_lc_rs/pq}/mlkem.rs | 11 ++-- .../src/crypto/aws_lc_rs/pq/mod.rs | 59 ++++--------------- 4 files changed, 26 insertions(+), 57 deletions(-) rename {rustls-post-quantum/src => rustls/src/crypto/aws_lc_rs/pq}/hybrid.rs (95%) rename {rustls-post-quantum/src => rustls/src/crypto/aws_lc_rs/pq}/mlkem.rs (90%) rename rustls-post-quantum/src/lib.rs => rustls/src/crypto/aws_lc_rs/pq/mod.rs (59%) diff --git a/rustls/src/crypto/aws_lc_rs/mod.rs b/rustls/src/crypto/aws_lc_rs/mod.rs index 8b2390c6583..1a46f5a71c5 100644 --- a/rustls/src/crypto/aws_lc_rs/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/mod.rs @@ -19,6 +19,8 @@ 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; @@ -227,6 +229,7 @@ static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms /// [`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, X25519MLKEM768}; } /// A list of the default key exchange groups supported by this provider. diff --git a/rustls-post-quantum/src/hybrid.rs b/rustls/src/crypto/aws_lc_rs/pq/hybrid.rs similarity index 95% rename from rustls-post-quantum/src/hybrid.rs rename to rustls/src/crypto/aws_lc_rs/pq/hybrid.rs index 2be2da77c21..f0c84be4a79 100644 --- a/rustls-post-quantum/src/hybrid.rs +++ b/rustls/src/crypto/aws_lc_rs/pq/hybrid.rs @@ -1,8 +1,10 @@ -use rustls::crypto::{ActiveKeyExchange, CompletedKeyExchange, SharedSecret, SupportedKxGroup}; -use rustls::ffdhe_groups::FfdheGroup; -use rustls::{Error, NamedGroup, ProtocolVersion}; +use alloc::boxed::Box; +use alloc::vec::Vec; -use crate::INVALID_KEY_SHARE; +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)] diff --git a/rustls-post-quantum/src/mlkem.rs b/rustls/src/crypto/aws_lc_rs/pq/mlkem.rs similarity index 90% rename from rustls-post-quantum/src/mlkem.rs rename to rustls/src/crypto/aws_lc_rs/pq/mlkem.rs index 9756b6ed474..05817fd07d5 100644 --- a/rustls-post-quantum/src/mlkem.rs +++ b/rustls/src/crypto/aws_lc_rs/pq/mlkem.rs @@ -1,9 +1,12 @@ +use alloc::boxed::Box; +use alloc::vec::Vec; + use aws_lc_rs::kem; -use rustls::crypto::{ActiveKeyExchange, CompletedKeyExchange, SharedSecret, SupportedKxGroup}; -use rustls::ffdhe_groups::FfdheGroup; -use rustls::{Error, NamedGroup, ProtocolVersion}; -use crate::INVALID_KEY_SHARE; +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; diff --git a/rustls-post-quantum/src/lib.rs b/rustls/src/crypto/aws_lc_rs/pq/mod.rs similarity index 59% rename from rustls-post-quantum/src/lib.rs rename to rustls/src/crypto/aws_lc_rs/pq/mod.rs index 89aae035b92..0717181c57a 100644 --- a/rustls-post-quantum/src/lib.rs +++ b/rustls/src/crypto/aws_lc_rs/pq/mod.rs @@ -1,12 +1,12 @@ -//! This crate provides a [`rustls::crypto::CryptoProvider`] that includes -//! a hybrid[^1], post-quantum-secure[^2] key exchange algorithm -- -//! specifically [X25519MLKEM768], as well as a non-hybrid +//! This module provides a hybrid[^1], post-quantum-secure[^2] key exchange +//! algorithm -- specifically [X25519MLKEM768], as well as a non-hybrid //! post-quantum-secure key exchange algorithm. //! -//! X25519MLKEM768 is pre-standardization, so you should treat -//! this as experimental. You may see unexpected connection failures (such as [tldr.fail]) -//! -- [please report these to us][interop-bug]. X25519MLKEM768 is becoming widely -//! deployed, eg, by [Chrome] and [Cloudflare]. +//! 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 @@ -29,53 +29,14 @@ //! [Cloudflare]: //! [interop-bug]: //! [tldr.fail]: -//! -//! -//! # How to use this crate -//! -//! There are a few options: -//! -//! **To use this as the rustls default provider**: include this code early in your program: -//! -//! ```rust -//! rustls_post_quantum::provider().install_default().unwrap(); -//! ``` -//! -//! **To incorporate just the key exchange algorithm(s) in a custom [`rustls::crypto::CryptoProvider`]**: -//! -//! ```rust -//! use rustls::crypto::{aws_lc_rs, CryptoProvider}; -//! let parent = aws_lc_rs::default_provider(); -//! let my_provider = CryptoProvider { -//! kx_groups: vec![ -//! rustls_post_quantum::X25519MLKEM768, -//! aws_lc_rs::kx_group::X25519, -//! rustls_post_quantum::MLKEM768, -//! ], -//! ..parent -//! }; -//! ``` -//! -use rustls::crypto::aws_lc_rs::{default_provider, kx_group}; -use rustls::crypto::{CryptoProvider, SupportedKxGroup}; -use rustls::{Error, NamedGroup, PeerMisbehaved}; +use crate::crypto::aws_lc_rs::kx_group; +use crate::crypto::SupportedKxGroup; +use crate::{Error, NamedGroup, PeerMisbehaved}; mod hybrid; mod mlkem; -/// A `CryptoProvider` which includes `X25519MLKEM768` and `MLKEM768` -/// key exchanges. -pub fn provider() -> CryptoProvider { - let mut parent = default_provider(); - - parent - .kx_groups - .splice(0..0, [X25519MLKEM768, MLKEM768]); - - parent -} - /// This is the [X25519MLKEM768] key exchange. /// /// [X25519MLKEM768]: From 4eb64bd25716f5f8e22cccc553a79cd09276ea7b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 18 Dec 2024 17:35:55 +0000 Subject: [PATCH 022/403] Implement fips() for ML-KEM and generic hybrid --- rustls/src/crypto/aws_lc_rs/pq/hybrid.rs | 21 +++++++++++++++++++++ rustls/src/crypto/aws_lc_rs/pq/mlkem.rs | 16 ++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/rustls/src/crypto/aws_lc_rs/pq/hybrid.rs b/rustls/src/crypto/aws_lc_rs/pq/hybrid.rs index f0c84be4a79..2611bc9085f 100644 --- a/rustls/src/crypto/aws_lc_rs/pq/hybrid.rs +++ b/rustls/src/crypto/aws_lc_rs/pq/hybrid.rs @@ -68,6 +68,27 @@ impl SupportedKxGroup for Hybrid { 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 + // (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 } diff --git a/rustls/src/crypto/aws_lc_rs/pq/mlkem.rs b/rustls/src/crypto/aws_lc_rs/pq/mlkem.rs index 05817fd07d5..fa2be078dd9 100644 --- a/rustls/src/crypto/aws_lc_rs/pq/mlkem.rs +++ b/rustls/src/crypto/aws_lc_rs/pq/mlkem.rs @@ -50,6 +50,22 @@ impl SupportedKxGroup for MlKem768 { 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 + // -- + // see + super::super::fips() + } + fn usable_for_version(&self, version: ProtocolVersion) -> bool { version == ProtocolVersion::TLSv1_3 } From c7a86ded664c5db255209131ebe1067caafa8a9f Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 18 Dec 2024 16:23:15 +0000 Subject: [PATCH 023/403] Add post-quantum key exchange algorithm to defaults The new "prefer-post-quantum" crate feature controls the default preference of `X25519MLKEM768` in the aws-lc-rs provider. If set, `X25519MLKEM768` is the most preferred algorithm in `DEFAULT_KX_GROUPS`. Otherwise, it is least preferred. `ALL_KX_GROUPS` contains both `X25519MLKEM768` and `MLKEM768`. `DEFAULT_KX_GROUPS` does not contain plain `MLKEM768`. That is out of an abundance of caution -- in case ML-KEM does not fare well in its first years of being (partially) load-bearing for internet traffic. This seems the most conservative choice. rustls-post-quantum sets this feature and re-exports the items that are now in the core crate. --- Cargo.lock | 1 - bogo/config.json.in | 4 ++++ bogo/src/main.rs | 2 +- rustls-post-quantum/Cargo.toml | 3 +-- rustls-post-quantum/src/lib.rs | 2 ++ rustls/Cargo.toml | 1 + rustls/src/crypto/aws_lc_rs/mod.rs | 25 ++++++++++++++++++++++--- rustls/src/lib.rs | 5 +++++ rustls/tests/api.rs | 14 ++++++++++---- rustls/tests/unbuffered.rs | 30 +++++++++++++++++++++++++----- 10 files changed, 71 insertions(+), 16 deletions(-) create mode 100644 rustls-post-quantum/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 3c6c62c6d23..75f16c75d77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2559,7 +2559,6 @@ checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" name = "rustls-post-quantum" version = "0.2.1" dependencies = [ - "aws-lc-rs", "criterion", "env_logger", "rustls 0.23.21", diff --git a/bogo/config.json.in b/bogo/config.json.in index 2586a6f303c..1c3c8e464a6 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -54,6 +54,10 @@ "MLKEMKeyShareIncludedThird": "^", #else "*MLKEM*": "not implemented", +#endif +#if defined(AWS_LC_RS) + "PostQuantumNotEnabledByDefaultInClients": "it is", + "PostQuantumNotEnabledByDefaultForAServer": "", #endif "*Kyber*": "old draft, not implemented", "ExtraClientEncryptedExtension-*": "we don't implement ALPS", diff --git a/bogo/src/main.rs b/bogo/src/main.rs index 8b8656a3eda..b875a8ce2b1 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -241,7 +241,7 @@ impl SelectedProvider { // this includes rustls-post-quantum, which just returns an altered // version of `aws_lc_rs::default_provider()` CryptoProvider { - kx_groups: aws_lc_rs::ALL_KX_GROUPS.to_vec(), + kx_groups: aws_lc_rs::DEFAULT_KX_GROUPS.to_vec(), cipher_suites: aws_lc_rs::ALL_CIPHER_SUITES.to_vec(), ..aws_lc_rs::default_provider() } diff --git a/rustls-post-quantum/Cargo.toml b/rustls-post-quantum/Cargo.toml index cb18f244858..b6a62419a14 100644 --- a/rustls-post-quantum/Cargo.toml +++ b/rustls-post-quantum/Cargo.toml @@ -12,8 +12,7 @@ categories = ["network-programming", "cryptography"] autobenches = false [dependencies] -rustls = { version = "0.23.20", features = ["aws_lc_rs"], path = "../rustls" } -aws-lc-rs = { workspace = true } +rustls = { version = "0.23.20", features = ["aws_lc_rs", "prefer-post-quantum"], path = "../rustls" } [dev-dependencies] criterion = "0.5" diff --git a/rustls-post-quantum/src/lib.rs b/rustls-post-quantum/src/lib.rs new file mode 100644 index 00000000000..eac92a1f649 --- /dev/null +++ b/rustls-post-quantum/src/lib.rs @@ -0,0 +1,2 @@ +pub use rustls::crypto::aws_lc_rs::default_provider as provider; +pub use rustls::crypto::aws_lc_rs::kx_group::{MLKEM768, X25519MLKEM768}; diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index ecf2a664ed5..01a5d0d33bd 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -23,6 +23,7 @@ brotli = ["dep:brotli", "dep:brotli-decompressor", "std"] custom-provider = [] fips = ["aws_lc_rs", "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"] diff --git a/rustls/src/crypto/aws_lc_rs/mod.rs b/rustls/src/crypto/aws_lc_rs/mod.rs index 1a46f5a71c5..5bafc3d8e0a 100644 --- a/rustls/src/crypto/aws_lc_rs/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/mod.rs @@ -233,11 +233,30 @@ pub mod kx_group { } /// A list of the default key exchange groups supported by this provider. -pub static DEFAULT_KX_GROUPS: &[&dyn SupportedKxGroup] = ALL_KX_GROUPS; +/// +/// 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] = - &[kx_group::X25519, kx_group::SECP256R1, kx_group::SECP384R1]; +pub static ALL_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, + kx_group::MLKEM768, +]; #[cfg(any(feature = "std", feature = "hashbrown"))] pub use ticketer::Ticketer; diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 2f9086d0cf8..5494a9da15b 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -296,6 +296,11 @@ //! //! See [manual::_06_fips] for more details. //! +//! - `prefer-post-quantum`: 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`. We expect to add this feature +//! to the default set in a future minor release. +//! //! - `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`. //! diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 95c8e00dd74..0989082d2f0 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -3894,10 +3894,16 @@ fn negotiated_ciphersuite_server_ignoring_client_preference() { } } -fn expected_kx_for_version(_version: &SupportedProtocolVersion) -> NamedGroup { - match provider_is_fips() { - true => NamedGroup::secp256r1, - false => NamedGroup::X25519, +fn expected_kx_for_version(version: &SupportedProtocolVersion) -> NamedGroup { + match ( + version.version, + provider_is_aws_lc_rs(), + provider_is_fips(), + cfg!(feature = "prefer-post-quantum"), + ) { + (ProtocolVersion::TLSv1_3, true, _, true) => NamedGroup::X25519MLKEM768, + (_, _, true, _) => NamedGroup::secp256r1, + (_, _, _, _) => NamedGroup::X25519, } } diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index e979940ee98..7dbc2fc70d6 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -42,12 +42,19 @@ fn tls12_handshake_fragmented() { server.max_fragment_size = Some(512); }); + let mut expected_client = TLS12_CLIENT_TRANSCRIPT_FRAGMENTED.to_vec(); + let mut expected_server = TLS12_SERVER_TRANSCRIPT_FRAGMENTED.to_vec(); + if provider_is_aws_lc_rs() && cfg!(feature = "prefer-post-quantum") { + // client hello is larger for X25519MLKEM768 + expected_client.splice(0..0, ["EncodeTlsData", "EncodeTlsData"]); + expected_server.splice(0..0, ["BlockedHandshake", "BlockedHandshake"]); + } assert_eq!( - outcome.client_transcript, TLS12_CLIENT_TRANSCRIPT_FRAGMENTED, + outcome.client_transcript, expected_client, "client transcript mismatch" ); assert_eq!( - outcome.server_transcript, TLS12_SERVER_TRANSCRIPT_FRAGMENTED, + outcome.server_transcript, expected_server, "server transcript mismatch" ); } @@ -74,12 +81,25 @@ fn tls13_handshake_fragmented() { server.max_fragment_size = Some(512); }); + let mut expected_client = TLS13_CLIENT_TRANSCRIPT_FRAGMENTED.to_vec(); + let mut expected_server = TLS13_SERVER_TRANSCRIPT_FRAGMENTED.to_vec(); + + if provider_is_aws_lc_rs() && cfg!(feature = "prefer-post-quantum") { + // client hello is larger for X25519MLKEM768 + expected_client.splice(0..0, ["EncodeTlsData", "EncodeTlsData"]); + expected_server.splice(0..0, ["BlockedHandshake", "BlockedHandshake"]); + + // and server flight + expected_client.splice(4..4, ["BlockedHandshake", "BlockedHandshake"]); + expected_server.splice(4..4, ["EncodeTlsData", "EncodeTlsData"]); + } + assert_eq!( - outcome.client_transcript, TLS13_CLIENT_TRANSCRIPT_FRAGMENTED, + outcome.client_transcript, expected_client, "client transcript mismatch" ); assert_eq!( - outcome.server_transcript, TLS13_SERVER_TRANSCRIPT_FRAGMENTED, + outcome.server_transcript, expected_server, "server transcript mismatch" ); } @@ -1257,7 +1277,7 @@ fn make_connection_pair( fn server_receives_handshake_byte_by_byte() { let (mut client, mut server) = make_connection_pair(&TLS13); - let mut client_hello_buffer = vec![0u8; 1024]; + let mut client_hello_buffer = vec![0u8; 2048]; let UnbufferedStatus { discard, state } = client.process_tls_records(&mut []); assert_eq!(discard, 0); From e883143bf5064e85f0f3b59545f35150af78b69a Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 19 Dec 2024 14:51:20 +0000 Subject: [PATCH 024/403] Bump rustls 0.23.22, rustls-post-quantum 0.2.2 rustls-post-quantum is now a stub, and will have a summit release that reexports the same API from the core crate. --- Cargo.lock | 58 +++++++++++++++---------------- README.md | 3 -- fuzz/Cargo.lock | 2 +- rustls-post-quantum/Cargo.toml | 4 +-- rustls-post-quantum/README.md | 62 +++------------------------------- rustls-post-quantum/src/lib.rs | 5 +++ rustls/Cargo.toml | 2 +- rustls/src/lib.rs | 3 -- 8 files changed, 42 insertions(+), 97 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 75f16c75d77..05fc40b5c3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -493,7 +493,7 @@ version = "0.1.0" dependencies = [ "base64", "env_logger", - "rustls 0.23.21", + "rustls 0.23.22", "rustls-post-quantum", ] @@ -1315,7 +1315,7 @@ dependencies = [ "ipnet", "once_cell", "rand", - "rustls 0.23.21 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.23.21", "thiserror 2.0.11", "tinyvec", "tokio", @@ -1340,7 +1340,7 @@ dependencies = [ "parking_lot", "rand", "resolv-conf", - "rustls 0.23.21 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.23.21", "smallvec", "thiserror 1.0.69", "tokio", @@ -2431,6 +2431,21 @@ dependencies = [ [[package]] name = "rustls" version = "0.23.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls" +version = "0.23.22" dependencies = [ "aws-lc-rs", "base64", @@ -2459,27 +2474,12 @@ dependencies = [ "zlib-rs", ] -[[package]] -name = "rustls" -version = "0.23.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8" -dependencies = [ - "log", - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - [[package]] name = "rustls-bench" version = "0.1.0" dependencies = [ "clap", - "rustls 0.23.21", + "rustls 0.23.22", "rustls-post-quantum", "tikv-jemallocator", ] @@ -2496,7 +2496,7 @@ dependencies = [ "fxhash", "itertools 0.14.0", "rayon", - "rustls 0.23.21", + "rustls 0.23.22", "tikv-jemallocator", ] @@ -2507,7 +2507,7 @@ dependencies = [ "hickory-resolver", "regex", "ring", - "rustls 0.23.21", + "rustls 0.23.22", "tokio", ] @@ -2522,7 +2522,7 @@ dependencies = [ "log", "mio", "rcgen", - "rustls 0.23.21", + "rustls 0.23.22", "serde", "tokio", "webpki-roots", @@ -2533,7 +2533,7 @@ name = "rustls-fuzzing-provider" version = "0.1.0" dependencies = [ "env_logger", - "rustls 0.23.21", + "rustls 0.23.22", "rustls-webpki", ] @@ -2546,7 +2546,7 @@ dependencies = [ "num-bigint", "once_cell", "openssl", - "rustls 0.23.21", + "rustls 0.23.22", ] [[package]] @@ -2557,11 +2557,11 @@ checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" [[package]] name = "rustls-post-quantum" -version = "0.2.1" +version = "0.2.2" dependencies = [ "criterion", "env_logger", - "rustls 0.23.21", + "rustls 0.23.22", "webpki-roots", ] @@ -2582,7 +2582,7 @@ dependencies = [ "rand_core", "rcgen", "rsa", - "rustls 0.23.21", + "rustls 0.23.22", "rustls-webpki", "sha2", "signature", @@ -2595,7 +2595,7 @@ name = "rustls-provider-test" version = "0.1.0" dependencies = [ "hex", - "rustls 0.23.21", + "rustls 0.23.22", "rustls-provider-example", "serde", "serde_json", @@ -2970,7 +2970,7 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ - "rustls 0.23.21 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.23.21", "tokio", ] diff --git a/README.md b/README.md index 2488264fce6..18216dc245c 100644 --- a/README.md +++ b/README.md @@ -92,8 +92,6 @@ The community has also started developing third-party providers for Rustls: * [`rustls-mbedtls-provider`] - a provider that uses [`mbedtls`] for cryptography. * [`rustls-openssl`] - a provider that uses [OpenSSL] for cryptography. -* [`rustls-post-quantum`]: an experimental provider that adds support for post-quantum -key exchange to the default aws-lc-rs provider. * [`boring-rustls-provider`] - a work-in-progress provider that uses [`boringssl`] for cryptography. * [`rustls-rustcrypto`] - an experimental provider that uses the crypto primitives @@ -111,7 +109,6 @@ from [`RustCrypto`] for cryptography. [`boringssl`]: https://github.com/google/boringssl [`rustls-rustcrypto`]: https://github.com/RustCrypto/rustls-rustcrypto [`RustCrypto`]: https://github.com/RustCrypto -[`rustls-post-quantum`]: https://crates.io/crates/rustls-post-quantum [`rustls-wolfcrypt-provider`]: https://github.com/wolfSSL/rustls-wolfcrypt-provider [`wolfCrypt`]: https://www.wolfssl.com/products/wolfcrypt diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 8a010650d8d..b56f990d0b5 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -212,7 +212,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.21" +version = "0.23.22" dependencies = [ "log", "once_cell", diff --git a/rustls-post-quantum/Cargo.toml b/rustls-post-quantum/Cargo.toml index b6a62419a14..54d0798272e 100644 --- a/rustls-post-quantum/Cargo.toml +++ b/rustls-post-quantum/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls-post-quantum" -version = "0.2.1" +version = "0.2.2" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" @@ -12,7 +12,7 @@ categories = ["network-programming", "cryptography"] autobenches = false [dependencies] -rustls = { version = "0.23.20", features = ["aws_lc_rs", "prefer-post-quantum"], path = "../rustls" } +rustls = { version = "0.23.22", features = ["aws_lc_rs", "prefer-post-quantum"], path = "../rustls" } [dev-dependencies] criterion = "0.5" diff --git a/rustls-post-quantum/README.md b/rustls-post-quantum/README.md index ba4681472c9..3d4f4f573c1 100644 --- a/rustls-post-quantum/README.md +++ b/rustls-post-quantum/README.md @@ -8,64 +8,10 @@ Rustls is a modern TLS library written in Rust. # rustls-post-quantum -This crate provides a [`rustls::crypto::CryptoProvider`] that includes -a hybrid[^1], post-quantum-secure[^2] key exchange algorithm -- -specifically [X25519MLKEM768], as well as a non-hybrid -post-quantum-secure key exchange algorithm. - -X25519MLKEM768 is pre-standardization, so you should treat -this as experimental. You may see unexpected connection failures (such as [tldr.fail]) --- [please report these to us][interop-bug]. X25519MLKEM768 is becoming widely -deployed, eg, by [Chrome] and [Cloudflare]. - -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]. - -[^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]: -[FIPS203]: -[Chrome]: -[Cloudflare]: -[interop-bug]: -[tldr.fail]: - - -## How to use this crate - -There are a few options: - -**To use this as the rustls default provider**: include this code early in your program: - -```rust -rustls_post_quantum::provider().install_default().unwrap(); -``` - -**To incorporate just the key exchange algorithm(s) in a custom [`rustls::crypto::CryptoProvider`]**: - -```rust -use rustls::crypto::{aws_lc_rs, CryptoProvider}; -let parent = aws_lc_rs::default_provider(); -let my_provider = CryptoProvider { - kx_groups: vec![ - rustls_post_quantum::X25519MLKEM768, - aws_lc_rs::kx_group::X25519, - rustls_post_quantum::MLKEM768, - ], - ..parent -}; -``` - +The functionality of this crate became part of the core rustls +crate from the 0.23.22 release. When using that version of the crate, +use the `prefer-post-quantum` Cargo feature to control whether to prefer +using post-quantum algorithms instead of using this crate. This crate is release under the same licenses as the [main rustls crate][rustls]. diff --git a/rustls-post-quantum/src/lib.rs b/rustls-post-quantum/src/lib.rs index eac92a1f649..71650ec53dd 100644 --- a/rustls-post-quantum/src/lib.rs +++ b/rustls-post-quantum/src/lib.rs @@ -1,2 +1,7 @@ +//! The functionality of this crate became part of the core rustls +//! crate from the 0.23.22 release. When using that version of the crate, +//! use the `prefer-post-quantum` Cargo feature to control whether to prefer +//! using post-quantum algorithms instead of using this crate. + pub use rustls::crypto::aws_lc_rs::default_provider as provider; pub use rustls::crypto::aws_lc_rs::kx_group::{MLKEM768, X25519MLKEM768}; diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 01a5d0d33bd..544e80f7113 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.21" +version = "0.23.22" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 5494a9da15b..0d43aae14fb 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -58,8 +58,6 @@ //! //! * [`rustls-mbedtls-provider`] - a provider that uses [`mbedtls`] for cryptography. //! * [`rustls-openssl`] - a provider that uses [OpenSSL] for cryptography. -//! * [`rustls-post-quantum`]: an experimental provider that adds support for post-quantum -//! key exchange to the default aws-lc-rs provider. //! * [`boring-rustls-provider`] - a work-in-progress provider that uses [`boringssl`] for //! cryptography. //! * [`rustls-rustcrypto`] - an experimental provider that uses the crypto primitives @@ -77,7 +75,6 @@ //! [`boringssl`]: https://github.com/google/boringssl //! [`rustls-rustcrypto`]: https://github.com/RustCrypto/rustls-rustcrypto //! [`RustCrypto`]: https://github.com/RustCrypto -//! [`rustls-post-quantum`]: https://crates.io/crates/rustls-post-quantum //! [`rustls-wolfcrypt-provider`]: https://github.com/wolfSSL/rustls-wolfcrypt-provider //! [`wolfCrypt`]: https://www.wolfssl.com/products/wolfcrypt //! From bf663b68312c22005677ade97602388124ff6bf9 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 22 Jan 2025 11:45:14 +0000 Subject: [PATCH 025/403] Move crypto::aws_lc_rs::pq docs into manual --- rustls/src/crypto/aws_lc_rs/pq/mod.rs | 32 -------------------- rustls/src/lib.rs | 4 ++- rustls/src/manual/defaults.rs | 42 +++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 33 deletions(-) diff --git a/rustls/src/crypto/aws_lc_rs/pq/mod.rs b/rustls/src/crypto/aws_lc_rs/pq/mod.rs index 0717181c57a..7914e11b4c0 100644 --- a/rustls/src/crypto/aws_lc_rs/pq/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/pq/mod.rs @@ -1,35 +1,3 @@ -//! This module provides a hybrid[^1], post-quantum-secure[^2] key exchange -//! algorithm -- specifically [X25519MLKEM768], as well as a non-hybrid -//! post-quantum-secure key exchange algorithm. -//! -//! 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]. -//! -//! [^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]: -//! [FIPS203]: -//! [Chrome]: -//! [Cloudflare]: -//! [interop-bug]: -//! [tldr.fail]: - use crate::crypto::aws_lc_rs::kx_group; use crate::crypto::SupportedKxGroup; use crate::{Error, NamedGroup, PeerMisbehaved}; diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 0d43aae14fb..590d1776916 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -296,7 +296,8 @@ //! - `prefer-post-quantum`: 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`. We expect to add this feature -//! to the default set in a future minor release. +//! to the default set in a future minor release. 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`. @@ -320,6 +321,7 @@ //! //! - `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)] diff --git a/rustls/src/manual/defaults.rs b/rustls/src/manual/defaults.rs index aa15863c163..746bf2aed23 100644 --- a/rustls/src/manual/defaults.rs +++ b/rustls/src/manual/defaults.rs @@ -26,4 +26,46 @@ the implementation security will be improved. We think this is an uncommon case 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]: +[`X25519MLKEM768`]: crate::crypto::aws_lc_rs::kx_group::X25519MLKEM768 +[`MLKEM768`]: crate::crypto::aws_lc_rs::kx_group::MLKEM768 +[FIPS203]: +[Chrome]: +[Cloudflare]: +[interop-bug]: +[tldr.fail]: + */ From 50d1acde9551380c6f4485f71a7414b1e1cfa0d0 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 22 Jan 2025 11:56:48 +0000 Subject: [PATCH 026/403] Add X25519MLKEM768 to features documentation --- rustls/src/manual/features.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rustls/src/manual/features.rs b/rustls/src/manual/features.rs index 9896ac27408..769e9d6e32b 100644 --- a/rustls/src/manual/features.rs +++ b/rustls/src/manual/features.rs @@ -12,6 +12,7 @@ APIs ([`CryptoProvider`] for example). * 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-kwiatkowski-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 @@ -36,6 +37,7 @@ APIs ([`CryptoProvider`] for example). 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 @@ -77,7 +79,7 @@ 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][^2]. + 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]. @@ -93,6 +95,6 @@ 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/ -[^2]: rustls does not currently implement ALPS, but it is something we +[^3]: rustls does not currently implement ALPS, but it is something we would consider once standardised and deployed. */ From 2551558babacb1db7767f4a964c294df14a062e1 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 22 Jan 2025 14:40:50 +0000 Subject: [PATCH 027/403] Increase accuracy of when to include second keyshare MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A HRR that does not request a specific KX group should lead to the precise same KeyShares extension in the second ClientHello. However, we omitted the second keyshare which does not meet the "without modification" requirement of RFC8446 §4.1.2. Fixes `ServerAcceptsEarlyDataOnHRR-Client-TLS13` when `prefer-post-quantum` feature is enabled. --- rustls/src/client/hs.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 44c7dee361d..06505cd2d2f 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -312,10 +312,14 @@ fn emit_client_hello_for_retry( debug_assert!(support_tls13); let mut shares = vec![KeyShareEntry::new(key_share.group(), key_share.pub_key())]; - if retryreq.is_none() { - // Only for the initial client hello, 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 !retryreq + .map(|rr| rr.requested_key_share_group().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() From 43c2336792409cb0b96694d9e6c3259bee389efe Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 22 Jan 2025 14:47:38 +0000 Subject: [PATCH 028/403] Detect illegal HRR if X25519 offered as secondary kx This condition only considered the primary kx. Fixes `UnnecessaryHelloRetryRequest-TLS13` when `prefer-post-quantum` feature enabled. --- rustls/src/client/hs.rs | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 06505cd2d2f..2ad8f1cc67a 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -976,13 +976,24 @@ impl ExpectServerHelloOrHelloRetryRequest { // A retry request is illegal if it contains no cookie and asks for // retry of a group we already sent. - if cookie.is_none() && req_group == Some(offered_key_share.group()) { - return Err({ - cx.common.send_fatal_alert( - AlertDescription::IllegalParameter, - PeerMisbehaved::IllegalHelloRetryRequestWithOfferedGroup, - ) - }); + let config = &self.next.input.config; + + if let (None, Some(req_group)) = (cookie, req_group) { + 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. @@ -1063,7 +1074,6 @@ impl ExpectServerHelloOrHelloRetryRequest { } // Or asks us to use a ciphersuite we didn't offer. - let config = &self.next.input.config; let Some(cs) = config.find_cipher_suite(hrr.cipher_suite) else { return Err({ cx.common.send_fatal_alert( From d978e2fad0424f069756ce5104e2385f6d67de18 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 29 Jan 2025 12:51:40 +0000 Subject: [PATCH 029/403] chore(deps): update rust crate x509-parser to 0.17 --- Cargo.lock | 24 ++++++++++++------------ Cargo.toml | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 05fc40b5c3e..7cd00a391e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -149,9 +149,9 @@ dependencies = [ [[package]] name = "asn1-rs" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" +checksum = "607495ec7113b178fbba7a6166a27f99e774359ef4823adbefd756b5b81d7970" dependencies = [ "asn1-rs-derive", "asn1-rs-impl", @@ -159,15 +159,15 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror 1.0.69", + "thiserror 2.0.11", "time", ] [[package]] name = "asn1-rs-derive" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" +checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", @@ -871,9 +871,9 @@ dependencies = [ [[package]] name = "der-parser" -version = "9.0.0" +version = "10.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" +checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" dependencies = [ "asn1-rs", "displaydoc", @@ -1918,9 +1918,9 @@ dependencies = [ [[package]] name = "oid-registry" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9" +checksum = "264c56d1492c13e769662197fb6b94e0a52abe52d27efac374615799a4bf453d" dependencies = [ "asn1-rs", ] @@ -3432,9 +3432,9 @@ dependencies = [ [[package]] name = "x509-parser" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" +checksum = "4569f339c0c402346d4a75a9e39cf8dad310e287eef1ff56d4c68e5067f53460" dependencies = [ "asn1-rs", "data-encoding", @@ -3443,7 +3443,7 @@ dependencies = [ "nom", "oid-registry", "rusticata-macros", - "thiserror 1.0.69", + "thiserror 2.0.11", "time", ] diff --git a/Cargo.toml b/Cargo.toml index b45909d5cc8..ebd8877c1dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,7 +89,7 @@ tokio = { version = "1.34", features = ["io-util", "macros", "net", "rt"] } webpki = { package = "rustls-webpki", version = "0.102.8", features = ["alloc"], default-features = false } webpki-roots = "0.26" x25519-dalek = "2" -x509-parser = "0.16" +x509-parser = "0.17" zeroize = "1.7" zlib-rs = "0.4" From a5d8a6b1edaee920fc89af9f7ab0c5a34cc93b69 Mon Sep 17 00:00:00 2001 From: Paolo Barbolini Date: Wed, 29 Jan 2025 09:14:23 +0100 Subject: [PATCH 030/403] Detect `ChunkVecBuffer::consume` larger than length --- rustls/src/vecbuf.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rustls/src/vecbuf.rs b/rustls/src/vecbuf.rs index 59bd8e99cf6..6a9d6653f17 100644 --- a/rustls/src/vecbuf.rs +++ b/rustls/src/vecbuf.rs @@ -150,12 +150,17 @@ impl ChunkVecBuffer { // buffers while let Some(buf) = self.chunks.front() { if self.prefix_used < buf.len() { - break; + 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` From 200d566e89c763d007d847c5caff1393c697baf6 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 29 Jan 2025 14:05:14 +0000 Subject: [PATCH 031/403] Re-privatize `ChunkVecBuffer::consume()` and defend misuse --- rustls/src/conn.rs | 3 ++- rustls/src/vecbuf.rs | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/rustls/src/conn.rs b/rustls/src/conn.rs index 1e4e755e5a2..43706241452 100644 --- a/rustls/src/conn.rs +++ b/rustls/src/conn.rs @@ -290,7 +290,8 @@ mod connection { } fn consume(&mut self, amt: usize) { - self.received_plaintext.consume(amt) + self.received_plaintext + .consume_first_chunk(amt) } } diff --git a/rustls/src/vecbuf.rs b/rustls/src/vecbuf.rs index 6a9d6653f17..3228e196400 100644 --- a/rustls/src/vecbuf.rs +++ b/rustls/src/vecbuf.rs @@ -142,7 +142,20 @@ impl ChunkVecBuffer { Ok(offs) } - pub(crate) fn consume(&mut self, used: usize) { + 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; From 784b87330788becaad1d932d0c592a4051e9ea0b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 29 Jan 2025 14:36:54 +0000 Subject: [PATCH 032/403] Further defend `ChunkVecBuffer::prefix_used` invariant --- rustls/src/vecbuf.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rustls/src/vecbuf.rs b/rustls/src/vecbuf.rs index 3228e196400..1343db5feca 100644 --- a/rustls/src/vecbuf.rs +++ b/rustls/src/vecbuf.rs @@ -76,6 +76,10 @@ impl ChunkVecBuffer { 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); } @@ -190,6 +194,7 @@ impl ChunkVecBuffer { } let len = cmp::min(bufs.len(), self.chunks.len()); let used = wr.write_vectored(&bufs[..len])?; + assert!(used <= self.len(), "illegal write_vectored return value"); self.consume(used); Ok(used) } From 3bda572a1aa153d5877744d25ca4c425e7a1e3db Mon Sep 17 00:00:00 2001 From: "@brody4hire - C. Jonathan Brody" Date: Thu, 30 Jan 2025 21:37:36 -0500 Subject: [PATCH 033/403] doc: fix tlsclient-mio sample usage in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 18216dc245c..ad5303bd4ed 100644 --- a/README.md +++ b/README.md @@ -181,7 +181,7 @@ 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 -p 8443 localhost +$ echo hello world | cargo run --bin tlsclient-mio -- --cafile test-ca/rsa-2048/ca.cert --port 8443 localhost hello world ^C ``` From cd6af670b7ae7c8da45816155f14177bdaf807ff Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 2 Feb 2025 00:57:20 +0000 Subject: [PATCH 034/403] chore(deps): update seanmiddleditch/gha-setup-ninja action to v6 --- .github/workflows/build.yml | 2 +- .github/workflows/daily-tests.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 39ba757762a..53a01290b45 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,7 +62,7 @@ jobs: - name: Install ninja-build tool for aws-lc-fips-sys on Windows if: runner.os == 'Windows' - uses: seanmiddleditch/gha-setup-ninja@v5 + uses: seanmiddleditch/gha-setup-ninja@v6 - name: Install golang for aws-lc-fips-sys on macos if: runner.os == 'MacOS' diff --git a/.github/workflows/daily-tests.yml b/.github/workflows/daily-tests.yml index e526a2e409d..f3f52c1c66b 100644 --- a/.github/workflows/daily-tests.yml +++ b/.github/workflows/daily-tests.yml @@ -46,7 +46,7 @@ jobs: - name: Install ninja-build tool for aws-lc-fips-sys on Windows if: runner.os == 'Windows' - uses: seanmiddleditch/gha-setup-ninja@v5 + uses: seanmiddleditch/gha-setup-ninja@v6 - name: Build example programs run: cargo build --locked -p rustls-examples @@ -90,7 +90,7 @@ jobs: - name: Install ninja-build tool for aws-lc-fips-sys on Windows if: runner.os == 'Windows' - uses: seanmiddleditch/gha-setup-ninja@v5 + uses: seanmiddleditch/gha-setup-ninja@v6 - name: Check simple client run: cargo run --locked -p rustls-examples --bin simpleclient From 486b6634b2f133af338af405efd8f5dab89d3fd7 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 3 Feb 2025 12:02:44 +0000 Subject: [PATCH 035/403] Use recent & published version of libfuzzer-sys This was pointing at a 2020-era archived repo. --- fuzz/Cargo.lock | 20 ++++++++++++++++---- fuzz/Cargo.toml | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index b56f990d0b5..a0019149e44 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -62,9 +62,9 @@ dependencies = [ [[package]] name = "arbitrary" -version = "0.2.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64cf76cb6e2222ed0ea86b2b0ee2f71c96ec6edd5af42e84d59160e91b836ec4" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" [[package]] name = "cc" @@ -72,6 +72,8 @@ version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" dependencies = [ + "jobserver", + "libc", "shlex", ] @@ -133,6 +135,15 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + [[package]] name = "libc" version = "0.2.169" @@ -141,8 +152,9 @@ checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libfuzzer-sys" -version = "0.1.0" -source = "git+https://github.com/rust-fuzz/libfuzzer-sys.git#35ce7d7177c254b9c798aec171dfe76877d1a20f" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75" dependencies = [ "arbitrary", "cc", diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 89637ad7963..b2884a8e10e 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -10,7 +10,7 @@ cargo-fuzz = true [dependencies] env_logger = "0.11" -libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer-sys.git" } +libfuzzer-sys = "0.4" rustls = { path = "../rustls", default-features = false, features = ["std", "tls12", "custom-provider"] } rustls-fuzzing-provider = { path = "../rustls-fuzzing-provider" } From c913b417953423e264cd155d9dabe501ac75922d Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 3 Feb 2025 17:30:40 +0000 Subject: [PATCH 036/403] fuzzers/deframer: address new clippy finding --- fuzz/fuzzers/deframer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fuzz/fuzzers/deframer.rs b/fuzz/fuzzers/deframer.rs index 2bc230caee3..f4c9ea3ea5b 100644 --- a/fuzz/fuzzers/deframer.rs +++ b/fuzz/fuzzers/deframer.rs @@ -5,4 +5,4 @@ extern crate rustls; use rustls::internal::fuzzing::fuzz_deframer; -fuzz_target!(|bytes: &[u8]| { fuzz_deframer(bytes) }); +fuzz_target!(|bytes: &[u8]| fuzz_deframer(bytes)); From fd929266286daacdc446235e5a880eeebf7f01aa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 18:26:55 +0000 Subject: [PATCH 037/403] build(deps): bump openssl from 0.10.68 to 0.10.70 Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.68 to 0.10.70. - [Release notes](https://github.com/sfackler/rust-openssl/releases) - [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.68...openssl-v0.10.70) --- updated-dependencies: - dependency-name: openssl dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7cd00a391e0..622e2eab337 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1945,9 +1945,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.68" +version = "0.10.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" +checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6" dependencies = [ "bitflags", "cfg-if", @@ -1971,9 +1971,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.104" +version = "0.9.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc" dependencies = [ "cc", "libc", From abf793ed2fd7309e12723688864cf049d85c7c20 Mon Sep 17 00:00:00 2001 From: "@brody4hire - C. Jonathan Brody" Date: Tue, 4 Feb 2025 21:34:23 -0500 Subject: [PATCH 038/403] chore: resolve overindented doc list items --- rustls/src/client/client_conn.rs | 2 +- rustls/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index c2540be6308..c7effea16fa 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -151,7 +151,7 @@ pub trait ResolvesClientCert: fmt::Debug + Send + Sync { /// /// * [`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. +/// 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()`]. diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 590d1776916..df48c4a1b62 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -300,7 +300,7 @@ //! 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`. +//! 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 From 6ee9aca6a5192153b319ab81d8e433abe4ee0b65 Mon Sep 17 00:00:00 2001 From: "@brody4hire - C. Jonathan Brody" Date: Tue, 4 Feb 2025 23:00:39 -0500 Subject: [PATCH 039/403] chore(ci): fix formatting of Taplo job --- .github/workflows/build.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 53a01290b45..51cde8db2cd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -513,18 +513,18 @@ jobs: run: cargo check-external-types taplo: - name: Taplo - runs-on: ubuntu-latest - steps: - - name: Checkout sources - uses: actions/checkout@v4 - with: - persist-credentials: false - - - name: Install rust toolchain - uses: dtolnay/rust-toolchain@stable - - run: cargo install taplo-cli --locked - - run: taplo format --check + name: Taplo + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Install rust toolchain + uses: dtolnay/rust-toolchain@stable + - run: cargo install taplo-cli --locked + - run: taplo format --check openssl-tests: name: Run openssl-tests From d97b319a24a07495cfacd4edd56b318430b0cc16 Mon Sep 17 00:00:00 2001 From: "@brody4hire - C. Jonathan Brody" Date: Tue, 4 Feb 2025 21:39:09 -0500 Subject: [PATCH 040/403] doc: minor crate feature doc cleanup --- README.md | 6 +++--- rustls/src/crypto/mod.rs | 2 +- rustls/src/lib.rs | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index ad5303bd4ed..3a66ee9a9ed 100644 --- a/README.md +++ b/README.md @@ -78,10 +78,10 @@ builder types. See the [`crypto::CryptoProvider`] documentation for more details #### Built-in providers -Rustls ships with two built-in providers controlled with associated feature flags: +Rustls ships with two built-in providers controlled by associated crate features: -* [`aws-lc-rs`] - enabled by default, available with the `aws_lc_rs` feature flag enabled. -* [`ring`] - available with the `ring` feature flag enabled. +* [`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. diff --git a/rustls/src/crypto/mod.rs b/rustls/src/crypto/mod.rs index 6a7db7a4009..13b5de8696a 100644 --- a/rustls/src/crypto/mod.rs +++ b/rustls/src/crypto/mod.rs @@ -61,7 +61,7 @@ pub use crate::suites::CipherSuiteCommon; /// This crate comes with two built-in options, provided as /// `CryptoProvider` structures: /// -/// - [`crypto::aws_lc_rs::default_provider`]: (behind the `aws_lc_rs` feature, +/// - [`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 diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index df48c4a1b62..7cf5b48b556 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -44,10 +44,10 @@ //! //! #### Built-in providers //! -//! Rustls ships with two built-in providers controlled with associated feature flags: +//! Rustls ships with two built-in providers controlled by associated crate features: //! -//! * [`aws-lc-rs`] - enabled by default, available with the `aws_lc_rs` feature flag enabled. -//! * [`ring`] - available with the `ring` feature flag enabled. +//! * [`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. @@ -286,8 +286,8 @@ //! 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` feature, which makes the rustls crate depend +//! - `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`]. //! From 931b75b770fc900f14c4b3db69a06a27e392a386 Mon Sep 17 00:00:00 2001 From: holodorum Date: Thu, 30 Jan 2025 10:51:30 +0100 Subject: [PATCH 041/403] Refactor Raw Key OpenSSL and API tests --- openssl-tests/src/raw_key_openssl_interop.rs | 54 +++++++++++-------- rustls/tests/api.rs | 57 ++++++++++++++++++-- 2 files changed, 86 insertions(+), 25 deletions(-) diff --git a/openssl-tests/src/raw_key_openssl_interop.rs b/openssl-tests/src/raw_key_openssl_interop.rs index f8a9bfb8890..58abb8b5a84 100644 --- a/openssl-tests/src/raw_key_openssl_interop.rs +++ b/openssl-tests/src/raw_key_openssl_interop.rs @@ -418,36 +418,46 @@ mod tests { .spawn() .expect("Failed to execute OpenSSL client"); - let mut stdin = openssl_client.stdin.take().unwrap(); - let mut stdout = openssl_client.stdout.take().unwrap(); + let stdin = openssl_client.stdin.take().unwrap(); + let stdout = openssl_client.stdout.take().unwrap(); + let received_server_msg = + process_openssl_client_interaction(stdin, stdout, "Hello, from openssl client!"); + + assert!(received_server_msg); + assert_eq!(server_thread.join().unwrap(), "Hello, from openssl client!"); + openssl_client.wait().unwrap(); + } + + fn process_openssl_client_interaction( + mut stdin: std::process::ChildStdin, + mut stdout: std::process::ChildStdout, + message: &str, + ) -> bool { let mut stdout_buf = [0; 1024]; let mut openssl_stdout = String::new(); - let mut received_server_msg = false; + loop { - match stdout.read(&mut stdout_buf) { + let len = match stdout.read(&mut stdout_buf) { Ok(0) => break, - Ok(len) => { - let read = &stdout_buf[..len]; - - std::io::stdout() - .write_all(read) - .unwrap(); - openssl_stdout.push_str(&String::from_utf8_lossy(read)); - if openssl_stdout.contains("Hello from the server") { - received_server_msg = true; - stdin - .write_all(b"Hello, from openssl client!") - .expect("Failed to write to stdin"); - break; - } - } + Ok(len) => len, Err(e) => panic!("Error reading from OpenSSL stdin: {e:?}"), + }; + + let read = &stdout_buf[..len]; + std::io::stdout() + .write_all(read) + .unwrap(); + openssl_stdout.push_str(&String::from_utf8_lossy(read)); + + if openssl_stdout.contains("Hello from the server") { + stdin + .write_all(message.as_bytes()) + .expect("Failed to write to stdin"); + return true; } } - assert!(received_server_msg); - assert_eq!(server_thread.join().unwrap(), "Hello, from openssl client!"); - openssl_client.wait().unwrap(); + false } #[test] diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 0989082d2f0..ee554c10140 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -164,10 +164,10 @@ mod test_raw_keys { } #[test] - fn incorrectly_alter_client_hello() { + fn client_sends_x509_and_rpk_server_does_not_support() { for kt in ALL_KEY_TYPES { let client_config = Arc::new(make_client_config(*kt)); - let server_config_rpk = Arc::new(make_server_config_with_raw_key_support(*kt)); + let server_config_rpk = Arc::new(make_server_config(*kt)); // Alter Client Hello client certificate extension let (client, server) = make_pair_for_arc_configs(&client_config, &server_config_rpk); @@ -175,7 +175,11 @@ mod test_raw_keys { client, |_: &mut Message| -> Altered { Altered::InPlace }, |msg: &mut Message| { - alter_client_hello_message(msg, Some(&vec![CertificateType::X509]), None) + alter_client_hello_message( + msg, + Some(&vec![CertificateType::X509, CertificateType::RawPublicKey]), + None, + ) }, server, ); @@ -211,6 +215,53 @@ mod test_raw_keys { } } + #[test] + fn alter_client_hello() { + connect_with_altered_certificate_type_extension( + true, + Some(&vec![CertificateType::X509]), + None, + Err(ErrorFromPeer::Server(Error::PeerIncompatible( + PeerIncompatible::IncorrectCertificateTypeExtension, + ))), + ); + connect_with_altered_certificate_type_extension( + true, + None, + Some(&vec![CertificateType::X509]), + Err(ErrorFromPeer::Server(Error::PeerIncompatible( + PeerIncompatible::IncorrectCertificateTypeExtension, + ))), + ); + } + + fn connect_with_altered_certificate_type_extension( + server_requires_raw_keys: bool, + server_cert_types: Option<&Vec>, + client_cert_types: Option<&Vec>, + expected_result: Result<(), ErrorFromPeer>, + ) { + for kt in ALL_KEY_TYPES { + let client_config = Arc::new(make_client_config(*kt)); + let server_config_rpk = match server_requires_raw_keys { + true => Arc::new(make_server_config_with_raw_key_support(*kt)), + false => Arc::new(make_server_config(*kt)), + }; + + // Alter Client Hello client certificate extension + let (client, server) = make_pair_for_arc_configs(&client_config, &server_config_rpk); + let cert_altered = do_handshake_altered( + client, + |_: &mut Message| -> Altered { Altered::InPlace }, + |msg: &mut Message| { + alter_client_hello_message(msg, server_cert_types, client_cert_types) + }, + server, + ); + assert_eq!(cert_altered, expected_result) + } + } + #[test] fn incorrectly_alter_server_hello() { for kt in ALL_KEY_TYPES { From fa3e31746d5721b60df4d407c5df346d4ec7e423 Mon Sep 17 00:00:00 2001 From: holodorum Date: Tue, 10 Dec 2024 17:43:52 +0100 Subject: [PATCH 042/403] Fix RFC 7250 Compliance (#2257) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated logic to validate `client_certificate_type_extension` and `server_certificate_type_extension` in the ClientHello. Added an openssl interop test to replicate the issue and verify it's handled correctly. Co-authored-by: Adolfo Ochagavía --- openssl-tests/src/raw_key_openssl_interop.rs | 53 ++++++++++++ rustls/src/client/hs.rs | 77 +++++++++-------- rustls/src/common_state.rs | 33 +------ rustls/src/server/hs.rs | 90 ++++++++++---------- rustls/tests/api.rs | 54 +----------- 5 files changed, 143 insertions(+), 164 deletions(-) diff --git a/openssl-tests/src/raw_key_openssl_interop.rs b/openssl-tests/src/raw_key_openssl_interop.rs index 58abb8b5a84..6726244818e 100644 --- a/openssl-tests/src/raw_key_openssl_interop.rs +++ b/openssl-tests/src/raw_key_openssl_interop.rs @@ -329,6 +329,9 @@ mod tests { use std::sync::mpsc::channel; use std::thread; + use rustls::pki_types::pem::PemObject; + use rustls::pki_types::{CertificateDer, PrivateKeyDer}; + use super::{client, server}; use crate::utils::verify_openssl3_available; @@ -385,6 +388,56 @@ mod tests { } } + #[test] + fn test_rust_x509_server_with_openssl_raw_key_and_x509_client() { + verify_openssl3_available(); + + let listener = tcp_listener(); + let port = listener.local_addr().unwrap().port(); + + let cert_file = SERVER_CERT_KEY_FILE; + let private_key_file = SERVER_PRIV_KEY_FILE; + + let certs = CertificateDer::pem_file_iter(cert_file) + .unwrap() + .map(|cert| cert.unwrap()) + .collect(); + let private_key = PrivateKeyDer::from_pem_file(private_key_file).unwrap(); + let config = rustls::ServerConfig::builder() + .with_no_client_auth() + .with_single_cert(certs, private_key) + .unwrap(); + let server_thread = thread::spawn(move || { + server::run_server(config, listener).expect("failed to run server to completion") + }); + + // Start the OpenSSL client + let mut openssl_client = Command::new("openssl") + .arg("s_client") + .arg("-connect") + .arg(format!("[::]:{:?}", port)) + .arg("-enable_client_rpk") + .arg("-key") + .arg(CLIENT_PRIV_KEY_FILE) + .arg("-cert") + .arg(CLIENT_CERT_KEY_FILE) + .arg("-tls1_3") + .arg("-debug") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .expect("Failed to execute OpenSSL client"); + + let stdin = openssl_client.stdin.take().unwrap(); + let stdout = openssl_client.stdout.take().unwrap(); + let received_server_msg = + process_openssl_client_interaction(stdin, stdout, "Hello, from openssl client!"); + + assert!(received_server_msg); + assert_eq!(server_thread.join().unwrap(), "Hello, from openssl client!"); + openssl_client.wait().unwrap(); + } + #[test] fn test_rust_server_with_openssl_client() { verify_openssl3_available(); diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 2ad8f1cc67a..c5f30bc2f71 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -16,9 +16,7 @@ use crate::client::client_conn::ClientConnectionData; use crate::client::common::ClientHelloDetails; use crate::client::ech::EchState; use crate::client::{tls13, ClientConfig, EchMode, EchStatus}; -use crate::common_state::{ - CommonState, HandshakeKind, KxState, RawKeyNegotationResult, RawKeyNegotiationParams, State, -}; +use crate::common_state::{CommonState, HandshakeKind, KxState, State}; use crate::conn::ConnectionRandoms; use crate::crypto::{ActiveKeyExchange, KeyExchangeAlgorithm}; use crate::enums::{AlertDescription, CipherSuite, ContentType, HandshakeType, ProtocolVersion}; @@ -701,46 +699,30 @@ pub(super) fn process_server_cert_type_extension( common: &mut CommonState, config: &ClientConfig, server_cert_extension: Option<&CertificateType>, -) -> Result<(), Error> { - let requires_server_rpk = config - .verifier - .requires_raw_public_keys(); - let server_offers_rpk = matches!(server_cert_extension, Some(CertificateType::RawPublicKey)); - - let raw_key_negotation_params = RawKeyNegotiationParams { - peer_supports_raw_key: server_offers_rpk, - local_expects_raw_key: requires_server_rpk, - extension_type: ExtensionType::ServerCertificateType, - }; - match raw_key_negotation_params.validate_raw_key_negotiation() { - RawKeyNegotationResult::Err(err) => { - Err(common.send_fatal_alert(AlertDescription::HandshakeFailure, err)) - } - _ => Ok(()), - } +) -> Result, 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<(), Error> { - let requires_client_rpk = config - .client_auth_cert_resolver - .only_raw_public_keys(); - let server_allows_rpk = matches!(client_cert_extension, Some(CertificateType::RawPublicKey)); - - let raw_key_negotation_params = RawKeyNegotiationParams { - peer_supports_raw_key: server_allows_rpk, - local_expects_raw_key: requires_client_rpk, - extension_type: ExtensionType::ClientCertificateType, - }; - match raw_key_negotation_params.validate_raw_key_negotiation() { - RawKeyNegotationResult::Err(err) => { - Err(common.send_fatal_alert(AlertDescription::HandshakeFailure, err)) - } - _ => Ok(()), - } +) -> Result, Error> { + process_cert_type_extension( + common, + config + .client_auth_cert_resolver + .only_raw_public_keys(), + client_cert_extension.copied(), + ExtensionType::ClientCertificateType, + ) } impl State for ExpectServerHello { @@ -1201,6 +1183,27 @@ impl State for ExpectServerHelloOrHelloRetryRequest { } } +fn process_cert_type_extension( + common: &mut CommonState, + client_expects: bool, + server_negotiated: Option, + extension_type: ExtensionType, +) -> Result, 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), + } +} + enum ClientSessionValue { Tls13(persist::Tls13ClientSessionValue), #[cfg(feature = "tls12")] diff --git a/rustls/src/common_state.rs b/rustls/src/common_state.rs index 9b9ab3f7f4c..3ff4609df8c 100644 --- a/rustls/src/common_state.rs +++ b/rustls/src/common_state.rs @@ -11,7 +11,7 @@ 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, ExtensionType, KeyUpdateRequest}; +use crate::msgs::enums::{AlertLevel, KeyUpdateRequest}; use crate::msgs::fragmenter::MessageFragmenter; use crate::msgs::handshake::{CertificateChain, HandshakeMessagePayload}; use crate::msgs::message::{ @@ -24,7 +24,7 @@ use crate::suites::{PartiallyExtractedSecrets, SupportedCipherSuite}; use crate::tls12::ConnectionSecrets; use crate::unbuffered::{EncryptError, InsufficientSizeError}; use crate::vecbuf::ChunkVecBuffer; -use crate::{quic, record_layer, PeerIncompatible}; +use crate::{quic, record_layer}; /// Connection state common to both client and server connections. pub struct CommonState { @@ -900,35 +900,6 @@ enum Limit { No, } -#[derive(Debug)] -pub(super) struct RawKeyNegotiationParams { - pub(super) peer_supports_raw_key: bool, - pub(super) local_expects_raw_key: bool, - pub(super) extension_type: ExtensionType, -} - -impl RawKeyNegotiationParams { - pub(super) fn validate_raw_key_negotiation(&self) -> RawKeyNegotationResult { - match (self.local_expects_raw_key, self.peer_supports_raw_key) { - (true, true) => RawKeyNegotationResult::Negotiated(self.extension_type), - (false, false) => RawKeyNegotationResult::NotNegotiated, - (true, false) => RawKeyNegotationResult::Err(Error::PeerIncompatible( - PeerIncompatible::IncorrectCertificateTypeExtension, - )), - (false, true) => RawKeyNegotationResult::Err(Error::PeerIncompatible( - PeerIncompatible::UnsolicitedCertificateTypeExtension, - )), - } - } -} - -#[derive(Debug)] -pub(crate) enum RawKeyNegotationResult { - Negotiated(ExtensionType), - NotNegotiated, - Err(Error), -} - /// Tracking technically-allowed protocol actions /// that we limit to avoid denial-of-service vectors. struct TemperCounters { diff --git a/rustls/src/server/hs.rs b/rustls/src/server/hs.rs index b50f00f3e44..5844d732ed9 100644 --- a/rustls/src/server/hs.rs +++ b/rustls/src/server/hs.rs @@ -7,9 +7,7 @@ use pki_types::DnsName; use super::server_conn::ServerConnectionData; #[cfg(feature = "tls12")] use super::tls12; -use crate::common_state::{ - KxState, Protocol, RawKeyNegotationResult, RawKeyNegotiationParams, State, -}; +use crate::common_state::{KxState, Protocol, State}; use crate::conn::ConnectionRandoms; use crate::crypto::SupportedKxGroup; use crate::enums::{ @@ -213,22 +211,17 @@ impl ExtensionProcessing { config: &ServerConfig, cx: &mut ServerContext<'_>, ) -> Result<(), Error> { - let requires_server_rpk = config - .cert_resolver - .only_raw_public_keys(); - let client_allows_rpk = hello + let client_supports = hello .server_certificate_extension() - .map(|certificate_types| certificate_types.contains(&CertificateType::RawPublicKey)) - .unwrap_or(false); - - let raw_key_negotation_params = RawKeyNegotiationParams { - peer_supports_raw_key: client_allows_rpk, - local_expects_raw_key: requires_server_rpk, - extension_type: ExtensionType::ServerCertificateType, - }; + .map(|certificate_types| certificate_types.to_vec()) + .unwrap_or_default(); self.process_cert_type_extension( - raw_key_negotation_params.validate_raw_key_negotiation(), + client_supports, + config + .cert_resolver + .only_raw_public_keys(), + ExtensionType::ServerCertificateType, cx, ) } @@ -239,52 +232,63 @@ impl ExtensionProcessing { config: &ServerConfig, cx: &mut ServerContext<'_>, ) -> Result<(), Error> { - let requires_client_rpk = config - .verifier - .requires_raw_public_keys(); - let client_offers_rpk = hello + let client_supports = hello .client_certificate_extension() - .map(|certificate_types| certificate_types.contains(&CertificateType::RawPublicKey)) - .unwrap_or(false); + .map(|certificate_types| certificate_types.to_vec()) + .unwrap_or_default(); - let raw_key_negotation_params = RawKeyNegotiationParams { - peer_supports_raw_key: client_offers_rpk, - local_expects_raw_key: requires_client_rpk, - extension_type: ExtensionType::ClientCertificateType, - }; self.process_cert_type_extension( - raw_key_negotation_params.validate_raw_key_negotiation(), + client_supports, + config + .verifier + .requires_raw_public_keys(), + ExtensionType::ClientCertificateType, cx, ) } fn process_cert_type_extension( &mut self, - raw_key_negotiation_result: RawKeyNegotationResult, + client_supports: Vec, + requires_raw_keys: bool, + extension_type: ExtensionType, cx: &mut ServerContext<'_>, ) -> Result<(), Error> { - match raw_key_negotiation_result { - RawKeyNegotationResult::Negotiated(ExtensionType::ClientCertificateType) => { + 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.exts - .push(ServerExtension::ClientCertType( - CertificateType::RawPublicKey, - )); + .push(ServerExtension::ClientCertType(cert_type)); } - RawKeyNegotationResult::Negotiated(ExtensionType::ServerCertificateType) => { + Ok((ExtensionType::ServerCertificateType, cert_type)) => { self.exts - .push(ServerExtension::ServerCertType( - CertificateType::RawPublicKey, - )); + .push(ServerExtension::ServerCertType(cert_type)); } - RawKeyNegotationResult::Err(err) => { + Err(err) => { return Err(cx .common .send_fatal_alert(AlertDescription::HandshakeFailure, err)); } - RawKeyNegotationResult::NotNegotiated => {} - RawKeyNegotationResult::Negotiated(_) => unreachable!( - "The extension type should only ever be ClientCertificateType or ServerCertificateType" - ), + Ok((_, _)) => unreachable!(), } Ok(()) } diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index ee554c10140..fe45606dc86 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -127,7 +127,7 @@ mod test_raw_keys { assert_eq!( err, ErrorFromPeer::Server(Error::PeerIncompatible( - PeerIncompatible::UnsolicitedCertificateTypeExtension + PeerIncompatible::IncorrectCertificateTypeExtension )) ) } @@ -163,58 +163,6 @@ mod test_raw_keys { } } - #[test] - fn client_sends_x509_and_rpk_server_does_not_support() { - for kt in ALL_KEY_TYPES { - let client_config = Arc::new(make_client_config(*kt)); - let server_config_rpk = Arc::new(make_server_config(*kt)); - - // Alter Client Hello client certificate extension - let (client, server) = make_pair_for_arc_configs(&client_config, &server_config_rpk); - let server_cert_altered = do_handshake_altered( - client, - |_: &mut Message| -> Altered { Altered::InPlace }, - |msg: &mut Message| { - alter_client_hello_message( - msg, - Some(&vec![CertificateType::X509, CertificateType::RawPublicKey]), - None, - ) - }, - server, - ); - match server_cert_altered { - Ok(_) => unreachable!("Expected error because server cert is altered"), - Err(err) => assert_eq!( - err, - ErrorFromPeer::Server(Error::PeerIncompatible( - PeerIncompatible::IncorrectCertificateTypeExtension - )) - ), - } - - // Alter Server Hello server certificate extension - let (client, server) = make_pair_for_arc_configs(&client_config, &server_config_rpk); - let client_cert_altered = do_handshake_altered( - client, - |_: &mut Message| -> Altered { Altered::InPlace }, - |msg: &mut Message| { - alter_client_hello_message(msg, None, Some(&vec![CertificateType::X509])) - }, - server, - ); - match client_cert_altered { - Ok(_) => unreachable!("Expected error because server cert is altered"), - Err(err) => assert_eq!( - err, - ErrorFromPeer::Server(Error::PeerIncompatible( - PeerIncompatible::IncorrectCertificateTypeExtension - )) - ), - } - } - } - #[test] fn alter_client_hello() { connect_with_altered_certificate_type_extension( From 530966772a29d7a4b2a54710d2f6d8f4bbbbea60 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 21:53:23 +0000 Subject: [PATCH 043/403] build(deps): bump hickory-proto from 0.25.0-alpha.4 to 0.25.0-alpha.5 Bumps [hickory-proto](https://github.com/hickory-dns/hickory-dns) from 0.25.0-alpha.4 to 0.25.0-alpha.5. - [Release notes](https://github.com/hickory-dns/hickory-dns/releases) - [Changelog](https://github.com/hickory-dns/hickory-dns/blob/main/CHANGELOG.md) - [Commits](https://github.com/hickory-dns/hickory-dns/compare/v0.25.0-alpha.4...v0.25.0-alpha.5) --- updated-dependencies: - dependency-name: hickory-proto dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Cargo.lock | 146 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 109 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 622e2eab337..c02d53002ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -445,7 +445,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools 0.10.5", "lazy_static", "lazycell", "log", @@ -803,7 +803,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", "subtle", "zeroize", ] @@ -955,7 +955,7 @@ dependencies = [ "group", "hkdf", "pkcs8", - "rand_core", + "rand_core 0.6.4", "sec1", "subtle", "zeroize", @@ -1051,7 +1051,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -1190,7 +1190,19 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets 0.52.6", ] [[package]] @@ -1234,7 +1246,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -1296,9 +1308,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hickory-proto" -version = "0.25.0-alpha.4" +version = "0.25.0-alpha.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d063c0692ee669aa6d261988aa19ca5510f1cc40e4f211024f50c888499a35d7" +checksum = "1d00147af6310f4392a31680db52a3ed45a2e0f68eb18e8c3fe5537ecc96d9e2" dependencies = [ "async-recursion", "async-trait", @@ -1314,7 +1326,7 @@ dependencies = [ "idna", "ipnet", "once_cell", - "rand", + "rand 0.9.0", "rustls 0.23.21", "thiserror 2.0.11", "tinyvec", @@ -1338,7 +1350,7 @@ dependencies = [ "lru-cache", "once_cell", "parking_lot", - "rand", + "rand 0.8.5", "resolv-conf", "rustls 0.23.21", "smallvec", @@ -1404,7 +1416,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c3f1ae0a26c18d6469a70db1217136056261c4a244b09a755bc60bd4e055b67" dependencies = [ - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -1419,8 +1431,8 @@ dependencies = [ "hpke-rs-crypto", "p256", "p384", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", "sha2", "x25519-dalek", ] @@ -1644,15 +1656,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.14.0" @@ -1724,7 +1727,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] @@ -1830,7 +1833,7 @@ checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] @@ -1866,7 +1869,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand", + "rand 0.8.5", "smallvec", "zeroize", ] @@ -2182,7 +2185,7 @@ version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -2235,8 +2238,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.0", + "zerocopy 0.8.17", ] [[package]] @@ -2246,7 +2260,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.0", ] [[package]] @@ -2255,7 +2279,17 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.15", +] + +[[package]] +name = "rand_core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" +dependencies = [ + "getrandom 0.3.1", + "zerocopy 0.8.17", ] [[package]] @@ -2357,7 +2391,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.15", "libc", "spin", "untrusted", @@ -2377,7 +2411,7 @@ dependencies = [ "num-traits", "pkcs1", "pkcs8", - "rand_core", + "rand_core 0.6.4", "sha2", "signature", "spki", @@ -2579,7 +2613,7 @@ dependencies = [ "hpke-rs-rust-crypto", "p256", "pkcs8", - "rand_core", + "rand_core 0.6.4", "rcgen", "rsa", "rustls 0.23.22", @@ -2716,7 +2750,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -3109,6 +3143,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" version = "0.2.100" @@ -3239,7 +3282,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] @@ -3406,6 +3449,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags", +] + [[package]] name = "write16" version = "1.0.0" @@ -3425,7 +3477,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ "curve25519-dalek", - "rand_core", + "rand_core 0.6.4", "serde", "zeroize", ] @@ -3487,7 +3539,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "byteorder", - "zerocopy-derive", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa91407dacce3a68c56de03abe2760159582b846c6a4acd2f456618087f12713" +dependencies = [ + "zerocopy-derive 0.8.17", ] [[package]] @@ -3501,6 +3562,17 @@ dependencies = [ "syn 2.0.96", ] +[[package]] +name = "zerocopy-derive" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06718a168365cad3d5ff0bb133aad346959a2074bd4a85c121255a11304a8626" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "zerofrom" version = "0.1.5" From f7beeecc9f1a87b3e02f87efe359e924c404873b Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 11 Feb 2025 10:14:29 +0100 Subject: [PATCH 044/403] server: rename AlwaysResolvesChain to SingleCertAndKey --- rustls/src/server/builder.rs | 4 ++-- rustls/src/server/handy.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/rustls/src/server/builder.rs b/rustls/src/server/builder.rs index fb15e807e7b..a8c4220a389 100644 --- a/rustls/src/server/builder.rs +++ b/rustls/src/server/builder.rs @@ -79,7 +79,7 @@ impl ConfigBuilder { Err(err) => return Err(err), } - let resolver = handy::AlwaysResolvesChain::new(certified_key); + let resolver = handy::SingleCertAndKey::new(certified_key); Ok(self.with_cert_resolver(Arc::new(resolver))) } @@ -114,7 +114,7 @@ impl ConfigBuilder { Err(err) => return Err(err), } - let resolver = handy::AlwaysResolvesChain::new_with_extras(certified_key, ocsp); + let resolver = handy::SingleCertAndKey::new_with_extras(certified_key, ocsp); Ok(self.with_cert_resolver(Arc::new(resolver))) } diff --git a/rustls/src/server/handy.rs b/rustls/src/server/handy.rs index be26b06537a..e1d4af76fe3 100644 --- a/rustls/src/server/handy.rs +++ b/rustls/src/server/handy.rs @@ -168,9 +168,9 @@ impl server::ProducesTickets for NeverProducesTickets { /// Something which always resolves to the same cert chain. #[derive(Debug)] -pub(super) struct AlwaysResolvesChain(Arc); +pub(super) struct SingleCertAndKey(Arc); -impl AlwaysResolvesChain { +impl SingleCertAndKey { /// Creates an `AlwaysResolvesChain`, using the supplied `CertifiedKey`. pub(super) fn new(certified_key: sign::CertifiedKey) -> Self { Self(Arc::new(certified_key)) @@ -193,7 +193,7 @@ impl AlwaysResolvesChain { } } -impl server::ResolvesServerCert for AlwaysResolvesChain { +impl server::ResolvesServerCert for SingleCertAndKey { fn resolve(&self, _client_hello: ClientHello<'_>) -> Option> { Some(Arc::clone(&self.0)) } From 27551e14f434683df0400a6e914d0bffe6525db2 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 11 Feb 2025 13:09:07 +0100 Subject: [PATCH 045/403] Move SingleCertAndKey to crypto::signer --- rustls/src/crypto/signer.rs | 35 ++++++++++++++++++++++++++++++++++- rustls/src/lib.rs | 1 + rustls/src/server/builder.rs | 8 ++++---- rustls/src/server/handy.rs | 33 --------------------------------- 4 files changed, 39 insertions(+), 38 deletions(-) diff --git a/rustls/src/crypto/signer.rs b/rustls/src/crypto/signer.rs index 9f4edbb2546..495eaebb94e 100644 --- a/rustls/src/crypto/signer.rs +++ b/rustls/src/crypto/signer.rs @@ -6,7 +6,7 @@ use pki_types::{AlgorithmIdentifier, CertificateDer, SubjectPublicKeyInfoDer}; use crate::enums::{SignatureAlgorithm, SignatureScheme}; use crate::error::{Error, InconsistentKeys}; -use crate::server::ParsedCertificate; +use crate::server::{ClientHello, ParsedCertificate, ResolvesServerCert}; use crate::sync::Arc; use crate::x509; @@ -85,6 +85,39 @@ pub trait Signer: Debug + Send + Sync { fn scheme(&self) -> SignatureScheme; } +/// Something which always resolves to the same cert chain. +#[derive(Debug)] +pub(crate) struct SingleCertAndKey(Arc); + +impl SingleCertAndKey { + /// Creates an `AlwaysResolvesChain`, using the supplied `CertifiedKey`. + pub(crate) fn new(certified_key: CertifiedKey) -> Self { + Self(Arc::new(certified_key)) + } + + /// Creates an `AlwaysResolvesChain`, using the supplied `CertifiedKey` and OCSP response. + /// + /// If non-empty, the given OCSP response is attached. + pub(crate) fn new_with_extras(certified_key: CertifiedKey, ocsp: Vec) -> Self { + let mut r = Self::new(certified_key); + + { + let cert = Arc::make_mut(&mut r.0); + if !ocsp.is_empty() { + cert.ocsp = Some(ocsp); + } + } + + r + } +} + +impl ResolvesServerCert for SingleCertAndKey { + fn resolve(&self, _client_hello: ClientHello<'_>) -> Option> { + Some(Arc::clone(&self.0)) + } +} + /// A packaged-together certificate chain, matching `SigningKey` and /// optional stapled OCSP response. /// diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 7cf5b48b556..5a9e7e08da0 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -668,6 +668,7 @@ pub mod pki_types { /// Message signing interfaces. pub mod sign { + pub(crate) use crate::crypto::signer::SingleCertAndKey; pub use crate::crypto::signer::{CertifiedKey, Signer, SigningKey}; } diff --git a/rustls/src/server/builder.rs b/rustls/src/server/builder.rs index a8c4220a389..b9e619d77cd 100644 --- a/rustls/src/server/builder.rs +++ b/rustls/src/server/builder.rs @@ -3,10 +3,10 @@ use core::marker::PhantomData; use pki_types::{CertificateDer, PrivateKeyDer}; +use super::{handy, ResolvesServerCert, ServerConfig}; use crate::builder::{ConfigBuilder, WantsVerifier}; use crate::error::Error; -use crate::server::{handy, ResolvesServerCert, ServerConfig}; -use crate::sign::CertifiedKey; +use crate::sign::{CertifiedKey, SingleCertAndKey}; use crate::sync::Arc; use crate::verify::{ClientCertVerifier, NoClientAuth}; use crate::{compress, versions, InconsistentKeys, NoKeyLog}; @@ -79,7 +79,7 @@ impl ConfigBuilder { Err(err) => return Err(err), } - let resolver = handy::SingleCertAndKey::new(certified_key); + let resolver = SingleCertAndKey::new(certified_key); Ok(self.with_cert_resolver(Arc::new(resolver))) } @@ -114,7 +114,7 @@ impl ConfigBuilder { Err(err) => return Err(err), } - let resolver = handy::SingleCertAndKey::new_with_extras(certified_key, ocsp); + let resolver = SingleCertAndKey::new_with_extras(certified_key, ocsp); Ok(self.with_cert_resolver(Arc::new(resolver))) } diff --git a/rustls/src/server/handy.rs b/rustls/src/server/handy.rs index e1d4af76fe3..a3467d7a4e6 100644 --- a/rustls/src/server/handy.rs +++ b/rustls/src/server/handy.rs @@ -166,39 +166,6 @@ impl server::ProducesTickets for NeverProducesTickets { } } -/// Something which always resolves to the same cert chain. -#[derive(Debug)] -pub(super) struct SingleCertAndKey(Arc); - -impl SingleCertAndKey { - /// Creates an `AlwaysResolvesChain`, using the supplied `CertifiedKey`. - pub(super) fn new(certified_key: sign::CertifiedKey) -> Self { - Self(Arc::new(certified_key)) - } - - /// Creates an `AlwaysResolvesChain`, using the supplied `CertifiedKey` and OCSP response. - /// - /// If non-empty, the given OCSP response is attached. - pub(super) fn new_with_extras(certified_key: sign::CertifiedKey, ocsp: Vec) -> Self { - let mut r = Self::new(certified_key); - - { - let cert = Arc::make_mut(&mut r.0); - if !ocsp.is_empty() { - cert.ocsp = Some(ocsp); - } - } - - r - } -} - -impl server::ResolvesServerCert for SingleCertAndKey { - fn resolve(&self, _client_hello: ClientHello<'_>) -> Option> { - Some(Arc::clone(&self.0)) - } -} - /// An exemplar `ResolvesServerCert` implementation that always resolves to a single /// [RFC 7250] raw public key. /// From 82c3c2d17962bc2d86ab3fa2e46013c45814b19e Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 11 Feb 2025 13:13:41 +0100 Subject: [PATCH 046/403] crypto: use From impl to construct SingleCertAndKey --- rustls/src/crypto/signer.rs | 13 +++++++------ rustls/src/server/builder.rs | 3 +-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/rustls/src/crypto/signer.rs b/rustls/src/crypto/signer.rs index 495eaebb94e..bdff9027f57 100644 --- a/rustls/src/crypto/signer.rs +++ b/rustls/src/crypto/signer.rs @@ -90,16 +90,11 @@ pub trait Signer: Debug + Send + Sync { pub(crate) struct SingleCertAndKey(Arc); impl SingleCertAndKey { - /// Creates an `AlwaysResolvesChain`, using the supplied `CertifiedKey`. - pub(crate) fn new(certified_key: CertifiedKey) -> Self { - Self(Arc::new(certified_key)) - } - /// Creates an `AlwaysResolvesChain`, using the supplied `CertifiedKey` and OCSP response. /// /// If non-empty, the given OCSP response is attached. pub(crate) fn new_with_extras(certified_key: CertifiedKey, ocsp: Vec) -> Self { - let mut r = Self::new(certified_key); + let mut r = Self::from(certified_key); { let cert = Arc::make_mut(&mut r.0); @@ -112,6 +107,12 @@ impl SingleCertAndKey { } } +impl From for SingleCertAndKey { + fn from(certified_key: CertifiedKey) -> Self { + Self(Arc::new(certified_key)) + } +} + impl ResolvesServerCert for SingleCertAndKey { fn resolve(&self, _client_hello: ClientHello<'_>) -> Option> { Some(Arc::clone(&self.0)) diff --git a/rustls/src/server/builder.rs b/rustls/src/server/builder.rs index b9e619d77cd..e9221f458fc 100644 --- a/rustls/src/server/builder.rs +++ b/rustls/src/server/builder.rs @@ -79,8 +79,7 @@ impl ConfigBuilder { Err(err) => return Err(err), } - let resolver = SingleCertAndKey::new(certified_key); - Ok(self.with_cert_resolver(Arc::new(resolver))) + Ok(self.with_cert_resolver(Arc::new(SingleCertAndKey::from(certified_key)))) } /// Sets a single certificate chain, matching private key and optional OCSP From be2865ad078ee03b37aa59fde26d8c9e127d8f94 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 11 Feb 2025 13:15:19 +0100 Subject: [PATCH 047/403] crypto: simplify SingleCertAndKey construction with OCSP --- rustls/src/crypto/signer.rs | 18 ------------------ rustls/src/server/builder.rs | 6 +++--- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/rustls/src/crypto/signer.rs b/rustls/src/crypto/signer.rs index bdff9027f57..ea6608efdeb 100644 --- a/rustls/src/crypto/signer.rs +++ b/rustls/src/crypto/signer.rs @@ -89,24 +89,6 @@ pub trait Signer: Debug + Send + Sync { #[derive(Debug)] pub(crate) struct SingleCertAndKey(Arc); -impl SingleCertAndKey { - /// Creates an `AlwaysResolvesChain`, using the supplied `CertifiedKey` and OCSP response. - /// - /// If non-empty, the given OCSP response is attached. - pub(crate) fn new_with_extras(certified_key: CertifiedKey, ocsp: Vec) -> Self { - let mut r = Self::from(certified_key); - - { - let cert = Arc::make_mut(&mut r.0); - if !ocsp.is_empty() { - cert.ocsp = Some(ocsp); - } - } - - r - } -} - impl From for SingleCertAndKey { fn from(certified_key: CertifiedKey) -> Self { Self(Arc::new(certified_key)) diff --git a/rustls/src/server/builder.rs b/rustls/src/server/builder.rs index e9221f458fc..45e663a5968 100644 --- a/rustls/src/server/builder.rs +++ b/rustls/src/server/builder.rs @@ -106,15 +106,15 @@ impl ConfigBuilder { .key_provider .load_private_key(key_der)?; - let certified_key = CertifiedKey::new(cert_chain, private_key); + let mut certified_key = CertifiedKey::new(cert_chain, private_key); match certified_key.keys_match() { // Don't treat unknown consistency as an error Ok(()) | Err(Error::InconsistentKeys(InconsistentKeys::Unknown)) => (), Err(err) => return Err(err), } - let resolver = SingleCertAndKey::new_with_extras(certified_key, ocsp); - Ok(self.with_cert_resolver(Arc::new(resolver))) + certified_key.ocsp = Some(ocsp); + Ok(self.with_cert_resolver(Arc::new(SingleCertAndKey::from(certified_key)))) } /// Sets a custom [`ResolvesServerCert`]. From b0cc4dfe3a62bff581733f473808c58b1d4e4f8d Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 11 Feb 2025 10:41:46 +0100 Subject: [PATCH 048/403] crypto: add CertifiedKey::from_der() --- rustls/src/crypto/signer.rs | 28 +++++++++++++++++++++++++++- rustls/src/server/builder.rs | 29 ++++------------------------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/rustls/src/crypto/signer.rs b/rustls/src/crypto/signer.rs index ea6608efdeb..7682141c9e7 100644 --- a/rustls/src/crypto/signer.rs +++ b/rustls/src/crypto/signer.rs @@ -2,7 +2,7 @@ use alloc::boxed::Box; use alloc::vec::Vec; use core::fmt::Debug; -use pki_types::{AlgorithmIdentifier, CertificateDer, SubjectPublicKeyInfoDer}; +use pki_types::{AlgorithmIdentifier, CertificateDer, PrivateKeyDer, SubjectPublicKeyInfoDer}; use crate::enums::{SignatureAlgorithm, SignatureScheme}; use crate::error::{Error, InconsistentKeys}; @@ -10,6 +10,8 @@ use crate::server::{ClientHello, ParsedCertificate, ResolvesServerCert}; use crate::sync::Arc; use crate::x509; +use super::CryptoProvider; + /// An abstract signing key. /// /// This interface is used by rustls to use a private signing key @@ -123,6 +125,30 @@ pub struct CertifiedKey { } 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>, + key: PrivateKeyDer<'static>, + provider: &CryptoProvider, + ) -> Result { + 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 diff --git a/rustls/src/server/builder.rs b/rustls/src/server/builder.rs index 45e663a5968..14407d5f5a0 100644 --- a/rustls/src/server/builder.rs +++ b/rustls/src/server/builder.rs @@ -9,7 +9,7 @@ use crate::error::Error; use crate::sign::{CertifiedKey, SingleCertAndKey}; use crate::sync::Arc; use crate::verify::{ClientCertVerifier, NoClientAuth}; -use crate::{compress, versions, InconsistentKeys, NoKeyLog}; +use crate::{compress, versions, NoKeyLog}; impl ConfigBuilder { /// Choose how to verify client certificates. @@ -67,18 +67,7 @@ impl ConfigBuilder { cert_chain: Vec>, key_der: PrivateKeyDer<'static>, ) -> Result { - let private_key = self - .provider - .key_provider - .load_private_key(key_der)?; - - let certified_key = CertifiedKey::new(cert_chain, private_key); - match certified_key.keys_match() { - // Don't treat unknown consistency as an error - Ok(()) | Err(Error::InconsistentKeys(InconsistentKeys::Unknown)) => (), - Err(err) => return Err(err), - } - + let certified_key = CertifiedKey::from_der(cert_chain, key_der, self.crypto_provider())?; Ok(self.with_cert_resolver(Arc::new(SingleCertAndKey::from(certified_key)))) } @@ -101,18 +90,8 @@ impl ConfigBuilder { key_der: PrivateKeyDer<'static>, ocsp: Vec, ) -> Result { - let private_key = self - .provider - .key_provider - .load_private_key(key_der)?; - - let mut certified_key = CertifiedKey::new(cert_chain, private_key); - match certified_key.keys_match() { - // Don't treat unknown consistency as an error - Ok(()) | Err(Error::InconsistentKeys(InconsistentKeys::Unknown)) => (), - Err(err) => return Err(err), - } - + 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)))) } From 82e16889254302c664254c4caa48d20fd3c3a4dc Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 11 Feb 2025 13:27:38 +0100 Subject: [PATCH 049/403] client: use SingleCertAndKey for with_client_auth_cert() --- rustls/src/client/builder.rs | 11 +++-------- rustls/src/client/handy.rs | 31 ------------------------------- rustls/src/crypto/signer.rs | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 39 deletions(-) diff --git a/rustls/src/client/builder.rs b/rustls/src/client/builder.rs index 9c0316f3013..8b76bf0fa9e 100644 --- a/rustls/src/client/builder.rs +++ b/rustls/src/client/builder.rs @@ -8,7 +8,7 @@ use crate::builder::{ConfigBuilder, WantsVerifier}; use crate::client::{handy, ClientConfig, EchMode, ResolvesClientCert}; use crate::error::Error; use crate::key_log::NoKeyLog; -use crate::msgs::handshake::CertificateChain; +use crate::sign::{CertifiedKey, SingleCertAndKey}; use crate::sync::Arc; use crate::versions::TLS13; use crate::webpki::{self, WebPkiServerVerifier}; @@ -148,13 +148,8 @@ impl ConfigBuilder { cert_chain: Vec>, key_der: PrivateKeyDer<'static>, ) -> Result { - let private_key = self - .provider - .key_provider - .load_private_key(key_der)?; - let resolver = - handy::AlwaysResolvesClientCert::new(private_key, CertificateChain(cert_chain))?; - Ok(self.with_client_cert_resolver(Arc::new(resolver))) + 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. diff --git a/rustls/src/client/handy.rs b/rustls/src/client/handy.rs index 911894f2bbe..80b02c27b45 100644 --- a/rustls/src/client/handy.rs +++ b/rustls/src/client/handy.rs @@ -1,8 +1,6 @@ use pki_types::ServerName; use crate::enums::SignatureScheme; -use crate::error::Error; -use crate::msgs::handshake::CertificateChain; use crate::msgs::persist; use crate::sync::Arc; use crate::{client, sign, NamedGroup}; @@ -211,35 +209,6 @@ impl client::ResolvesClientCert for FailResolveClientCert { } } -#[derive(Debug)] -pub(super) struct AlwaysResolvesClientCert(Arc); - -impl AlwaysResolvesClientCert { - pub(super) fn new( - private_key: Arc, - chain: CertificateChain<'static>, - ) -> Result { - Ok(Self(Arc::new(sign::CertifiedKey::new( - chain.0, - private_key, - )))) - } -} - -impl client::ResolvesClientCert for AlwaysResolvesClientCert { - fn resolve( - &self, - _root_hint_subjects: &[&[u8]], - _sigschemes: &[SignatureScheme], - ) -> Option> { - Some(Arc::clone(&self.0)) - } - - fn has_certs(&self) -> bool { - true - } -} - /// An exemplar `ResolvesClientCert` implementation that always resolves to a single /// [RFC 7250] raw public key. /// diff --git a/rustls/src/crypto/signer.rs b/rustls/src/crypto/signer.rs index 7682141c9e7..e11437fddfb 100644 --- a/rustls/src/crypto/signer.rs +++ b/rustls/src/crypto/signer.rs @@ -4,6 +4,7 @@ use core::fmt::Debug; use pki_types::{AlgorithmIdentifier, CertificateDer, PrivateKeyDer, SubjectPublicKeyInfoDer}; +use crate::client::ResolvesClientCert; use crate::enums::{SignatureAlgorithm, SignatureScheme}; use crate::error::{Error, InconsistentKeys}; use crate::server::{ClientHello, ParsedCertificate, ResolvesServerCert}; @@ -97,6 +98,20 @@ impl From for SingleCertAndKey { } } +impl ResolvesClientCert for SingleCertAndKey { + fn resolve( + &self, + _root_hint_subjects: &[&[u8]], + _sigschemes: &[SignatureScheme], + ) -> Option> { + Some(Arc::clone(&self.0)) + } + + fn has_certs(&self) -> bool { + true + } +} + impl ResolvesServerCert for SingleCertAndKey { fn resolve(&self, _client_hello: ClientHello<'_>) -> Option> { Some(Arc::clone(&self.0)) From 591c0c1b6a472951f8b053417750e6ddba23d0c5 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 11 Feb 2025 13:35:35 +0100 Subject: [PATCH 050/403] crypto: expose SingleCertAndKey --- rustls/src/crypto/signer.rs | 8 ++++++-- rustls/src/lib.rs | 3 +-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/rustls/src/crypto/signer.rs b/rustls/src/crypto/signer.rs index e11437fddfb..77bf402c75f 100644 --- a/rustls/src/crypto/signer.rs +++ b/rustls/src/crypto/signer.rs @@ -88,9 +88,13 @@ pub trait Signer: Debug + Send + Sync { fn scheme(&self) -> SignatureScheme; } -/// Something which always resolves to the same cert chain. +/// 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(crate) struct SingleCertAndKey(Arc); +pub struct SingleCertAndKey(Arc); impl From for SingleCertAndKey { fn from(certified_key: CertifiedKey) -> Self { diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 5a9e7e08da0..dfcdd1d5ab4 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -668,8 +668,7 @@ pub mod pki_types { /// Message signing interfaces. pub mod sign { - pub(crate) use crate::crypto::signer::SingleCertAndKey; - pub use crate::crypto::signer::{CertifiedKey, Signer, SigningKey}; + pub use crate::crypto::signer::{CertifiedKey, Signer, SigningKey, SingleCertAndKey}; } /// APIs for implementing QUIC TLS From ad5a31b763c68af4909dc4cd127e62110a31dcdc Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 11 Feb 2025 13:33:09 +0100 Subject: [PATCH 051/403] tests: reuse SingleCertAndKey --- rustls/tests/api.rs | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index fe45606dc86..470a1ad1ac1 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -7734,7 +7734,8 @@ fn test_cert_decompression_by_server_would_result_in_excessively_large_cert() { .load_private_key(KeyType::Rsa2048.get_client_key()) .unwrap(); let big_cert_and_key = sign::CertifiedKey::new(vec![big_cert], key); - client_config.client_auth_cert_resolver = Arc::new(AlwaysResolves(big_cert_and_key.into())); + client_config.client_auth_cert_resolver = + Arc::new(sign::SingleCertAndKey::from(big_cert_and_key)); let (mut client, mut server) = make_pair_for_configs(client_config, server_config); assert_eq!( @@ -7748,23 +7749,6 @@ fn test_cert_decompression_by_server_would_result_in_excessively_large_cert() { client.process_new_packets(), Err(Error::AlertReceived(AlertDescription::BadCertificate)) ); - - #[derive(Debug)] - struct AlwaysResolves(Arc); - - impl ResolvesClientCert for AlwaysResolves { - fn resolve( - &self, - _root_hint_subjects: &[&[u8]], - _sigschemes: &[SignatureScheme], - ) -> Option> { - Some(self.0.clone()) - } - - fn has_certs(&self) -> bool { - true - } - } } #[derive(Debug)] From 1963cc76a2579a7d3871c63ce183dff382034d3e Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 11 Feb 2025 10:29:48 +0100 Subject: [PATCH 052/403] Bump version to 0.23.23 --- Cargo.lock | 22 +++++++++++----------- fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c02d53002ab..31ba4d51fa7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -493,7 +493,7 @@ version = "0.1.0" dependencies = [ "base64", "env_logger", - "rustls 0.23.22", + "rustls 0.23.23", "rustls-post-quantum", ] @@ -2479,7 +2479,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.22" +version = "0.23.23" dependencies = [ "aws-lc-rs", "base64", @@ -2513,7 +2513,7 @@ name = "rustls-bench" version = "0.1.0" dependencies = [ "clap", - "rustls 0.23.22", + "rustls 0.23.23", "rustls-post-quantum", "tikv-jemallocator", ] @@ -2530,7 +2530,7 @@ dependencies = [ "fxhash", "itertools 0.14.0", "rayon", - "rustls 0.23.22", + "rustls 0.23.23", "tikv-jemallocator", ] @@ -2541,7 +2541,7 @@ dependencies = [ "hickory-resolver", "regex", "ring", - "rustls 0.23.22", + "rustls 0.23.23", "tokio", ] @@ -2556,7 +2556,7 @@ dependencies = [ "log", "mio", "rcgen", - "rustls 0.23.22", + "rustls 0.23.23", "serde", "tokio", "webpki-roots", @@ -2567,7 +2567,7 @@ name = "rustls-fuzzing-provider" version = "0.1.0" dependencies = [ "env_logger", - "rustls 0.23.22", + "rustls 0.23.23", "rustls-webpki", ] @@ -2580,7 +2580,7 @@ dependencies = [ "num-bigint", "once_cell", "openssl", - "rustls 0.23.22", + "rustls 0.23.23", ] [[package]] @@ -2595,7 +2595,7 @@ version = "0.2.2" dependencies = [ "criterion", "env_logger", - "rustls 0.23.22", + "rustls 0.23.23", "webpki-roots", ] @@ -2616,7 +2616,7 @@ dependencies = [ "rand_core 0.6.4", "rcgen", "rsa", - "rustls 0.23.22", + "rustls 0.23.23", "rustls-webpki", "sha2", "signature", @@ -2629,7 +2629,7 @@ name = "rustls-provider-test" version = "0.1.0" dependencies = [ "hex", - "rustls 0.23.22", + "rustls 0.23.23", "rustls-provider-example", "serde", "serde_json", diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index a0019149e44..dc9f44da2aa 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -224,7 +224,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.22" +version = "0.23.23" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 544e80f7113..1f7a332e1b2 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.22" +version = "0.23.23" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From 7abb149a3d93d8c47df75b71eda3bdfbbb70fd68 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 11 Feb 2025 12:17:31 +0000 Subject: [PATCH 053/403] tests/unbuffered: refactor Reduce rightward drift and prefer match to trivial if-let. --- rustls/tests/unbuffered.rs | 64 +++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index 7dbc2fc70d6..d4cc7f5589f 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -862,11 +862,9 @@ fn write_traffic) -> R>( ) -> R { let UnbufferedStatus { discard, state } = status; assert_eq!(discard, 0); - let state = state.unwrap(); - if let ConnectionState::WriteTraffic(state) = state { - f(state) - } else { - panic!("unexpected client state {state:?} (wanted WriteTraffic)"); + match state.unwrap() { + ConnectionState::WriteTraffic(state) => f(state), + other => panic!("unexpected state {other:?} (wanted WriteTraffic)"), } } @@ -976,23 +974,21 @@ fn advance_client( let state = match state { ConnectionState::TransmitTlsData(mut state) => { let mut sent_early_data = false; - if let Some(early_data) = actions.early_data_to_send { - if let Some(mut state) = state.may_encrypt_early_data() { - write_with_buffer_size_checks( - |out_buf| state.encrypt(early_data, out_buf), - |e| { - println!("encrypt error: {e}"); - if let EarlyDataError::Encrypt(EncryptError::InsufficientSize(ise)) = e - { - ise - } else { - unreachable!() - } - }, - &mut buffers.outgoing, - ); - sent_early_data = true; - } + if let (Some(early_data), Some(mut state)) = + (actions.early_data_to_send, state.may_encrypt_early_data()) + { + write_with_buffer_size_checks( + |out_buf| state.encrypt(early_data, out_buf), + |e| { + println!("encrypt error: {e}"); + match e { + EarlyDataError::Encrypt(EncryptError::InsufficientSize(ise)) => ise, + _ => unreachable!(), + } + }, + &mut buffers.outgoing, + ); + sent_early_data = true; } state.done(); State::TransmitTlsData { @@ -1055,10 +1051,9 @@ fn handle_state( |out_buf| state.encode(out_buf), |e| { println!("encode error: {e}"); - if let EncodeError::InsufficientSize(ise) = e { - ise - } else { - unreachable!() + match e { + EncodeError::InsufficientSize(ise) => ise, + _ => unreachable!(), } }, outgoing, @@ -1074,11 +1069,11 @@ fn handle_state( ConnectionState::TransmitTlsData(mut state) => { let mut sent_app_data = false; - if let Some(app_data) = actions.app_data_to_send { - if let Some(mut state) = state.may_encrypt_app_data() { - encrypt(&mut state, app_data, outgoing); - sent_app_data = true; - } + if let (Some(app_data), Some(mut state)) = + (actions.app_data_to_send, state.may_encrypt_app_data()) + { + encrypt(&mut state, app_data, outgoing); + sent_app_data = true; } let mut sent_close_notify = false; @@ -1159,10 +1154,9 @@ fn encrypt(state: &mut WriteTraffic<'_, Data>, app_data: &[u8], outgoing: } fn map_encrypt_error(e: EncryptError) -> InsufficientSizeError { - if let EncryptError::InsufficientSize(ise) = e { - ise - } else { - unreachable!() + match e { + EncryptError::InsufficientSize(ise) => ise, + _ => unreachable!(), } } From 774214751ba5e8e62a49f80fbaf13630441eddd1 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 5 Feb 2025 14:58:45 +0000 Subject: [PATCH 054/403] unbuffered: introduce `PeerClosed` state `Closed` is now bi-directional, terminal closure state. --- rustls/src/common_state.rs | 4 ++ rustls/src/conn.rs | 2 + rustls/src/conn/unbuffered.rs | 35 ++++++++++- rustls/tests/unbuffered.rs | 111 +++++++++++++++++++++++++++++----- 4 files changed, 136 insertions(+), 16 deletions(-) diff --git a/rustls/src/common_state.rs b/rustls/src/common_state.rs index 3ff4609df8c..12aca203a4b 100644 --- a/rustls/src/common_state.rs +++ b/rustls/src/common_state.rs @@ -40,6 +40,8 @@ pub struct CommonState { 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")] @@ -74,6 +76,7 @@ impl CommonState { 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, @@ -573,6 +576,7 @@ impl CommonState { } 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); } diff --git a/rustls/src/conn.rs b/rustls/src/conn.rs index 43706241452..426d3770cce 100644 --- a/rustls/src/conn.rs +++ b/rustls/src/conn.rs @@ -811,6 +811,7 @@ impl From> for ConnectionCommon { pub struct UnbufferedConnectionCommon { pub(crate) core: ConnectionCore, wants_write: bool, + emitted_peer_closed_state: bool, } impl From> for UnbufferedConnectionCommon { @@ -818,6 +819,7 @@ impl From> for UnbufferedConnectionCommon { Self { core, wants_write: false, + emitted_peer_closed_state: false, } } } diff --git a/rustls/src/conn/unbuffered.rs b/rustls/src/conn/unbuffered.rs index ef8146e098e..ffe14c75f7d 100644 --- a/rustls/src/conn/unbuffered.rs +++ b/rustls/src/conn/unbuffered.rs @@ -131,6 +131,18 @@ impl UnbufferedConnectionCommon { .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 @@ -185,7 +197,26 @@ pub enum ConnectionState<'c, 'i, Data> { /// the received data. ReadTraffic(ReadTraffic<'c, 'i, Data>), - /// Connection has been cleanly closed by the peer + /// 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 @@ -262,6 +293,8 @@ impl fmt::Debug for ConnectionState<'_, '_, Data> { 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(), diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index d4cc7f5589f..e37030b5b5e 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -5,8 +5,8 @@ use std::num::NonZeroUsize; use rustls::client::{ClientConnectionData, EarlyDataError, UnbufferedClientConnection}; use rustls::server::{ServerConnectionData, UnbufferedServerConnection}; use rustls::unbuffered::{ - ConnectionState, EncodeError, EncryptError, InsufficientSizeError, UnbufferedConnectionCommon, - UnbufferedStatus, WriteTraffic, + ConnectionState, EncodeError, EncryptError, InsufficientSizeError, ReadTraffic, + UnbufferedConnectionCommon, UnbufferedStatus, WriteTraffic, }; use rustls::version::TLS13; use rustls::{ @@ -329,10 +329,10 @@ fn run( .client_received_app_data .extend(records); } - State::Closed => { - client_handshake_done = true; - outcome.client_reached_connection_closed_state = true + State::PeerClosed => { + outcome.client_saw_peer_closed_state = true; } + State::Closed => {} state => unreachable!("{state:?}"), } @@ -385,10 +385,10 @@ fn run( .server_received_app_data .extend(records); } - State::Closed => { - server_handshake_done = true; - outcome.server_reached_connection_closed_state = true + State::PeerClosed => { + outcome.server_saw_peer_closed_state = true; } + State::Closed => {} } count += 1; @@ -435,7 +435,7 @@ fn close_notify_client_to_server() { ); assert!(!client_actions.send_close_notify); - assert!(outcome.server_reached_connection_closed_state); + assert!(outcome.server_saw_peer_closed_state); } } @@ -459,7 +459,59 @@ fn close_notify_server_to_client() { ); assert!(!server_actions.send_close_notify); - assert!(outcome.client_reached_connection_closed_state); + assert!(outcome.client_saw_peer_closed_state); + } +} + +#[test] +fn full_closure_server_to_client() { + for version in rustls::ALL_VERSIONS { + eprintln!("{version:?}"); + let mut outcome = handshake(version); + let mut client = outcome.client.take().unwrap(); + let mut server = outcome.server.take().unwrap(); + + let mut buf = Buffer::default(); + + // server sends message followed by close_notify, in one flight + write_traffic( + server.process_tls_records(&mut []), + |mut wt: WriteTraffic<_>| { + encrypt(&mut wt, b"hello", &mut buf); + queue_close_notify(&mut wt, &mut buf); + }, + ); + + let (_, discard) = read_traffic(client.process_tls_records(buf.filled()), |mut rt| { + assert_eq!(rt.peek_len(), NonZeroUsize::new(5)); + let app_data = rt.next_record().unwrap().unwrap(); + assert_eq!(app_data.payload, b"hello"); + }); + buf.discard(discard); + + let discard = peer_closed(client.process_tls_records(buf.filled())); + buf.discard(discard); + assert_eq!(buf.used, 0); + + // client replies with its own data and close_notify + write_traffic(client.process_tls_records(&mut []), |mut wt| { + encrypt(&mut wt, b"goodbye", &mut buf); + queue_close_notify(&mut wt, &mut buf); + }); + + let (_, discard) = read_traffic(server.process_tls_records(buf.filled()), |mut rt| { + assert_eq!(rt.peek_len(), NonZeroUsize::new(7)); + let app_data = rt.next_record().unwrap().unwrap(); + assert_eq!(app_data.payload, b"goodbye"); + }); + buf.discard(discard); + + let discard = peer_closed(server.process_tls_records(buf.filled())); + buf.discard(discard); + assert_eq!(buf.used, 0); + + closed(client.process_tls_records(&mut [])); + closed(server.process_tls_records(&mut [])); } } @@ -483,13 +535,13 @@ fn junk_after_close_notify_received() { let discard = match dbg!(server.process_tls_records(dbg!(&mut client_send_buf[..len]))) { UnbufferedStatus { discard, - state: Ok(ConnectionState::Closed), + state: Ok(ConnectionState::PeerClosed), } => { assert_eq!(discard, 24); discard } st => { - panic!("unexpected server state {st:?} (wanted Closed)"); + panic!("unexpected server state {st:?} (wanted PeerClosed)"); } }; @@ -785,7 +837,7 @@ fn tls12_connection_fails_after_key_reaches_confidentiality_limit() { match server.process_tls_records(&mut data) { UnbufferedStatus { discard, - state: Ok(ConnectionState::Closed), + state: Ok(ConnectionState::PeerClosed), } if discard == data_len => {} st => panic!("unexpected server state {st:?}"), } @@ -868,6 +920,33 @@ fn write_traffic) -> R>( } } +fn read_traffic) -> R>( + status: UnbufferedStatus<'_, '_, T>, + mut f: F, +) -> (R, usize) { + let UnbufferedStatus { discard, state } = status; + match state.unwrap() { + ConnectionState::ReadTraffic(state) => (f(state), discard), + other => panic!("unexpected state {other:?} (wanted ReadTraffic)"), + } +} + +fn peer_closed(status: UnbufferedStatus<'_, '_, T>) -> usize { + let UnbufferedStatus { discard, state } = status; + match state.unwrap() { + ConnectionState::PeerClosed => discard, + other => panic!("unexpected state {other:?} (wanted PeerClosed)"), + } +} + +fn closed(status: UnbufferedStatus<'_, '_, T>) -> usize { + let UnbufferedStatus { discard, state } = status; + match state.unwrap() { + ConnectionState::Closed => discard, + other => panic!("unexpected state {other:?} (wanted Closed)"), + } +} + fn encode_tls_data(status: UnbufferedStatus<'_, '_, T>) -> (Vec, usize) { match status { UnbufferedStatus { @@ -907,6 +986,7 @@ fn confirm_transmit_tls_data(status: UnbufferedStatus<'_, '_, T>) { #[derive(Debug)] enum State { Closed, + PeerClosed, EncodedTlsData, TransmitTlsData { sent_app_data: bool, @@ -953,11 +1033,11 @@ struct Outcome { server_transcript: Vec, server_received_early_data: Vec>, server_received_app_data: Vec>, - server_reached_connection_closed_state: bool, + server_saw_peer_closed_state: bool, client: Option, client_transcript: Vec, client_received_app_data: Vec>, - client_reached_connection_closed_state: bool, + client_saw_peer_closed_state: bool, } fn advance_client( @@ -1131,6 +1211,7 @@ fn handle_state( State::ReceivedAppData { records } } + ConnectionState::PeerClosed => State::PeerClosed, ConnectionState::Closed => State::Closed, _ => unreachable!(), From 598f962ef65f669e84408b7b150f7fae6151447f Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 13 Feb 2025 11:51:03 +0000 Subject: [PATCH 055/403] Take & unpin hickory-resolver 0.25.0-alpha.5 --- Cargo.lock | 266 ++++++++++++++++++++++++++++++++++++++++++++++++----- Cargo.toml | 2 +- 2 files changed, 246 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 31ba4d51fa7..dc8a148a0fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -765,6 +765,15 @@ dependencies = [ "itertools 0.10.5", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -1171,6 +1180,19 @@ dependencies = [ "byteorder", ] +[[package]] +name = "generator" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bd114ceda131d3b1d665eba35788690ad37f5916457286b32ab6fd3c438dd" +dependencies = [ + "cfg-if", + "libc", + "log", + "rustversion", + "windows", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1339,22 +1361,22 @@ dependencies = [ [[package]] name = "hickory-resolver" -version = "0.25.0-alpha.3" +version = "0.25.0-alpha.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eec9ac701a9b34a77c8ccbe39d589db876290f6bdc6e05ac118fd114cb1ad26" +checksum = "5762f69ebdbd4ddb2e975cd24690bf21fe6b2604039189c26acddbc427f12887" dependencies = [ "cfg-if", "futures-util", "hickory-proto", "ipconfig", - "lru-cache", + "moka", "once_cell", "parking_lot", - "rand 0.8.5", + "rand 0.9.0", "resolv-conf", "rustls 0.23.21", "smallvec", - "thiserror 1.0.69", + "thiserror 2.0.11", "tokio", "tokio-rustls", "tracing", @@ -1727,7 +1749,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -1736,12 +1758,6 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -1774,12 +1790,16 @@ dependencies = [ ] [[package]] -name = "lru-cache" -version = "0.1.2" +name = "loom" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" dependencies = [ - "linked-hash-map", + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", ] [[package]] @@ -1804,6 +1824,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "memchr" version = "2.7.4" @@ -1837,6 +1866,25 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "moka" +version = "0.12.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926" +dependencies = [ + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "loom", + "parking_lot", + "portable-atomic", + "rustc_version", + "smallvec", + "tagptr", + "thiserror 1.0.69", + "uuid", +] + [[package]] name = "nom" version = "7.1.3" @@ -1847,6 +1895,16 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -1984,6 +2042,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "p256" version = "0.13.2" @@ -2173,6 +2237,12 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "portable-atomic" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" + [[package]] name = "powerfmt" version = "0.2.0" @@ -2237,7 +2307,6 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", ] @@ -2342,8 +2411,17 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", ] [[package]] @@ -2354,9 +2432,15 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.5", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.8.5" @@ -2668,6 +2752,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -2737,6 +2827,15 @@ dependencies = [ "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.3.0" @@ -2845,6 +2944,12 @@ dependencies = [ "syn 2.0.96", ] +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "thiserror" version = "1.0.69" @@ -2885,6 +2990,16 @@ dependencies = [ "syn 2.0.96", ] +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "tikv-jemalloc-sys" version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" @@ -3050,6 +3165,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", ] [[package]] @@ -3109,6 +3254,21 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced87ca4be083373936a67f8de945faa23b6b42384bd5b64434850802c6dccd0" +dependencies = [ + "getrandom 0.3.1", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "value-bag" version = "1.10.0" @@ -3282,7 +3442,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -3291,6 +3451,70 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index ebd8877c1dd..833a76d92d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,7 +57,7 @@ env_logger = "0.11" fxhash = "0.2.1" hashbrown = { version = "0.15", default-features = false, features = ["default-hasher", "inline-more"] } hex = "0.4" -hickory-resolver = { version = "=0.25.0-alpha.3", features = ["dns-over-https-rustls", "webpki-roots"] } +hickory-resolver = { version = "0.25.0-alpha.5", features = ["dns-over-https-rustls", "webpki-roots"] } hmac = "0.12" hpke-rs = "0.2" hpke-rs-crypto = "0.2" From 10181859a41a05ecd4f9fc966c7933bd6e56ae55 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 13 Feb 2025 12:38:31 +0000 Subject: [PATCH 056/403] Respect `PeerClosed` state in unbuffered examples --- examples/src/bin/unbuffered-async-client.rs | 8 +++++--- examples/src/bin/unbuffered-client.rs | 8 +++++--- examples/src/bin/unbuffered-server.rs | 5 +++++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/examples/src/bin/unbuffered-async-client.rs b/examples/src/bin/unbuffered-async-client.rs index 5cfb1390d9a..851c01256a1 100644 --- a/examples/src/bin/unbuffered-async-client.rs +++ b/examples/src/bin/unbuffered-async-client.rs @@ -54,12 +54,12 @@ async fn converse( let mut outgoing_used = 0; let mut we_closed = false; - let mut peer_closed = false; + let mut fully_closed = false; let mut sent_request = false; let mut received_response = false; let mut iter_count = 0; - while !(peer_closed || (we_closed && incoming_used == 0)) { + while !fully_closed { let UnbufferedStatus { mut discard, state } = conn.process_tls_records(&mut incoming_tls[..incoming_used]); @@ -155,8 +155,10 @@ async fn converse( } } + ConnectionState::PeerClosed => {} + ConnectionState::Closed => { - peer_closed = true; + fully_closed = true; } // other states are not expected in this example diff --git a/examples/src/bin/unbuffered-client.rs b/examples/src/bin/unbuffered-client.rs index ec0f4c1b193..d502c631185 100644 --- a/examples/src/bin/unbuffered-client.rs +++ b/examples/src/bin/unbuffered-client.rs @@ -51,13 +51,13 @@ fn converse( let mut outgoing_used = 0; let mut we_closed = false; - let mut peer_closed = false; + let mut fully_closed = false; let mut sent_request = false; let mut received_response = false; let mut sent_early_data = false; let mut iter_count = 0; - while !(peer_closed || (we_closed && incoming_used == 0)) { + while !fully_closed { let UnbufferedStatus { mut discard, state } = conn.process_tls_records(&mut incoming_tls[..incoming_used]); @@ -168,8 +168,10 @@ fn converse( } } + ConnectionState::PeerClosed => {} + ConnectionState::Closed => { - peer_closed = true; + fully_closed = true; } // other states are not expected in this example diff --git a/examples/src/bin/unbuffered-server.rs b/examples/src/bin/unbuffered-server.rs index 80e567b5bc9..764a2594280 100644 --- a/examples/src/bin/unbuffered-server.rs +++ b/examples/src/bin/unbuffered-server.rs @@ -170,6 +170,11 @@ fn handle( } } + ConnectionState::PeerClosed => {} + ConnectionState::Closed => { + open_connection = false; + } + _ => unreachable!(), } From 11ce78e1468dd38bb4b099cae9a9e1492e26f501 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 13 Feb 2025 15:37:42 +0000 Subject: [PATCH 057/403] ci: improve performance via more cache usage Each overall build.yml run builds bindgen-cli 7 times, cross 8 times, etc. Instead of that, use `taiki-e/cache-cargo-install-action` for all places we would use cargo install/binstall. --- .github/workflows/build.yml | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 51cde8db2cd..04a24f3caed 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -247,7 +247,9 @@ jobs: uses: dtolnay/rust-toolchain@nightly - name: Install cargo fuzz - run: cargo install cargo-fuzz + uses: taiki-e/cache-cargo-install-action@v2 + with: + tool: cargo-fuzz - name: Smoke-test fuzz targets run: | @@ -321,7 +323,9 @@ jobs: components: llvm-tools - name: Install cargo-llvm-cov - run: cargo install cargo-llvm-cov + uses: taiki-e/cache-cargo-install-action@v2 + with: + tool: cargo-llvm-cov - name: Measure coverage run: ./admin/coverage --lcov --output-path final.info @@ -385,11 +389,20 @@ jobs: - name: Install rust toolchain uses: dtolnay/rust-toolchain@stable - - name: Install cross (cross-rs) from GitHub - run: cargo install cross --git https://github.com/cross-rs/cross - - name: Install bindgen feature & CLI for aws-lc-sys (as needed for many cross targets) + - name: Install cross + uses: taiki-e/cache-cargo-install-action@v2 + with: + tool: cross + git: https://github.com/cross-rs/cross + # known-working main in feb 2025, bump as needed + rev: c7dee4d + - name: Install bindgen-cli + uses: taiki-e/cache-cargo-install-action@v2 + with: + tool: bindgen-cli + - name: Enable bindgen feature for aws-lc-sys (as needed for many cross targets) if: ${{ matrix.target != 'i686-unknown-linux-gnu' }} - run: cargo add --dev --features bindgen 'aws-lc-sys@>0.20' --package rustls --verbose && cargo install bindgen-cli --verbose + run: cargo add --dev --features bindgen 'aws-lc-sys@>0.20' --package rustls --verbose - run: cross test --package rustls --target ${{ matrix.target }} semver: @@ -507,7 +520,10 @@ jobs: with: toolchain: nightly-2024-06-30 # ^ sync with https://github.com/awslabs/cargo-check-external-types/blob/main/rust-toolchain.toml - - run: cargo install --locked cargo-check-external-types + - name: Install cargo-check-external-types + uses: taiki-e/cache-cargo-install-action@v2 + with: + tool: cargo-check-external-types - name: run cargo-check-external-types for rustls/ working-directory: rustls/ run: cargo check-external-types @@ -523,7 +539,10 @@ jobs: - name: Install rust toolchain uses: dtolnay/rust-toolchain@stable - - run: cargo install taplo-cli --locked + - name: Install taplo-cli + uses: taiki-e/cache-cargo-install-action@v2 + with: + tool: taplo-cli - run: taplo format --check openssl-tests: From d8a2790078cbbb4ffb9296f2df51b00528791d1b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 17 Feb 2025 16:19:33 +0000 Subject: [PATCH 058/403] Take semver-compatible dependencies --- Cargo.lock | 284 +++++++++++++++++++++++++++-------------------------- 1 file changed, 146 insertions(+), 138 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc8a148a0fb..d5e2ac37c42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -123,11 +123,12 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", + "once_cell", "windows-sys 0.59.0", ] @@ -171,7 +172,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", "synstructure", ] @@ -183,7 +184,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -194,7 +195,7 @@ checksum = "a200809d0138620b3dba989f1d08d0620e76248bc1e62a2ec1b2df5eb1ee08ad" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -296,7 +297,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -334,13 +335,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.85" +version = "0.1.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" +checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -357,25 +358,24 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-fips-sys" -version = "0.13.0" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59057b878509d88952425fe694a2806e468612bde2d71943f3cd8034935b5032" +checksum = "29003a681b2b9465c1139bfb726da452a841a8b025f35953f3bce71139f10b21" dependencies = [ "bindgen", "cc", "cmake", "dunce", "fs_extra", - "libc", "paste", "regex", ] [[package]] name = "aws-lc-rs" -version = "1.12.0" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f409eb70b561706bf8abba8ca9c112729c481595893fd06a2dd9af8ed8441148" +checksum = "4c2b7ddaa2c56a367ad27a094ad8ef4faacf8a617c2575acb2ba88949df999ca" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", @@ -385,9 +385,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.24.1" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "923ded50f602b3007e5e63e3f094c479d9c8a9b42d7f4034e4afe456aa48bfd2" +checksum = "54ac4f13dad353b209b34cbec082338202cbc01c8f00336b55c750c13ac91f8f" dependencies = [ "bindgen", "cc", @@ -445,7 +445,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "itertools 0.10.5", + "itertools 0.12.1", "lazy_static", "lazycell", "log", @@ -455,15 +455,15 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.96", + "syn 2.0.98", "which", ] [[package]] name = "bitflags" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "block-buffer" @@ -510,9 +510,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "4.0.1" +version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" +checksum = "74fa05ad7d803d413eb8380983b092cbbaf9a85f151b871360e7b00cd7060b37" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -520,9 +520,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "byteorder" @@ -532,9 +532,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" [[package]] name = "cast" @@ -544,9 +544,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.9" +version = "1.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" +checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9" dependencies = [ "jobserver", "libc", @@ -643,9 +643,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.26" +version = "4.5.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" +checksum = "8acebd8ad879283633b343856142139f2da2317c96b05b4dd6181c61e2480184" dependencies = [ "clap_builder", "clap_derive", @@ -653,9 +653,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.26" +version = "4.5.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" +checksum = "f6ba32cbda51c7e1dfd49acc1457ba1a7dec5b64fe360e828acb13ca8dc9c2f9" dependencies = [ "anstream", "anstyle", @@ -665,14 +665,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.24" +version = "4.5.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" +checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -683,9 +683,9 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "cmake" -version = "0.1.52" +version = "0.1.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" dependencies = [ "cc", ] @@ -713,9 +713,9 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "cpufeatures" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] @@ -801,9 +801,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" [[package]] name = "crypto-bigint" @@ -859,14 +859,14 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] name = "data-encoding" -version = "2.6.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" +checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" [[package]] name = "der" @@ -921,7 +921,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -979,7 +979,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -1007,9 +1007,9 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" @@ -1349,7 +1349,7 @@ dependencies = [ "ipnet", "once_cell", "rand 0.9.0", - "rustls 0.23.21", + "rustls 0.23.23 (registry+https://github.com/rust-lang/crates.io-index)", "thiserror 2.0.11", "tinyvec", "tokio", @@ -1374,7 +1374,7 @@ dependencies = [ "parking_lot", "rand 0.9.0", "resolv-conf", - "rustls 0.23.21", + "rustls 0.23.23 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec", "thiserror 2.0.11", "tokio", @@ -1591,7 +1591,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -1617,9 +1617,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown", @@ -1648,19 +1648,19 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.10.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "is-terminal" -version = "0.4.13" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1678,6 +1678,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.14.0" @@ -1782,9 +1791,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" dependencies = [ "value-bag", ] @@ -1847,9 +1856,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" +checksum = "b3b1c9bd4fe1f0f8b387f6eb9eb3b4a1aa26185e5750efb9140301703f62cd1b" dependencies = [ "adler2", ] @@ -1979,18 +1988,18 @@ dependencies = [ [[package]] name = "oid-registry" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "264c56d1492c13e769662197fb6b94e0a52abe52d27efac374615799a4bf453d" +checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" dependencies = [ "asn1-rs", ] [[package]] name = "once_cell" -version = "1.20.2" +version = "1.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" [[package]] name = "oorandom" @@ -2006,9 +2015,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.70" +version = "0.10.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6" +checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" dependencies = [ "bitflags", "cfg-if", @@ -2027,14 +2036,14 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] name = "openssl-sys" -version = "0.9.105" +version = "0.9.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc" +checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" dependencies = [ "cc", "libc", @@ -2062,9 +2071,9 @@ dependencies = [ [[package]] name = "p384" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" +checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" dependencies = [ "elliptic-curve", "primeorder", @@ -2265,7 +2274,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" dependencies = [ "proc-macro2", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -2318,8 +2327,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.0", - "zerocopy 0.8.17", + "rand_core 0.9.1", + "zerocopy 0.8.18", ] [[package]] @@ -2339,7 +2348,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.0", + "rand_core 0.9.1", ] [[package]] @@ -2353,12 +2362,12 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" +checksum = "a88e0da7a2c97baa202165137c158d0a2e824ac465d13d81046727b34cb247d3" dependencies = [ "getrandom 0.3.1", - "zerocopy 0.8.17", + "zerocopy 0.8.18", ] [[package]] @@ -2469,15 +2478,14 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.8" +version = "0.17.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +checksum = "e75ec5e92c4d8aede845126adc388046234541629e76029599ed35a003c7ed24" dependencies = [ "cc", "cfg-if", "getrandom 0.2.15", "libc", - "spin", "untrusted", "windows-sys 0.52.0", ] @@ -2535,9 +2543,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.43" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ "bitflags", "errno", @@ -2546,21 +2554,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "rustls" -version = "0.23.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8" -dependencies = [ - "log", - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - [[package]] name = "rustls" version = "0.23.23" @@ -2592,6 +2585,21 @@ dependencies = [ "zlib-rs", ] +[[package]] +name = "rustls" +version = "0.23.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-bench" version = "0.1.0" @@ -2669,9 +2677,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" +checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" [[package]] name = "rustls-post-quantum" @@ -2739,9 +2747,9 @@ checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" [[package]] name = "same-file" @@ -2780,9 +2788,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" +checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" [[package]] name = "serde" @@ -2801,14 +2809,14 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] name = "serde_json" -version = "1.0.135" +version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" dependencies = [ "itoa", "memchr", @@ -2863,9 +2871,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.2" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" [[package]] name = "socket2" @@ -2924,9 +2932,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.96" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", @@ -2941,7 +2949,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -2976,7 +2984,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -2987,7 +2995,7 @@ checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -3110,7 +3118,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -3119,7 +3127,7 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ - "rustls 0.23.21", + "rustls 0.23.23 (registry+https://github.com/rust-lang/crates.io-index)", "tokio", ] @@ -3155,7 +3163,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -3205,9 +3213,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" [[package]] name = "universal-hash" @@ -3334,7 +3342,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", "wasm-bindgen-shared", ] @@ -3369,7 +3377,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3395,9 +3403,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.7" +version = "0.26.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" +checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" dependencies = [ "rustls-pki-types", ] @@ -3482,7 +3490,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -3493,7 +3501,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -3752,7 +3760,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", "synstructure", ] @@ -3768,11 +3776,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.17" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa91407dacce3a68c56de03abe2760159582b846c6a4acd2f456618087f12713" +checksum = "79386d31a42a4996e3336b0919ddb90f81112af416270cff95b5f5af22b839c2" dependencies = [ - "zerocopy-derive 0.8.17", + "zerocopy-derive 0.8.18", ] [[package]] @@ -3783,18 +3791,18 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] name = "zerocopy-derive" -version = "0.8.17" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06718a168365cad3d5ff0bb133aad346959a2074bd4a85c121255a11304a8626" +checksum = "76331675d372f91bf8d17e13afbd5fe639200b73d01f0fc748bb059f9cca2db7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -3814,7 +3822,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", "synstructure", ] @@ -3835,7 +3843,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] @@ -3857,7 +3865,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] From 8cf91611e46930e8d72c79b6d1e06c690d9cfddd Mon Sep 17 00:00:00 2001 From: edef Date: Mon, 17 Feb 2025 22:22:41 +0000 Subject: [PATCH 059/403] Move dangerous_extract_secrets implementation into ConnectionCore The method body only accesses members of ConnectionCore, so it makes more sense to have it as a method of ConnectionCore directly. ConnectionCore is used by both the unbuffered and buffered APIs, so this simplifies exposing it from both without code duplication. --- rustls/src/conn.rs | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/rustls/src/conn.rs b/rustls/src/conn.rs index 426d3770cce..450b4e298b2 100644 --- a/rustls/src/conn.rs +++ b/rustls/src/conn.rs @@ -467,18 +467,7 @@ impl ConnectionCommon { /// 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 { - if !self.enable_secret_extraction { - return Err(Error::General("Secret extraction is disabled".into())); - } - - let st = self.core.state?; - - let record_layer = self.core.common_state.record_layer; - let PartiallyExtractedSecrets { tx, rx } = st.extract_secrets()?; - Ok(ExtractedSecrets { - tx: (record_layer.write_seq(), tx), - rx: (record_layer.read_seq(), rx), - }) + self.core.dangerous_extract_secrets() } /// Sets a limit on the internal buffers used to buffer @@ -1161,6 +1150,24 @@ impl ConnectionCore { .process_main_protocol(msg, state, &mut self.data, sendable_plaintext) } + pub(crate) fn dangerous_extract_secrets(self) -> Result { + if !self + .common_state + .enable_secret_extraction + { + return Err(Error::General("Secret extraction is disabled".into())); + } + + let st = self.state?; + + let record_layer = self.common_state.record_layer; + let PartiallyExtractedSecrets { tx, rx } = st.extract_secrets()?; + Ok(ExtractedSecrets { + tx: (record_layer.write_seq(), tx), + rx: (record_layer.read_seq(), rx), + }) + } + pub(crate) fn export_keying_material>( &self, mut output: T, From f4fc28a4c0c6142d9235affec6c6bb4ad35012f6 Mon Sep 17 00:00:00 2001 From: edef Date: Mon, 17 Feb 2025 22:22:41 +0000 Subject: [PATCH 060/403] unbuffered: introduce dangerous_extract_secrets, analogous to buffered API The test is largely copied from the buffered API tests, and doesn't provide full coverage. They are testing the same underlying code, so this seems minor compared to creating further unnecessary duplication. --- rustls/src/client/client_conn.rs | 8 ++- rustls/src/conn.rs | 8 +++ rustls/src/server/server_conn.rs | 7 +++ rustls/tests/unbuffered.rs | 95 +++++++++++++++++++++++++++++++- 4 files changed, 116 insertions(+), 2 deletions(-) diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index c7effea16fa..e2706c762b6 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -18,7 +18,7 @@ use crate::log::trace; use crate::msgs::enums::NamedGroup; use crate::msgs::handshake::ClientExtension; use crate::msgs::persist; -use crate::suites::SupportedCipherSuite; +use crate::suites::{ExtractedSecrets, SupportedCipherSuite}; use crate::sync::Arc; #[cfg(feature = "std")] use crate::time_provider::DefaultTimeProvider; @@ -847,6 +847,12 @@ impl UnbufferedClientConnection { inner: ConnectionCore::for_client(config, name, Vec::new(), Protocol::Tcp)?.into(), }) } + + /// 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 { + self.inner.dangerous_extract_secrets() + } } impl Deref for UnbufferedClientConnection { diff --git a/rustls/src/conn.rs b/rustls/src/conn.rs index 450b4e298b2..92512a72a1b 100644 --- a/rustls/src/conn.rs +++ b/rustls/src/conn.rs @@ -813,6 +813,14 @@ impl From> for UnbufferedConnectionCommon { } } +impl UnbufferedConnectionCommon { + /// 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 { + self.core.dangerous_extract_secrets() + } +} + impl Deref for UnbufferedConnectionCommon { type Target = CommonState; diff --git a/rustls/src/server/server_conn.rs b/rustls/src/server/server_conn.rs index bb790da83fc..902f56fbe20 100644 --- a/rustls/src/server/server_conn.rs +++ b/rustls/src/server/server_conn.rs @@ -25,6 +25,7 @@ use crate::msgs::base::Payload; use crate::msgs::enums::CertificateType; use crate::msgs::handshake::{ClientHelloPayload, ProtocolName, ServerExtension}; use crate::msgs::message::Message; +use crate::suites::ExtractedSecrets; use crate::sync::Arc; #[cfg(feature = "std")] use crate::time_provider::DefaultTimeProvider; @@ -891,6 +892,12 @@ impl UnbufferedServerConnection { )?), }) } + + /// 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 { + self.inner.dangerous_extract_secrets() + } } impl Deref for UnbufferedServerConnection { diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index e37030b5b5e..a255a84741f 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -3,6 +3,7 @@ use std::num::NonZeroUsize; use rustls::client::{ClientConnectionData, EarlyDataError, UnbufferedClientConnection}; +use rustls::crypto::CryptoProvider; use rustls::server::{ServerConnectionData, UnbufferedServerConnection}; use rustls::unbuffered::{ ConnectionState, EncodeError, EncryptError, InsufficientSizeError, ReadTraffic, @@ -10,13 +11,15 @@ use rustls::unbuffered::{ }; use rustls::version::TLS13; use rustls::{ - AlertDescription, CertificateError, ClientConfig, Error, InvalidMessage, ServerConfig, SideData, + AlertDescription, CertificateError, ClientConfig, ConnectionTrafficSecrets, Error, + InvalidMessage, ServerConfig, SideData, }; use super::*; mod common; use common::*; +use provider::cipher_suite; const MAX_ITERATIONS: usize = 100; @@ -1411,6 +1414,96 @@ fn server_receives_incorrect_first_handshake_message() { }; } +/// Test that secrets can be extracted and used for encryption/decryption. +#[test] +fn test_secret_extraction_enabled() { + // Normally, secret extraction would be used to configure kTLS (TLS offload + // to the kernel). We want this test to run on any platform, though, so + // instead we just compare secrets for equality. + + // TLS 1.2 and 1.3 have different mechanisms for key exchange and handshake, + // and secrets are stored/extracted differently, so we want to test them both. + // We support 3 different AEAD algorithms (AES-128-GCM mode, AES-256-GCM, and + // Chacha20Poly1305), so that's 2*3 = 6 combinations to test. + let kt = KeyType::Rsa2048; + for suite in [ + cipher_suite::TLS13_AES_128_GCM_SHA256, + cipher_suite::TLS13_AES_256_GCM_SHA384, + #[cfg(not(feature = "fips"))] + cipher_suite::TLS13_CHACHA20_POLY1305_SHA256, + cipher_suite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + cipher_suite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + #[cfg(not(feature = "fips"))] + cipher_suite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + ] { + let version = suite.version(); + println!("Testing suite {:?}", suite.suite().as_str()); + + // Only offer the cipher suite (and protocol version) that we're testing + let mut server_config = ServerConfig::builder_with_provider( + CryptoProvider { + cipher_suites: vec![suite], + ..provider::default_provider() + } + .into(), + ) + .with_protocol_versions(&[version]) + .unwrap() + .with_no_client_auth() + .with_single_cert(kt.get_chain(), kt.get_key()) + .unwrap(); + // Opt into secret extraction from both sides + server_config.enable_secret_extraction = true; + let server_config = Arc::new(server_config); + + let mut client_config = make_client_config(kt); + client_config.enable_secret_extraction = true; + + let mut outcome = run( + Arc::new(client_config), + &mut NO_ACTIONS.clone(), + server_config.clone(), + &mut NO_ACTIONS.clone(), + ); + + let client = outcome.client.take().unwrap(); + let server = outcome.server.take().unwrap(); + + // The handshake is finished, we're now able to extract traffic secrets + let client_secrets = client + .dangerous_extract_secrets() + .unwrap(); + let server_secrets = server + .dangerous_extract_secrets() + .unwrap(); + + // Comparing secrets for equality is something you should never have to + // do in production code, so ConnectionTrafficSecrets doesn't implement + // PartialEq/Eq on purpose. Instead, we have to get creative. + fn explode_secrets(s: &ConnectionTrafficSecrets) -> (&[u8], &[u8]) { + match s { + ConnectionTrafficSecrets::Aes128Gcm { key, iv } => (key.as_ref(), iv.as_ref()), + ConnectionTrafficSecrets::Aes256Gcm { key, iv } => (key.as_ref(), iv.as_ref()), + ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv } => { + (key.as_ref(), iv.as_ref()) + } + _ => panic!("unexpected secret type"), + } + } + + fn assert_secrets_equal( + (l_seq, l_sec): (u64, ConnectionTrafficSecrets), + (r_seq, r_sec): (u64, ConnectionTrafficSecrets), + ) { + assert_eq!(l_seq, r_seq); + assert_eq!(explode_secrets(&l_sec), explode_secrets(&r_sec)); + } + + assert_secrets_equal(client_secrets.tx, server_secrets.rx); + assert_secrets_equal(client_secrets.rx, server_secrets.tx); + } +} + const TLS12_CLIENT_TRANSCRIPT: &[&str] = &[ "EncodeTlsData", "TransmitTlsData", From f0e71ab638eee6602171cd50f398df0491d56cfa Mon Sep 17 00:00:00 2001 From: "@brody4hire - C. Jonathan Brody" Date: Tue, 18 Feb 2025 21:43:05 -0500 Subject: [PATCH 061/403] docs: fix MSRV etc. --- README.md | 4 ++-- rustls/src/lib.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3a66ee9a9ed..c0786c10ab4 100644 --- a/README.md +++ b/README.md @@ -55,10 +55,10 @@ can replace all cryptography dependencies of rustls. This is a route to being p 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 +Specifying `default-features = false` when depending on rustls will remove the implicit dependency on aws-lc-rs. -Rustls requires Rust 1.63 or later. It has an optional dependency on zlib-rs which requires 1.75 or later. +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 diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index dfcdd1d5ab4..4cf6e9b679c 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -21,10 +21,10 @@ //! 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 +//! Specifying `default-features = false` when depending on rustls will remove the implicit //! dependency on aws-lc-rs. //! -//! Rustls requires Rust 1.63 or later. It has an optional dependency on zlib-rs which requires 1.75 or later. +//! 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 From ede4b26fa5e24de5ced0ea874fd3a97e18e18a9e Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Fri, 21 Feb 2025 10:03:26 +0100 Subject: [PATCH 062/403] Allow disallowed_types in test modules --- rustls/benches/benchmarks.rs | 1 + rustls/tests/api.rs | 2 +- rustls/tests/client_cert_verifier.rs | 2 +- rustls/tests/common/mod.rs | 2 +- rustls/tests/runners/key_log_file_env.rs | 2 ++ rustls/tests/server_cert_verifier.rs | 2 +- rustls/tests/unbuffered.rs | 2 +- 7 files changed, 8 insertions(+), 5 deletions(-) diff --git a/rustls/benches/benchmarks.rs b/rustls/benches/benchmarks.rs index cc8016fc7a7..6591aa9f7ae 100644 --- a/rustls/benches/benchmarks.rs +++ b/rustls/benches/benchmarks.rs @@ -1,4 +1,5 @@ #![cfg(feature = "ring")] +#![allow(clippy::disallowed_types)] use bencher::{benchmark_group, benchmark_main, Bencher}; use rustls::crypto::ring as provider; diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 470a1ad1ac1..935ee456d02 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -1,6 +1,6 @@ //! Assorted public API tests. -#![allow(clippy::duplicate_mod)] +#![allow(clippy::disallowed_types, clippy::duplicate_mod)] use std::fmt::Debug; use std::io::{self, BufRead, IoSlice, Read, Write}; diff --git a/rustls/tests/client_cert_verifier.rs b/rustls/tests/client_cert_verifier.rs index 9069680f667..5c3cfeb15ba 100644 --- a/rustls/tests/client_cert_verifier.rs +++ b/rustls/tests/client_cert_verifier.rs @@ -1,6 +1,6 @@ //! Tests for configuring and using a [`ClientCertVerifier`] for a server. -#![allow(clippy::duplicate_mod)] +#![allow(clippy::disallowed_types, clippy::duplicate_mod)] use super::*; diff --git a/rustls/tests/common/mod.rs b/rustls/tests/common/mod.rs index a66812d19d7..9118b2b4cea 100644 --- a/rustls/tests/common/mod.rs +++ b/rustls/tests/common/mod.rs @@ -1,5 +1,5 @@ #![allow(dead_code)] -#![allow(clippy::duplicate_mod)] +#![allow(clippy::disallowed_types, clippy::duplicate_mod)] use std::io; use std::ops::DerefMut; diff --git a/rustls/tests/runners/key_log_file_env.rs b/rustls/tests/runners/key_log_file_env.rs index 74832344851..9a34b5a214f 100644 --- a/rustls/tests/runners/key_log_file_env.rs +++ b/rustls/tests/runners/key_log_file_env.rs @@ -1,3 +1,5 @@ +#![allow(clippy::disallowed_types)] + use std::env; use std::sync::Mutex; diff --git a/rustls/tests/server_cert_verifier.rs b/rustls/tests/server_cert_verifier.rs index 6a3ecad7042..188f5c0b682 100644 --- a/rustls/tests/server_cert_verifier.rs +++ b/rustls/tests/server_cert_verifier.rs @@ -1,6 +1,6 @@ //! Tests for configuring and using a [`ServerCertVerifier`] for a client. -#![allow(clippy::duplicate_mod)] +#![allow(clippy::disallowed_types, clippy::duplicate_mod)] use super::*; diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index a255a84741f..657b0782e20 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -1,4 +1,4 @@ -#![allow(clippy::duplicate_mod)] +#![allow(clippy::disallowed_types, clippy::duplicate_mod)] use std::num::NonZeroUsize; From 177cb0cef4d97b09335948b9265112deb03f2b23 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Fri, 21 Feb 2025 10:03:55 +0100 Subject: [PATCH 063/403] Switch to 2024 style --- .rustfmt.toml | 1 + bogo/src/main.rs | 19 +- ci-bench/src/benchmark.rs | 2 +- ci-bench/src/callgrind.rs | 7 +- ci-bench/src/main.rs | 14 +- ci-bench/src/util.rs | 2 +- connect-tests/tests/ech.rs | 8 +- examples/src/bin/ech-client.rs | 17 +- examples/src/bin/limitedclient.rs | 4 +- examples/src/bin/server_acceptor.rs | 19 +- examples/src/bin/simple_0rtt_client.rs | 2 +- examples/src/bin/simpleclient.rs | 2 +- examples/src/bin/tlsclient-mio.rs | 8 +- examples/src/bin/tlsserver-mio.rs | 4 +- examples/src/bin/unbuffered-server.rs | 2 +- openssl-tests/src/ffdhe.rs | 4 +- openssl-tests/src/ffdhe_kx_with_openssl.rs | 2 +- openssl-tests/src/raw_key_openssl_interop.rs | 8 +- openssl-tests/src/validate_ffdhe_params.rs | 2 +- provider-example/examples/client.rs | 2 +- provider-example/examples/server.rs | 2 +- provider-example/src/aead.rs | 8 +- provider-example/src/hpke.rs | 10 +- provider-example/src/verify.rs | 4 +- rustls-fuzzing-provider/src/lib.rs | 12 +- rustls-post-quantum/benches/benchmarks.rs | 4 +- rustls-post-quantum/examples/client.rs | 2 +- rustls/benches/benchmarks.rs | 2 +- rustls/examples/internal/test_ca.rs | 6 +- rustls/src/client/builder.rs | 6 +- rustls/src/client/client_conn.rs | 12 +- rustls/src/client/common.rs | 2 +- rustls/src/client/ech.rs | 8 +- rustls/src/client/handy.rs | 6 +- rustls/src/client/hs.rs | 6 +- rustls/src/client/tls12.rs | 4 +- rustls/src/client/tls13.rs | 16 +- rustls/src/common_state.rs | 8 +- rustls/src/compress.rs | 2 +- rustls/src/conn.rs | 11 +- rustls/src/conn/unbuffered.rs | 2 +- rustls/src/crypto/aws_lc_rs/hpke.rs | 4 +- rustls/src/crypto/aws_lc_rs/mod.rs | 8 +- rustls/src/crypto/aws_lc_rs/pq/mod.rs | 2 +- rustls/src/crypto/aws_lc_rs/sign.rs | 106 +++++---- rustls/src/crypto/aws_lc_rs/ticketer.rs | 4 +- rustls/src/crypto/aws_lc_rs/tls12.rs | 4 +- rustls/src/crypto/aws_lc_rs/tls13.rs | 12 +- rustls/src/crypto/hpke.rs | 2 +- rustls/src/crypto/mod.rs | 14 +- rustls/src/crypto/ring/mod.rs | 2 +- rustls/src/crypto/ring/sign.rs | 76 ++++--- rustls/src/crypto/ring/tls12.rs | 6 +- rustls/src/crypto/ring/tls13.rs | 4 +- rustls/src/crypto/tls12.rs | 2 +- rustls/src/crypto/tls13.rs | 13 +- rustls/src/enums.rs | 2 +- rustls/src/key_log_file.rs | 26 ++- rustls/src/lib.rs | 16 +- rustls/src/msgs/deframer/handshake.rs | 2 +- rustls/src/msgs/deframer/mod.rs | 50 +++-- rustls/src/msgs/fragmenter.rs | 2 +- rustls/src/msgs/handshake.rs | 2 +- rustls/src/msgs/handshake_test.rs | 28 ++- rustls/src/msgs/message/outbound.rs | 2 +- rustls/src/msgs/message_test.rs | 2 +- rustls/src/msgs/persist.rs | 2 +- rustls/src/quic.rs | 4 +- rustls/src/server/builder.rs | 4 +- rustls/src/server/handy.rs | 50 +++-- rustls/src/server/hs.rs | 4 +- rustls/src/server/server_conn.rs | 6 +- rustls/src/server/tls12.rs | 2 +- rustls/src/server/tls13.rs | 10 +- rustls/src/suites.rs | 24 +- rustls/src/ticketer.rs | 2 +- rustls/src/tls12/mod.rs | 28 ++- rustls/src/tls13/key_schedule.rs | 10 +- rustls/src/verifybench.rs | 2 +- rustls/src/webpki/client_verifier.rs | 12 +- rustls/src/webpki/mod.rs | 10 +- rustls/src/webpki/server_verifier.rs | 12 +- rustls/src/webpki/verify.rs | 5 +- rustls/tests/api.rs | 218 +++++++++++-------- rustls/tests/api_ffdhe.rs | 2 +- rustls/tests/client_cert_verifier.rs | 5 +- rustls/tests/common/mod.rs | 52 +++-- rustls/tests/ech.rs | 5 +- rustls/tests/key_log_file_env.rs | 4 +- rustls/tests/process_provider.rs | 4 +- rustls/tests/server_cert_verifier.rs | 28 ++- rustls/tests/unbuffered.rs | 36 +-- 92 files changed, 670 insertions(+), 524 deletions(-) diff --git a/.rustfmt.toml b/.rustfmt.toml index 745d2dc30f6..c72ffcd3f73 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1 +1,2 @@ chain_width = 40 +style_edition = "2024" diff --git a/bogo/src/main.rs b/bogo/src/main.rs index b875a8ce2b1..d4aa72c3e8d 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -9,7 +9,7 @@ use std::io::{self, Read, Write}; use std::sync::Arc; use std::{env, net, process, thread, time}; -use base64::prelude::{Engine, BASE64_STANDARD}; +use base64::prelude::{BASE64_STANDARD, Engine}; use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; use rustls::client::{ ClientConfig, ClientConnection, EchConfig, EchGreaseConfig, EchMode, EchStatus, Resumption, @@ -17,7 +17,7 @@ use rustls::client::{ }; use rustls::crypto::aws_lc_rs::hpke; use rustls::crypto::hpke::{Hpke, HpkePublicKey}; -use rustls::crypto::{aws_lc_rs, ring, CryptoProvider}; +use rustls::crypto::{CryptoProvider, aws_lc_rs, ring}; use rustls::internal::msgs::codec::{Codec, Reader}; use rustls::internal::msgs::handshake::EchConfigPayload; use rustls::internal::msgs::persist::ServerSessionValue; @@ -28,10 +28,10 @@ use rustls::server::{ ClientHello, ProducesTickets, ServerConfig, ServerConnection, WebPkiClientVerifier, }; use rustls::{ - client, compress, server, sign, version, AlertDescription, CertificateCompressionAlgorithm, - CertificateError, Connection, DigitallySignedStruct, DistinguishedName, Error, HandshakeKind, - InvalidMessage, NamedGroup, PeerIncompatible, PeerMisbehaved, ProtocolVersion, RootCertStore, - Side, SignatureAlgorithm, SignatureScheme, SupportedProtocolVersion, + AlertDescription, CertificateCompressionAlgorithm, CertificateError, Connection, + DigitallySignedStruct, DistinguishedName, Error, HandshakeKind, InvalidMessage, NamedGroup, + PeerIncompatible, PeerMisbehaved, ProtocolVersion, RootCertStore, Side, SignatureAlgorithm, + SignatureScheme, SupportedProtocolVersion, client, compress, server, sign, version, }; static BOGO_NACK: i32 = 89; @@ -1704,9 +1704,10 @@ pub fn main() { ccfg: &Option>, ) -> Connection { assert!(opts.quic_transport_params.is_empty()); - assert!(opts - .expect_quic_transport_params - .is_empty()); + assert!( + opts.expect_quic_transport_params + .is_empty() + ); if opts.side == Side::Server { let scfg = Arc::clone(scfg.as_ref().unwrap()); diff --git a/ci-bench/src/benchmark.rs b/ci-bench/src/benchmark.rs index 6434df68a54..1e38cc5401e 100644 --- a/ci-bench/src/benchmark.rs +++ b/ci-bench/src/benchmark.rs @@ -3,9 +3,9 @@ use std::sync::Arc; use fxhash::FxHashMap; use itertools::Itertools; +use crate::Side; use crate::callgrind::InstructionCounts; use crate::util::KeyType; -use crate::Side; /// Validates a benchmark collection, returning an error if the provided benchmarks are invalid /// diff --git a/ci-bench/src/callgrind.rs b/ci-bench/src/callgrind.rs index 2dba776762d..4ff3a0f6639 100644 --- a/ci-bench/src/callgrind.rs +++ b/ci-bench/src/callgrind.rs @@ -6,8 +6,8 @@ use std::process::{Child, Command, Stdio}; use anyhow::Context; -use crate::benchmark::Benchmark; use crate::Side; +use crate::benchmark::Benchmark; /// The subdirectory in which the callgrind output should be stored const CALLGRIND_OUTPUT_SUBDIR: &str = "callgrind"; @@ -89,7 +89,10 @@ impl CallgrindRunner { if status.success() { Ok(()) } else { - anyhow::bail!("Failed to launch callgrind. Error: {}. Please ensure that valgrind is installed and on the $PATH.", status) + anyhow::bail!( + "Failed to launch callgrind. Error: {}. Please ensure that valgrind is installed and on the $PATH.", + status + ) } } } diff --git a/ci-bench/src/main.rs b/ci-bench/src/main.rs index fd27a77cdbe..2b768bab87a 100644 --- a/ci-bench/src/main.rs +++ b/ci-bench/src/main.rs @@ -16,9 +16,9 @@ use itertools::Itertools; use rayon::iter::Either; use rayon::prelude::*; use rustls::client::Resumption; -use rustls::crypto::{aws_lc_rs, ring, CryptoProvider, GetRandomFailed, SecureRandom}; -use rustls::pki_types::pem::PemObject; +use rustls::crypto::{CryptoProvider, GetRandomFailed, SecureRandom, aws_lc_rs, ring}; use rustls::pki_types::CertificateDer; +use rustls::pki_types::pem::PemObject; use rustls::server::{NoServerSessionStorage, ServerSessionMemoryCache, WebPkiClientVerifier}; use rustls::{ CipherSuite, ClientConfig, ClientConnection, HandshakeKind, ProtocolVersion, RootCertStore, @@ -26,16 +26,16 @@ use rustls::{ }; use crate::benchmark::{ - get_reported_instr_count, validate_benchmarks, Benchmark, BenchmarkKind, BenchmarkParams, - ResumptionKind, + Benchmark, BenchmarkKind, BenchmarkParams, ResumptionKind, get_reported_instr_count, + validate_benchmarks, }; use crate::callgrind::{CallgrindRunner, CountInstructions}; +use crate::util::KeyType; use crate::util::async_io::{self, AsyncRead, AsyncWrite}; use crate::util::transport::{ read_handshake_message, read_plaintext_to_end_bounded, send_handshake_message, write_all_plaintext_bounded, }; -use crate::util::KeyType; mod benchmark; mod callgrind; @@ -787,7 +787,9 @@ fn print_report(result: &CompareResult) { if !result.missing_in_baseline.is_empty() { println!("### ⚠️ Warning: missing benchmarks"); println!(); - println!("The following benchmark scenarios are present in the candidate but not in the baseline:"); + println!( + "The following benchmark scenarios are present in the candidate but not in the baseline:" + ); println!(); for scenario in &result.missing_in_baseline { println!("* {scenario}"); diff --git a/ci-bench/src/util.rs b/ci-bench/src/util.rs index b32da09cd7b..177663bc963 100644 --- a/ci-bench/src/util.rs +++ b/ci-bench/src/util.rs @@ -37,7 +37,7 @@ pub mod async_io { use std::collections::VecDeque; use std::fs::File; use std::future::Future; - use std::pin::{pin, Pin}; + use std::pin::{Pin, pin}; use std::rc::Rc; use std::task::{Poll, RawWaker, RawWakerVTable, Waker}; use std::{io, ptr, task}; diff --git a/connect-tests/tests/ech.rs b/connect-tests/tests/ech.rs index d0a3f466b51..134eb8a610b 100644 --- a/connect-tests/tests/ech.rs +++ b/connect-tests/tests/ech.rs @@ -29,9 +29,11 @@ mod ech_config { let parsed_configs = Vec::::read(&mut Reader::init(&tls_encoded_list)) .expect("failed to deserialize ECH config list"); assert!(!parsed_configs.is_empty()); - assert!(parsed_configs - .iter() - .all(|config| matches!(config, EchConfigPayload::V18(_)))); + assert!( + parsed_configs + .iter() + .all(|config| matches!(config, EchConfigPayload::V18(_))) + ); } /// Use `resolver` to make an HTTPS record type query for `domain`, returning the diff --git a/examples/src/bin/ech-client.rs b/examples/src/bin/ech-client.rs index 62e9869b489..46cabdc1c7d 100644 --- a/examples/src/bin/ech-client.rs +++ b/examples/src/bin/ech-client.rs @@ -30,7 +30,7 @@ use std::error::Error; use std::fs; -use std::io::{stdout, BufReader, Read, Write}; +use std::io::{BufReader, Read, Write, stdout}; use std::net::{TcpStream, ToSocketAddrs}; use std::sync::Arc; @@ -40,13 +40,13 @@ use hickory_resolver::proto::rr::rdata::svcb::{SvcParamKey, SvcParamValue}; use hickory_resolver::proto::rr::{RData, RecordType}; use hickory_resolver::{ResolveError, Resolver, TokioResolver}; use log::trace; +use rustls::RootCertStore; use rustls::client::{EchConfig, EchGreaseConfig, EchMode, EchStatus}; use rustls::crypto::aws_lc_rs; use rustls::crypto::aws_lc_rs::hpke::ALL_SUPPORTED_SUITES; use rustls::crypto::hpke::Hpke; use rustls::pki_types::pem::PemObject; use rustls::pki_types::{CertificateDer, EchConfigListBytes, ServerName}; -use rustls::RootCertStore; #[tokio::main] async fn main() -> Result<(), Box> { @@ -136,12 +136,13 @@ async fn main() -> Result<(), Box> { let mut sock = TcpStream::connect(sock_addr)?; let mut tls = rustls::Stream::new(&mut conn, &mut sock); - let request = - format!( - "GET /{} HTTP/1.1\r\nHost: {}\r\nConnection: close\r\nAccept-Encoding: identity\r\n\r\n", - args.path, - args.host.as_ref().unwrap_or(&args.inner_hostname), - ); + let request = format!( + "GET /{} HTTP/1.1\r\nHost: {}\r\nConnection: close\r\nAccept-Encoding: identity\r\n\r\n", + args.path, + args.host + .as_ref() + .unwrap_or(&args.inner_hostname), + ); dbg!(&request); tls.write_all(request.as_bytes())?; assert!(!tls.conn.is_handshaking()); diff --git a/examples/src/bin/limitedclient.rs b/examples/src/bin/limitedclient.rs index 62443caef7e..701c75c703f 100644 --- a/examples/src/bin/limitedclient.rs +++ b/examples/src/bin/limitedclient.rs @@ -2,11 +2,11 @@ //! so that unused cryptography in rustls can be discarded by the linker. You can //! observe using `nm` that the binary of this program does not contain any AES code. -use std::io::{stdout, Read, Write}; +use std::io::{Read, Write, stdout}; use std::net::TcpStream; use std::sync::Arc; -use rustls::crypto::{aws_lc_rs as provider, CryptoProvider}; +use rustls::crypto::{CryptoProvider, aws_lc_rs as provider}; fn main() { let root_store = rustls::RootCertStore::from_iter( diff --git a/examples/src/bin/server_acceptor.rs b/examples/src/bin/server_acceptor.rs index 46f4141b3e8..0239bb4442d 100644 --- a/examples/src/bin/server_acceptor.rs +++ b/examples/src/bin/server_acceptor.rs @@ -14,9 +14,9 @@ use std::{fs, thread}; use clap::Parser; use rcgen::KeyPair; +use rustls::RootCertStore; use rustls::pki_types::{CertificateRevocationListDer, PrivatePkcs8KeyDer}; use rustls::server::{Acceptor, ClientHello, ServerConfig, WebPkiClientVerifier}; -use rustls::RootCertStore; fn main() { let args = Args::parse(); @@ -280,14 +280,15 @@ impl CrlUpdater { thread::sleep(self.sleep_duration); let revoked_certs = if revoked { - vec![self - .pki - .client_cert - .cert - .params() - .serial_number - .clone() - .unwrap()] + vec![ + self.pki + .client_cert + .cert + .params() + .serial_number + .clone() + .unwrap(), + ] } else { Vec::default() }; diff --git a/examples/src/bin/simple_0rtt_client.rs b/examples/src/bin/simple_0rtt_client.rs index 6a27d44cb0e..5ffbeb6ce88 100644 --- a/examples/src/bin/simple_0rtt_client.rs +++ b/examples/src/bin/simple_0rtt_client.rs @@ -19,9 +19,9 @@ use std::net::TcpStream; use std::str::FromStr; use std::sync::Arc; +use rustls::RootCertStore; use rustls::pki_types::pem::PemObject; use rustls::pki_types::{CertificateDer, ServerName}; -use rustls::RootCertStore; fn start_connection(config: &Arc, domain_name: &str, port: u16) { let server_name = ServerName::try_from(domain_name) diff --git a/examples/src/bin/simpleclient.rs b/examples/src/bin/simpleclient.rs index 6b042ed0211..b3fd033d69b 100644 --- a/examples/src/bin/simpleclient.rs +++ b/examples/src/bin/simpleclient.rs @@ -8,7 +8,7 @@ //! Note that `unwrap()` is used to deal with networking errors; this is not something //! that is sensible outside of example code. -use std::io::{stdout, Read, Write}; +use std::io::{Read, Write, stdout}; use std::net::TcpStream; use std::sync::Arc; diff --git a/examples/src/bin/tlsclient-mio.rs b/examples/src/bin/tlsclient-mio.rs index 02a84384322..b999223b08e 100644 --- a/examples/src/bin/tlsclient-mio.rs +++ b/examples/src/bin/tlsclient-mio.rs @@ -26,10 +26,10 @@ use std::{process, str}; use clap::Parser; use mio::net::TcpStream; -use rustls::crypto::{aws_lc_rs as provider, CryptoProvider}; +use rustls::RootCertStore; +use rustls::crypto::{CryptoProvider, aws_lc_rs as provider}; use rustls::pki_types::pem::PemObject; use rustls::pki_types::{CertificateDer, PrivateKeyDer, ServerName}; -use rustls::RootCertStore; const CLIENT: mio::Token = mio::Token(0); @@ -329,10 +329,10 @@ fn load_private_key(filename: &str) -> PrivateKeyDer<'static> { } mod danger { + use rustls::DigitallySignedStruct; use rustls::client::danger::HandshakeSignatureValid; - use rustls::crypto::{verify_tls12_signature, verify_tls13_signature, CryptoProvider}; + use rustls::crypto::{CryptoProvider, verify_tls12_signature, verify_tls13_signature}; use rustls::pki_types::{CertificateDer, ServerName, UnixTime}; - use rustls::DigitallySignedStruct; #[derive(Debug)] pub struct NoCertificateVerification(CryptoProvider); diff --git a/examples/src/bin/tlsserver-mio.rs b/examples/src/bin/tlsserver-mio.rs index 7dac1af6ff7..c85222058f7 100644 --- a/examples/src/bin/tlsserver-mio.rs +++ b/examples/src/bin/tlsserver-mio.rs @@ -28,11 +28,11 @@ use std::{fs, net}; use clap::{Parser, Subcommand}; use log::{debug, error}; use mio::net::{TcpListener, TcpStream}; -use rustls::crypto::{aws_lc_rs as provider, CryptoProvider}; +use rustls::RootCertStore; +use rustls::crypto::{CryptoProvider, aws_lc_rs as provider}; use rustls::pki_types::pem::PemObject; use rustls::pki_types::{CertificateDer, CertificateRevocationListDer, PrivateKeyDer}; use rustls::server::WebPkiClientVerifier; -use rustls::RootCertStore; // Token for our listening socket. const LISTENER: mio::Token = mio::Token(0); diff --git a/examples/src/bin/unbuffered-server.rs b/examples/src/bin/unbuffered-server.rs index 764a2594280..7dcbee84171 100644 --- a/examples/src/bin/unbuffered-server.rs +++ b/examples/src/bin/unbuffered-server.rs @@ -8,6 +8,7 @@ use std::net::{TcpListener, TcpStream}; use std::path::Path; use std::sync::Arc; +use rustls::ServerConfig; use rustls::pki_types::pem::PemObject; use rustls::pki_types::{CertificateDer, PrivateKeyDer}; use rustls::server::UnbufferedServerConnection; @@ -15,7 +16,6 @@ use rustls::unbuffered::{ AppDataRecord, ConnectionState, EncodeError, EncryptError, InsufficientSizeError, UnbufferedStatus, }; -use rustls::ServerConfig; fn main() -> Result<(), Box> { let mut args = env::args(); diff --git a/openssl-tests/src/ffdhe.rs b/openssl-tests/src/ffdhe.rs index 941005b4b36..20bd634b36f 100644 --- a/openssl-tests/src/ffdhe.rs +++ b/openssl-tests/src/ffdhe.rs @@ -1,7 +1,7 @@ use num_bigint::BigUint; use rustls::crypto::{ - aws_lc_rs as provider, ActiveKeyExchange, CipherSuiteCommon, KeyExchangeAlgorithm, - SharedSecret, SupportedKxGroup, + ActiveKeyExchange, CipherSuiteCommon, KeyExchangeAlgorithm, SharedSecret, SupportedKxGroup, + aws_lc_rs as provider, }; use rustls::ffdhe_groups::FfdheGroup; use rustls::{CipherSuite, NamedGroup, SupportedCipherSuite, Tls12CipherSuite}; diff --git a/openssl-tests/src/ffdhe_kx_with_openssl.rs b/openssl-tests/src/ffdhe_kx_with_openssl.rs index cc7cf3fa1d3..19ed8c54970 100644 --- a/openssl-tests/src/ffdhe_kx_with_openssl.rs +++ b/openssl-tests/src/ffdhe_kx_with_openssl.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use std::{fs, str, thread}; use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; -use rustls::crypto::{aws_lc_rs as provider, CryptoProvider}; +use rustls::crypto::{CryptoProvider, aws_lc_rs as provider}; use rustls::pki_types::pem::PemObject; use rustls::pki_types::{CertificateDer, PrivateKeyDer}; use rustls::version::{TLS12, TLS13}; diff --git a/openssl-tests/src/raw_key_openssl_interop.rs b/openssl-tests/src/raw_key_openssl_interop.rs index 6726244818e..589e4a08bb6 100644 --- a/openssl-tests/src/raw_key_openssl_interop.rs +++ b/openssl-tests/src/raw_key_openssl_interop.rs @@ -9,10 +9,10 @@ mod client { use std::net::TcpStream; use std::sync::Arc; - use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; use rustls::client::AlwaysResolvesClientRawPublicKeys; + use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; use rustls::crypto::{ - aws_lc_rs as provider, verify_tls13_signature_with_raw_key, WebPkiSupportedAlgorithms, + WebPkiSupportedAlgorithms, aws_lc_rs as provider, verify_tls13_signature_with_raw_key, }; use rustls::pki_types::pem::PemObject; use rustls::pki_types::{ @@ -162,12 +162,12 @@ mod server { use rustls::client::danger::HandshakeSignatureValid; use rustls::crypto::{ - aws_lc_rs as provider, verify_tls13_signature_with_raw_key, WebPkiSupportedAlgorithms, + WebPkiSupportedAlgorithms, aws_lc_rs as provider, verify_tls13_signature_with_raw_key, }; use rustls::pki_types::pem::PemObject; use rustls::pki_types::{CertificateDer, PrivateKeyDer, SubjectPublicKeyInfoDer, UnixTime}; - use rustls::server::danger::{ClientCertVerified, ClientCertVerifier}; use rustls::server::AlwaysResolvesServerRawPublicKeys; + use rustls::server::danger::{ClientCertVerified, ClientCertVerifier}; use rustls::sign::CertifiedKey; use rustls::version::TLS13; use rustls::{ diff --git a/openssl-tests/src/validate_ffdhe_params.rs b/openssl-tests/src/validate_ffdhe_params.rs index ae10871dc0e..76bab5471af 100644 --- a/openssl-tests/src/validate_ffdhe_params.rs +++ b/openssl-tests/src/validate_ffdhe_params.rs @@ -1,6 +1,6 @@ use base64::prelude::*; use rustls::ffdhe_groups::FfdheGroup; -use rustls::{ffdhe_groups, NamedGroup}; +use rustls::{NamedGroup, ffdhe_groups}; use crate::utils::verify_openssl3_available; diff --git a/provider-example/examples/client.rs b/provider-example/examples/client.rs index 9fab7e097a4..ea4a3885672 100644 --- a/provider-example/examples/client.rs +++ b/provider-example/examples/client.rs @@ -1,4 +1,4 @@ -use std::io::{stdout, Read, Write}; +use std::io::{Read, Write, stdout}; use std::net::TcpStream; use std::sync::Arc; diff --git a/provider-example/examples/server.rs b/provider-example/examples/server.rs index 4f69fc237c6..eee2de189d2 100644 --- a/provider-example/examples/server.rs +++ b/provider-example/examples/server.rs @@ -1,9 +1,9 @@ use std::io::Write; use std::sync::Arc; +use rustls::ServerConfig; use rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer}; use rustls::server::Acceptor; -use rustls::ServerConfig; fn main() { env_logger::init(); diff --git a/provider-example/src/aead.rs b/provider-example/src/aead.rs index cd7eb23a880..94073ed7e00 100644 --- a/provider-example/src/aead.rs +++ b/provider-example/src/aead.rs @@ -3,10 +3,10 @@ use alloc::boxed::Box; use chacha20poly1305::aead::Buffer; use chacha20poly1305::{AeadInPlace, KeyInit, KeySizeUser}; use rustls::crypto::cipher::{ - make_tls12_aad, make_tls13_aad, AeadKey, BorrowedPayload, InboundOpaqueMessage, - InboundPlainMessage, Iv, KeyBlockShape, MessageDecrypter, MessageEncrypter, Nonce, - OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload, Tls12AeadAlgorithm, - Tls13AeadAlgorithm, UnsupportedOperationError, NONCE_LEN, + AeadKey, BorrowedPayload, InboundOpaqueMessage, InboundPlainMessage, Iv, KeyBlockShape, + MessageDecrypter, MessageEncrypter, NONCE_LEN, Nonce, OutboundOpaqueMessage, + OutboundPlainMessage, PrefixedPayload, Tls12AeadAlgorithm, Tls13AeadAlgorithm, + UnsupportedOperationError, make_tls12_aad, make_tls13_aad, }; use rustls::{ConnectionTrafficSecrets, ContentType, ProtocolVersion}; diff --git a/provider-example/src/hpke.rs b/provider-example/src/hpke.rs index 890c2d57a22..7d61f842763 100644 --- a/provider-example/src/hpke.rs +++ b/provider-example/src/hpke.rs @@ -2,8 +2,8 @@ use alloc::boxed::Box; use alloc::vec::Vec; use core::fmt::Debug; -use hpke_rs_crypto::types::{AeadAlgorithm, KdfAlgorithm, KemAlgorithm}; use hpke_rs_crypto::HpkeCrypto; +use hpke_rs_crypto::types::{AeadAlgorithm, KdfAlgorithm, KemAlgorithm}; use hpke_rs_rust_crypto::HpkeRustCrypto; use rustls::crypto::hpke::{ EncapsulatedSecret, Hpke, HpkeOpener, HpkePrivateKey, HpkePublicKey, HpkeSealer, HpkeSuite, @@ -287,8 +287,10 @@ mod tests { #[test] fn test_fips() { // None of the rust-crypto backed hpke-rs suites should be considered FIPS approved. - assert!(ALL_SUPPORTED_SUITES - .iter() - .all(|suite| !suite.fips())); + assert!( + ALL_SUPPORTED_SUITES + .iter() + .all(|suite| !suite.fips()) + ); } } diff --git a/provider-example/src/verify.rs b/provider-example/src/verify.rs index dbd6f73ddd8..89596c2ba55 100644 --- a/provider-example/src/verify.rs +++ b/provider-example/src/verify.rs @@ -1,9 +1,9 @@ use der::Reader; use rsa::signature::Verifier; -use rsa::{pkcs1v15, pss, BigUint, RsaPublicKey}; +use rsa::{BigUint, RsaPublicKey, pkcs1v15, pss}; +use rustls::SignatureScheme; use rustls::crypto::WebPkiSupportedAlgorithms; use rustls::pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm}; -use rustls::SignatureScheme; use webpki::alg_id; pub static ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms { diff --git a/rustls-fuzzing-provider/src/lib.rs b/rustls-fuzzing-provider/src/lib.rs index eb9d7bcf1ae..72e7df83ce5 100644 --- a/rustls-fuzzing-provider/src/lib.rs +++ b/rustls-fuzzing-provider/src/lib.rs @@ -1,15 +1,15 @@ use std::sync::Arc; -use rustls::client::danger::ServerCertVerifier; use rustls::client::WebPkiServerVerifier; +use rustls::client::danger::ServerCertVerifier; use rustls::crypto::cipher::{ AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, KeyBlockShape, MessageDecrypter, MessageEncrypter, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload, Tls12AeadAlgorithm, Tls13AeadAlgorithm, UnsupportedOperationError, }; use rustls::crypto::{ - hash, tls12, tls13, CipherSuiteCommon, GetRandomFailed, KeyExchangeAlgorithm, - WebPkiSupportedAlgorithms, + CipherSuiteCommon, GetRandomFailed, KeyExchangeAlgorithm, WebPkiSupportedAlgorithms, hash, + tls12, tls13, }; use rustls::ffdhe_groups::FfdheGroup; use rustls::pki_types::{ @@ -17,9 +17,9 @@ use rustls::pki_types::{ SignatureVerificationAlgorithm, }; use rustls::{ - crypto, server, sign, CipherSuite, ConnectionTrafficSecrets, ContentType, Error, NamedGroup, - PeerMisbehaved, ProtocolVersion, RootCertStore, SignatureAlgorithm, SignatureScheme, - SupportedCipherSuite, Tls12CipherSuite, Tls13CipherSuite, + CipherSuite, ConnectionTrafficSecrets, ContentType, Error, NamedGroup, PeerMisbehaved, + ProtocolVersion, RootCertStore, SignatureAlgorithm, SignatureScheme, SupportedCipherSuite, + Tls12CipherSuite, Tls13CipherSuite, crypto, server, sign, }; use webpki::alg_id; diff --git a/rustls-post-quantum/benches/benchmarks.rs b/rustls-post-quantum/benches/benchmarks.rs index cc85f1a0883..fe6023cafd2 100644 --- a/rustls-post-quantum/benches/benchmarks.rs +++ b/rustls-post-quantum/benches/benchmarks.rs @@ -1,9 +1,9 @@ use std::sync::Arc; -use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput}; +use criterion::{Criterion, Throughput, black_box, criterion_group, criterion_main}; use rustls::crypto::aws_lc_rs::kx_group::X25519; use rustls::crypto::{ - aws_lc_rs, ActiveKeyExchange, CryptoProvider, SharedSecret, SupportedKxGroup, + ActiveKeyExchange, CryptoProvider, SharedSecret, SupportedKxGroup, aws_lc_rs, }; use rustls::ffdhe_groups::FfdheGroup; use rustls::{ClientConfig, ClientConnection, Error, NamedGroup, RootCertStore}; diff --git a/rustls-post-quantum/examples/client.rs b/rustls-post-quantum/examples/client.rs index b11f0578d3a..3f257806734 100644 --- a/rustls-post-quantum/examples/client.rs +++ b/rustls-post-quantum/examples/client.rs @@ -7,7 +7,7 @@ //! Note that `unwrap()` is used to deal with networking errors; this is not something //! that is sensible outside of example code. -use std::io::{stdout, Read, Write}; +use std::io::{Read, Write, stdout}; use std::net::TcpStream; use std::sync::Arc; diff --git a/rustls/benches/benchmarks.rs b/rustls/benches/benchmarks.rs index 6591aa9f7ae..28d596ff3c5 100644 --- a/rustls/benches/benchmarks.rs +++ b/rustls/benches/benchmarks.rs @@ -1,7 +1,7 @@ #![cfg(feature = "ring")] #![allow(clippy::disallowed_types)] -use bencher::{benchmark_group, benchmark_main, Bencher}; +use bencher::{Bencher, benchmark_group, benchmark_main}; use rustls::crypto::ring as provider; #[path = "../tests/common/mod.rs"] diff --git a/rustls/examples/internal/test_ca.rs b/rustls/examples/internal/test_ca.rs index 79e2ab37725..daf468a08f2 100644 --- a/rustls/examples/internal/test_ca.rs +++ b/rustls/examples/internal/test_ca.rs @@ -11,9 +11,9 @@ use std::time::Duration; use rcgen::{ BasicConstraints, CertificateParams, CertificateRevocationListParams, CertifiedKey, DistinguishedName, DnType, ExtendedKeyUsagePurpose, Ia5String, IsCa, KeyIdMethod, KeyPair, - KeyUsagePurpose, RevocationReason, RevokedCertParams, RsaKeySize, SanType, SerialNumber, - SignatureAlgorithm, PKCS_ECDSA_P256_SHA256, PKCS_ECDSA_P384_SHA384, PKCS_ECDSA_P521_SHA512, - PKCS_ED25519, PKCS_RSA_SHA256, PKCS_RSA_SHA384, PKCS_RSA_SHA512, + 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; diff --git a/rustls/src/client/builder.rs b/rustls/src/client/builder.rs index 8b76bf0fa9e..b301e75077e 100644 --- a/rustls/src/client/builder.rs +++ b/rustls/src/client/builder.rs @@ -5,14 +5,14 @@ use pki_types::{CertificateDer, PrivateKeyDer}; use super::client_conn::Resumption; use crate::builder::{ConfigBuilder, WantsVerifier}; -use crate::client::{handy, ClientConfig, EchMode, ResolvesClientCert}; +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::{compress, verify, versions, WantsVersions}; +use crate::{WantsVersions, compress, verify, versions}; impl ConfigBuilder { /// Enable Encrypted Client Hello (ECH) in the given mode. @@ -93,7 +93,7 @@ pub(super) mod danger { use crate::client::WantsClientCert; use crate::sync::Arc; - use crate::{verify, ClientConfig, ConfigBuilder, WantsVerifier}; + use crate::{ClientConfig, ConfigBuilder, WantsVerifier, verify}; /// Accessor for dangerous configuration options. #[derive(Debug)] diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index e2706c762b6..92cc538db15 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -7,6 +7,8 @@ use pki_types::{ServerName, UnixTime}; use super::handy::NoClientSessionStorage; use super::hs; +#[cfg(feature = "std")] +use crate::WantsVerifier; use crate::builder::ConfigBuilder; use crate::client::{EchMode, EchStatus}; use crate::common_state::{CommonState, Protocol, Side}; @@ -24,11 +26,9 @@ use crate::sync::Arc; use crate::time_provider::DefaultTimeProvider; use crate::time_provider::TimeProvider; use crate::unbuffered::{EncryptError, TransmitTlsData}; -#[cfg(feature = "std")] -use crate::WantsVerifier; -use crate::{compress, sign, verify, versions, KeyLog, WantsVersions}; #[cfg(doc)] -use crate::{crypto, DistinguishedName}; +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. @@ -511,8 +511,8 @@ pub enum Tls12Resumption { /// Container for unsafe APIs pub(super) mod danger { - use super::verify::ServerCertVerifier; use super::ClientConfig; + use super::verify::ServerCertVerifier; use crate::sync::Arc; /// Accessor for dangerous configuration options. @@ -618,13 +618,13 @@ mod connection { use pki_types::ServerName; use super::ClientConnectionData; + 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; - use crate::ClientConfig; /// Stub that implements io::Write and dispatches to `write_early_data`. pub struct WriteEarlyData<'a> { diff --git a/rustls/src/client/common.rs b/rustls/src/client/common.rs index a468af93839..048b77a640f 100644 --- a/rustls/src/client/common.rs +++ b/rustls/src/client/common.rs @@ -6,7 +6,7 @@ use crate::log::{debug, trace}; use crate::msgs::enums::ExtensionType; use crate::msgs::handshake::{CertificateChain, DistinguishedName, ServerExtension}; use crate::sync::Arc; -use crate::{compress, sign, SignatureScheme}; +use crate::{SignatureScheme, compress, sign}; #[derive(Debug)] pub(super) struct ServerCertDetails<'a> { diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index 513852553e6..f6a5f8e633f 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -5,10 +5,11 @@ 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::crypto::SecureRandom; use crate::hash_hs::{HandshakeHash, HandshakeHashBuffer}; use crate::log::{debug, trace, warn}; use crate::msgs::base::{Payload, PayloadU16}; @@ -24,9 +25,8 @@ use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; use crate::msgs::persist::Retrieved; use crate::tls13::key_schedule::{ - server_ech_hrr_confirmation_secret, KeyScheduleEarly, KeyScheduleHandshakeStart, + KeyScheduleEarly, KeyScheduleHandshakeStart, server_ech_hrr_confirmation_secret, }; -use crate::CipherSuite::TLS_EMPTY_RENEGOTIATION_INFO_SCSV; use crate::{ AlertDescription, CommonState, EncryptedClientHelloError, Error, HandshakeType, PeerIncompatible, PeerMisbehaved, ProtocolVersion, Tls13CipherSuite, @@ -499,7 +499,7 @@ impl EchState { AlertDescription::DecodeError, PeerMisbehaved::IllegalHelloRetryRequestWithInvalidEch, ) - }) + }); } Some(ech_conf) => ech_conf, }; diff --git a/rustls/src/client/handy.rs b/rustls/src/client/handy.rs index 80b02c27b45..a2585da9eae 100644 --- a/rustls/src/client/handy.rs +++ b/rustls/src/client/handy.rs @@ -3,7 +3,7 @@ use pki_types::ServerName; use crate::enums::SignatureScheme; use crate::msgs::persist; use crate::sync::Arc; -use crate::{client, sign, NamedGroup}; +use crate::{NamedGroup, client, sign}; /// An implementer of `ClientSessionStore` which does nothing. #[derive(Debug)] @@ -40,7 +40,7 @@ mod cache { use crate::lock::Mutex; use crate::msgs::persist; - use crate::{limited_cache, NamedGroup}; + use crate::{NamedGroup, limited_cache}; const MAX_TLS13_TICKETS_PER_SERVER: usize = 8; @@ -251,8 +251,8 @@ mod tests { use pki_types::{ServerName, UnixTime}; - use super::provider::cipher_suite; use super::NoClientSessionStorage; + use super::provider::cipher_suite; use crate::client::ClientSessionStore; use crate::msgs::base::PayloadU16; use crate::msgs::enums::NamedGroup; diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index c5f30bc2f71..260aaae55e3 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -6,16 +6,17 @@ use core::ops::Deref; use pki_types::ServerName; +use super::Tls12Resumption; #[cfg(feature = "tls12")] use super::tls12; -use super::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::{tls13, ClientConfig, EchMode, EchStatus}; +use crate::client::{ClientConfig, EchMode, EchStatus, tls13}; use crate::common_state::{CommonState, HandshakeKind, KxState, State}; use crate::conn::ConnectionRandoms; use crate::crypto::{ActiveKeyExchange, KeyExchangeAlgorithm}; @@ -36,7 +37,6 @@ use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; use crate::sync::Arc; use crate::tls13::key_schedule::KeyScheduleEarly; -use crate::SupportedCipherSuite; pub(super) type NextState<'a> = Box + 'a>; pub(super) type NextStateOrError<'a> = Result, Error>; diff --git a/rustls/src/client/tls12.rs b/rustls/src/client/tls12.rs index c0af6f2e59d..2adb92a3766 100644 --- a/rustls/src/client/tls12.rs +++ b/rustls/src/client/tls12.rs @@ -11,7 +11,7 @@ use super::client_conn::ClientConnectionData; use super::hs::ClientContext; use crate::check::{inappropriate_handshake_message, inappropriate_message}; use crate::client::common::{ClientAuthDetails, ServerCertDetails}; -use crate::client::{hs, ClientConfig}; +use crate::client::{ClientConfig, hs}; use crate::common_state::{CommonState, HandshakeKind, KxState, Side, State}; use crate::conn::ConnectionRandoms; use crate::crypto::KeyExchangeAlgorithm; @@ -19,7 +19,7 @@ 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, PayloadU16, PayloadU8}; +use crate::msgs::base::{Payload, PayloadU8, PayloadU16}; use crate::msgs::ccs::ChangeCipherSpecPayload; use crate::msgs::handshake::{ CertificateChain, ClientDhParams, ClientEcdhParams, ClientKeyExchangeParams, diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index 94d904f0ee0..d0cda04fd76 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -10,7 +10,7 @@ use super::hs::ClientContext; use crate::check::inappropriate_handshake_message; use crate::client::common::{ClientAuthDetails, ClientHelloDetails, ServerCertDetails}; use crate::client::ech::{self, EchState, EchStatus}; -use crate::client::{hs, ClientConfig, ClientSessionStore}; +use crate::client::{ClientConfig, ClientSessionStore, hs}; use crate::common_state::{ CommonState, HandshakeFlightTls13, HandshakeKind, KxState, Protocol, Side, State, }; @@ -27,10 +27,10 @@ use crate::msgs::ccs::ChangeCipherSpecPayload; use crate::msgs::codec::{Codec, Reader}; use crate::msgs::enums::{ExtensionType, KeyUpdateRequest}; use crate::msgs::handshake::{ - CertificatePayloadTls13, ClientExtension, EchConfigPayload, HandshakeMessagePayload, - HandshakePayload, HasServerExtensions, KeyShareEntry, NewSessionTicketPayloadTls13, - PresharedKeyIdentity, PresharedKeyOffer, ServerExtension, ServerHelloPayload, - CERTIFICATE_MAX_SIZE_LIMIT, + CERTIFICATE_MAX_SIZE_LIMIT, CertificatePayloadTls13, ClientExtension, EchConfigPayload, + HandshakeMessagePayload, HandshakePayload, HasServerExtensions, KeyShareEntry, + NewSessionTicketPayloadTls13, PresharedKeyIdentity, PresharedKeyOffer, ServerExtension, + ServerHelloPayload, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; @@ -42,10 +42,10 @@ use crate::tls13::key_schedule::{ ResumptionSecret, }; use crate::tls13::{ - construct_client_verify_message, construct_server_verify_message, Tls13CipherSuite, + Tls13CipherSuite, construct_client_verify_message, construct_server_verify_message, }; use crate::verify::{self, DigitallySignedStruct}; -use crate::{compress, crypto, KeyLog}; +use crate::{KeyLog, compress, crypto}; // Extensions we expect in plaintext in the ServerHello. static ALLOWED_PLAINTEXT_EXTS: &[ExtensionType] = &[ @@ -479,7 +479,7 @@ impl State for ExpectEncryptedExtensions { 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 diff --git a/rustls/src/common_state.rs b/rustls/src/common_state.rs index 12aca203a4b..626e4b2277c 100644 --- a/rustls/src/common_state.rs +++ b/rustls/src/common_state.rs @@ -259,7 +259,9 @@ impl CommonState { self.refresh_traffic_keys_pending = true; } _ => { - error!("traffic keys exhausted, closing connection to prevent security failure"); + error!( + "traffic keys exhausted, closing connection to prevent security failure" + ); self.send_close_notify(); return Err(EncryptError::EncryptExhausted); } @@ -362,7 +364,9 @@ impl CommonState { self.refresh_traffic_keys_pending = true; } _ => { - error!("traffic keys exhausted, closing connection to prevent security failure"); + error!( + "traffic keys exhausted, closing connection to prevent security failure" + ); self.send_close_notify(); return; } diff --git a/rustls/src/compress.rs b/rustls/src/compress.rs index e7b07d1db09..ffce77669f3 100644 --- a/rustls/src/compress.rs +++ b/rustls/src/compress.rs @@ -126,7 +126,7 @@ pub struct CompressionFailed; #[cfg(feature = "zlib")] mod feat_zlib_rs { use zlib_rs::c_api::Z_BEST_COMPRESSION; - use zlib_rs::{deflate, inflate, ReturnCode}; + use zlib_rs::{ReturnCode, deflate, inflate}; use super::*; diff --git a/rustls/src/conn.rs b/rustls/src/conn.rs index 92512a72a1b..32fc1935975 100644 --- a/rustls/src/conn.rs +++ b/rustls/src/conn.rs @@ -5,13 +5,13 @@ use core::ops::{Deref, DerefMut, Range}; #[cfg(feature = "std")] use std::io; -use crate::common_state::{CommonState, Context, IoState, State, DEFAULT_BUFFER_LIMIT}; +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::deframer::DeframerIter; use crate::msgs::handshake::Random; use crate::msgs::message::{InboundPlainMessage, Message, MessagePayload}; use crate::record_layer::Decrypted; @@ -27,12 +27,12 @@ mod connection { 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; - use crate::ConnectionCommon; /// A client or server connection. #[derive(Debug)] @@ -295,8 +295,7 @@ mod connection { } } - const UNEXPECTED_EOF_MESSAGE: &str = - "peer closed connection without sending TLS close_notify: \ + 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. @@ -1003,7 +1002,7 @@ impl ConnectionCore { Ok(None) if !self.hs_deframer.is_aligned() => { return Err( PeerMisbehaved::RejectedEarlyDataInterleavedWithHandshakeMessage.into(), - ) + ); } // failed decryption during trial decryption. diff --git a/rustls/src/conn/unbuffered.rs b/rustls/src/conn/unbuffered.rs index ffe14c75f7d..e3fe4f6e7ca 100644 --- a/rustls/src/conn/unbuffered.rs +++ b/rustls/src/conn/unbuffered.rs @@ -7,10 +7,10 @@ use core::{fmt, mem}; 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; -use crate::Error; impl UnbufferedConnectionCommon { /// Processes the TLS records in `incoming_tls` buffer until a new [`UnbufferedStatus`] is diff --git a/rustls/src/crypto/aws_lc_rs/hpke.rs b/rustls/src/crypto/aws_lc_rs/hpke.rs index e7b1a949d4d..de0e5d630d0 100644 --- a/rustls/src/crypto/aws_lc_rs/hpke.rs +++ b/rustls/src/crypto/aws_lc_rs/hpke.rs @@ -3,7 +3,7 @@ use alloc::vec::Vec; use core::fmt::{self, Debug, Formatter}; use aws_lc_rs::aead::{ - self, Aad, BoundKey, Nonce, NonceSequence, OpeningKey, SealingKey, UnboundKey, NONCE_LEN, + 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}; @@ -16,7 +16,7 @@ use crate::crypto::aws_lc_rs::unspecified_err; use crate::crypto::hpke::{ EncapsulatedSecret, Hpke, HpkeOpener, HpkePrivateKey, HpkePublicKey, HpkeSealer, HpkeSuite, }; -use crate::crypto::tls13::{expand, HkdfExpander, HkdfPrkExtract, HkdfUsingHmac}; +use crate::crypto::tls13::{HkdfExpander, HkdfPrkExtract, HkdfUsingHmac, expand}; use crate::msgs::enums::{HpkeAead, HpkeKdf, HpkeKem}; use crate::msgs::handshake::HpkeSymmetricCipherSuite; #[cfg(feature = "std")] diff --git a/rustls/src/crypto/aws_lc_rs/mod.rs b/rustls/src/crypto/aws_lc_rs/mod.rs index 5bafc3d8e0a..fe631bfc9f7 100644 --- a/rustls/src/crypto/aws_lc_rs/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/mod.rs @@ -297,9 +297,11 @@ mod tests { #[cfg(feature = "fips")] #[test] fn default_suites_are_fips() { - assert!(super::DEFAULT_CIPHER_SUITES - .iter() - .all(|scs| scs.fips())); + assert!( + super::DEFAULT_CIPHER_SUITES + .iter() + .all(|scs| scs.fips()) + ); } #[cfg(not(feature = "fips"))] diff --git a/rustls/src/crypto/aws_lc_rs/pq/mod.rs b/rustls/src/crypto/aws_lc_rs/pq/mod.rs index 7914e11b4c0..86bd686259c 100644 --- a/rustls/src/crypto/aws_lc_rs/pq/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/pq/mod.rs @@ -1,5 +1,5 @@ -use crate::crypto::aws_lc_rs::kx_group; use crate::crypto::SupportedKxGroup; +use crate::crypto::aws_lc_rs::kx_group; use crate::{Error, NamedGroup, PeerMisbehaved}; mod hybrid; diff --git a/rustls/src/crypto/aws_lc_rs/sign.rs b/rustls/src/crypto/aws_lc_rs/sign.rs index e251c4a7c64..f4efa73f665 100644 --- a/rustls/src/crypto/aws_lc_rs/sign.rs +++ b/rustls/src/crypto/aws_lc_rs/sign.rs @@ -11,7 +11,7 @@ use webpki::alg_id; use super::ring_like::rand::SystemRandom; use super::ring_like::signature::{self, EcdsaKeyPair, Ed25519KeyPair, KeyPair, RsaKeyPair}; -use crate::crypto::signer::{public_key_to_spki, Signer, SigningKey}; +use crate::crypto::signer::{Signer, SigningKey, public_key_to_spki}; use crate::enums::{SignatureAlgorithm, SignatureScheme}; use crate::error::Error; use crate::sync::Arc; @@ -432,12 +432,14 @@ mod tests { 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()); + 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(); @@ -447,10 +449,11 @@ mod tests { ); 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])); + assert!( + s.sign(b"hello") + .unwrap() + .starts_with(&[0x30]) + ); } #[test] @@ -482,12 +485,14 @@ mod tests { 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::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(); @@ -497,10 +502,11 @@ mod tests { ); 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])); + assert!( + s.sign(b"hello") + .unwrap() + .starts_with(&[0x30]) + ); } #[test] @@ -532,15 +538,18 @@ mod tests { 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()); + 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(); @@ -550,10 +559,11 @@ mod tests { ); 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])); + assert!( + s.sign(b"hello") + .unwrap() + .starts_with(&[0x30]) + ); } #[test] @@ -576,12 +586,14 @@ mod tests { ); 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()); + 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(); @@ -619,12 +631,14 @@ mod tests { 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()); + 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]) diff --git a/rustls/src/crypto/aws_lc_rs/ticketer.rs b/rustls/src/crypto/aws_lc_rs/ticketer.rs index 3157a65f673..31d94bf38bf 100644 --- a/rustls/src/crypto/aws_lc_rs/ticketer.rs +++ b/rustls/src/crypto/aws_lc_rs/ticketer.rs @@ -5,8 +5,8 @@ use core::fmt::{Debug, Formatter}; use core::sync::atomic::{AtomicUsize, Ordering}; use aws_lc_rs::cipher::{ - DecryptionContext, PaddedBlockDecryptingKey, PaddedBlockEncryptingKey, UnboundCipherKey, - AES_256, AES_256_KEY_LEN, AES_CBC_IV_LEN, + AES_256, AES_256_KEY_LEN, AES_CBC_IV_LEN, DecryptionContext, PaddedBlockDecryptingKey, + PaddedBlockEncryptingKey, UnboundCipherKey, }; use aws_lc_rs::{hmac, iv}; diff --git a/rustls/src/crypto/aws_lc_rs/tls12.rs b/rustls/src/crypto/aws_lc_rs/tls12.rs index 38b368353e6..3845af5837b 100644 --- a/rustls/src/crypto/aws_lc_rs/tls12.rs +++ b/rustls/src/crypto/aws_lc_rs/tls12.rs @@ -3,8 +3,8 @@ use alloc::boxed::Box; use aws_lc_rs::{aead, tls_prf}; use crate::crypto::cipher::{ - make_tls12_aad, AeadKey, InboundOpaqueMessage, Iv, KeyBlockShape, MessageDecrypter, - MessageEncrypter, Nonce, Tls12AeadAlgorithm, UnsupportedOperationError, NONCE_LEN, + AeadKey, InboundOpaqueMessage, Iv, KeyBlockShape, MessageDecrypter, MessageEncrypter, + NONCE_LEN, Nonce, Tls12AeadAlgorithm, UnsupportedOperationError, make_tls12_aad, }; use crate::crypto::tls12::Prf; use crate::crypto::{ActiveKeyExchange, KeyExchangeAlgorithm}; diff --git a/rustls/src/crypto/aws_lc_rs/tls13.rs b/rustls/src/crypto/aws_lc_rs/tls13.rs index 9d234c82e44..dbc9d912c68 100644 --- a/rustls/src/crypto/aws_lc_rs/tls13.rs +++ b/rustls/src/crypto/aws_lc_rs/tls13.rs @@ -5,8 +5,8 @@ use aws_lc_rs::{aead, hkdf, hmac}; use crate::crypto; use crate::crypto::cipher::{ - make_tls13_aad, AeadKey, InboundOpaqueMessage, Iv, MessageDecrypter, MessageEncrypter, Nonce, - Tls13AeadAlgorithm, UnsupportedOperationError, + 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}; @@ -88,9 +88,7 @@ impl Tls13AeadAlgorithm for Chacha20Poly1305Aead { fn encrypter(&self, key: AeadKey, iv: Iv) -> Box { // 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(), - ), + enc_key: aead::LessSafeKey::new(aead::UnboundKey::new(self.0.0, key.as_ref()).unwrap()), iv, }) } @@ -98,9 +96,7 @@ impl Tls13AeadAlgorithm for Chacha20Poly1305Aead { fn decrypter(&self, key: AeadKey, iv: Iv) -> Box { // 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(), - ), + dec_key: aead::LessSafeKey::new(aead::UnboundKey::new(self.0.0, key.as_ref()).unwrap()), iv, }) } diff --git a/rustls/src/crypto/hpke.rs b/rustls/src/crypto/hpke.rs index a08f7ca62d0..6207415022f 100644 --- a/rustls/src/crypto/hpke.rs +++ b/rustls/src/crypto/hpke.rs @@ -4,9 +4,9 @@ use core::fmt::Debug; use zeroize::Zeroize; +use crate::Error; use crate::msgs::enums::HpkeKem; use crate::msgs::handshake::HpkeSymmetricCipherSuite; -use crate::Error; /// An HPKE suite, specifying a key encapsulation mechanism and a symmetric cipher suite. #[derive(Clone, Copy, Debug, Eq, PartialEq)] diff --git a/rustls/src/crypto/mod.rs b/rustls/src/crypto/mod.rs index 13b5de8696a..635d3918917 100644 --- a/rustls/src/crypto/mod.rs +++ b/rustls/src/crypto/mod.rs @@ -5,21 +5,21 @@ 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::{ - verify_tls12_signature, verify_tls13_signature, verify_tls13_signature_with_raw_key, - WebPkiSupportedAlgorithms, + WebPkiSupportedAlgorithms, verify_tls12_signature, verify_tls13_signature, + verify_tls13_signature_with_raw_key, }; -#[cfg(all(doc, feature = "tls12"))] -use crate::Tls12CipherSuite; #[cfg(doc)] use crate::{ - client, crypto, server, sign, ClientConfig, ConfigBuilder, ServerConfig, SupportedCipherSuite, - Tls13CipherSuite, + ClientConfig, ConfigBuilder, ServerConfig, SupportedCipherSuite, Tls13CipherSuite, client, + crypto, server, sign, }; -use crate::{suites, Error, NamedGroup, ProtocolVersion, SupportedProtocolVersion}; +use crate::{Error, NamedGroup, ProtocolVersion, SupportedProtocolVersion, suites}; /// *ring* based CryptoProvider. #[cfg(feature = "ring")] diff --git a/rustls/src/crypto/ring/mod.rs b/rustls/src/crypto/ring/mod.rs index 5ddc87e20ac..79c2307ea18 100644 --- a/rustls/src/crypto/ring/mod.rs +++ b/rustls/src/crypto/ring/mod.rs @@ -2,6 +2,7 @@ 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; @@ -9,7 +10,6 @@ use crate::sign::SigningKey; use crate::suites::SupportedCipherSuite; use crate::sync::Arc; use crate::webpki::WebPkiSupportedAlgorithms; -use crate::Error; /// Using software keys for authentication. pub mod sign; diff --git a/rustls/src/crypto/ring/sign.rs b/rustls/src/crypto/ring/sign.rs index 63496766a48..7b384508ad5 100644 --- a/rustls/src/crypto/ring/sign.rs +++ b/rustls/src/crypto/ring/sign.rs @@ -11,7 +11,7 @@ use webpki::alg_id; use super::ring_like::rand::{SecureRandom, SystemRandom}; use super::ring_like::signature::{self, EcdsaKeyPair, Ed25519KeyPair, KeyPair, RsaKeyPair}; -use crate::crypto::signer::{public_key_to_spki, Signer, SigningKey}; +use crate::crypto::signer::{Signer, SigningKey, public_key_to_spki}; use crate::enums::{SignatureAlgorithm, SignatureScheme}; use crate::error::Error; use crate::sync::Arc; @@ -465,12 +465,14 @@ mod tests { 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()); + 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(); @@ -480,10 +482,11 @@ mod tests { ); 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])); + assert!( + s.sign(b"hello") + .unwrap() + .starts_with(&[0x30]) + ); } #[test] @@ -515,12 +518,14 @@ mod tests { 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::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(); @@ -530,10 +535,11 @@ mod tests { ); 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])); + assert!( + s.sign(b"hello") + .unwrap() + .starts_with(&[0x30]) + ); } #[test] @@ -556,12 +562,14 @@ mod tests { ); 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()); + 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(); @@ -599,12 +607,14 @@ mod tests { 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()); + 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]) diff --git a/rustls/src/crypto/ring/tls12.rs b/rustls/src/crypto/ring/tls12.rs index 5bc2926000b..63dfae8b8a5 100644 --- a/rustls/src/crypto/ring/tls12.rs +++ b/rustls/src/crypto/ring/tls12.rs @@ -1,12 +1,12 @@ use alloc::boxed::Box; use super::ring_like::aead; +use crate::crypto::KeyExchangeAlgorithm; use crate::crypto::cipher::{ - make_tls12_aad, AeadKey, InboundOpaqueMessage, Iv, KeyBlockShape, MessageDecrypter, - MessageEncrypter, Nonce, Tls12AeadAlgorithm, UnsupportedOperationError, NONCE_LEN, + AeadKey, InboundOpaqueMessage, Iv, KeyBlockShape, MessageDecrypter, MessageEncrypter, + NONCE_LEN, Nonce, Tls12AeadAlgorithm, UnsupportedOperationError, make_tls12_aad, }; use crate::crypto::tls12::PrfUsingHmac; -use crate::crypto::KeyExchangeAlgorithm; use crate::enums::{CipherSuite, SignatureScheme}; use crate::error::Error; use crate::msgs::fragmenter::MAX_FRAGMENT_LEN; diff --git a/rustls/src/crypto/ring/tls13.rs b/rustls/src/crypto/ring/tls13.rs index d390b2a4e24..ef488b624b1 100644 --- a/rustls/src/crypto/ring/tls13.rs +++ b/rustls/src/crypto/ring/tls13.rs @@ -4,8 +4,8 @@ use super::ring_like::hkdf::KeyType; use super::ring_like::{aead, hkdf, hmac}; use crate::crypto; use crate::crypto::cipher::{ - make_tls13_aad, AeadKey, InboundOpaqueMessage, Iv, MessageDecrypter, MessageEncrypter, Nonce, - Tls13AeadAlgorithm, UnsupportedOperationError, + 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}; diff --git a/rustls/src/crypto/tls12.rs b/rustls/src/crypto/tls12.rs index fce7cb132c9..7128de4b2f3 100644 --- a/rustls/src/crypto/tls12.rs +++ b/rustls/src/crypto/tls12.rs @@ -1,6 +1,6 @@ use alloc::boxed::Box; -use super::{hmac, ActiveKeyExchange}; +use super::{ActiveKeyExchange, hmac}; use crate::error::Error; use crate::version::TLS12; diff --git a/rustls/src/crypto/tls13.rs b/rustls/src/crypto/tls13.rs index a2e8029b31f..50ecaa89c7d 100644 --- a/rustls/src/crypto/tls13.rs +++ b/rustls/src/crypto/tls13.rs @@ -3,7 +3,7 @@ use alloc::vec::Vec; use zeroize::Zeroize; -use super::{hmac, ActiveKeyExchange}; +use super::{ActiveKeyExchange, hmac}; use crate::error::Error; use crate::version::TLS13; @@ -266,7 +266,7 @@ pub struct OutputLengthError; mod tests { use std::prelude::v1::*; - use super::{expand, Hkdf, HkdfUsingHmac}; + 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; @@ -397,9 +397,10 @@ mod tests { let info = &[]; let mut output = [0u8; 32 * 255 + 1]; - assert!(hkdf - .extract_from_secret(None, ikm) - .expand_slice(info, &mut output) - .is_err()); + assert!( + hkdf.extract_from_secret(None, ikm) + .expand_slice(info, &mut output) + .is_err() + ); } } diff --git a/rustls/src/enums.rs b/rustls/src/enums.rs index 298989ff763..0dc0e356666 100644 --- a/rustls/src/enums.rs +++ b/rustls/src/enums.rs @@ -601,7 +601,7 @@ enum_builder! { #[cfg(test)] mod tests { use super::*; - use crate::msgs::enums::tests::{test_enum16, test_enum8}; + use crate::msgs::enums::tests::{test_enum8, test_enum16}; #[test] fn test_enums() { diff --git a/rustls/src/key_log_file.rs b/rustls/src/key_log_file.rs index f0ad95223ad..4781b98be27 100644 --- a/rustls/src/key_log_file.rs +++ b/rustls/src/key_log_file.rs @@ -7,8 +7,8 @@ use std::io; use std::io::Write; use std::sync::Mutex; -use crate::log::warn; use crate::KeyLog; +use crate::log::warn; // Internal mutable state for KeyLogFile struct KeyLogFileInner { @@ -134,26 +134,32 @@ mod tests { 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()); + 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()); + 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()); + assert!( + inner + .try_write("label", b"random", b"secret") + .is_err() + ); } } diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 4cf6e9b679c..e13c39ff836 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -526,12 +526,12 @@ pub mod internal { /// [`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, }; - pub use crate::conn::UnbufferedConnectionCommon; } // The public interface is: @@ -567,7 +567,7 @@ pub use crate::ticketer::TicketSwitcher; pub use crate::tls12::Tls12CipherSuite; pub use crate::tls13::Tls13CipherSuite; pub use crate::verify::DigitallySignedStruct; -pub use crate::versions::{SupportedProtocolVersion, ALL_VERSIONS, DEFAULT_VERSIONS}; +pub use crate::versions::{ALL_VERSIONS, DEFAULT_VERSIONS, SupportedProtocolVersion}; pub use crate::webpki::RootCertStore; /// Items for use in a client. @@ -603,8 +603,8 @@ pub mod client { pub use crate::msgs::persist::{Tls12ClientSessionValue, Tls13ClientSessionValue}; pub use crate::webpki::{ - verify_server_cert_signed_by_trust_anchor, verify_server_name, ServerCertVerifierBuilder, - VerifierBuilderError, WebPkiServerVerifier, + ServerCertVerifierBuilder, VerifierBuilderError, WebPkiServerVerifier, + verify_server_cert_signed_by_trust_anchor, verify_server_name, }; } @@ -691,13 +691,13 @@ pub(crate) mod polyfill; #[cfg(any(feature = "std", feature = "hashbrown"))] mod hash_map { - #[cfg(feature = "std")] - pub(crate) use std::collections::hash_map::Entry; #[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::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/rustls/src/msgs/deframer/handshake.rs b/rustls/src/msgs/deframer/handshake.rs index c781e9309cd..0d91f0eac82 100644 --- a/rustls/src/msgs/deframer/handshake.rs +++ b/rustls/src/msgs/deframer/handshake.rs @@ -4,7 +4,7 @@ use core::ops::Range; use super::buffers::{BufferProgress, Coalescer, Delocator, Locator}; use crate::error::InvalidMessage; -use crate::msgs::codec::{u24, Codec}; +use crate::msgs::codec::{Codec, u24}; use crate::msgs::message::InboundPlainMessage; use crate::{ContentType, ProtocolVersion}; diff --git a/rustls/src/msgs/deframer/mod.rs b/rustls/src/msgs/deframer/mod.rs index 2f44962c779..4122b52591d 100644 --- a/rustls/src/msgs/deframer/mod.rs +++ b/rustls/src/msgs/deframer/mod.rs @@ -3,7 +3,7 @@ use core::mem; use crate::error::{Error, InvalidMessage}; use crate::msgs::codec::Reader; use crate::msgs::message::{ - read_opaque_message_header, InboundOpaqueMessage, MessageError, HEADER_SIZE, + HEADER_SIZE, InboundOpaqueMessage, MessageError, read_opaque_message_header, }; pub(crate) mod buffers; @@ -106,24 +106,36 @@ mod tests { #[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()); + 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] diff --git a/rustls/src/msgs/fragmenter.rs b/rustls/src/msgs/fragmenter.rs index bad02853287..4863677792c 100644 --- a/rustls/src/msgs/fragmenter.rs +++ b/rustls/src/msgs/fragmenter.rs @@ -1,6 +1,6 @@ +use crate::Error; use crate::enums::{ContentType, ProtocolVersion}; use crate::msgs::message::{OutboundChunks, OutboundPlainMessage, PlainMessage}; -use crate::Error; 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; diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 101f73d1c61..e246bea938a 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -19,7 +19,7 @@ use crate::error::InvalidMessage; #[cfg(feature = "tls12")] use crate::ffdhe_groups::FfdheGroup; use crate::log::warn; -use crate::msgs::base::{Payload, PayloadU16, PayloadU24, PayloadU8}; +use crate::msgs::base::{Payload, PayloadU8, PayloadU16, PayloadU24}; use crate::msgs::codec::{self, Codec, LengthPrefixedBuffer, ListLength, Reader, TlsListElement}; use crate::msgs::enums::{ CertificateStatusType, CertificateType, ClientCertificateType, Compression, ECCurveType, diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index dc77e7f6020..9e5a7b8f98b 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -3,8 +3,8 @@ use std::{format, println, vec}; use pki_types::{CertificateDer, DnsName}; -use super::base::{Payload, PayloadU16, PayloadU24, PayloadU8}; -use super::codec::{put_u16, Codec, Reader}; +use super::base::{Payload, PayloadU8, PayloadU16, PayloadU24}; +use super::codec::{Codec, Reader, put_u16}; use super::enums::{ CertificateType, ClientCertificateType, Compression, ECCurveType, ECPointFormat, ExtensionType, KeyUpdateRequest, NamedGroup, PSKKeyExchangeMode, ServerNameType, @@ -799,11 +799,13 @@ fn can_detect_truncation_of_all_tls12_handshake_payloads() { _ => {} }; - assert!(HandshakeMessagePayload::read_version( - &mut Reader::init(&enc), - ProtocolVersion::TLSv1_2 - ) - .is_err()); + assert!( + HandshakeMessagePayload::read_version( + &mut Reader::init(&enc), + ProtocolVersion::TLSv1_2 + ) + .is_err() + ); assert!(HandshakeMessagePayload::read_bytes(&enc).is_err()); } } @@ -863,11 +865,13 @@ fn can_detect_truncation_of_all_tls13_handshake_payloads() { _ => {} }; - assert!(HandshakeMessagePayload::read_version( - &mut Reader::init(&enc), - ProtocolVersion::TLSv1_3 - ) - .is_err()); + assert!( + HandshakeMessagePayload::read_version( + &mut Reader::init(&enc), + ProtocolVersion::TLSv1_3 + ) + .is_err() + ); } } } diff --git a/rustls/src/msgs/message/outbound.rs b/rustls/src/msgs/message/outbound.rs index f6fdeb86235..8dc924c156d 100644 --- a/rustls/src/msgs/message/outbound.rs +++ b/rustls/src/msgs/message/outbound.rs @@ -1,6 +1,6 @@ use alloc::vec::Vec; -use super::{MessageError, PlainMessage, HEADER_SIZE, MAX_PAYLOAD}; +use super::{HEADER_SIZE, MAX_PAYLOAD, MessageError, PlainMessage}; use crate::enums::{ContentType, ProtocolVersion}; use crate::msgs::base::Payload; use crate::msgs::codec::{Codec, Reader}; diff --git a/rustls/src/msgs/message_test.rs b/rustls/src/msgs/message_test.rs index 53fca53e190..672fdddde42 100644 --- a/rustls/src/msgs/message_test.rs +++ b/rustls/src/msgs/message_test.rs @@ -8,7 +8,7 @@ use super::codec::Reader; use super::enums::AlertLevel; use super::message::{Message, OutboundOpaqueMessage, PlainMessage}; use crate::enums::{AlertDescription, HandshakeType}; -use crate::msgs::base::{PayloadU16, PayloadU24, PayloadU8}; +use crate::msgs::base::{PayloadU8, PayloadU16, PayloadU24}; #[test] fn test_read_fuzz_corpus() { diff --git a/rustls/src/msgs/persist.rs b/rustls/src/msgs/persist.rs index 1867e021eab..05117ae2e1d 100644 --- a/rustls/src/msgs/persist.rs +++ b/rustls/src/msgs/persist.rs @@ -6,7 +6,7 @@ use zeroize::Zeroizing; use crate::enums::{CipherSuite, ProtocolVersion}; use crate::error::InvalidMessage; -use crate::msgs::base::{PayloadU16, PayloadU8}; +use crate::msgs::base::{PayloadU8, PayloadU16}; use crate::msgs::codec::{Codec, Reader}; use crate::msgs::handshake::CertificateChain; #[cfg(feature = "tls12")] diff --git a/rustls/src/quic.rs b/rustls/src/quic.rs index ab2c28bd410..69c2fc49ab9 100644 --- a/rustls/src/quic.rs +++ b/rustls/src/quic.rs @@ -10,10 +10,10 @@ 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, }; -use crate::tls13::Tls13CipherSuite; #[cfg(feature = "std")] mod connection { @@ -26,7 +26,7 @@ mod connection { use super::{DirectionalKeys, KeyChange, Version}; use crate::client::{ClientConfig, ClientConnectionData}; - use crate::common_state::{CommonState, Protocol, DEFAULT_BUFFER_LIMIT}; + use crate::common_state::{CommonState, DEFAULT_BUFFER_LIMIT, Protocol}; use crate::conn::{ConnectionCore, SideData}; use crate::enums::{AlertDescription, ContentType, ProtocolVersion}; use crate::error::Error; diff --git a/rustls/src/server/builder.rs b/rustls/src/server/builder.rs index 14407d5f5a0..d1b7b24a638 100644 --- a/rustls/src/server/builder.rs +++ b/rustls/src/server/builder.rs @@ -3,13 +3,13 @@ use core::marker::PhantomData; use pki_types::{CertificateDer, PrivateKeyDer}; -use super::{handy, ResolvesServerCert, ServerConfig}; +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::{compress, versions, NoKeyLog}; +use crate::{NoKeyLog, compress, versions}; impl ConfigBuilder { /// Choose how to verify client certificates. diff --git a/rustls/src/server/handy.rs b/rustls/src/server/handy.rs index a3467d7a4e6..710a1f28411 100644 --- a/rustls/src/server/handy.rs +++ b/rustls/src/server/handy.rs @@ -201,7 +201,7 @@ mod sni_resolver { use crate::hash_map::HashMap; use crate::server::ClientHello; use crate::sync::Arc; - use crate::webpki::{verify_server_name, ParsedCertificate}; + use crate::webpki::{ParsedCertificate, verify_server_name}; use crate::{server, sign}; /// Something that resolves do different cert chains/keys based @@ -272,17 +272,19 @@ mod sni_resolver { #[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, - }) - .is_none()); + assert!( + rscsni + .resolve(ClientHello { + server_name: &None, + signature_schemes: &[], + alpn: None, + server_cert_types: None, + client_cert_types: None, + cipher_suites: &[], + certificate_authorities: None, + }) + .is_none() + ); } #[test] @@ -291,17 +293,19 @@ mod sni_resolver { 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, - }) - .is_none()); + 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, + }) + .is_none() + ); } } } diff --git a/rustls/src/server/hs.rs b/rustls/src/server/hs.rs index 5844d732ed9..aafa2be1f63 100644 --- a/rustls/src/server/hs.rs +++ b/rustls/src/server/hs.rs @@ -27,9 +27,9 @@ use crate::msgs::handshake::{ use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; use crate::server::common::ActiveCertifiedKey; -use crate::server::{tls13, ClientHello, ServerConfig}; +use crate::server::{ClientHello, ServerConfig, tls13}; use crate::sync::Arc; -use crate::{suites, SupportedCipherSuite}; +use crate::{SupportedCipherSuite, suites}; pub(super) type NextState<'a> = Box + 'a>; pub(super) type NextStateOrError<'a> = Result, Error>; diff --git a/rustls/src/server/server_conn.rs b/rustls/src/server/server_conn.rs index 902f56fbe20..ba72be2d2d9 100644 --- a/rustls/src/server/server_conn.rs +++ b/rustls/src/server/server_conn.rs @@ -10,6 +10,8 @@ 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")] @@ -31,9 +33,7 @@ use crate::sync::Arc; use crate::time_provider::DefaultTimeProvider; use crate::time_provider::TimeProvider; use crate::vecbuf::ChunkVecBuffer; -#[cfg(feature = "std")] -use crate::WantsVerifier; -use crate::{compress, sign, verify, versions, DistinguishedName, KeyLog, WantsVersions}; +use crate::{DistinguishedName, KeyLog, WantsVersions, compress, sign, verify, versions}; /// A trait for the ability to store server session data. /// diff --git a/rustls/src/server/tls12.rs b/rustls/src/server/tls12.rs index 12b8d4da780..a9cecda0733 100644 --- a/rustls/src/server/tls12.rs +++ b/rustls/src/server/tls12.rs @@ -746,7 +746,7 @@ impl State for ExpectCcs { return Err(inappropriate_message( &payload, &[ContentType::ChangeCipherSpec], - )) + )); } } diff --git a/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index 8dde9260e76..d02360d7d28 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -20,8 +20,8 @@ use crate::log::{debug, trace, warn}; use crate::msgs::codec::{Codec, Reader}; use crate::msgs::enums::KeyUpdateRequest; use crate::msgs::handshake::{ - CertificateChain, CertificatePayloadTls13, HandshakeMessagePayload, HandshakePayload, - NewSessionTicketExtension, NewSessionTicketPayloadTls13, CERTIFICATE_MAX_SIZE_LIMIT, + CERTIFICATE_MAX_SIZE_LIMIT, CertificateChain, CertificatePayloadTls13, HandshakeMessagePayload, + HandshakePayload, NewSessionTicketExtension, NewSessionTicketPayloadTls13, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; @@ -32,7 +32,7 @@ use crate::tls13::key_schedule::{ KeyScheduleTraffic, KeyScheduleTrafficWithClientFinishedPending, ResumptionSecret, }; use crate::tls13::{ - construct_client_verify_message, construct_server_verify_message, Tls13CipherSuite, + Tls13CipherSuite, construct_client_verify_message, construct_server_verify_message, }; use crate::{compress, rand, verify}; @@ -402,7 +402,9 @@ mod client_hello { cx.data.early_data.reject(); } EarlyDataDecision::RequestedButRejected => { - debug!("Client requested early_data, but not accepted: switching to handshake keys with trial decryption"); + 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, diff --git a/rustls/src/suites.rs b/rustls/src/suites.rs index 9e6f1c782fd..c40b88dfce8 100644 --- a/rustls/src/suites.rs +++ b/rustls/src/suites.rs @@ -254,15 +254,19 @@ mod tests { #[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()); + 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/rustls/src/ticketer.rs b/rustls/src/ticketer.rs index 1a9ca2c72ca..1d78b1ec9b0 100644 --- a/rustls/src/ticketer.rs +++ b/rustls/src/ticketer.rs @@ -10,7 +10,7 @@ use crate::lock::{Mutex, MutexGuard}; use crate::server::ProducesTickets; #[cfg(not(feature = "std"))] use crate::time_provider::TimeProvider; -use crate::{rand, Error}; +use crate::{Error, rand}; #[derive(Debug)] pub(crate) struct TicketSwitcherState { diff --git a/rustls/src/tls12/mod.rs b/rustls/src/tls12/mod.rs index f0b179e715e..c9271850548 100644 --- a/rustls/src/tls12/mod.rs +++ b/rustls/src/tls12/mod.rs @@ -355,22 +355,26 @@ mod tests { server_buf.push(34); let mut common = CommonState::new(Side::Client); - assert!(decode_kx_params::( - KeyExchangeAlgorithm::ECDHE, - &mut common, - &server_buf - ) - .is_err()); + assert!( + decode_kx_params::( + KeyExchangeAlgorithm::ECDHE, + &mut common, + &server_buf + ) + .is_err() + ); } #[test] fn client_ecdhe_invalid() { let mut common = CommonState::new(Side::Server); - assert!(decode_kx_params::( - KeyExchangeAlgorithm::ECDHE, - &mut common, - &[34], - ) - .is_err()); + assert!( + decode_kx_params::( + KeyExchangeAlgorithm::ECDHE, + &mut common, + &[34], + ) + .is_err() + ); } } diff --git a/rustls/src/tls13/key_schedule.rs b/rustls/src/tls13/key_schedule.rs index 8b6afb850e2..833720a864e 100644 --- a/rustls/src/tls13/key_schedule.rs +++ b/rustls/src/tls13/key_schedule.rs @@ -5,12 +5,12 @@ use alloc::string::ToString; use crate::common_state::{CommonState, Side}; use crate::crypto::cipher::{AeadKey, Iv, MessageDecrypter, Tls13AeadAlgorithm}; -use crate::crypto::tls13::{expand, Hkdf, HkdfExpander, OkmBlock, OutputLengthError}; -use crate::crypto::{hash, hmac, SharedSecret}; +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::{quic, KeyLog, Tls13CipherSuite}; +use crate::{KeyLog, Tls13CipherSuite, quic}; /// The kinds of secret we can extract from `KeySchedule`. #[derive(Debug, Clone, Copy, PartialEq)] @@ -909,7 +909,7 @@ mod tests { use super::provider::tls13::{ TLS13_AES_128_GCM_SHA256_INTERNAL, TLS13_CHACHA20_POLY1305_SHA256_INTERNAL, }; - use super::{derive_traffic_iv, derive_traffic_key, KeySchedule, SecretKind}; + use super::{KeySchedule, SecretKind, derive_traffic_iv, derive_traffic_key}; use crate::KeyLog; #[test] @@ -1094,7 +1094,7 @@ mod benchmarks { use core::fmt::Debug; use super::provider::tls13::TLS13_CHACHA20_POLY1305_SHA256_INTERNAL; - use super::{derive_traffic_iv, derive_traffic_key, KeySchedule, SecretKind}; + use super::{KeySchedule, SecretKind, derive_traffic_iv, derive_traffic_key}; use crate::KeyLog; fn extract_traffic_secret(ks: &KeySchedule, kind: SecretKind) { diff --git a/rustls/src/verifybench.rs b/rustls/src/verifybench.rs index cab32e366fe..a71c10f65a8 100644 --- a/rustls/src/verifybench.rs +++ b/rustls/src/verifybench.rs @@ -15,7 +15,7 @@ use crate::webpki::{RootCertStore, WebPkiServerVerifier}; #[macro_rules_attribute::apply(bench_for_each_provider)] mod benchmarks { - use super::{provider, Context}; + use super::{Context, provider}; #[bench] fn reddit_cert(b: &mut test::Bencher) { diff --git a/rustls/src/webpki/client_verifier.rs b/rustls/src/webpki/client_verifier.rs index 90b6f325f2e..a69264bcb0c 100644 --- a/rustls/src/webpki/client_verifier.rs +++ b/rustls/src/webpki/client_verifier.rs @@ -3,7 +3,9 @@ use alloc::vec::Vec; use pki_types::{CertificateDer, CertificateRevocationListDer, UnixTime}; use webpki::{CertRevocationList, ExpirationPolicy, RevocationCheckDepth, UnknownStatusPolicy}; -use super::{pki_error, VerifierBuilderError}; +use super::{VerifierBuilderError, pki_error}; +#[cfg(doc)] +use crate::ConfigBuilder; #[cfg(doc)] use crate::crypto; use crate::crypto::{CryptoProvider, WebPkiSupportedAlgorithms}; @@ -15,9 +17,7 @@ use crate::verify::{ NoClientAuth, }; use crate::webpki::parse_crls; -use crate::webpki::verify::{verify_tls12_signature, verify_tls13_signature, ParsedCertificate}; -#[cfg(doc)] -use crate::ConfigBuilder; +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. @@ -437,10 +437,10 @@ mod tests { use pki_types::pem::PemObject; use pki_types::{CertificateDer, CertificateRevocationListDer}; - use super::{provider, WebPkiClientVerifier}; + use super::{WebPkiClientVerifier, provider}; + use crate::RootCertStore; use crate::server::VerifierBuilderError; use crate::sync::Arc; - use crate::RootCertStore; fn load_crls(crls_der: &[&[u8]]) -> Vec> { crls_der diff --git a/rustls/src/webpki/mod.rs b/rustls/src/webpki/mod.rs index 77c83751858..771bb6966ec 100644 --- a/rustls/src/webpki/mod.rs +++ b/rustls/src/webpki/mod.rs @@ -19,11 +19,11 @@ pub use server_verifier::{ServerCertVerifierBuilder, WebPkiServerVerifier}; // Conditionally exported from crate. #[allow(unreachable_pub)] pub use verify::{ - verify_server_cert_signed_by_trust_anchor, verify_server_name, ParsedCertificate, + ParsedCertificate, verify_server_cert_signed_by_trust_anchor, verify_server_name, }; pub use verify::{ - verify_tls12_signature, verify_tls13_signature, verify_tls13_signature_with_raw_key, - WebPkiSupportedAlgorithms, + WebPkiSupportedAlgorithms, verify_tls12_signature, verify_tls13_signature, + verify_tls13_signature_with_raw_key, }; /// An error that can occur when building a certificate verifier. @@ -120,7 +120,7 @@ fn parse_crls( mod tests { #[test] fn pki_crl_errors() { - use super::{pki_error, CertRevocationListError, CertificateError, Error}; + use super::{CertRevocationListError, CertificateError, Error, pki_error}; // CRL signature errors should be turned into BadSignature. assert_eq!( @@ -151,8 +151,8 @@ mod tests { #[test] fn crl_error_from_webpki() { - use super::crl_error; use super::CertRevocationListError::*; + use super::crl_error; let testcases = &[ (webpki::Error::InvalidCrlSignatureForPublicKey, BadSignature), diff --git a/rustls/src/webpki/server_verifier.rs b/rustls/src/webpki/server_verifier.rs index 50a56fd4081..5c54e7fe660 100644 --- a/rustls/src/webpki/server_verifier.rs +++ b/rustls/src/webpki/server_verifier.rs @@ -10,12 +10,12 @@ use crate::verify::{ DigitallySignedStruct, HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier, }; use crate::webpki::verify::{ - verify_server_cert_signed_by_trust_anchor_impl, verify_tls12_signature, verify_tls13_signature, - ParsedCertificate, + ParsedCertificate, verify_server_cert_signed_by_trust_anchor_impl, verify_tls12_signature, + verify_tls13_signature, }; -use crate::webpki::{parse_crls, verify_server_name, VerifierBuilderError}; +use crate::webpki::{VerifierBuilderError, parse_crls, verify_server_name}; #[cfg(doc)] -use crate::{crypto, ConfigBuilder, ServerConfig}; +use crate::{ConfigBuilder, ServerConfig, crypto}; use crate::{Error, RootCertStore, SignatureScheme}; /// A builder for configuring a `webpki` server certificate verifier. @@ -309,9 +309,9 @@ mod tests { use pki_types::pem::PemObject; use pki_types::{CertificateDer, CertificateRevocationListDer}; - use super::{provider, VerifierBuilderError, WebPkiServerVerifier}; - use crate::sync::Arc; + use super::{VerifierBuilderError, WebPkiServerVerifier, provider}; use crate::RootCertStore; + use crate::sync::Arc; fn load_crls(crls_der: &[&[u8]]) -> Vec> { crls_der diff --git a/rustls/src/webpki/verify.rs b/rustls/src/webpki/verify.rs index 38caa93cdee..d99459be063 100644 --- a/rustls/src/webpki/verify.rs +++ b/rustls/src/webpki/verify.rs @@ -275,7 +275,10 @@ mod tests { 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) + format!( + "{:?}", + crate::crypto::ring::default_provider().signature_verification_algorithms + ) ); } } diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 935ee456d02..23decdc9ed4 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -5,13 +5,13 @@ use std::fmt::Debug; use std::io::{self, BufRead, IoSlice, Read, Write}; use std::ops::{Deref, DerefMut}; -use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Mutex; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::{fmt, mem}; use pki_types::{CertificateDer, IpAddr, ServerName, UnixTime}; -use rustls::client::{verify_server_cert_signed_by_trust_anchor, ResolvesClientCert, Resumption}; +use rustls::client::{ResolvesClientCert, Resumption, verify_server_cert_signed_by_trust_anchor}; use rustls::crypto::{ActiveKeyExchange, CryptoProvider, SharedSecret, SupportedKxGroup}; use rustls::internal::msgs::base::Payload; use rustls::internal::msgs::codec::Codec; @@ -22,6 +22,13 @@ use rustls::internal::msgs::handshake::{ }; use rustls::internal::msgs::message::{Message, MessagePayload, PlainMessage}; use rustls::server::{ClientHello, ParsedCertificate, ResolvesServerCert}; +use rustls::{ + AlertDescription, CertificateError, CipherSuite, ClientConfig, ClientConnection, + ConnectionCommon, ConnectionTrafficSecrets, ContentType, DistinguishedName, Error, + HandshakeKind, HandshakeType, InconsistentKeys, InvalidMessage, KeyLog, NamedGroup, + PeerIncompatible, PeerMisbehaved, ProtocolVersion, ServerConfig, ServerConnection, SideData, + SignatureScheme, Stream, StreamOwned, SupportedCipherSuite, SupportedProtocolVersion, sign, +}; #[cfg(feature = "aws_lc_rs")] use rustls::{ client::{EchConfig, EchGreaseConfig, EchMode}, @@ -32,13 +39,6 @@ use rustls::{ }, pki_types::{DnsName, EchConfigListBytes}, }; -use rustls::{ - sign, AlertDescription, CertificateError, CipherSuite, ClientConfig, ClientConnection, - ConnectionCommon, ConnectionTrafficSecrets, ContentType, DistinguishedName, Error, - HandshakeKind, HandshakeType, InconsistentKeys, InvalidMessage, KeyLog, NamedGroup, - PeerIncompatible, PeerMisbehaved, ProtocolVersion, ServerConfig, ServerConnection, SideData, - SignatureScheme, Stream, StreamOwned, SupportedCipherSuite, SupportedProtocolVersion, -}; use super::*; @@ -950,12 +950,16 @@ fn resumption_combinations() { assert_eq!(client.handshake_kind(), Some(HandshakeKind::Resumed)); assert_eq!(server.handshake_kind(), Some(HandshakeKind::Resumed)); if version.version == TLSv1_2 { - assert!(client - .negotiated_key_exchange_group() - .is_none()); - assert!(server - .negotiated_key_exchange_group() - .is_none()); + assert!( + client + .negotiated_key_exchange_group() + .is_none() + ); + assert!( + server + .negotiated_key_exchange_group() + .is_none() + ); } else { assert_eq!( client @@ -1901,14 +1905,16 @@ fn client_check_server_certificate_helper_api() { _ => KeyType::Rsa2048, }); // Using the correct trust anchors, we should verify without error. - assert!(verify_server_cert_signed_by_trust_anchor( - &ParsedCertificate::try_from(chain.first().unwrap()).unwrap(), - &correct_roots, - &[chain.get(1).unwrap().clone()], - UnixTime::now(), - webpki::ALL_VERIFICATION_ALGS, - ) - .is_ok()); + assert!( + verify_server_cert_signed_by_trust_anchor( + &ParsedCertificate::try_from(chain.first().unwrap()).unwrap(), + &correct_roots, + &[chain.get(1).unwrap().clone()], + UnixTime::now(), + webpki::ALL_VERIFICATION_ALGS, + ) + .is_ok() + ); // Using the wrong trust anchors, we should get the expected error. assert_eq!( verify_server_cert_signed_by_trust_anchor( @@ -2041,9 +2047,11 @@ fn client_cert_resolve_default() { // In a default configuration we expect that the verifier's trust anchors are used // for the hint subjects. - let expected_root_hint_subjects = vec![key_type - .ca_distinguished_name() - .to_vec()]; + let expected_root_hint_subjects = vec![ + key_type + .ca_distinguished_name() + .to_vec(), + ]; test_client_cert_resolve(*key_type, server_config, expected_root_hint_subjects); } @@ -3587,12 +3595,16 @@ fn do_exporter_test(client_config: ClientConfig, server_config: ServerConfig) { ); do_handshake(&mut client, &mut server); - assert!(client - .export_keying_material(&mut client_secret, b"label", Some(b"context")) - .is_ok()); - assert!(server - .export_keying_material(&mut server_secret, b"label", Some(b"context")) - .is_ok()); + assert!( + client + .export_keying_material(&mut client_secret, b"label", Some(b"context")) + .is_ok() + ); + assert!( + server + .export_keying_material(&mut server_secret, b"label", Some(b"context")) + .is_ok() + ); assert_eq!(client_secret.to_vec(), server_secret.to_vec()); let mut empty = vec![]; @@ -3613,13 +3625,17 @@ fn do_exporter_test(client_config: ClientConfig, server_config: ServerConfig) { )) ); - assert!(client - .export_keying_material(&mut client_secret, b"label", None) - .is_ok()); + assert!( + client + .export_keying_material(&mut client_secret, b"label", None) + .is_ok() + ); assert_ne!(client_secret.to_vec(), server_secret.to_vec()); - assert!(server - .export_keying_material(&mut server_secret, b"label", None) - .is_ok()); + assert!( + server + .export_keying_material(&mut server_secret, b"label", None) + .is_ok() + ); assert_eq!(client_secret.to_vec(), server_secret.to_vec()); } @@ -4971,12 +4987,16 @@ mod test_quic { assert!(!server.is_handshaking()); assert!(compatible_keys(&server_1rtt, &client_1rtt)); assert!(!compatible_keys(&server_hs, &server_1rtt)); - assert!(step(&mut client, &mut server) - .unwrap() - .is_none()); - assert!(step(&mut server, &mut client) - .unwrap() - .is_none()); + assert!( + step(&mut client, &mut server) + .unwrap() + .is_none() + ); + assert!( + step(&mut server, &mut client) + .unwrap() + .is_none() + ); // 0-RTT handshake let mut client = quic::ClientConnection::new( @@ -4986,9 +5006,11 @@ mod test_quic { client_params.into(), ) .unwrap(); - assert!(client - .negotiated_cipher_suite() - .is_some()); + assert!( + client + .negotiated_cipher_suite() + .is_some() + ); let mut server = quic::ServerConnection::new( Arc::clone(&server_config), @@ -5162,25 +5184,29 @@ mod test_quic { client_config.alpn_protocols = vec!["foo".into()]; let client_config = Arc::new(client_config); - assert!(quic::ClientConnection::new( - client_config, - quic::Version::V1, - server_name("localhost"), - b"client params".to_vec(), - ) - .is_err()); + assert!( + quic::ClientConnection::new( + client_config, + quic::Version::V1, + server_name("localhost"), + b"client params".to_vec(), + ) + .is_err() + ); let mut server_config = make_server_config_with_versions(KeyType::Ed25519, &[&rustls::version::TLS12]); server_config.alpn_protocols = vec!["foo".into()]; let server_config = Arc::new(server_config); - assert!(quic::ServerConnection::new( - server_config, - quic::Version::V1, - b"server params".to_vec(), - ) - .is_err()); + assert!( + quic::ServerConnection::new( + server_config, + quic::Version::V1, + b"server params".to_vec(), + ) + .is_err() + ); } #[test] @@ -5342,8 +5368,8 @@ mod test_quic { #[test] fn packet_key_api() { use cipher_suite::TLS13_AES_128_GCM_SHA256; - use rustls::quic::{Keys, Version}; use rustls::Side; + use rustls::quic::{Keys, Version}; // Test vectors: https://www.rfc-editor.org/rfc/rfc9001.html#name-client-initial const CONNECTION_ID: &[u8] = &[0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08]; @@ -5583,10 +5609,10 @@ mod test_quic { #[test] fn test_client_does_not_offer_sha1() { + use rustls::HandshakeType; use rustls::internal::msgs::codec::Reader; use rustls::internal::msgs::handshake::HandshakePayload; use rustls::internal::msgs::message::{MessagePayload, OutboundOpaqueMessage}; - use rustls::HandshakeType; for kt in ALL_KEY_TYPES { for version in rustls::ALL_VERSIONS { @@ -6089,9 +6115,11 @@ fn test_server_mtu_reduction() { server.write_tls(&mut pipe).unwrap(); assert_eq!(pipe.writevs.len(), 1); - assert!(pipe.writevs[0] - .iter() - .all(|x| *x <= 64 + encryption_overhead)); + assert!( + pipe.writevs[0] + .iter() + .all(|x| *x <= 64 + encryption_overhead) + ); } client.process_new_packets().unwrap(); @@ -6101,9 +6129,11 @@ fn test_server_mtu_reduction() { let mut pipe = OtherSession::new(&mut client); server.write_tls(&mut pipe).unwrap(); assert_eq!(pipe.writevs.len(), 1); - assert!(pipe.writevs[0] - .iter() - .all(|x| *x <= 64 + encryption_overhead)); + assert!( + pipe.writevs[0] + .iter() + .all(|x| *x <= 64 + encryption_overhead) + ); } client.process_new_packets().unwrap(); @@ -6939,19 +6969,25 @@ fn test_received_plaintext_backpressure() { // Fill the server's received plaintext buffer with 16k bytes let client_buf = [0; 16_385]; - dbg!(client - .writer() - .write(&client_buf) - .unwrap()); + dbg!( + client + .writer() + .write(&client_buf) + .unwrap() + ); let mut network_buf = Vec::with_capacity(32_768); - let sent = dbg!(client - .write_tls(&mut network_buf) - .unwrap()); + let sent = dbg!( + client + .write_tls(&mut network_buf) + .unwrap() + ); let mut read = 0; while read < sent { - let new = dbg!(server - .read_tls(&mut &network_buf[read..sent]) - .unwrap()); + let new = dbg!( + server + .read_tls(&mut &network_buf[read..sent]) + .unwrap() + ); if new == 4096 { read += new; } else { @@ -6961,18 +6997,24 @@ fn test_received_plaintext_backpressure() { server.process_new_packets().unwrap(); // Send two more bytes from client to server - dbg!(client - .writer() - .write(&client_buf[..2]) - .unwrap()); - let sent = dbg!(client - .write_tls(&mut network_buf) - .unwrap()); + dbg!( + client + .writer() + .write(&client_buf[..2]) + .unwrap() + ); + let sent = dbg!( + client + .write_tls(&mut network_buf) + .unwrap() + ); // Get an error because the received plaintext buffer is full - assert!(server - .read_tls(&mut &network_buf[..sent]) - .is_err()); + assert!( + server + .read_tls(&mut &network_buf[..sent]) + .is_err() + ); // Read out some of the plaintext server diff --git a/rustls/tests/api_ffdhe.rs b/rustls/tests/api_ffdhe.rs index ddfcbb75793..31b7f9864a3 100644 --- a/rustls/tests/api_ffdhe.rs +++ b/rustls/tests/api_ffdhe.rs @@ -366,7 +366,7 @@ mod ffdhe { SupportedKxGroup, }; use rustls::ffdhe_groups::FfdheGroup; - use rustls::{ffdhe_groups, CipherSuite, NamedGroup, SupportedCipherSuite, Tls12CipherSuite}; + use rustls::{CipherSuite, NamedGroup, SupportedCipherSuite, Tls12CipherSuite, ffdhe_groups}; use super::provider; diff --git a/rustls/tests/client_cert_verifier.rs b/rustls/tests/client_cert_verifier.rs index 5c3cfeb15ba..a0915d9d316 100644 --- a/rustls/tests/client_cert_verifier.rs +++ b/rustls/tests/client_cert_verifier.rs @@ -7,9 +7,10 @@ use super::*; mod common; use common::{ - do_handshake_until_both_error, do_handshake_until_error, make_client_config_with_versions, + ALL_KEY_TYPES, Arc, ErrorFromPeer, KeyType, MockClientVerifier, do_handshake_until_both_error, + do_handshake_until_error, make_client_config_with_versions, make_client_config_with_versions_with_auth, make_pair_for_arc_configs, server_config_builder, - server_name, Arc, ErrorFromPeer, KeyType, MockClientVerifier, ALL_KEY_TYPES, + server_name, }; use rustls::server::danger::ClientCertVerified; diff --git a/rustls/tests/common/mod.rs b/rustls/tests/common/mod.rs index 9118b2b4cea..6445442b766 100644 --- a/rustls/tests/common/mod.rs +++ b/rustls/tests/common/mod.rs @@ -16,7 +16,7 @@ use rustls::client::{ AlwaysResolvesClientRawPublicKeys, ServerCertVerifierBuilder, WebPkiServerVerifier, }; use rustls::crypto::cipher::{InboundOpaqueMessage, MessageDecrypter, MessageEncrypter}; -use rustls::crypto::{verify_tls13_signature_with_raw_key, CryptoProvider}; +use rustls::crypto::{CryptoProvider, verify_tls13_signature_with_raw_key}; use rustls::internal::msgs::codec::{Codec, Reader}; use rustls::internal::msgs::message::{Message, OutboundOpaqueMessage, PlainMessage}; use rustls::server::danger::{ClientCertVerified, ClientCertVerifier}; @@ -530,9 +530,11 @@ pub fn get_client_root_store(kt: KeyType) -> Arc { let chain = kt.get_chain(); let trust_anchor = chain.last().unwrap(); RootCertStore { - roots: vec![anchor_from_trusted_cert(trust_anchor) - .unwrap() - .to_owned()], + roots: vec![ + anchor_from_trusted_cert(trust_anchor) + .unwrap() + .to_owned(), + ], } .into() } @@ -869,12 +871,16 @@ pub fn do_suite_and_kx_test( assert_eq!(None, client.negotiated_cipher_suite()); assert_eq!(None, server.negotiated_cipher_suite()); - assert!(client - .negotiated_key_exchange_group() - .is_none()); - assert!(server - .negotiated_key_exchange_group() - .is_none()); + assert!( + client + .negotiated_key_exchange_group() + .is_none() + ); + assert!( + server + .negotiated_key_exchange_group() + .is_none() + ); assert_eq!(None, client.protocol_version()); assert_eq!(None, server.protocol_version()); assert!(client.is_handshaking()); @@ -889,13 +895,17 @@ pub fn do_suite_and_kx_test( assert_eq!(Some(expect_version), server.protocol_version()); assert_eq!(None, client.negotiated_cipher_suite()); assert_eq!(Some(expect_suite), server.negotiated_cipher_suite()); - assert!(client - .negotiated_key_exchange_group() - .is_none()); - if matches!(expect_version, ProtocolVersion::TLSv1_2) { - assert!(server + assert!( + client .negotiated_key_exchange_group() - .is_none()); + .is_none() + ); + if matches!(expect_version, ProtocolVersion::TLSv1_2) { + assert!( + server + .negotiated_key_exchange_group() + .is_none() + ); } else { assert_eq!( expect_kx, @@ -919,9 +929,11 @@ pub fn do_suite_and_kx_test( .name() ); if matches!(expect_version, ProtocolVersion::TLSv1_2) { - assert!(server - .negotiated_key_exchange_group() - .is_none()); + assert!( + server + .negotiated_key_exchange_group() + .is_none() + ); } else { assert_eq!( expect_kx, @@ -1402,11 +1414,11 @@ pub fn unsafe_plaintext_crypto_provider() -> Arc { } mod plaintext { + use rustls::ConnectionTrafficSecrets; use rustls::crypto::cipher::{ AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, MessageDecrypter, MessageEncrypter, OutboundPlainMessage, PrefixedPayload, Tls13AeadAlgorithm, UnsupportedOperationError, }; - use rustls::ConnectionTrafficSecrets; use super::*; diff --git a/rustls/tests/ech.rs b/rustls/tests/ech.rs index 444f1e20494..23e385226c7 100644 --- a/rustls/tests/ech.rs +++ b/rustls/tests/ech.rs @@ -1,4 +1,4 @@ -use base64::prelude::{Engine, BASE64_STANDARD}; +use base64::prelude::{BASE64_STANDARD, Engine}; use pki_types::DnsName; use rustls::internal::msgs::codec::{Codec, Reader}; use rustls::internal::msgs::enums::{EchVersion, HpkeAead, HpkeKdf, HpkeKem}; @@ -119,8 +119,7 @@ const BASE64_ECHCONFIG_LIST_LOCALHOST: &str = "AED+DQA8AAAgACAxoIJyV36iDlfFRmqE+ho2PxXE0EISPfUUJYKCy6T8VwAIAAEAAQABAAOACWxvY2FsaG9zdAAA"; // Two EchConfigs, both with server-name "cloudflare-esni.com". -const BASE64_ECHCONFIG_LIST_CF: &str = - "AK3+DQBCwwAgACAJ9T5U4FeM6631r2bvAuGtmEd8zQaoTkFAtArTcMl/XQAEAAEAASUTY2xvdWRmbGFyZS1lc25pLmNvbQAA/g0AYwMAEABBBGGbUlGLuGRorUeFwmrgHImkrh9uxoPrnFKpS5bQvnc5grfMS3PvymQ2FYL02WQi1ZzZJg5OsYYdzlaGYnEoJNsABAABAAEqE2Nsb3VkZmxhcmUtZXNuaS5jb20AAA=="; +const BASE64_ECHCONFIG_LIST_CF: &str = "AK3+DQBCwwAgACAJ9T5U4FeM6631r2bvAuGtmEd8zQaoTkFAtArTcMl/XQAEAAEAASUTY2xvdWRmbGFyZS1lc25pLmNvbQAA/g0AYwMAEABBBGGbUlGLuGRorUeFwmrgHImkrh9uxoPrnFKpS5bQvnc5grfMS3PvymQ2FYL02WQi1ZzZJg5OsYYdzlaGYnEoJNsABAABAAEqE2Nsb3VkZmxhcmUtZXNuaS5jb20AAA=="; // Three EchConfigs, the first one with an unsupported version. const BASE64_ECHCONFIG_LIST_WITH_UNSUPPORTED: &str = "AQW63QAFBQQDAgH+DQBmAAAQAEEE5itp4r9ln5e+Lx4NlIpM1Zdrt6keDUb73ampHp3culoB59aXqAoY+cPEox5W4nyDSNsWGhz1HX7xlC1Lz3IiwQAMAAEAAQABAAIAAQADQA5wdWJsaWMuZXhhbXBsZQAA/g0APQAAIAAgfWYWFXMCFK7ucFMzZvNqYJ6tZcDCCOYjIjRqtbzY3hwABBERIiJADnB1YmxpYy5leGFtcGxlAAD+DQBNAAAgACCFvWoDJ3wlQntS4mngx3qOtSS6HrPS8TJmLUsKxstzVwAMAAEAAQABAAIAAQADQA5wdWJsaWMuZXhhbXBsZQAIqqoABHRlc3Q="; diff --git a/rustls/tests/key_log_file_env.rs b/rustls/tests/key_log_file_env.rs index 81f517c5143..878fa2fd75f 100644 --- a/rustls/tests/key_log_file_env.rs +++ b/rustls/tests/key_log_file_env.rs @@ -30,8 +30,8 @@ use super::*; mod common; use common::{ - do_handshake, make_client_config_with_versions, make_pair_for_arc_configs, make_server_config, - transfer, Arc, KeyType, + Arc, KeyType, do_handshake, make_client_config_with_versions, make_pair_for_arc_configs, + make_server_config, transfer, }; #[test] diff --git a/rustls/tests/process_provider.rs b/rustls/tests/process_provider.rs index e1ab14199b7..007033225fa 100644 --- a/rustls/tests/process_provider.rs +++ b/rustls/tests/process_provider.rs @@ -4,14 +4,14 @@ //! executable, and runs tests in an indeterminate order. That restricts us //! to doing all the desired tests, in series, in one function. +use rustls::ClientConfig; +use rustls::crypto::CryptoProvider; #[cfg(all(feature = "aws_lc_rs", not(feature = "ring")))] use rustls::crypto::aws_lc_rs as provider; #[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))] use rustls::crypto::ring as provider; #[cfg(all(feature = "ring", feature = "aws_lc_rs"))] use rustls::crypto::ring as provider; -use rustls::crypto::CryptoProvider; -use rustls::ClientConfig; mod common; use crate::common::*; diff --git a/rustls/tests/server_cert_verifier.rs b/rustls/tests/server_cert_verifier.rs index 188f5c0b682..e00e1cee57c 100644 --- a/rustls/tests/server_cert_verifier.rs +++ b/rustls/tests/server_cert_verifier.rs @@ -7,16 +7,16 @@ use super::*; mod common; use common::{ - client_config_builder, client_config_builder_with_versions, do_handshake, - do_handshake_until_both_error, do_handshake_until_error, make_client_config_with_versions, - make_pair_for_arc_configs, make_server_config, server_config_builder, transfer_altered, - Altered, Arc, ErrorFromPeer, KeyType, MockServerVerifier, ALL_KEY_TYPES, + ALL_KEY_TYPES, Altered, Arc, ErrorFromPeer, KeyType, MockServerVerifier, client_config_builder, + client_config_builder_with_versions, do_handshake, do_handshake_until_both_error, + do_handshake_until_error, make_client_config_with_versions, make_pair_for_arc_configs, + make_server_config, server_config_builder, transfer_altered, }; use pki_types::{CertificateDer, ServerName}; -use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; use rustls::client::WebPkiServerVerifier; +use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; use rustls::internal::msgs::handshake::{ClientExtension, HandshakePayload}; use rustls::internal::msgs::message::{Message, MessagePayload}; use rustls::server::{ClientHello, ResolvesServerCert}; @@ -186,10 +186,12 @@ fn cas_extension_in_client_hello_if_server_verifier_requests_it() { .unwrap(); let cas_sending_server_verifier = Arc::new(ServerCertVerifierWithCasExt { verifier: server_verifier.clone(), - ca_names: vec![KeyType::Rsa2048 - .ca_distinguished_name() - .to_vec() - .into()], + ca_names: vec![ + KeyType::Rsa2048 + .ca_distinguished_name() + .to_vec() + .into(), + ], }); for (protocol_version, cas_extension_expected) in [(&TLS12, false), (&TLS13, true)] { @@ -209,7 +211,9 @@ fn cas_extension_in_client_hello_if_server_verifier_requests_it() { .any(|ext| matches!(ext, ClientExtension::AuthorityNames(_))), cas_extension_expected ); - println!("cas extension expectation met! cas_extension_expected: {cas_extension_expected}"); + println!( + "cas extension expectation met! cas_extension_expected: {cas_extension_expected}" + ); } } Altered::InPlace @@ -312,7 +316,9 @@ pub struct ResolvesCertChainByCaName(Vec<(DistinguishedName, Arc)> impl ResolvesServerCert for ResolvesCertChainByCaName { fn resolve(&self, client_hello: ClientHello<'_>) -> Option> { let Some(cas_extension) = client_hello.certificate_authorities() else { - println!("ResolvesCertChainByCaName: no CAs extension in ClientHello, returning default cert"); + println!( + "ResolvesCertChainByCaName: no CAs extension in ClientHello, returning default cert" + ); return Some(self.0[0].1.clone()); }; for (name, certified_key) in self.0.iter() { diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index 657b0782e20..4ceb3472f8b 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -147,9 +147,11 @@ fn app_data_client_to_server() { &mut NO_ACTIONS.clone(), ); - assert!(client_actions - .app_data_to_send - .is_none()); + assert!( + client_actions + .app_data_to_send + .is_none() + ); assert_eq!( [expected], outcome @@ -179,9 +181,11 @@ fn app_data_server_to_client() { &mut server_actions, ); - assert!(server_actions - .app_data_to_send - .is_none()); + assert!( + server_actions + .app_data_to_send + .is_none() + ); assert_eq!( [expected], outcome @@ -253,9 +257,11 @@ fn early_data() { "WriteTraffic" ] ); - assert!(client_actions - .early_data_to_send - .is_none()); + assert!( + client_actions + .early_data_to_send + .is_none() + ); assert_eq!( [expected], outcome @@ -526,11 +532,13 @@ fn junk_after_close_notify_received() { let mut server = outcome.server.take().unwrap(); let mut client_send_buf = [0u8; 128]; - let mut len = dbg!(write_traffic( - client.process_tls_records(&mut []), - |mut wt: WriteTraffic<_>| wt.queue_close_notify(&mut client_send_buf), - ) - .unwrap()); + let mut len = dbg!( + write_traffic( + client.process_tls_records(&mut []), + |mut wt: WriteTraffic<_>| wt.queue_close_notify(&mut client_send_buf), + ) + .unwrap() + ); client_send_buf[len..len + 4].copy_from_slice(&[0x17, 0x03, 0x03, 0x01]); len += 4; From 3ccfcece31d727f57e9ad3806e4652e146ac3eed Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Fri, 21 Feb 2025 10:27:48 +0100 Subject: [PATCH 064/403] Use 2024 idiom where possible --- rustls/src/client/hs.rs | 34 ++-- rustls/src/client/tls13.rs | 209 ++++++++++++----------- rustls/src/limited_cache.rs | 23 ++- rustls/src/msgs/handshake.rs | 6 +- rustls/src/server/server_conn.rs | 28 ++- rustls/src/server/tls12.rs | 11 +- rustls/src/ticketer.rs | 11 +- rustls/tests/api.rs | 13 +- rustls/tests/common/mod.rs | 26 ++- rustls/tests/key_log_file_env.rs | 4 +- rustls/tests/runners/key_log_file_env.rs | 2 +- 11 files changed, 180 insertions(+), 187 deletions(-) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 260aaae55e3..a07e59a6cfb 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -119,25 +119,27 @@ pub(super) fn start_handshake( None }; - let session_id = if let Some(_resuming) = &mut 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)?; + 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) } - Some(inner.session_id) + _ => None, } - _ => None, } - } else { - debug!("Not resuming any session"); - None + _ => { + debug!("Not resuming any session"); + None + } }; // https://tools.ietf.org/html/rfc8446#appendix-D.4 diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index d0cda04fd76..71d6ea0d12c 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -98,52 +98,56 @@ pub(super) fn handle_server_hello( ) })?; - let key_schedule_pre_handshake = if let (Some(selected_psk), Some(early_key_schedule)) = - (server_hello.psk_index(), early_key_schedule) - { - if let Some(ref resuming) = resuming_session { - let Some(resuming_suite) = suite.can_resume_from(resuming.suite()) else { - return Err({ - cx.common.send_fatal_alert( - AlertDescription::IllegalParameter, - PeerMisbehaved::ResumptionOfferedWithIncompatibleCipherSuite, - ) - }); - }; + let key_schedule_pre_handshake = match (server_hello.psk_index(), early_key_schedule) { + (Some(selected_psk), Some(early_key_schedule)) => { + match resuming_session { + Some(ref 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 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, + ) + }); + } - 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()); + } } - - debug!("Resuming using PSK"); - // The key schedule has been initialized and set in fill_in_psk_binder() - } else { - 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) } - KeySchedulePreHandshake::from(early_key_schedule) - } else { - 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(); @@ -500,75 +504,78 @@ impl State for ExpectEncryptedExtensions { } } - if let Some(resuming_session) = self.resuming_session { - let was_early_traffic = cx.common.early_traffic; - if was_early_traffic { - if exts.early_data_extension_offered() { - cx.data.early_data.accepted(); - } else { - cx.data.early_data.rejected(); - cx.common.early_traffic = false; + match self.resuming_session { + Some(resuming_session) => { + let was_early_traffic = cx.common.early_traffic; + if was_early_traffic { + if exts.early_data_extension_offered() { + cx.data.early_data.accepted(); + } else { + 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, - })) - } else { - if exts.early_data_extension_offered() { - return Err(PeerMisbehaved::EarlyDataExtensionWithoutResumption.into()); - } - cx.common - .handshake_kind - .get_or_insert(HandshakeKind::Full); + 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); + } - 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 { + 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_extension_offered() { + 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, + }) }) - }) + } } } @@ -1493,7 +1500,7 @@ impl ExpectTraffic { } } - if let Some(ref quic_params) = &cx.common.quic.params { + if let Some(quic_params) = &cx.common.quic.params { value.set_quic_params(quic_params); } } diff --git a/rustls/src/limited_cache.rs b/rustls/src/limited_cache.rs index 4252a337f97..6ae8bf94d2e 100644 --- a/rustls/src/limited_cache.rs +++ b/rustls/src/limited_cache.rs @@ -102,19 +102,18 @@ where where K: Borrow, { - if let Some(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) - } else { - None + 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) } } diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index e246bea938a..c2d6de203a3 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -492,7 +492,7 @@ pub enum CertificateStatusRequest { impl Codec<'_> for CertificateStatusRequest { fn encode(&self, bytes: &mut Vec) { match self { - Self::Ocsp(ref r) => r.encode(bytes), + Self::Ocsp(r) => r.encode(bytes), Self::Unknown((typ, payload)) => { typ.encode(bytes); payload.encode(bytes); @@ -1130,7 +1130,7 @@ impl ClientHelloPayload { pub(crate) fn set_psk_binder(&mut self, binder: impl Into>) { let last_extension = self.extensions.last_mut(); - if let Some(ClientExtension::PresharedKey(ref mut offer)) = last_extension { + if let Some(ClientExtension::PresharedKey(offer)) = last_extension { offer.binders[0] = PresharedKeyBinder::from(binder.into()); } } @@ -2772,7 +2772,7 @@ impl<'a> HandshakeMessagePayload<'a> { let binder_len = match self.payload { HandshakePayload::ClientHello(ref ch) => match ch.extensions.last() { - Some(ClientExtension::PresharedKey(ref offer)) => { + Some(ClientExtension::PresharedKey(offer)) => { let mut binders_encoding = Vec::new(); offer .binders diff --git a/rustls/src/server/server_conn.rs b/rustls/src/server/server_conn.rs index ba72be2d2d9..0541ee0a93d 100644 --- a/rustls/src/server/server_conn.rs +++ b/rustls/src/server/server_conn.rs @@ -1060,9 +1060,7 @@ impl EarlyDataState { fn pop(&mut self) -> Option> { match self { - Self::Accepted { - ref mut received, .. - } => received.pop(), + Self::Accepted { received, .. } => received.pop(), _ => None, } } @@ -1070,9 +1068,7 @@ impl EarlyDataState { #[cfg(feature = "std")] fn read(&mut self, buf: &mut [u8]) -> io::Result { match self { - Self::Accepted { - ref mut received, .. - } => received.read(buf), + Self::Accepted { received, .. } => received.read(buf), _ => Err(io::Error::from(io::ErrorKind::BrokenPipe)), } } @@ -1089,17 +1085,17 @@ impl EarlyDataState { pub(super) fn take_received_plaintext(&mut self, bytes: Payload<'_>) -> bool { let available = bytes.bytes().len(); - match self { - Self::Accepted { - ref mut received, - ref mut left, - } if received.apply_limit(available) == available && available <= *left => { - received.append(bytes.into_vec()); - *left -= available; - true - } - _ => false, + 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 } } diff --git a/rustls/src/server/tls12.rs b/rustls/src/server/tls12.rs index a9cecda0733..5183b037678 100644 --- a/rustls/src/server/tls12.rs +++ b/rustls/src/server/tls12.rs @@ -598,8 +598,8 @@ impl State for ExpectClientKx<'_> { cx.common .start_encryption_tls12(&secrets, Side::Server); - if let Some(client_cert) = self.client_cert { - Ok(Box::new(ExpectCertificateVerify { + match self.client_cert { + Some(client_cert) => Ok(Box::new(ExpectCertificateVerify { config: self.config, secrets, transcript: self.transcript, @@ -607,9 +607,8 @@ impl State for ExpectClientKx<'_> { using_ems: self.using_ems, client_cert, send_ticket: self.send_ticket, - })) - } else { - Ok(Box::new(ExpectCcs { + })), + _ => Ok(Box::new(ExpectCcs { config: self.config, secrets, transcript: self.transcript, @@ -617,7 +616,7 @@ impl State for ExpectClientKx<'_> { using_ems: self.using_ems, resuming: false, send_ticket: self.send_ticket, - })) + })), } } diff --git a/rustls/src/ticketer.rs b/rustls/src/ticketer.rs index 1d78b1ec9b0..d1b5e143574 100644 --- a/rustls/src/ticketer.rs +++ b/rustls/src/ticketer.rs @@ -140,11 +140,12 @@ impl TicketSwitcher { } // Make the switch, or mark for recovery if not possible - if let Some(next) = state.next.take() { - state.previous = Some(mem::replace(&mut state.current, next)); - state.next_switch_time = now.saturating_add(u64::from(self.lifetime)); - } else { - are_recovering = true; + 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, } } diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 23decdc9ed4..ef6715a68d4 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -4895,12 +4895,9 @@ mod test_quic { break None; } }; - if let Err(e) = recv.read_hs(&buf) { - return Err(e); - } else { - assert_eq!(recv.alert(), None); - } + recv.read_hs(&buf)?; + assert_eq!(recv.alert(), None); Ok(change) } @@ -6521,11 +6518,7 @@ fn test_client_tls12_no_resume_after_server_downgrade() { #[test] fn test_client_with_custom_verifier_can_accept_ecdsa_sha1_signatures() { fn alter_server_signature_to_ecdsa_sha1(msg: &mut Message) -> Altered { - if let MessagePayload::Handshake { - parsed, - ref mut encoded, - } = &mut msg.payload - { + if let MessagePayload::Handshake { parsed, encoded } = &mut msg.payload { if let HandshakePayload::ServerKeyExchange(_) = &mut parsed.payload { // nb. we don't care that this corrupts the signature, key exchange, etc. let original = encoded.bytes(); diff --git a/rustls/tests/common/mod.rs b/rustls/tests/common/mod.rs index 6445442b766..dd84391c7c4 100644 --- a/rustls/tests/common/mod.rs +++ b/rustls/tests/common/mod.rs @@ -1004,10 +1004,9 @@ impl ServerCertVerifier for MockServerVerifier { if let Some(expected_ocsp) = &self.expected_ocsp_response { assert_eq!(expected_ocsp, ocsp_response); } - if let Some(error) = &self.cert_rejection_error { - Err(error.clone()) - } else { - Ok(ServerCertVerified::assertion()) + match &self.cert_rejection_error { + Some(error) => Err(error.clone()), + _ => Ok(ServerCertVerified::assertion()), } } @@ -1021,10 +1020,9 @@ impl ServerCertVerifier for MockServerVerifier { "verify_tls12_signature({:?}, {:?}, {:?})", message, cert, dss ); - if let Some(error) = &self.tls12_signature_error { - Err(error.clone()) - } else { - Ok(HandshakeSignatureValid::assertion()) + match &self.tls12_signature_error { + Some(error) => Err(error.clone()), + _ => Ok(HandshakeSignatureValid::assertion()), } } @@ -1038,17 +1036,15 @@ impl ServerCertVerifier for MockServerVerifier { "verify_tls13_signature({:?}, {:?}, {:?})", message, cert, dss ); - if let Some(error) = &self.tls13_signature_error { - Err(error.clone()) - } else if self.requires_raw_public_keys { - verify_tls13_signature_with_raw_key( + match &self.tls13_signature_error { + Some(error) => Err(error.clone()), + _ if self.requires_raw_public_keys => verify_tls13_signature_with_raw_key( message, &SubjectPublicKeyInfoDer::from(cert.as_ref()), dss, &provider::default_provider().signature_verification_algorithms, - ) - } else { - Ok(HandshakeSignatureValid::assertion()) + ), + _ => Ok(HandshakeSignatureValid::assertion()), } } diff --git a/rustls/tests/key_log_file_env.rs b/rustls/tests/key_log_file_env.rs index 878fa2fd75f..0f2c889549b 100644 --- a/rustls/tests/key_log_file_env.rs +++ b/rustls/tests/key_log_file_env.rs @@ -38,7 +38,7 @@ use common::{ fn exercise_key_log_file_for_client() { serialized(|| { let server_config = Arc::new(make_server_config(KeyType::Rsa2048)); - env::set_var("SSLKEYLOGFILE", "./sslkeylogfile.txt"); + unsafe { env::set_var("SSLKEYLOGFILE", "./sslkeylogfile.txt") }; for version in rustls::ALL_VERSIONS { let mut client_config = make_client_config_with_versions(KeyType::Rsa2048, &[version]); @@ -61,7 +61,7 @@ fn exercise_key_log_file_for_server() { serialized(|| { let mut server_config = make_server_config(KeyType::Rsa2048); - env::set_var("SSLKEYLOGFILE", "./sslkeylogfile.txt"); + unsafe { env::set_var("SSLKEYLOGFILE", "./sslkeylogfile.txt") }; server_config.key_log = Arc::new(rustls::KeyLogFile::new()); let server_config = Arc::new(server_config); diff --git a/rustls/tests/runners/key_log_file_env.rs b/rustls/tests/runners/key_log_file_env.rs index 9a34b5a214f..dff6588b69f 100644 --- a/rustls/tests/runners/key_log_file_env.rs +++ b/rustls/tests/runners/key_log_file_env.rs @@ -41,7 +41,7 @@ fn serialized(f: impl FnOnce()) { let _guard = MUTEX.lock().unwrap(); // XXX: NOT thread safe. - env::set_var("SSLKEYLOGFILE", "./sslkeylogfile.txt"); + unsafe { env::set_var("SSLKEYLOGFILE", "./sslkeylogfile.txt") }; f() } From b299743a4ef67937e0311a9467b8e7d466630942 Mon Sep 17 00:00:00 2001 From: "@brody4hire - C. Jonathan Brody" Date: Mon, 24 Feb 2025 09:44:13 -0500 Subject: [PATCH 065/403] cleanup: specify once_cell version etc. in only 1 place --- rustls/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 1f7a332e1b2..2fe8c4b7809 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -40,7 +40,7 @@ brotli-decompressor = { workspace = true, optional = true } hashbrown = { workspace = true, optional = true } log = { workspace = true, optional = true } # only required for no-std -once_cell = { version = "1.16", default-features = false, features = ["alloc", "race"] } +once_cell = { workspace = true } ring = { workspace = true, optional = true } subtle = { workspace = true } webpki = { workspace = true } From a5ec652913f89605bbd58f0aa95535e3592fbf0a Mon Sep 17 00:00:00 2001 From: "@brody4hire - C. Jonathan Brody" Date: Sun, 23 Feb 2025 21:33:23 -0500 Subject: [PATCH 066/403] docs: update reference to danger NoCertificateVerification struct in examples --- rustls/src/manual/features.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustls/src/manual/features.rs b/rustls/src/manual/features.rs index 769e9d6e32b..d8b85d61402 100644 --- a/rustls/src/manual/features.rs +++ b/rustls/src/manual/features.rs @@ -59,7 +59,7 @@ and will not support: 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/992e2364a006b2e84a8cf6a7c3eaf0bdb773c9de/examples/src/bin/tlsclient-mio.rs#L318)_ `*` + see the [example code](https://github.com/rustls/rustls/blob/v/0.23.23/examples/src/bin/tlsclient-mio.rs#L338)_ `*` ### About "custom extensions" From a419389ec45b33ce73d51c6c8fc3f7964ecf2184 Mon Sep 17 00:00:00 2001 From: "@brody4hire - C. Jonathan Brody" Date: Mon, 24 Feb 2025 11:07:21 -0500 Subject: [PATCH 067/403] docs: minor improvements to CryptoProvider doc --- rustls/src/crypto/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rustls/src/crypto/mod.rs b/rustls/src/crypto/mod.rs index 635d3918917..e80370343a6 100644 --- a/rustls/src/crypto/mod.rs +++ b/rustls/src/crypto/mod.rs @@ -120,7 +120,7 @@ pub use crate::suites::CipherSuiteCommon; /// provider (dynamically). /// /// For example, if we want to make a provider that just overrides key loading in the config builder -/// API ([`ConfigBuilder::with_single_cert`] etc.), it might look like this: +/// API (with [`ConfigBuilder::with_single_cert`], etc.), it might look like this: /// /// ``` /// # #[cfg(feature = "aws_lc_rs")] { @@ -212,7 +212,7 @@ pub struct CryptoProvider { /// Source of cryptographically secure random numbers. pub secure_random: &'static dyn SecureRandom, - /// Provider for loading private [SigningKey]s from [PrivateKeyDer]. + /// Provider for loading private [`SigningKey`]s from [`PrivateKeyDer`]. pub key_provider: &'static dyn KeyProvider, } From 6ede5cb8fce7b1cd656a0f5f976e14007d1fa798 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 6 Feb 2025 11:57:31 +0000 Subject: [PATCH 068/403] unbuffered::ReadTraffic: do not prematurely consume data Previously, the point at the application is given a `ReadTraffic` state is when the data is consumed. That meant `ReadTraffic::peek_len()` was too late for an application to decide not to accept the data just yet. Note that `ReadTraffic::next_record()` remains one-shot, as there is at most one item in `received_plaintext` in unbuffered mode. --- rustls/src/conn/unbuffered.rs | 55 ++++++++++++++++++----------------- rustls/src/vecbuf.rs | 7 +++++ rustls/tests/unbuffered.rs | 47 ++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 27 deletions(-) diff --git a/rustls/src/conn/unbuffered.rs b/rustls/src/conn/unbuffered.rs index e3fe4f6e7ca..107d9202d49 100644 --- a/rustls/src/conn/unbuffered.rs +++ b/rustls/src/conn/unbuffered.rs @@ -53,15 +53,15 @@ impl UnbufferedConnectionCommon { break (buffer.pending_discard(), execute(self, incoming_tls, value)); } - if let Some(chunk) = self + if !self .core .common_state .received_plaintext - .pop() + .is_empty() { break ( buffer.pending_discard(), - ReadTraffic::new(self, incoming_tls, chunk).into(), + ReadTraffic::new(self, incoming_tls).into(), ); } @@ -316,50 +316,51 @@ impl fmt::Debug for ConnectionState<'_, '_, Data> { /// Application data is available pub struct ReadTraffic<'c, 'i, Data> { - _conn: &'c mut UnbufferedConnectionCommon, + conn: &'c mut UnbufferedConnectionCommon, // for forwards compatibility; to support in-place decryption in the future _incoming_tls: &'i mut [u8], - chunk: Vec, - taken: bool, + + // owner of the latest chunk obtained in `next_record`, as borrowed by + // `AppDataRecord` + chunk: Option>, } impl<'c, 'i, Data> ReadTraffic<'c, 'i, Data> { - fn new( - _conn: &'c mut UnbufferedConnectionCommon, - _incoming_tls: &'i mut [u8], - chunk: Vec, - ) -> Self { + fn new(conn: &'c mut UnbufferedConnectionCommon, _incoming_tls: &'i mut [u8]) -> Self { Self { - _conn, + conn, _incoming_tls, - chunk, - taken: false, + 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, Error>> { - if self.taken { - None - } else { - self.taken = true; - Some(Ok(AppDataRecord { + self.chunk = self + .conn + .core + .common_state + .received_plaintext + .pop(); + self.chunk.as_ref().map(|chunk| { + Ok(AppDataRecord { discard: 0, - payload: &self.chunk, - })) - } + 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 { - if self.taken { - None - } else { - NonZeroUsize::new(self.chunk.len()) - } + self.conn + .core + .common_state + .received_plaintext + .peek() + .and_then(|ch| NonZeroUsize::new(ch.len())) } } diff --git a/rustls/src/vecbuf.rs b/rustls/src/vecbuf.rs index 1343db5feca..ddc150d529e 100644 --- a/rustls/src/vecbuf.rs +++ b/rustls/src/vecbuf.rs @@ -113,6 +113,13 @@ impl ChunkVecBuffer { 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")] diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index 4ceb3472f8b..850f149bd03 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -919,6 +919,53 @@ fn rejects_junk() { confirm_transmit_tls_data(server.process_tls_records(&mut [])); } +#[test] +fn read_traffic_not_consumed_too_early() { + let mut outcome = handshake(&rustls::version::TLS13); + let mut client = outcome.client.take().unwrap(); + let mut server = outcome.server.take().unwrap(); + + let mut client_to_server_buf = Buffer::default(); + write_traffic(client.process_tls_records(&mut []), |mut wt| { + encrypt(&mut wt, b"hello", &mut client_to_server_buf) + }); + + // if we just peek, we are presented the same data again + let (_, discard) = read_traffic( + server.process_tls_records(client_to_server_buf.filled()), + |rt| assert_eq!(rt.peek_len(), NonZeroUsize::new(5)), + ); + assert!(discard > 0); + client_to_server_buf.discard(discard); + + // ditto + let (_, discard) = read_traffic( + server.process_tls_records(client_to_server_buf.filled()), + |rt| assert_eq!(rt.peek_len(), NonZeroUsize::new(5)), + ); + assert_eq!(discard, 0); + + // now consume + let (data, discard) = read_traffic( + server.process_tls_records(client_to_server_buf.filled()), + |mut rt| { + rt.next_record() + .unwrap() + .unwrap() + .payload + .to_vec() + }, + ); + assert_eq!(discard, 0); + assert_eq!(data, b"hello"); + + // server is now idle + write_traffic( + server.process_tls_records(client_to_server_buf.filled()), + |_| (), + ); +} + fn write_traffic) -> R>( status: UnbufferedStatus<'_, '_, T>, mut f: F, From 8558a335f5af34f9db48d0d24024512164c27f8a Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 11 Feb 2025 13:39:21 +0000 Subject: [PATCH 069/403] unbuffered: clarify `process_tls_records_common` arg names --- rustls/src/conn/unbuffered.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/rustls/src/conn/unbuffered.rs b/rustls/src/conn/unbuffered.rs index 107d9202d49..aca86c3bf29 100644 --- a/rustls/src/conn/unbuffered.rs +++ b/rustls/src/conn/unbuffered.rs @@ -42,15 +42,18 @@ impl UnbufferedConnectionCommon { fn process_tls_records_common<'c, 'i, T>( &'c mut self, incoming_tls: &'i mut [u8], - mut check: impl FnMut(&mut Self) -> Option, - execute: impl FnOnce(&'c mut Self, &'i mut [u8], T) -> ConnectionState<'c, 'i, Data>, + mut early_data_available: impl FnMut(&mut Self) -> Option, + early_data_state: impl FnOnce(&'c mut Self, &'i mut [u8], T) -> 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 let Some(value) = check(self) { - break (buffer.pending_discard(), execute(self, incoming_tls, value)); + if let Some(value) = early_data_available(self) { + break ( + buffer.pending_discard(), + early_data_state(self, incoming_tls, value), + ); } if !self From 4015d9303f5e5a270c997f875a392508ffd32031 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 11 Feb 2025 15:01:32 +0000 Subject: [PATCH 070/403] unbuffered::ReadEarlyData: do not prematurely consume data --- rustls/src/conn/unbuffered.rs | 59 +++++++++++++++----------------- rustls/src/server/server_conn.rs | 11 ++++++ 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/rustls/src/conn/unbuffered.rs b/rustls/src/conn/unbuffered.rs index aca86c3bf29..59c5a51fb52 100644 --- a/rustls/src/conn/unbuffered.rs +++ b/rustls/src/conn/unbuffered.rs @@ -19,7 +19,7 @@ impl UnbufferedConnectionCommon { &'c mut self, incoming_tls: &'i mut [u8], ) -> UnbufferedStatus<'c, 'i, ClientConnectionData> { - self.process_tls_records_common(incoming_tls, |_| None, |_, _, ()| unreachable!()) + self.process_tls_records_common(incoming_tls, |_| false, |_, _| unreachable!()) } } @@ -32,27 +32,27 @@ impl UnbufferedConnectionCommon { ) -> UnbufferedStatus<'c, 'i, ServerConnectionData> { self.process_tls_records_common( incoming_tls, - |conn| conn.pop_early_data(), - |conn, incoming_tls, chunk| ReadEarlyData::new(conn, incoming_tls, chunk).into(), + |conn| conn.peek_early_data().is_some(), + |conn, incoming_tls| ReadEarlyData::new(conn, incoming_tls).into(), ) } } impl UnbufferedConnectionCommon { - fn process_tls_records_common<'c, 'i, T>( + fn process_tls_records_common<'c, 'i>( &'c mut self, incoming_tls: &'i mut [u8], - mut early_data_available: impl FnMut(&mut Self) -> Option, - early_data_state: impl FnOnce(&'c mut Self, &'i mut [u8], T) -> ConnectionState<'c, 'i, Data>, + 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 let Some(value) = early_data_available(self) { + if early_data_available(self) { break ( buffer.pending_discard(), - early_data_state(self, incoming_tls, value), + early_data_state(self, incoming_tls), ); } @@ -369,52 +369,47 @@ impl<'c, 'i, Data> ReadTraffic<'c, 'i, Data> { /// Early application-data is available. pub struct ReadEarlyData<'c, 'i, Data> { - _conn: &'c mut UnbufferedConnectionCommon, + conn: &'c mut UnbufferedConnectionCommon, + // for forwards compatibility; to support in-place decryption in the future _incoming_tls: &'i mut [u8], - chunk: Vec, - taken: bool, + + // owner of the latest chunk obtained in `next_record`, as borrowed by + // `AppDataRecord` + chunk: Option>, } -impl<'c, 'i, Data> ReadEarlyData<'c, 'i, Data> { +impl<'c, 'i> ReadEarlyData<'c, 'i, ServerConnectionData> { fn new( - _conn: &'c mut UnbufferedConnectionCommon, + conn: &'c mut UnbufferedConnectionCommon, _incoming_tls: &'i mut [u8], - chunk: Vec, ) -> Self { Self { - _conn, + conn, _incoming_tls, - chunk, - taken: false, + chunk: None, } } -} -impl ReadEarlyData<'_, '_, ServerConnectionData> { /// 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, Error>> { - if self.taken { - None - } else { - self.taken = true; - Some(Ok(AppDataRecord { + self.chunk = self.conn.pop_early_data(); + self.chunk.as_ref().map(|chunk| { + Ok(AppDataRecord { discard: 0, - payload: &self.chunk, - })) - } + 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 { - if self.taken { - None - } else { - NonZeroUsize::new(self.chunk.len()) - } + self.conn + .peek_early_data() + .and_then(|ch| NonZeroUsize::new(ch.len())) } } diff --git a/rustls/src/server/server_conn.rs b/rustls/src/server/server_conn.rs index 0541ee0a93d..8108701e146 100644 --- a/rustls/src/server/server_conn.rs +++ b/rustls/src/server/server_conn.rs @@ -918,6 +918,10 @@ impl UnbufferedConnectionCommon { pub(crate) fn pop_early_data(&mut self) -> Option> { 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`]. @@ -1058,6 +1062,13 @@ impl EarlyDataState { matches!(self, Self::Rejected) } + fn peek(&self) -> Option<&[u8]> { + match self { + Self::Accepted { received, .. } => received.peek(), + _ => None, + } + } + fn pop(&mut self) -> Option> { match self { Self::Accepted { received, .. } => received.pop(), From 6ffdc23863b4a55655d5f62b962b7f7adbe55800 Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Wed, 19 Feb 2025 14:27:31 -0500 Subject: [PATCH 071/403] bogo: implement -wait-for-debugger in shim Also updates the `runme` script to conditionally exclude the `-test.timeout` flag given to the BoGo runner when `-wait-for-debugger` is in use. The implementation in the shim depends on UNIX SIGSTOP signalling, and so is conditional to UNIX-like systems. Providing the flag on another platform will panic with an error message. --- Cargo.lock | 19 +++++++++++++++++++ bogo/Cargo.toml | 1 + bogo/runme | 10 +++++++--- bogo/src/main.rs | 24 ++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d5e2ac37c42..f9320d1d14c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -493,6 +493,7 @@ version = "0.1.0" dependencies = [ "base64", "env_logger", + "nix", "rustls 0.23.23", "rustls-post-quantum", ] @@ -568,6 +569,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chacha20" version = "0.9.1" @@ -1894,6 +1901,18 @@ dependencies = [ "uuid", ] +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "nom" version = "7.1.3" diff --git a/bogo/Cargo.toml b/bogo/Cargo.toml index cc3f2d3d64d..f8831396c82 100644 --- a/bogo/Cargo.toml +++ b/bogo/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] base64 = { workspace = true } env_logger = { workspace = true } +nix = { version = "0.29", default-features = false, features = ["signal"] } rustls = { path = "../rustls", features = ["aws_lc_rs", "ring", "tls12"] } rustls-post-quantum = { path = "../rustls-post-quantum", optional = true } diff --git a/bogo/runme b/bogo/runme index 1a79f77a5d4..795451494bb 100755 --- a/bogo/runme +++ b/bogo/runme @@ -38,10 +38,14 @@ fi # Best effort on OS-X case $OSTYPE in darwin*) set +e ;; esac +# Set default timeout unless -wait-for-debugger flag is present. +# When this flag is set the shim will pause itself, and the runner will +# print the PID to attach to in order to continue. +runner_args="-pipe -allow-unimplemented" +[[ ! "$*" =~ "-wait-for-debugger" ]] && runner_args+=" -test.timeout 60s" + ( cd bogo/ssl/test/runner && ./runner.test -shim-path ../../../../../target/debug/bogo \ -shim-config ../../../../config.json \ - -pipe \ - -allow-unimplemented \ - -test.timeout 60s \ + $runner_args \ "$@") # you can pass in `-test "Foo;Bar"` to run specific tests true diff --git a/bogo/src/main.rs b/bogo/src/main.rs index d4aa72c3e8d..907bcbe3e5e 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -10,6 +10,10 @@ use std::sync::Arc; use std::{env, net, process, thread, time}; use base64::prelude::{BASE64_STANDARD, Engine}; +#[cfg(unix)] +use nix::sys::signal::{self, Signal}; +#[cfg(unix)] +use nix::unistd::Pid; use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; use rustls::client::{ ClientConfig, ClientConnection, EchConfig, EchGreaseConfig, EchMode, EchStatus, Resumption, @@ -107,6 +111,7 @@ struct Options { expect_curve_id: Option, on_initial_expect_curve_id: Option, on_resume_expect_curve_id: Option, + wait_for_debugger: bool, } impl Options { @@ -176,6 +181,7 @@ impl Options { expect_curve_id: None, on_initial_expect_curve_id: None, on_resume_expect_curve_id: None, + wait_for_debugger: false, } } @@ -1600,6 +1606,16 @@ pub fn main() { "-server-preference" => { opts.server_preference = true; } + "-wait-for-debugger" => { + #[cfg(windows)] + { + panic("-wait-for-debugger not supported on Windows"); + } + #[cfg(unix)] + { + opts.wait_for_debugger = true; + } + } // defaults: "-enable-all-curves" | @@ -1693,6 +1709,14 @@ pub fn main() { println!("opts {:?}", opts); + #[cfg(unix)] + if opts.wait_for_debugger { + // On Unix systems when -wait-for-debugger is passed from the BoGo runner + // we should SIGSTOP ourselves to allow a debugger to attach to the shim to + // continue the testing process. + signal::kill(Pid::from_raw(process::id() as i32), Signal::SIGSTOP).unwrap(); + } + let (mut client_cfg, mut server_cfg) = match opts.side { Side::Client => (Some(make_client_cfg(&opts)), None), Side::Server => (None, Some(make_server_cfg(&opts))), From 66df89304424f3583bc543be858f01ec511d2607 Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Fri, 21 Feb 2025 14:46:09 -0500 Subject: [PATCH 072/403] clippy: allow disallowed_types for bogo main We can use the standard `Arc` here without worry. --- bogo/src/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bogo/src/main.rs b/bogo/src/main.rs index 907bcbe3e5e..78aa152207d 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -4,6 +4,8 @@ // https://boringssl.googlesource.com/boringssl/+/master/ssl/test // +#![allow(clippy::disallowed_types)] + use std::fmt::{Debug, Formatter}; use std::io::{self, Read, Write}; use std::sync::Arc; From 39b8eacd0c6ac98f8b6679e56d9eeedbc769b4a4 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 11 Feb 2025 16:47:13 +0000 Subject: [PATCH 073/403] tlsclient-mio: use `Display` for printing TLS errors --- connect-tests/tests/badssl.rs | 16 ++++++++-------- examples/src/bin/tlsclient-mio.rs | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/connect-tests/tests/badssl.rs b/connect-tests/tests/badssl.rs index a3671e532e3..36e47e8c554 100644 --- a/connect-tests/tests/badssl.rs +++ b/connect-tests/tests/badssl.rs @@ -15,7 +15,7 @@ mod online { fn no_cbc() { connect("cbc.badssl.com") .fails() - .expect(r"TLS error: AlertReceived\(HandshakeFailure\)") + .expect(r"TLS error: received fatal alert: HandshakeFailure") .go() .unwrap(); } @@ -24,7 +24,7 @@ mod online { fn no_rc4() { connect("rc4.badssl.com") .fails() - .expect(r"TLS error: AlertReceived\(HandshakeFailure\)") + .expect(r"TLS error: received fatal alert: HandshakeFailure") .go() .unwrap(); } @@ -33,7 +33,7 @@ mod online { fn expired() { connect("expired.badssl.com") .fails() - .expect(r"TLS error: InvalidCertificate\(Expired\)") + .expect(r"TLS error: invalid peer certificate: Expired") .go() .unwrap(); } @@ -42,7 +42,7 @@ mod online { fn wrong_host() { connect("wrong.host.badssl.com") .fails() - .expect(r"TLS error: InvalidCertificate\(NotValidForName\)") + .expect(r"TLS error: invalid peer certificate: NotValidForName") .go() .unwrap(); } @@ -51,7 +51,7 @@ mod online { fn self_signed() { connect("self-signed.badssl.com") .fails() - .expect(r"TLS error: InvalidCertificate\(UnknownIssuer\)") + .expect(r"TLS error: invalid peer certificate: UnknownIssuer") .go() .unwrap(); } @@ -60,7 +60,7 @@ mod online { fn no_dh() { connect("dh2048.badssl.com") .fails() - .expect(r"TLS error: AlertReceived\(HandshakeFailure\)") + .expect(r"TLS error: received fatal alert: HandshakeFailure") .go() .unwrap(); } @@ -101,7 +101,7 @@ mod online { fn too_many_sans() { connect("10000-sans.badssl.com") .fails() - .expect(r"TLS error: InvalidMessage\(HandshakePayloadTooLarge\)") + .expect(r"TLS error: received corrupt message of type HandshakePayloadTooLarge") .go() .unwrap(); } @@ -119,7 +119,7 @@ mod online { fn sha1_2016() { connect("sha1-2016.badssl.com") .fails() - .expect(r"TLS error: InvalidCertificate\(Expired\)") + .expect(r"TLS error: invalid peer certificate: Expired") .go() .unwrap(); } diff --git a/examples/src/bin/tlsclient-mio.rs b/examples/src/bin/tlsclient-mio.rs index b999223b08e..cc8e2de4b79 100644 --- a/examples/src/bin/tlsclient-mio.rs +++ b/examples/src/bin/tlsclient-mio.rs @@ -115,7 +115,7 @@ impl TlsClient { let io_state = match self.tls_conn.process_new_packets() { Ok(io_state) => io_state, Err(err) => { - println!("TLS error: {:?}", err); + println!("TLS error: {err}"); self.closing = true; return; } From 4c5ad2b85951891d22dae5ee2f55100d6672761b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 27 Jan 2025 16:06:08 +0000 Subject: [PATCH 074/403] Take webpki 0.103.0 and pki-types 1.11.0 --- Cargo.lock | 17 +++++++++++++---- Cargo.toml | 4 ++-- fuzz/Cargo.lock | 9 ++++----- provider-example/Cargo.toml | 1 - provider-example/src/verify.rs | 5 +++-- rustls-fuzzing-provider/Cargo.toml | 1 - rustls-fuzzing-provider/src/lib.rs | 3 +-- rustls/Cargo.toml | 2 +- rustls/src/crypto/aws_lc_rs/sign.rs | 3 +-- rustls/src/crypto/ring/sign.rs | 3 +-- rustls/src/webpki/mod.rs | 10 +++++----- 11 files changed, 31 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f9320d1d14c..ea90c6daef0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2592,7 +2592,7 @@ dependencies = [ "rcgen", "ring", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.103.0", "rustversion", "serde", "serde_json", @@ -2614,7 +2614,7 @@ dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] @@ -2679,7 +2679,6 @@ version = "0.1.0" dependencies = [ "env_logger", "rustls 0.23.23", - "rustls-webpki", ] [[package]] @@ -2728,7 +2727,6 @@ dependencies = [ "rcgen", "rsa", "rustls 0.23.23", - "rustls-webpki", "sha2", "signature", "webpki-roots", @@ -2751,6 +2749,17 @@ name = "rustls-webpki" version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aa4eeac2588ffff23e9d7a7e9b3f971c5fb5b7ebc9452745e0c232c64f83b2f" dependencies = [ "aws-lc-rs", "ring", diff --git a/Cargo.toml b/Cargo.toml index 833a76d92d7..824660ec61c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,7 +71,7 @@ once_cell = { version = "1.16", default-features = false, features = ["alloc", " openssl = "0.10" p256 = { version = "0.13.2", default-features = false, features = ["alloc", "ecdsa", "pkcs8"] } pkcs8 = "0.10.2" -pki-types = { package = "rustls-pki-types", version = "1.10", features = ["alloc"] } +pki-types = { package = "rustls-pki-types", version = "1.11", features = ["alloc"] } rand_core = { version = "0.6", features = ["getrandom"] } rayon = "1.7" rcgen = { version = "0.13", features = ["pem", "aws_lc_rs"], default-features = false } @@ -86,7 +86,7 @@ subtle = { version = "2.5.0", default-features = false } time = { version = "0.3.6", default-features = false } tikv-jemallocator = "0.6" tokio = { version = "1.34", features = ["io-util", "macros", "net", "rt"] } -webpki = { package = "rustls-webpki", version = "0.102.8", features = ["alloc"], default-features = false } +webpki = { package = "rustls-webpki", version = "0.103", features = ["alloc"], default-features = false } webpki-roots = "0.26" x25519-dalek = "2" x509-parser = "0.17" diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index dc9f44da2aa..5f1c4c721ab 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -249,20 +249,19 @@ name = "rustls-fuzzing-provider" version = "0.1.0" dependencies = [ "rustls", - "rustls-webpki", ] [[package]] name = "rustls-pki-types" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" +checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" [[package]] name = "rustls-webpki" -version = "0.102.8" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +checksum = "0aa4eeac2588ffff23e9d7a7e9b3f971c5fb5b7ebc9452745e0c232c64f83b2f" dependencies = [ "ring", "rustls-pki-types", diff --git a/provider-example/Cargo.toml b/provider-example/Cargo.toml index f116a6c0aa8..3ca1a442311 100644 --- a/provider-example/Cargo.toml +++ b/provider-example/Cargo.toml @@ -21,7 +21,6 @@ rustls = { path = "../rustls", default-features = false, features = ["logging", rsa = { workspace = true } sha2 = { workspace = true } signature = { workspace = true } -webpki = { workspace = true } x25519-dalek = { workspace = true } [dev-dependencies] diff --git a/provider-example/src/verify.rs b/provider-example/src/verify.rs index 89596c2ba55..5d3c5dbc276 100644 --- a/provider-example/src/verify.rs +++ b/provider-example/src/verify.rs @@ -3,8 +3,9 @@ use rsa::signature::Verifier; use rsa::{BigUint, RsaPublicKey, pkcs1v15, pss}; use rustls::SignatureScheme; use rustls::crypto::WebPkiSupportedAlgorithms; -use rustls::pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm}; -use webpki::alg_id; +use rustls::pki_types::{ + AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm, alg_id, +}; pub static ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms { all: &[RSA_PSS_SHA256, RSA_PKCS1_SHA256], diff --git a/rustls-fuzzing-provider/Cargo.toml b/rustls-fuzzing-provider/Cargo.toml index 0307c40bfcf..80d6ae06523 100644 --- a/rustls-fuzzing-provider/Cargo.toml +++ b/rustls-fuzzing-provider/Cargo.toml @@ -6,7 +6,6 @@ publish = false [dependencies] rustls = { path = "../rustls", default-features = false, features = ["logging", "std", "tls12"] } -webpki = { workspace = true } [dev-dependencies] env_logger = { workspace = true } diff --git a/rustls-fuzzing-provider/src/lib.rs b/rustls-fuzzing-provider/src/lib.rs index 72e7df83ce5..fed5aa444ca 100644 --- a/rustls-fuzzing-provider/src/lib.rs +++ b/rustls-fuzzing-provider/src/lib.rs @@ -14,14 +14,13 @@ use rustls::crypto::{ use rustls::ffdhe_groups::FfdheGroup; use rustls::pki_types::{ AlgorithmIdentifier, CertificateDer, InvalidSignature, PrivateKeyDer, - SignatureVerificationAlgorithm, + SignatureVerificationAlgorithm, alg_id, }; use rustls::{ CipherSuite, ConnectionTrafficSecrets, ContentType, Error, NamedGroup, PeerMisbehaved, ProtocolVersion, RootCertStore, SignatureAlgorithm, SignatureScheme, SupportedCipherSuite, Tls12CipherSuite, Tls13CipherSuite, crypto, server, sign, }; -use webpki::alg_id; /// This is a `CryptoProvider` that provides NO SECURITY and is for fuzzing only. pub fn provider() -> crypto::CryptoProvider { diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 2fe8c4b7809..210ae3e05f7 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -18,7 +18,7 @@ build = "build.rs" default = ["aws_lc_rs", "logging", "std", "tls12"] aws-lc-rs = ["aws_lc_rs"] # Alias because Cargo features commonly use `-` -aws_lc_rs = ["dep:aws-lc-rs", "webpki/aws_lc_rs"] +aws_lc_rs = ["dep:aws-lc-rs", "webpki/aws-lc-rs"] brotli = ["dep:brotli", "dep:brotli-decompressor", "std"] custom-provider = [] fips = ["aws_lc_rs", "aws-lc-rs?/fips"] diff --git a/rustls/src/crypto/aws_lc_rs/sign.rs b/rustls/src/crypto/aws_lc_rs/sign.rs index f4efa73f665..4139906a226 100644 --- a/rustls/src/crypto/aws_lc_rs/sign.rs +++ b/rustls/src/crypto/aws_lc_rs/sign.rs @@ -6,8 +6,7 @@ use alloc::vec::Vec; use alloc::{format, vec}; use core::fmt::{self, Debug, Formatter}; -use pki_types::{PrivateKeyDer, PrivatePkcs8KeyDer, SubjectPublicKeyInfoDer}; -use webpki::alg_id; +use pki_types::{PrivateKeyDer, PrivatePkcs8KeyDer, SubjectPublicKeyInfoDer, alg_id}; use super::ring_like::rand::SystemRandom; use super::ring_like::signature::{self, EcdsaKeyPair, Ed25519KeyPair, KeyPair, RsaKeyPair}; diff --git a/rustls/src/crypto/ring/sign.rs b/rustls/src/crypto/ring/sign.rs index 7b384508ad5..91b753a1cae 100644 --- a/rustls/src/crypto/ring/sign.rs +++ b/rustls/src/crypto/ring/sign.rs @@ -6,8 +6,7 @@ use alloc::vec::Vec; use alloc::{format, vec}; use core::fmt::{self, Debug, Formatter}; -use pki_types::{PrivateKeyDer, PrivatePkcs8KeyDer, SubjectPublicKeyInfoDer}; -use webpki::alg_id; +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}; diff --git a/rustls/src/webpki/mod.rs b/rustls/src/webpki/mod.rs index 771bb6966ec..bc74b02eaa4 100644 --- a/rustls/src/webpki/mod.rs +++ b/rustls/src/webpki/mod.rs @@ -58,13 +58,13 @@ fn pki_error(error: webpki::Error) -> Error { use webpki::Error::*; match error { BadDer | BadDerTime | TrailingData(_) => CertificateError::BadEncoding.into(), - CertNotValidYet => CertificateError::NotValidYet.into(), - CertExpired | InvalidCertValidity => CertificateError::Expired.into(), + CertNotValidYet { .. } => CertificateError::NotValidYet.into(), + CertExpired { .. } | InvalidCertValidity => CertificateError::Expired.into(), UnknownIssuer => CertificateError::UnknownIssuer.into(), - CertNotValidForName => CertificateError::NotValidForName.into(), + CertNotValidForName { .. } => CertificateError::NotValidForName.into(), CertRevoked => CertificateError::Revoked.into(), UnknownRevocationStatus => CertificateError::UnknownRevocationStatus.into(), - CrlExpired => CertificateError::ExpiredRevocationList.into(), + CrlExpired { .. } => CertificateError::ExpiredRevocationList.into(), IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl.into(), InvalidSignatureForPublicKey @@ -189,7 +189,7 @@ mod tests { ), ]; for t in testcases { - assert_eq!(crl_error(t.0), t.1); + assert_eq!(crl_error(t.0.clone()), t.1); } assert!(matches!( From 3e19b006767da193e11ce9da99c19f962bd75a2c Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 27 Jan 2025 16:10:26 +0000 Subject: [PATCH 075/403] Pass-through detailed certificate name errors --- rustls/src/error.rs | 58 +++++++++++++++++++++++++++++++++++++++- rustls/src/webpki/mod.rs | 11 ++++++-- rustls/tests/api.rs | 26 +++++++++++++++--- 3 files changed, 88 insertions(+), 7 deletions(-) diff --git a/rustls/src/error.rs b/rustls/src/error.rs index 7453880daae..1c1fa925e3c 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -2,6 +2,7 @@ use alloc::format; use alloc::string::String; use alloc::vec::Vec; use core::fmt; +use pki_types::ServerName; #[cfg(feature = "std")] use std::time::SystemTimeError; @@ -372,6 +373,22 @@ pub enum CertificateError { /// 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, + }, + /// The certificate is being used for a different purpose than allowed. InvalidPurpose, @@ -405,6 +422,16 @@ impl PartialEq for CertificateError { (UnknownIssuer, UnknownIssuer) => true, (BadSignature, BadSignature) => true, (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, (ApplicationVerificationFailure, ApplicationVerificationFailure) => true, (ExpiredRevocationList, ExpiredRevocationList) => true, @@ -420,7 +447,10 @@ impl From for AlertDescription { fn from(e: CertificateError) -> Self { use CertificateError::*; match e { - BadEncoding | UnhandledCriticalExtension | NotValidForName => Self::BadCertificate, + BadEncoding + | UnhandledCriticalExtension + | NotValidForName + | NotValidForNameContext { .. } => Self::BadCertificate, // RFC 5246/RFC 8446 // certificate_expired // A certificate has expired or **is not currently valid**. @@ -681,6 +711,7 @@ mod tests { use super::{CertRevocationListError, Error, InconsistentKeys, InvalidMessage, OtherError}; #[cfg(feature = "std")] use crate::sync::Arc; + use pki_types::ServerName; #[test] fn certificate_error_equality() { @@ -693,6 +724,31 @@ mod tests { assert_eq!(UnknownIssuer, UnknownIssuer); assert_eq!(BadSignature, BadSignature); 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, diff --git a/rustls/src/webpki/mod.rs b/rustls/src/webpki/mod.rs index bc74b02eaa4..4743b468c2a 100644 --- a/rustls/src/webpki/mod.rs +++ b/rustls/src/webpki/mod.rs @@ -2,7 +2,7 @@ use alloc::vec::Vec; use core::fmt; use pki_types::CertificateRevocationListDer; -use webpki::{CertRevocationList, OwnedCertRevocationList}; +use webpki::{CertRevocationList, InvalidNameContext, OwnedCertRevocationList}; use crate::error::{CertRevocationListError, CertificateError, Error, OtherError}; #[cfg(feature = "std")] @@ -61,7 +61,14 @@ fn pki_error(error: webpki::Error) -> Error { CertNotValidYet { .. } => CertificateError::NotValidYet.into(), CertExpired { .. } | InvalidCertValidity => CertificateError::Expired.into(), UnknownIssuer => CertificateError::UnknownIssuer.into(), - CertNotValidForName { .. } => CertificateError::NotValidForName.into(), + CertNotValidForName(InvalidNameContext { + expected, + presented, + }) => CertificateError::NotValidForNameContext { + expected, + presented, + } + .into(), CertRevoked => CertificateError::Revoked.into(), UnknownRevocationStatus => CertificateError::UnknownRevocationStatus.into(), CrlExpired { .. } => CertificateError::ExpiredRevocationList.into(), diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index ef6715a68d4..761cc5e10b7 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -1661,7 +1661,7 @@ fn client_checks_server_certificate_with_given_name() { assert_eq!( err, Err(ErrorFromPeer::Client(Error::InvalidCertificate( - CertificateError::NotValidForName + certificate_error_expecting_name("not-the-right-hostname.com") ))) ); } @@ -1696,7 +1696,7 @@ fn client_checks_server_certificate_with_given_ip_address() { assert_eq!( check_server_name(client_config.clone(), server_config.clone(), "198.51.100.2"), Err(ErrorFromPeer::Client(Error::InvalidCertificate( - CertificateError::NotValidForName + certificate_error_expecting_name("198.51.100.2") ))) ); @@ -1710,7 +1710,7 @@ fn client_checks_server_certificate_with_given_ip_address() { assert_eq!( check_server_name(client_config.clone(), server_config.clone(), "2001:db8::2"), Err(ErrorFromPeer::Client(Error::InvalidCertificate( - CertificateError::NotValidForName + certificate_error_expecting_name("2001:db8::2") ))) ); } @@ -3425,7 +3425,9 @@ fn sni_resolver_rejects_wrong_names() { ) ); assert_eq!( - Err(Error::InvalidCertificate(CertificateError::NotValidForName)), + Err(Error::InvalidCertificate(certificate_error_expecting_name( + "not-localhost" + ))), resolver.add( "not-localhost", sign::CertifiedKey::new(kt.get_chain(), signing_key.clone()) @@ -3440,6 +3442,22 @@ fn sni_resolver_rejects_wrong_names() { ); } +fn certificate_error_expecting_name(expected: &str) -> CertificateError { + CertificateError::NotValidForNameContext { + expected: ServerName::try_from(expected) + .unwrap() + .to_owned(), + presented: vec![ + // ref. examples/internal/test_ca.rs + r#"DnsName("testserver.com")"#.into(), + r#"DnsName("second.testserver.com")"#.into(), + r#"DnsName("localhost")"#.into(), + "IpAddress(198.51.100.1)".into(), + "IpAddress(2001:db8::1)".into(), + ], + } +} + #[test] fn sni_resolver_lower_cases_configured_names() { let kt = KeyType::Rsa2048; From 8a8c1cd5d78b67b144ce850db8066d015519a51f Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 13 Feb 2025 10:34:56 +0000 Subject: [PATCH 076/403] Pass-through detailed certificate expiry errors --- rustls/src/error.rs | 136 +++++++++++++++++++++++++++++++++++++-- rustls/src/webpki/mod.rs | 13 +++- rustls/tests/api.rs | 6 +- 3 files changed, 145 insertions(+), 10 deletions(-) diff --git a/rustls/src/error.rs b/rustls/src/error.rs index 1c1fa925e3c..0c20e8672d7 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -2,7 +2,7 @@ use alloc::format; use alloc::string::String; use alloc::vec::Vec; use core::fmt; -use pki_types::ServerName; +use pki_types::{ServerName, UnixTime}; #[cfg(feature = "std")] use std::time::SystemTimeError; @@ -346,9 +346,31 @@ pub enum CertificateError { /// 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, @@ -365,6 +387,17 @@ pub enum CertificateError { /// 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, @@ -416,7 +449,27 @@ impl PartialEq for CertificateError { 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, @@ -435,6 +488,16 @@ impl PartialEq for CertificateError { (InvalidPurpose, InvalidPurpose) => true, (ApplicationVerificationFailure, ApplicationVerificationFailure) => 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, } } @@ -454,11 +517,16 @@ impl From for AlertDescription { // RFC 5246/RFC 8446 // certificate_expired // A certificate has expired or **is not currently valid**. - Expired | NotValidYet => Self::CertificateExpired, + 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 => Self::UnknownCA, + UnknownIssuer + | UnknownRevocationStatus + | ExpiredRevocationList + | ExpiredRevocationListContext { .. } => Self::UnknownCA, BadSignature => Self::DecryptError, InvalidPurpose => Self::UnsupportedCertificate, ApplicationVerificationFailure => Self::AccessDenied, @@ -705,10 +773,13 @@ pub use other_error::OtherError; #[cfg(test)] mod tests { + use core::time::Duration; use std::prelude::v1::*; use std::{println, vec}; - use super::{CertRevocationListError, Error, InconsistentKeys, InvalidMessage, OtherError}; + use super::{ + CertRevocationListError, Error, InconsistentKeys, InvalidMessage, OtherError, UnixTime, + }; #[cfg(feature = "std")] use crate::sync::Arc; use pki_types::ServerName; @@ -718,10 +789,67 @@ mod tests { 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); + 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); assert_eq!(NotValidForName, NotValidForName); let context = NotValidForNameContext { diff --git a/rustls/src/webpki/mod.rs b/rustls/src/webpki/mod.rs index 4743b468c2a..55566e978e8 100644 --- a/rustls/src/webpki/mod.rs +++ b/rustls/src/webpki/mod.rs @@ -58,8 +58,13 @@ fn pki_error(error: webpki::Error) -> Error { use webpki::Error::*; match error { BadDer | BadDerTime | TrailingData(_) => CertificateError::BadEncoding.into(), - CertNotValidYet { .. } => CertificateError::NotValidYet.into(), - CertExpired { .. } | InvalidCertValidity => CertificateError::Expired.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, @@ -71,7 +76,9 @@ fn pki_error(error: webpki::Error) -> Error { .into(), CertRevoked => CertificateError::Revoked.into(), UnknownRevocationStatus => CertificateError::UnknownRevocationStatus.into(), - CrlExpired { .. } => CertificateError::ExpiredRevocationList.into(), + CrlExpired { time, next_update } => { + CertificateError::ExpiredRevocationListContext { time, next_update }.into() + } IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl.into(), InvalidSignatureForPublicKey diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 761cc5e10b7..e03bfc98eab 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -1872,12 +1872,12 @@ fn client_check_server_certificate_ee_crl_expired() { // We expect the handshake to fail since the CRL is expired. let err = do_handshake_until_error(&mut client, &mut server); - assert_eq!( + assert!(matches!( err, Err(ErrorFromPeer::Client(Error::InvalidCertificate( - CertificateError::ExpiredRevocationList + CertificateError::ExpiredRevocationListContext { .. } ))) - ); + )); let client_config = make_client_config_with_verifier(&[version], ignore_expiration_builder.clone()); From 77c9baf4b58f3c784fe34ed6e7f271bd5bf4d41d Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 13 Feb 2025 10:55:35 +0000 Subject: [PATCH 077/403] Correct equality of `UnknownRevocationStatus` --- rustls/src/error.rs | 3 +++ rustls/tests/api.rs | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/rustls/src/error.rs b/rustls/src/error.rs index 0c20e8672d7..c43c7390157 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -487,6 +487,7 @@ impl PartialEq for CertificateError { ) => (left_expected, left_presented) == (right_expected, right_presented), (InvalidPurpose, InvalidPurpose) => true, (ApplicationVerificationFailure, ApplicationVerificationFailure) => true, + (UnknownRevocationStatus, UnknownRevocationStatus) => true, (ExpiredRevocationList, ExpiredRevocationList) => true, ( ExpiredRevocationListContext { @@ -831,6 +832,8 @@ mod tests { 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)), diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index e03bfc98eab..185e324bbc0 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -1775,12 +1775,12 @@ fn client_check_server_certificate_ee_unknown_revocation() { // We expect if we use the forbid_unknown_verifier that the handshake will fail since the // server's EE certificate's revocation status is unknown given the CRLs we've provided. let err = do_handshake_until_error(&mut client, &mut server); - assert!(matches!( + assert_eq!( err, Err(ErrorFromPeer::Client(Error::InvalidCertificate( CertificateError::UnknownRevocationStatus ))) - )); + ); // We expect if we use the allow_unknown_verifier that the handshake will not fail. let client_config = @@ -2162,12 +2162,12 @@ fn client_mandatory_auth_client_revocation_works() { let (mut client, mut server) = make_pair_for_arc_configs(&client_config, &missing_client_crl_server_config); let res = do_handshake_until_error(&mut client, &mut server); - assert!(matches!( + assert_eq!( res, Err(ErrorFromPeer::Server(Error::InvalidCertificate( CertificateError::UnknownRevocationStatus ))) - )); + ); // Connecting to the server missing CRL information for the client should not error // if the server's verifier allows unknown revocation status. let (mut client, mut server) = From ded5d4ff5c3f2f447bb7002cdf1f3f52038d38d7 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 11 Feb 2025 16:30:23 +0000 Subject: [PATCH 078/403] Pretty print `CertificateError::NotValidForNameContext` --- connect-tests/tests/badssl.rs | 2 +- rustls/src/error.rs | 68 ++++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/connect-tests/tests/badssl.rs b/connect-tests/tests/badssl.rs index 36e47e8c554..f9870841318 100644 --- a/connect-tests/tests/badssl.rs +++ b/connect-tests/tests/badssl.rs @@ -42,7 +42,7 @@ mod online { fn wrong_host() { connect("wrong.host.badssl.com") .fails() - .expect(r"TLS error: invalid peer certificate: NotValidForName") + .expect(r#"TLS error: invalid peer certificate: certificate not valid for name \"wrong.host.badssl.com\"; certificate is only valid for DnsName\(\"\*.badssl.com\"\) or DnsName\(\"badssl.com\"\)"#) .go() .unwrap(); } diff --git a/rustls/src/error.rs b/rustls/src/error.rs index c43c7390157..7b7691071d6 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -540,6 +540,48 @@ impl From for AlertDescription { } } +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) + } + } + } + other => write!(f, "{:?}", other), + } + } +} + impl From for Error { #[inline] fn from(e: CertificateError) -> Self { @@ -673,7 +715,7 @@ impl fmt::Display for Error { Self::PeerMisbehaved(ref why) => write!(f, "peer misbehaved: {:?}", why), Self::AlertReceived(ref alert) => write!(f, "received fatal alert: {:?}", alert), Self::InvalidCertificate(ref err) => { - write!(f, "invalid peer certificate: {:?}", err) + write!(f, "invalid peer certificate: {}", err) } Self::InvalidCertRevocationList(ref err) => { write!(f, "invalid certificate revocation list: {:?}", err) @@ -946,6 +988,30 @@ mod tests { 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(), Error::General("undocumented error".to_string()), Error::FailedToGetCurrentTime, Error::FailedToGetRandomBytes, From 72c4c07542da2466db76a53c4dff06e45b52a167 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 13 Feb 2025 13:39:07 +0000 Subject: [PATCH 079/403] Pretty print time-based `CertificateErrors`s --- connect-tests/tests/badssl.rs | 4 +-- rustls/src/error.rs | 51 +++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/connect-tests/tests/badssl.rs b/connect-tests/tests/badssl.rs index f9870841318..4b9210ef0cd 100644 --- a/connect-tests/tests/badssl.rs +++ b/connect-tests/tests/badssl.rs @@ -33,7 +33,7 @@ mod online { fn expired() { connect("expired.badssl.com") .fails() - .expect(r"TLS error: invalid peer certificate: Expired") + .expect(r"TLS error: invalid peer certificate: certificate expired: verification time [0-9]+ \(UNIX\), but certificate is not valid after [0-9]+ \([0-9]+ seconds ago\)") .go() .unwrap(); } @@ -119,7 +119,7 @@ mod online { fn sha1_2016() { connect("sha1-2016.badssl.com") .fails() - .expect(r"TLS error: invalid peer certificate: Expired") + .expect(r"TLS error: invalid peer certificate: certificate expired: verification time [0-9]+ \(UNIX\), but certificate is not valid after [0-9]+ \([0-9]+ seconds ago\)") .go() .unwrap(); } diff --git a/rustls/src/error.rs b/rustls/src/error.rs index 7b7691071d6..7e45f30353f 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -577,6 +577,42 @@ impl fmt::Display for CertificateError { } } } + + 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()) + ), + other => write!(f, "{:?}", other), } } @@ -1012,6 +1048,21 @@ mod tests { ], } .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(), Error::General("undocumented error".to_string()), Error::FailedToGetCurrentTime, Error::FailedToGetRandomBytes, From e2d501f0f893cb5f14fa5579095c68bf3c8ac104 Mon Sep 17 00:00:00 2001 From: Joseph Birr-Pixton Date: Thu, 14 Sep 2023 13:50:29 +0100 Subject: [PATCH 080/403] Avoid handshake message round-tripping for binders Verifying a _received_ `ClientHello` binder should be done against the original received bytes, not our re-encoding of them. This previously worked, because we required and tested that we could accurately round-trip handshake messages. But that is a less-robust approach. --- rustls/src/msgs/handshake.rs | 13 +++++++------ rustls/src/server/tls13.rs | 6 ++++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index c2d6de203a3..cf4a687deab 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -2769,8 +2769,13 @@ impl<'a> HandshakeMessagePayload<'a> { pub(crate) fn encoding_for_binder_signing(&self) -> Vec { let mut ret = self.get_encoding(); + let ret_len = ret.len() - self.total_binder_length(); + ret.truncate(ret_len); + ret + } - let binder_len = match self.payload { + pub(crate) fn total_binder_length(&self) -> usize { + match self.payload { HandshakePayload::ClientHello(ref ch) => match ch.extensions.last() { Some(ClientExtension::PresharedKey(offer)) => { let mut binders_encoding = Vec::new(); @@ -2782,11 +2787,7 @@ impl<'a> HandshakeMessagePayload<'a> { _ => 0, }, _ => 0, - }; - - let ret_len = ret.len() - binder_len; - ret.truncate(ret_len); - ret + } } pub(crate) fn payload_encode(&self, bytes: &mut Vec, encoding: Encoding) { diff --git a/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index d02360d7d28..89137bc30cc 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -97,13 +97,15 @@ mod client_hello { binder: &[u8], ) -> bool { let binder_plaintext = match &client_hello.payload { - MessagePayload::Handshake { parsed, .. } => parsed.encoding_for_binder_signing(), + MessagePayload::Handshake { parsed, encoded } => { + &encoded.bytes()[..encoded.bytes().len() - parsed.total_binder_length()] + } _ => unreachable!(), }; let handshake_hash = self .transcript - .hash_given(&binder_plaintext); + .hash_given(binder_plaintext); let key_schedule = KeyScheduleEarly::new(suite, psk); let real_binder = From a3384610e7aebae7ba1ea6d5baa67003050daa83 Mon Sep 17 00:00:00 2001 From: "@brody4hire - C. Jonathan Brody" Date: Mon, 24 Feb 2025 22:46:15 -0500 Subject: [PATCH 081/403] docs: improve some more links, etc. --- README.md | 7 +++---- rustls-post-quantum/README.md | 1 - rustls/src/client/ech.rs | 4 ++-- rustls/src/crypto/mod.rs | 18 +++++++++--------- rustls/src/lib.rs | 7 +++---- rustls/src/manual/howto.rs | 12 ++++++------ 6 files changed, 23 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index c0786c10ab4..f467d715cb7 100644 --- a/README.md +++ b/README.md @@ -114,14 +114,13 @@ from [`RustCrypto`] for cryptography. #### 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. +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`]: https://github.com/rustls/rustls/tree/main/provider-example/ +[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 diff --git a/rustls-post-quantum/README.md b/rustls-post-quantum/README.md index 3d4f4f573c1..7d2230a86e5 100644 --- a/rustls-post-quantum/README.md +++ b/rustls-post-quantum/README.md @@ -16,4 +16,3 @@ using post-quantum algorithms instead of using this crate. This crate is release under the same licenses as the [main rustls crate][rustls]. [rustls]: https://crates.io/crates/rustls -[`rustls::crypto::CryptoProvider`]: https://docs.rs/rustls/latest/rustls/crypto/struct.CryptoProvider.html diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index f6a5f8e633f..8a2bd9a86c1 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -93,9 +93,9 @@ impl EchConfig { /// 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. + /// 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 + /// [`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], diff --git a/rustls/src/crypto/mod.rs b/rustls/src/crypto/mod.rs index e80370343a6..3ce026b9df1 100644 --- a/rustls/src/crypto/mod.rs +++ b/rustls/src/crypto/mod.rs @@ -110,12 +110,12 @@ pub use crate::suites::CipherSuiteCommon; /// /// # Making a custom `CryptoProvider` /// -/// Your goal will be to populate a [`crypto::CryptoProvider`] struct instance. +/// 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 +/// 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). /// @@ -160,8 +160,8 @@ pub use crate::suites::CipherSuiteCommon; /// /// # Example code /// -/// See [provider-example/] for a full client and server example that uses -/// cryptography from the [rust-crypto] and [dalek-cryptography] projects. +/// 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 @@ -171,9 +171,9 @@ pub use crate::suites::CipherSuiteCommon; /// Content-Length: 19899 /// ``` /// -/// [provider-example/]: https://github.com/rustls/rustls/tree/main/provider-example/ -/// [rust-crypto]: https://github.com/rustcrypto -/// [dalek-cryptography]: https://github.com/dalek-cryptography +/// [`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. @@ -323,7 +323,7 @@ pub trait SecureRandom: Send + Sync + Debug { } } -/// A mechanism for loading private [SigningKey]s from [PrivateKeyDer]. +/// 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 diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index e13c39ff836..68d33752206 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -80,14 +80,13 @@ //! //! #### 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. +//! 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`]: https://github.com/rustls/rustls/tree/main/provider-example/ +//! [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 //! diff --git a/rustls/src/manual/howto.rs b/rustls/src/manual/howto.rs index f3a8219cdf0..2e1959ae9b1 100644 --- a/rustls/src/manual/howto.rs +++ b/rustls/src/manual/howto.rs @@ -6,7 +6,7 @@ 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 +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. @@ -21,18 +21,18 @@ Once you have these two pieces, configuring a server to use them involves, brief - 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 [rustls-cng] crate. +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() +[choose_scheme]: crate::crypto::signer::SigningKey::choose_scheme [sig_scheme]: crate::SignatureScheme [signer]: crate::crypto::signer::Signer -[sign_method]: crate::crypto::Signer.sign() +[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]: https://github.com/rustls/rustls-cng/blob/dev/src/signer.rs +[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. From 8926dc62b2d7547e9cbe26698255b918ff32cb07 Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Thu, 27 Feb 2025 13:58:04 -0500 Subject: [PATCH 082/403] adjust FIPS feature handling w.r.t aws-lc-sys Previously rustls unconditionally used the aws-lc-sys and prebuilt-nasm features of the aws-lc-rs dep, meaning we always brought along aws-lc-sys (note the prebuilt-nasm feature customizes that dep). However, when a user is looking for a FIPS crypto provider we want to avoid bringing in aws-lc-sys and instead use aws-lc-rs/fips to get aws-lc-fips-sys. This commit makes the aws-lc-rs feature of webpki activate the "usual" config: aws-lc-rs/aws-lc-sys w/ aws-lc-rs/prebuilt-nasm to have aws-lc-sys with prebuilt assmebly to avoid the nasm dep. The pre-existing fips feature of rustls activates aws-lc-rs/fips and the new downstream webpki/aws-lc-rs-fips feature is activated to have that crate do similar. The net result should be no `aws-lc-sys` dep, just `aws-lc-fips-sys`. --- Cargo.toml | 2 +- rustls/Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 824660ec61c..529dacc4a6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ anyhow = "1.0.73" asn1 = "0.20" async-std = { version = "1.12.0", features = ["attributes"] } async-trait = "0.1.74" -aws-lc-rs = { version = "1.12", default-features = false, features = ["aws-lc-sys", "prebuilt-nasm"] } +aws-lc-rs = { version = "1.12", default-features = false } base64 = "0.22" bencher = "0.1.5" brotli = { version = "7", default-features = false, features = ["std"] } diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 210ae3e05f7..0c05dd954f8 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -18,10 +18,10 @@ build = "build.rs" default = ["aws_lc_rs", "logging", "std", "tls12"] aws-lc-rs = ["aws_lc_rs"] # Alias because Cargo features commonly use `-` -aws_lc_rs = ["dep:aws-lc-rs", "webpki/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 = [] -fips = ["aws_lc_rs", "aws-lc-rs?/fips"] +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"] From 185494682755a3e2b3e2490f283ae79b4f65f01c Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Wed, 26 Feb 2025 16:58:28 -0500 Subject: [PATCH 083/403] client: reject TLS 1.3 compat session ID in 1.2 If the client hello input had no resuming session, but has a non-empty SessionId, it means we generated a TLS 1.3 legacy_session_id for middle-box compatibility purposes. In this case if we end up handshaking for TLS 1.2 we should ensure the server didn't echo the session ID back to us. Since it was invented at random to fill the need of a non-empty value it should never be a recognized server session. --- bogo/config.json.in | 2 +- rustls/src/client/hs.rs | 17 +++++++++++++++++ rustls/src/error.rs | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index 1c3c8e464a6..ad19c3ea6f7 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -17,7 +17,6 @@ "CheckLeafCurve": "", "SendWarningAlerts-*": "", "Peek-*": "", - "EchoTLS13CompatibilitySessionID": "", "ClientOCSPCallback*": "ocsp not supported yet", "ServerOCSPCallback*": "", "SendUnsolicitedOCSPOnCertificate-TLS13": "we unconditionally request a stapled OCSP response", @@ -156,6 +155,7 @@ ":ENCRYPTED_LENGTH_TOO_LONG:": ":GARBAGE:" }, "TestErrorMap": { + "EchoTLS13CompatibilitySessionID": ":PEER_MISBEHAVIOUR:", "EmptyCertificateList": ":NO_CERTS:", "SendInvalidRecordType": ":GARBAGE:", "NoSharedCipher": ":HANDSHAKE_FAILURE:", diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index a07e59a6cfb..b8ff81c33f7 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -907,6 +907,23 @@ impl State for ExpectServerHello { } #[cfg(feature = "tls12")] SupportedCipherSuite::Tls12(suite) => { + // 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 resuming_session = self .input .resuming diff --git a/rustls/src/error.rs b/rustls/src/error.rs index 7e45f30353f..bd0e7013694 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -264,6 +264,7 @@ pub enum PeerMisbehaved { SelectedUnofferedKxGroup, SelectedUnofferedPsk, SelectedUnusableCipherSuiteForVersion, + ServerEchoedCompatibilitySessionId, ServerHelloMustOfferUncompressedEcPoints, ServerNameDifferedOnRetry, ServerNameMustContainOneHostName, From d6726c8db019a880cb0ab89df9cbfcd3921455f6 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Fri, 7 Mar 2025 09:23:47 +0100 Subject: [PATCH 084/403] Update semver-compatible dependencies --- Cargo.lock | 283 +++++++++++++++++++++++++++-------------------------- 1 file changed, 144 insertions(+), 139 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ea90c6daef0..0c829491d21 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -134,9 +134,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.95" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" +checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" [[package]] name = "asn1" @@ -160,7 +160,7 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror 2.0.11", + "thiserror 2.0.12", "time", ] @@ -172,7 +172,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", "synstructure", ] @@ -184,7 +184,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -195,7 +195,7 @@ checksum = "a200809d0138620b3dba989f1d08d0620e76248bc1e62a2ec1b2df5eb1ee08ad" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -297,7 +297,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -335,13 +335,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.86" +version = "0.1.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d" +checksum = "d556ec1359574147ec0c4fc5eb525f3f23263a592b1a9c07e0a75b427de55c97" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -373,9 +373,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.12.2" +version = "1.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b7ddaa2c56a367ad27a094ad8ef4faacf8a617c2575acb2ba88949df999ca" +checksum = "5e4e8200b9a4a5801a769d50eeabc05670fec7e959a8cb7a63a93e4e519942ae" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", @@ -385,9 +385,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.25.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54ac4f13dad353b209b34cbec082338202cbc01c8f00336b55c750c13ac91f8f" +checksum = "0f9dd2e03ee80ca2822dd6ea431163d2ef259f2066a4d6ccaca6d9dcb386aa43" dependencies = [ "bindgen", "cc", @@ -455,15 +455,15 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.98", + "syn 2.0.99", "which", ] [[package]] name = "bitflags" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "block-buffer" @@ -533,9 +533,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cast" @@ -545,9 +545,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.14" +version = "1.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9" +checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" dependencies = [ "jobserver", "libc", @@ -650,9 +650,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.29" +version = "4.5.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acebd8ad879283633b343856142139f2da2317c96b05b4dd6181c61e2480184" +checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767" dependencies = [ "clap_builder", "clap_derive", @@ -660,9 +660,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.29" +version = "4.5.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ba32cbda51c7e1dfd49acc1457ba1a7dec5b64fe360e828acb13ca8dc9c2f9" +checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863" dependencies = [ "anstream", "anstyle", @@ -679,7 +679,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -866,7 +866,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -928,7 +928,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -953,9 +953,9 @@ dependencies = [ [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "elliptic-curve" @@ -986,7 +986,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -1281,9 +1281,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" +checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" dependencies = [ "atomic-waker", "bytes", @@ -1329,6 +1329,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +[[package]] +name = "hermit-abi" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" + [[package]] name = "hex" version = "0.4.3" @@ -1357,7 +1363,7 @@ dependencies = [ "once_cell", "rand 0.9.0", "rustls 0.23.23 (registry+https://github.com/rust-lang/crates.io-index)", - "thiserror 2.0.11", + "thiserror 2.0.12", "tinyvec", "tokio", "tokio-rustls", @@ -1383,7 +1389,7 @@ dependencies = [ "resolv-conf", "rustls 0.23.23 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec", - "thiserror 2.0.11", + "thiserror 2.0.12", "tokio", "tokio-rustls", "tracing", @@ -1598,7 +1604,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -1634,9 +1640,9 @@ dependencies = [ [[package]] name = "inout" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ "generic-array", ] @@ -1661,11 +1667,11 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "is-terminal" -version = "0.4.15" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ - "hermit-abi", + "hermit-abi 0.5.0", "libc", "windows-sys 0.59.0", ] @@ -1705,9 +1711,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jobserver" @@ -1754,9 +1760,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.169" +version = "0.2.170" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" [[package]] name = "libloading" @@ -1782,9 +1788,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "litemap" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" +checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" [[package]] name = "lock_api" @@ -1798,9 +1804,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.25" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" +checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" dependencies = [ "value-bag", ] @@ -1863,9 +1869,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3b1c9bd4fe1f0f8b387f6eb9eb3b4a1aa26185e5750efb9140301703f62cd1b" +checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" dependencies = [ "adler2", ] @@ -2055,7 +2061,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -2135,9 +2141,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pem" -version = "3.0.4" +version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" +checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" dependencies = [ "base64", "serde", @@ -2195,9 +2201,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "plotters" @@ -2235,7 +2241,7 @@ checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi", + "hermit-abi 0.4.0", "pin-project-lite", "rustix", "tracing", @@ -2267,9 +2273,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" [[package]] name = "powerfmt" @@ -2288,12 +2294,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.29" +version = "0.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" +checksum = "f1ccf34da56fc294e7d4ccf69a85992b7dfb826b7cf57bac6a70bba3494cc08a" dependencies = [ "proc-macro2", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -2307,9 +2313,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] @@ -2322,9 +2328,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.38" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" dependencies = [ "proc-macro2", ] @@ -2346,8 +2352,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.1", - "zerocopy 0.8.18", + "rand_core 0.9.3", + "zerocopy 0.8.23", ] [[package]] @@ -2367,7 +2373,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.1", + "rand_core 0.9.3", ] [[package]] @@ -2381,12 +2387,11 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a88e0da7a2c97baa202165137c158d0a2e824ac465d13d81046727b34cb247d3" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ "getrandom 0.3.1", - "zerocopy 0.8.18", ] [[package]] @@ -2424,9 +2429,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" dependencies = [ "bitflags", ] @@ -2497,9 +2502,9 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.9" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75ec5e92c4d8aede845126adc388046234541629e76029599ed35a003c7ed24" +checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" dependencies = [ "cc", "cfg-if", @@ -2769,15 +2774,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" [[package]] name = "ryu" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "same-file" @@ -2816,35 +2821,35 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" -version = "1.0.217" +version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] name = "serde_json" -version = "1.0.138" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", @@ -2960,9 +2965,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.98" +version = "2.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" dependencies = [ "proc-macro2", "quote", @@ -2977,7 +2982,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -2997,11 +3002,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ - "thiserror-impl 2.0.11", + "thiserror-impl 2.0.12", ] [[package]] @@ -3012,18 +3017,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] name = "thiserror-impl" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3058,9 +3063,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.37" +version = "0.3.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +checksum = "dad298b01a40a23aac4580b67e3dbedb7cc8402f3592d7f49469de2ea4aecdd8" dependencies = [ "deranged", "itoa", @@ -3073,15 +3078,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef" [[package]] name = "time-macros" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c" dependencies = [ "num-conv", "time-core", @@ -3109,9 +3114,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" dependencies = [ "tinyvec_macros", ] @@ -3146,14 +3151,14 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] name = "tokio-rustls" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ "rustls 0.23.23 (registry+https://github.com/rust-lang/crates.io-index)", "tokio", @@ -3191,7 +3196,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3235,15 +3240,15 @@ dependencies = [ [[package]] name = "typenum" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "unicode-ident" -version = "1.0.16" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "universal-hash" @@ -3292,9 +3297,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.13.1" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced87ca4be083373936a67f8de945faa23b6b42384bd5b64434850802c6dccd0" +checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" dependencies = [ "getrandom 0.3.1", ] @@ -3370,7 +3375,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", "wasm-bindgen-shared", ] @@ -3405,7 +3410,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3518,7 +3523,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3529,7 +3534,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3755,7 +3760,7 @@ dependencies = [ "nom", "oid-registry", "rusticata-macros", - "thiserror 2.0.11", + "thiserror 2.0.12", "time", ] @@ -3788,7 +3793,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", "synstructure", ] @@ -3804,11 +3809,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.18" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79386d31a42a4996e3336b0919ddb90f81112af416270cff95b5f5af22b839c2" +checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" dependencies = [ - "zerocopy-derive 0.8.18", + "zerocopy-derive 0.8.23", ] [[package]] @@ -3819,38 +3824,38 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] name = "zerocopy-derive" -version = "0.8.18" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76331675d372f91bf8d17e13afbd5fe639200b73d01f0fc748bb059f9cca2db7" +checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] name = "zerofrom" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", "synstructure", ] @@ -3871,7 +3876,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3893,11 +3898,11 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] name = "zlib-rs" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aada01553a9312bad4b9569035a1f12b05e5ec9770a1a4b323757356928944f8" +checksum = "8b20717f0917c908dc63de2e44e97f1e6b126ca58d0e391cee86d504eb8fbd05" From 5860d10317528e4f162db6e26c74f81575c51403 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Fri, 7 Mar 2025 10:12:50 +0100 Subject: [PATCH 085/403] Avoid semver errors on discriminant changes --- rustls/Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 0c05dd954f8..a067079b825 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -121,3 +121,6 @@ allowed_external_types = [ "rustls_pki_types", "rustls_pki_types::*", ] + +[package.metadata.cargo-semver-checks.lints] +enum_no_repr_variant_discriminant_changed = "warn" From 41f186d507fc3c9f0c40696ab7bf5f39ca9b654b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 10 Mar 2025 09:27:42 +0000 Subject: [PATCH 086/403] fuzz/Cargo.lock: take semver-compatible updates Notably this removes a further ring 0.17.8 usage. --- fuzz/Cargo.lock | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 5f1c4c721ab..7b7af1ae2e6 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -52,11 +52,12 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", + "once_cell", "windows-sys 0.59.0", ] @@ -68,9 +69,9 @@ checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" [[package]] name = "cc" -version = "1.2.9" +version = "1.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" +checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" dependencies = [ "jobserver", "libc", @@ -146,9 +147,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.169" +version = "0.2.170" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" [[package]] name = "libfuzzer-sys" @@ -162,9 +163,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" [[package]] name = "memchr" @@ -174,9 +175,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "once_cell" -version = "1.20.2" +version = "1.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" [[package]] name = "regex" @@ -209,15 +210,14 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "ring" -version = "0.17.8" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" dependencies = [ "cc", "cfg-if", "getrandom", "libc", - "spin", "untrusted", "windows-sys 0.52.0", ] @@ -274,12 +274,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - [[package]] name = "subtle" version = "2.6.1" From 503944186604091198b427c3e05ede40be995c4e Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 28 Feb 2025 13:28:00 +0000 Subject: [PATCH 087/403] Extend `CountingLogger` to remember messages too --- rustls/tests/api.rs | 20 ++++++++++---------- rustls/tests/runners/api.rs | 26 ++++++++++++++------------ 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 185e324bbc0..8489eeed5b0 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -6722,20 +6722,20 @@ fn test_no_warning_logging_during_successful_sessions() { if cfg!(feature = "logging") { COUNTS.with(|c| { println!("After tests: {:?}", c.borrow()); - assert_eq!(c.borrow().warn, 0); - assert_eq!(c.borrow().error, 0); - assert_eq!(c.borrow().info, 0); - assert!(c.borrow().trace > 0); - assert!(c.borrow().debug > 0); + assert!(c.borrow().warn.is_empty()); + assert!(c.borrow().error.is_empty()); + assert!(c.borrow().info.is_empty()); + assert!(!c.borrow().trace.is_empty()); + assert!(!c.borrow().debug.is_empty()); }); } else { COUNTS.with(|c| { println!("After tests: {:?}", c.borrow()); - assert_eq!(c.borrow().warn, 0); - assert_eq!(c.borrow().error, 0); - assert_eq!(c.borrow().info, 0); - assert_eq!(c.borrow().trace, 0); - assert_eq!(c.borrow().debug, 0); + assert!(c.borrow().warn.is_empty()); + assert!(c.borrow().error.is_empty()); + assert!(c.borrow().info.is_empty()); + assert!(c.borrow().trace.is_empty()); + assert!(c.borrow().debug.is_empty()); }); } } diff --git a/rustls/tests/runners/api.rs b/rustls/tests/runners/api.rs index 39bb2cf5ad3..99cb0c29487 100644 --- a/rustls/tests/runners/api.rs +++ b/rustls/tests/runners/api.rs @@ -60,7 +60,8 @@ impl log::Log for CountingLogger { println!("logging at {:?}: {:?}", record.level(), record.args()); COUNTS.with(|c| { - c.borrow_mut().add(record.level()); + c.borrow_mut() + .add(record.level(), format!("{}", record.args())); }); } @@ -69,11 +70,11 @@ impl log::Log for CountingLogger { #[derive(Default, Debug)] struct LogCounts { - trace: usize, - debug: usize, - info: usize, - warn: usize, - error: usize, + trace: Vec, + debug: Vec, + info: Vec, + warn: Vec, + error: Vec, } impl LogCounts { @@ -87,13 +88,14 @@ impl LogCounts { *self = Self::new(); } - fn add(&mut self, level: log::Level) { + fn add(&mut self, level: log::Level, message: String) { match level { - log::Level::Trace => self.trace += 1, - log::Level::Debug => self.debug += 1, - log::Level::Info => self.info += 1, - log::Level::Warn => self.warn += 1, - log::Level::Error => self.error += 1, + log::Level::Trace => &mut self.trace, + log::Level::Debug => &mut self.debug, + log::Level::Info => &mut self.info, + log::Level::Warn => &mut self.warn, + log::Level::Error => &mut self.error, } + .push(message); } } From da46c215cff2cd5c8eb617f6990f97d2c8a7aaed Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 17 Dec 2024 13:14:48 +0000 Subject: [PATCH 088/403] Prevent resumption between "incompatible" clients "Compatible" here means they have ~interchangeable security, which means they have the same server certificate verifier and same potentially-offered client credentials. "Same" is defined by `Arc` equality, which means a rustls user wishing to arrange for multiple `ClientConfig`s to share a `resumption` _also_ now need to share the `client_auth_cert_resolver` and `verifier`. (The way to do this is to clone-and-edit the original config, or keep hold of the verifier and insert it using the `dangerous().set_certificate_verifier()`.) --- .clippy.toml | 1 + rustls/src/client/client_conn.rs | 16 ++++++++ rustls/src/client/handy.rs | 66 ++++++++++++++++++++++++++++++- rustls/src/client/hs.rs | 21 ++++++++++ rustls/src/client/tls12.rs | 2 + rustls/src/client/tls13.rs | 2 + rustls/src/lib.rs | 2 + rustls/src/msgs/persist.rs | 44 ++++++++++++++++++++- rustls/tests/api.rs | 67 ++++++++++++++++++++++++++++++++ 9 files changed, 219 insertions(+), 2 deletions(-) diff --git a/.clippy.toml b/.clippy.toml index 1d849dc657e..779a21d1dd9 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -3,4 +3,5 @@ upper-case-acronyms-aggressive = true # only intended to affect main rustls crate - need to allow disallowed-types in all other crates in Clippy CI job disallowed-types = [ { path = "std::sync::Arc", reason = "must use Arc from sync module to support downstream forks targetting architectures without atomic ptrs" }, + { path = "std::sync::Weak", reason = "must use Weak from sync module to support downstream forks targetting architectures without atomic ptrs" }, ] diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index 92cc538db15..39c9d8dca0a 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -166,6 +166,22 @@ pub struct ClientConfig { pub alpn_protocols: Vec>, /// 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. diff --git a/rustls/src/client/handy.rs b/rustls/src/client/handy.rs index a2585da9eae..eabe1cb3a7b 100644 --- a/rustls/src/client/handy.rs +++ b/rustls/src/client/handy.rs @@ -253,21 +253,26 @@ mod tests { use super::NoClientSessionStorage; use super::provider::cipher_suite; - use crate::client::ClientSessionStore; + 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 = Arc::new(DummyServerCertVerifier); + let resolves_client_cert: Arc = Arc::new(DummyResolvesClientCert); c.set_kx_hint(name.clone(), NamedGroup::X25519); assert_eq!(None, c.kx_hint(&name)); @@ -289,6 +294,8 @@ mod tests { Arc::new(PayloadU16::empty()), &[], CertificateChain::default(), + &server_cert_verifier, + &resolves_client_cert, now, 0, true, @@ -309,6 +316,8 @@ mod tests { Arc::new(PayloadU16::empty()), &[], CertificateChain::default(), + &server_cert_verifier, + &resolves_client_cert, now, 0, 0, @@ -317,4 +326,59 @@ mod tests { ); assert!(c.take_tls13_ticket(&name).is_none()); } + + #[derive(Debug)] + struct DummyServerCertVerifier; + + impl ServerCertVerifier for DummyServerCertVerifier { + fn verify_server_cert( + &self, + _end_entity: &CertificateDer<'_>, + _intermediates: &[CertificateDer<'_>], + _server_name: &ServerName<'_>, + _ocsp_response: &[u8], + _now: UnixTime, + ) -> Result { + unreachable!() + } + + fn verify_tls12_signature( + &self, + _message: &[u8], + _cert: &CertificateDer<'_>, + _dss: &DigitallySignedStruct, + ) -> Result { + unreachable!() + } + + fn verify_tls13_signature( + &self, + _message: &[u8], + _cert: &CertificateDer<'_>, + _dss: &DigitallySignedStruct, + ) -> Result { + unreachable!() + } + + fn supported_verify_schemes(&self) -> Vec { + unreachable!() + } + } + + #[derive(Debug)] + struct DummyResolvesClientCert; + + impl ResolvesClientCert for DummyResolvesClientCert { + fn resolve( + &self, + _root_hint_subjects: &[&[u8]], + _sigschemes: &[SignatureScheme], + ) -> Option> { + unreachable!() + } + + fn has_certs(&self) -> bool { + unreachable!() + } + } } diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index b8ff81c33f7..66ea8c67faf 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -6,6 +6,7 @@ use core::ops::Deref; use pki_types::ServerName; +use super::ResolvesClientCert; use super::Tls12Resumption; #[cfg(feature = "tls12")] use super::tls12; @@ -37,6 +38,7 @@ 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 + 'a>; pub(super) type NextStateOrError<'a> = Result, Error>; @@ -65,6 +67,9 @@ fn find_session( #[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() @@ -1245,6 +1250,22 @@ impl ClientSessionValue { Self::Tls12(_) => None, } } + + fn compatible_config( + self, + server_cert_verifier: &Arc, + client_creds: &Arc, + ) -> Option { + 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 { diff --git a/rustls/src/client/tls12.rs b/rustls/src/client/tls12.rs index 2adb92a3766..9391c3d8de9 100644 --- a/rustls/src/client/tls12.rs +++ b/rustls/src/client/tls12.rs @@ -1199,6 +1199,8 @@ impl ExpectFinished { .peer_certificates .clone() .unwrap_or_default(), + &self.config.verifier, + &self.config.client_auth_cert_resolver, now, lifetime, self.using_ems, diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index 71d6ea0d12c..d6f772db268 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -1486,6 +1486,8 @@ impl ExpectTraffic { .peer_certificates .clone() .unwrap_or_default(), + &self.config.verifier, + &self.config.client_auth_cert_resolver, now, nst.lifetime, nst.age_add, diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 68d33752206..c56bd92007e 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -413,6 +413,8 @@ mod test_macros; mod sync { #[allow(clippy::disallowed_types)] pub(crate) type Arc = alloc::sync::Arc; + #[allow(clippy::disallowed_types)] + pub(crate) type Weak = alloc::sync::Weak; } #[macro_use] diff --git a/rustls/src/msgs/persist.rs b/rustls/src/msgs/persist.rs index 05117ae2e1d..c5e67ad0903 100644 --- a/rustls/src/msgs/persist.rs +++ b/rustls/src/msgs/persist.rs @@ -4,6 +4,7 @@ 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::{PayloadU8, PayloadU16}; @@ -11,10 +12,11 @@ use crate::msgs::codec::{Codec, Reader}; use crate::msgs::handshake::CertificateChain; #[cfg(feature = "tls12")] use crate::msgs::handshake::SessionId; -use crate::sync::Arc; +use crate::sync::{Arc, Weak}; #[cfg(feature = "tls12")] use crate::tls12::Tls12CipherSuite; use crate::tls13::Tls13CipherSuite; +use crate::verify::ServerCertVerifier; pub(crate) struct Retrieved { pub(crate) value: T, @@ -82,6 +84,8 @@ impl Tls13ClientSessionValue { ticket: Arc, secret: &[u8], server_cert_chain: CertificateChain<'static>, + server_cert_verifier: &Arc, + client_creds: &Arc, time_now: UnixTime, lifetime_secs: u32, age_add: u32, @@ -97,6 +101,8 @@ impl Tls13ClientSessionValue { time_now, lifetime_secs, server_cert_chain, + server_cert_verifier, + client_creds, ), quic_params: PayloadU16(Vec::new()), } @@ -160,6 +166,8 @@ impl Tls12ClientSessionValue { ticket: Arc, master_secret: &[u8], server_cert_chain: CertificateChain<'static>, + server_cert_verifier: &Arc, + client_creds: &Arc, time_now: UnixTime, lifetime_secs: u32, extended_ms: bool, @@ -174,6 +182,8 @@ impl Tls12ClientSessionValue { time_now, lifetime_secs, server_cert_chain, + server_cert_verifier, + client_creds, ), } } @@ -213,6 +223,8 @@ pub struct ClientSessionCommon { epoch: u64, lifetime_secs: u32, server_cert_chain: Arc>, + server_cert_verifier: Weak, + client_creds: Weak, } impl ClientSessionCommon { @@ -222,6 +234,8 @@ impl ClientSessionCommon { time_now: UnixTime, lifetime_secs: u32, server_cert_chain: CertificateChain<'static>, + server_cert_verifier: &Arc, + client_creds: &Arc, ) -> Self { Self { ticket, @@ -229,6 +243,34 @@ impl ClientSessionCommon { 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, + client_creds: &Arc, + ) -> 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 + } } } diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 8489eeed5b0..168256178f5 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -861,12 +861,14 @@ fn client_can_get_server_cert_after_resumption() { let (mut client, mut server) = make_pair_for_configs(client_config.clone(), server_config.clone()); do_handshake(&mut client, &mut server); + assert_eq!(client.handshake_kind(), Some(HandshakeKind::Full)); let original_certs = client.peer_certificates(); let (mut client, mut server) = make_pair_for_configs(client_config.clone(), server_config.clone()); do_handshake(&mut client, &mut server); + assert_eq!(client.handshake_kind(), Some(HandshakeKind::Resumed)); let resumed_certs = client.peer_certificates(); @@ -875,6 +877,71 @@ fn client_can_get_server_cert_after_resumption() { } } +#[test] +fn client_only_attempts_resumption_with_compatible_security() { + let kt = KeyType::Rsa2048; + CountingLogger::install(); + CountingLogger::reset(); + + let server_config = make_server_config(kt); + for version in rustls::ALL_VERSIONS { + let base_client_config = make_client_config_with_versions(kt, &[version]); + let (mut client, mut server) = + make_pair_for_configs(base_client_config.clone(), server_config.clone()); + do_handshake(&mut client, &mut server); + assert_eq!(client.handshake_kind(), Some(HandshakeKind::Full)); + + // base case + let (mut client, mut server) = + make_pair_for_configs(base_client_config.clone(), server_config.clone()); + do_handshake(&mut client, &mut server); + assert_eq!(client.handshake_kind(), Some(HandshakeKind::Resumed)); + + // allowed case, using `clone` + let client_config = ClientConfig::clone(&base_client_config); + let (mut client, mut server) = + make_pair_for_configs(client_config.clone(), server_config.clone()); + do_handshake(&mut client, &mut server); + assert_eq!(client.handshake_kind(), Some(HandshakeKind::Resumed)); + + // disallowed case: unmatching `client_auth_cert_resolver` + let mut client_config = ClientConfig::clone(&base_client_config); + client_config.client_auth_cert_resolver = + make_client_config_with_versions_with_auth(kt, &[version]).client_auth_cert_resolver; + + CountingLogger::reset(); + let (mut client, mut server) = + make_pair_for_configs(client_config.clone(), server_config.clone()); + do_handshake(&mut client, &mut server); + assert_eq!(client.handshake_kind(), Some(HandshakeKind::Full)); + #[cfg(feature = "logging")] + assert!(COUNTS.with(|c| { + c.borrow().trace.iter().any(|item| { + item == "resumption not allowed between different ResolvesClientCert values" + }) + })); + + // disallowed case: unmatching `verifier` + let mut client_config = make_client_config_with_versions_with_auth(kt, &[version]); + client_config.resumption = base_client_config.resumption.clone(); + client_config.client_auth_cert_resolver = + Arc::clone(&base_client_config.client_auth_cert_resolver); + + CountingLogger::reset(); + let (mut client, mut server) = + make_pair_for_configs(client_config.clone(), server_config.clone()); + do_handshake(&mut client, &mut server); + assert_eq!(client.handshake_kind(), Some(HandshakeKind::Full)); + #[cfg(feature = "logging")] + assert!(COUNTS.with(|c| { + c.borrow() + .trace + .iter() + .any(|item| item == "resumption not allowed between different ServerCertVerifiers") + })); + } +} + #[test] fn server_can_get_client_cert() { for kt in ALL_KEY_TYPES { From 7b493513029bb5fc45c978f38f588747a0bbf86b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 11 Mar 2025 02:28:25 +0000 Subject: [PATCH 089/403] chore(deps): update rust crate asn1 to 0.21 --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0c829491d21..4278deee4ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,9 +140,9 @@ checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" [[package]] name = "asn1" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d8b84b4ea1de2bf1dcd2a759737ddb328fb6695b2a95eb7e44fed67e3406f32" +checksum = "9c48ea2b435a08bc0fc63de853bda3d5dd1b794ce5f188edd036ad39a7c069d9" dependencies = [ "asn1_derive", "itoa", @@ -189,9 +189,9 @@ dependencies = [ [[package]] name = "asn1_derive" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a200809d0138620b3dba989f1d08d0620e76248bc1e62a2ec1b2df5eb1ee08ad" +checksum = "67c7e14dc2fafd01c4c68c054e128b770d5a4a07b04d76bfaedca40dce3cb2c0" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 529dacc4a6e..6d94452d556 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ resolver = "2" [workspace.dependencies] anyhow = "1.0.73" -asn1 = "0.20" +asn1 = "0.21" async-std = { version = "1.12.0", features = ["attributes"] } async-trait = "0.1.74" aws-lc-rs = { version = "1.12", default-features = false } From 4f2d21ea40e2761801c0c6e8d70dee2d6297cefc Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 10 Mar 2025 15:59:16 +0000 Subject: [PATCH 090/403] Prefer to put check-cfg data in Cargo.toml --- rustls/Cargo.toml | 3 +++ rustls/build.rs | 7 +------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index a067079b825..250140124dd 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -124,3 +124,6 @@ allowed_external_types = [ [package.metadata.cargo-semver-checks.lints] enum_no_repr_variant_discriminant_changed = "warn" + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ["cfg(bench)", "cfg(read_buf)"] } diff --git a/rustls/build.rs b/rustls/build.rs index a22a4c8176c..9c73252a655 100644 --- a/rustls/build.rs +++ b/rustls/build.rs @@ -4,15 +4,10 @@ /// See the comment in lib.rs to understand why we need this. #[cfg_attr(feature = "read_buf", rustversion::not(nightly))] -fn main() { - println!("cargo:rustc-check-cfg=cfg(bench)"); - println!("cargo:rustc-check-cfg=cfg(read_buf)"); -} +fn main() {} #[cfg(feature = "read_buf")] #[rustversion::nightly] fn main() { - println!("cargo:rustc-check-cfg=cfg(bench)"); - println!("cargo:rustc-check-cfg=cfg(read_buf)"); println!("cargo:rustc-cfg=read_buf"); } From 84643563190c95c1d6db5c0d5449e0bec450c116 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 10 Mar 2025 15:31:35 +0000 Subject: [PATCH 091/403] Mark unreachable functions with `coverage(off)` This is nightly-only, so: - measure coverage under nightly - mention llvm-cov's `cfg(coverage_nightly)` in our check-cfg stanza - opt-in to `feature(coverage_attribute)` on nightly coverage builds --- .github/workflows/build.yml | 2 +- rustls/Cargo.toml | 2 +- rustls/src/client/handy.rs | 6 ++++++ rustls/src/lib.rs | 6 +++++- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 04a24f3caed..2def5802a7b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -318,7 +318,7 @@ jobs: persist-credentials: false - name: Install rust toolchain - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@nightly with: components: llvm-tools diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 250140124dd..221a7990c07 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -126,4 +126,4 @@ allowed_external_types = [ enum_no_repr_variant_discriminant_changed = "warn" [lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ["cfg(bench)", "cfg(read_buf)"] } +unexpected_cfgs = { level = "warn", check-cfg = ["cfg(bench)", "cfg(coverage_nightly)", "cfg(read_buf)"] } diff --git a/rustls/src/client/handy.rs b/rustls/src/client/handy.rs index eabe1cb3a7b..1097156374d 100644 --- a/rustls/src/client/handy.rs +++ b/rustls/src/client/handy.rs @@ -331,6 +331,7 @@ mod tests { struct DummyServerCertVerifier; impl ServerCertVerifier for DummyServerCertVerifier { + #[cfg_attr(coverage_nightly, coverage(off))] fn verify_server_cert( &self, _end_entity: &CertificateDer<'_>, @@ -342,6 +343,7 @@ mod tests { unreachable!() } + #[cfg_attr(coverage_nightly, coverage(off))] fn verify_tls12_signature( &self, _message: &[u8], @@ -351,6 +353,7 @@ mod tests { unreachable!() } + #[cfg_attr(coverage_nightly, coverage(off))] fn verify_tls13_signature( &self, _message: &[u8], @@ -360,6 +363,7 @@ mod tests { unreachable!() } + #[cfg_attr(coverage_nightly, coverage(off))] fn supported_verify_schemes(&self) -> Vec { unreachable!() } @@ -369,6 +373,7 @@ mod tests { struct DummyResolvesClientCert; impl ResolvesClientCert for DummyResolvesClientCert { + #[cfg_attr(coverage_nightly, coverage(off))] fn resolve( &self, _root_hint_subjects: &[&[u8]], @@ -377,6 +382,7 @@ mod tests { unreachable!() } + #[cfg_attr(coverage_nightly, coverage(off))] fn has_certs(&self) -> bool { unreachable!() } diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index c56bd92007e..ebc11b60669 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -324,7 +324,7 @@ // Require docs for public APIs, deny unsafe code, etc. #![forbid(unsafe_code, unused_must_use)] -#![cfg_attr(not(any(read_buf, bench)), forbid(unstable_features))] +#![cfg_attr(not(any(read_buf, bench, coverage_nightly)), forbid(unstable_features))] #![warn( clippy::alloc_instead_of_core, clippy::clone_on_ref_ptr, @@ -360,6 +360,10 @@ )] // 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 +// +// (`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. From a209a0e805ed2391eb4e0f3b3ed00b50ed3f4829 Mon Sep 17 00:00:00 2001 From: "@brody4hire - C. Jonathan Brody" Date: Tue, 25 Feb 2025 08:45:58 -0500 Subject: [PATCH 092/403] docs: link to manual from front page Co-authored-by: Joe Birr-Pixton --- rustls/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index ebc11b60669..74bb61e1d19 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -265,6 +265,10 @@ //! //! [`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. From 94d4cb7eef677ec7e80bba4f08bba719aafa1a33 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 11 Mar 2025 17:14:34 +0000 Subject: [PATCH 093/403] chore(deps): update dependency go to v1.24.1 --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2def5802a7b..30e2985de8c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -68,7 +68,7 @@ jobs: if: runner.os == 'MacOS' uses: actions/setup-go@v5 with: - go-version: "1.22.2" + go-version: "1.24.1" - name: cargo build (debug; default features) run: cargo build --locked @@ -207,7 +207,7 @@ jobs: - name: Install golang toolchain uses: actions/setup-go@v5 with: - go-version: "1.21" + go-version: "1.24" cache: false - name: Run test suite (ring) From 7a64c7414607f9f79b278bfd3913f632a482083c Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 10 Mar 2025 17:38:46 +0000 Subject: [PATCH 094/403] admin/coverage: only measure core crate coverage --- admin/coverage | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/admin/coverage b/admin/coverage index 61360e42284..b23c0ef2a63 100755 --- a/admin/coverage +++ b/admin/coverage @@ -17,10 +17,4 @@ cargo test --locked $(admin/all-features-except brotli rustls) ## bogo cargo test --locked --test bogo -- --ignored --test-threads 1 -# provider example unit tests -cargo test --locked --package rustls-provider-example - -## provider example tests -cargo test --locked --package rustls-provider-test - -cargo llvm-cov report "$@" +cargo llvm-cov report --ignore-filename-regex bogo/ "$@" From 1c318bcd53607d7e1106f913e5040da2349df63f Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 13 Mar 2025 10:36:35 +0000 Subject: [PATCH 095/403] Refactor: prefer to take reference on match scrutinee This makes everything take advantage of match ergonomics. --- bogo/src/main.rs | 6 +- examples/src/bin/simple_0rtt_server.rs | 2 +- examples/src/bin/tlsserver-mio.rs | 2 +- rustls/src/client/tls13.rs | 14 +- rustls/src/conn.rs | 2 +- rustls/src/error.rs | 30 +-- rustls/src/key_log_file.rs | 4 +- rustls/src/msgs/handshake.rs | 294 ++++++++++++------------- rustls/src/msgs/handshake_test.rs | 4 +- rustls/src/msgs/message/outbound.rs | 4 +- rustls/src/msgs/persist.rs | 6 +- rustls/src/server/hs.rs | 2 +- rustls/src/server/server_conn.rs | 4 +- rustls/src/server/tls13.rs | 4 +- 14 files changed, 188 insertions(+), 190 deletions(-) diff --git a/bogo/src/main.rs b/bogo/src/main.rs index 78aa152207d..5f237de56ea 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -1026,7 +1026,7 @@ fn read_n_bytes(opts: &Options, sess: &mut Connection, conn: &mut net::TcpStream sess.read_tls(&mut io::Cursor::new(&mut bytes[..count])) .expect("read_tls not expected to fail reading from buffer"); } - Err(ref err) if err.kind() == io::ErrorKind::ConnectionReset => {} + Err(err) if err.kind() == io::ErrorKind::ConnectionReset => {} Err(err) => panic!("invalid read: {}", err), }; @@ -1036,7 +1036,7 @@ fn read_n_bytes(opts: &Options, sess: &mut Connection, conn: &mut net::TcpStream fn read_all_bytes(opts: &Options, sess: &mut Connection, conn: &mut net::TcpStream) { match sess.read_tls(conn) { Ok(_) => {} - Err(ref err) if err.kind() == io::ErrorKind::ConnectionReset => {} + Err(err) if err.kind() == io::ErrorKind::ConnectionReset => {} Err(err) => panic!("invalid read: {}", err), }; @@ -1097,7 +1097,7 @@ fn exec(opts: &Options, mut sess: Connection, count: usize) { } if opts.side == Side::Server && opts.enable_early_data { - if let Some(ref mut ed) = server(&mut sess).early_data() { + if let Some(ed) = &mut server(&mut sess).early_data() { let mut data = Vec::new(); let data_len = ed .read_to_end(&mut data) diff --git a/examples/src/bin/simple_0rtt_server.rs b/examples/src/bin/simple_0rtt_server.rs index 1256c57fb0b..fcdf799abb7 100644 --- a/examples/src/bin/simple_0rtt_server.rs +++ b/examples/src/bin/simple_0rtt_server.rs @@ -68,7 +68,7 @@ fn main() -> Result<(), Box> { match conn.read_tls(&mut stream) { Ok(0) => return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()), Ok(_) => break, - Err(ref err) if err.kind() == io::ErrorKind::Interrupted => {} + Err(err) if err.kind() == io::ErrorKind::Interrupted => {} Err(err) => return Err(err.into()), }; } diff --git a/examples/src/bin/tlsserver-mio.rs b/examples/src/bin/tlsserver-mio.rs index c85222058f7..6478b55710c 100644 --- a/examples/src/bin/tlsserver-mio.rs +++ b/examples/src/bin/tlsserver-mio.rs @@ -90,7 +90,7 @@ impl TlsServer { self.connections .insert(token, connection); } - Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => return Ok(()), + Err(err) if err.kind() == io::ErrorKind::WouldBlock => return Ok(()), Err(err) => { println!( "encountered error while accepting connection; err={:?}", diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index d6f772db268..94378d68d4c 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -100,8 +100,8 @@ pub(super) fn handle_server_hello( let key_schedule_pre_handshake = match (server_hello.psk_index(), early_key_schedule) { (Some(selected_psk), Some(early_key_schedule)) => { - match resuming_session { - Some(ref resuming) => { + match &resuming_session { + Some(resuming) => { let Some(resuming_suite) = suite.can_resume_from(resuming.suite()) else { return Err({ cx.common.send_fatal_alert( @@ -323,7 +323,7 @@ pub(super) fn fill_in_psk_binder( 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(ref mut ch) = hmp.payload { + if let HandshakePayload::ClientHello(ch) = &mut hmp.payload { ch.set_psk_binder(real_binder.as_ref()); }; @@ -1555,19 +1555,19 @@ impl State for ExpectTraffic { MessagePayload::Handshake { parsed: HandshakeMessagePayload { - payload: HandshakePayload::NewSessionTicketTls13(ref new_ticket), + payload: HandshakePayload::NewSessionTicketTls13(new_ticket), .. }, .. - } => self.handle_new_ticket_tls13(cx, new_ticket)?, + } => self.handle_new_ticket_tls13(cx, &new_ticket)?, MessagePayload::Handshake { parsed: HandshakeMessagePayload { - payload: HandshakePayload::KeyUpdate(ref key_update), + payload: HandshakePayload::KeyUpdate(key_update), .. }, .. - } => self.handle_key_update(cx.common, key_update)?, + } => self.handle_key_update(cx.common, &key_update)?, payload => { return Err(inappropriate_handshake_message( &payload, diff --git a/rustls/src/conn.rs b/rustls/src/conn.rs index 32fc1935975..1b370c242b8 100644 --- a/rustls/src/conn.rs +++ b/rustls/src/conn.rs @@ -638,7 +638,7 @@ impl ConnectionCommon { rdlen += n; Some(n) } - Err(ref err) if err.kind() == io::ErrorKind::Interrupted => None, // nothing to do + Err(err) if err.kind() == io::ErrorKind::Interrupted => None, // nothing to do Err(err) => return Err(err), }; if read_size.is_some() { diff --git a/rustls/src/error.rs b/rustls/src/error.rs index bd0e7013694..91288b6a460 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -726,10 +726,10 @@ fn join(items: &[T]) -> String { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { + match self { Self::InappropriateMessage { - ref expect_types, - ref got_type, + expect_types, + got_type, } => write!( f, "received unexpected message: got {:?} when expecting {}", @@ -737,30 +737,30 @@ impl fmt::Display for Error { join::(expect_types) ), Self::InappropriateHandshakeMessage { - ref expect_types, - ref got_type, + expect_types, + got_type, } => write!( f, "received unexpected handshake message: got {:?} when expecting {}", got_type, join::(expect_types) ), - Self::InvalidMessage(ref typ) => { + Self::InvalidMessage(typ) => { write!(f, "received corrupt message of type {:?}", typ) } - Self::PeerIncompatible(ref why) => write!(f, "peer is incompatible: {:?}", why), - Self::PeerMisbehaved(ref why) => write!(f, "peer misbehaved: {:?}", why), - Self::AlertReceived(ref alert) => write!(f, "received fatal alert: {:?}", alert), - Self::InvalidCertificate(ref err) => { + 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(ref 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(ref err) => { + Self::InvalidEncryptedClientHello(err) => { write!(f, "encrypted client hello failure: {:?}", err) } Self::EncryptError => write!(f, "cannot encrypt message"), @@ -772,11 +772,11 @@ impl fmt::Display for Error { Self::BadMaxFragmentSize => { write!(f, "the supplied max_fragment_size was too small or large") } - Self::InconsistentKeys(ref why) => { + Self::InconsistentKeys(why) => { write!(f, "keys may not be consistent: {:?}", why) } - Self::General(ref err) => write!(f, "unexpected error: {}", err), - Self::Other(ref err) => write!(f, "other error: {}", err), + Self::General(err) => write!(f, "unexpected error: {}", err), + Self::Other(err) => write!(f, "other error: {}", err), } } } diff --git a/rustls/src/key_log_file.rs b/rustls/src/key_log_file.rs index 4781b98be27..c79771a62a8 100644 --- a/rustls/src/key_log_file.rs +++ b/rustls/src/key_log_file.rs @@ -45,11 +45,11 @@ impl KeyLogFileInner { } fn try_write(&mut self, label: &str, client_random: &[u8], secret: &[u8]) -> io::Result<()> { - let mut file = match self.file { + let file = match &mut self.file { None => { return Ok(()); } - Some(ref f) => f, + Some(f) => f, }; self.buf.truncate(0); diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index cf4a687deab..f5abbf6987d 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -248,13 +248,13 @@ impl ServerNamePayload { } fn encode(&self, bytes: &mut Vec) { - match *self { - Self::HostName(ref name) => { + match self { + Self::HostName(name) => { (name.as_ref().len() as u16).encode(bytes); bytes.extend_from_slice(name.as_ref().as_bytes()); } - Self::IpAddress(ref r) => r.encode(bytes), - Self::Unknown(ref r) => r.encode(bytes), + Self::IpAddress(r) => r.encode(bytes), + Self::Unknown(r) => r.encode(bytes), } } } @@ -300,7 +300,7 @@ impl ConvertServerNameList for [ServerName] { fn single_hostname(&self) -> Option> { fn only_dns_hostnames(name: &ServerName) -> Option> { - if let ServerNamePayload::HostName(ref dns) = name.payload { + if let ServerNamePayload::HostName(dns) = &name.payload { Some(dns.borrow()) } else { None @@ -577,7 +577,7 @@ pub enum ClientExtension { impl ClientExtension { pub(crate) fn ext_type(&self) -> ExtensionType { - match *self { + match self { Self::EcPointFormats(_) => ExtensionType::ECPointFormats, Self::NamedGroups(_) => ExtensionType::EllipticCurves, Self::SignatureAlgorithms(_) => ExtensionType::SignatureAlgorithms, @@ -602,7 +602,7 @@ impl ClientExtension { ExtensionType::EncryptedClientHelloOuterExtensions } Self::AuthorityNames(_) => ExtensionType::CertificateAuthorities, - Self::Unknown(ref r) => r.typ, + Self::Unknown(r) => r.typ, } } } @@ -612,32 +612,32 @@ impl Codec<'_> for ClientExtension { self.ext_type().encode(bytes); let nested = LengthPrefixedBuffer::new(ListLength::U16, bytes); - match *self { - Self::EcPointFormats(ref r) => r.encode(nested.buf), - Self::NamedGroups(ref r) => r.encode(nested.buf), - Self::SignatureAlgorithms(ref r) => r.encode(nested.buf), - Self::ServerName(ref r) => r.encode(nested.buf), + match self { + Self::EcPointFormats(r) => r.encode(nested.buf), + Self::NamedGroups(r) => r.encode(nested.buf), + Self::SignatureAlgorithms(r) => r.encode(nested.buf), + Self::ServerName(r) => r.encode(nested.buf), Self::SessionTicket(ClientSessionTicket::Request) | Self::ExtendedMasterSecretRequest | Self::EarlyData => {} - Self::SessionTicket(ClientSessionTicket::Offer(ref r)) => r.encode(nested.buf), - Self::Protocols(ref r) => r.encode(nested.buf), - Self::SupportedVersions(ref r) => r.encode(nested.buf), - Self::KeyShare(ref r) => r.encode(nested.buf), - Self::PresharedKeyModes(ref r) => r.encode(nested.buf), - Self::PresharedKey(ref r) => r.encode(nested.buf), - Self::Cookie(ref r) => r.encode(nested.buf), - Self::CertificateStatusRequest(ref r) => r.encode(nested.buf), - Self::ClientCertTypes(ref r) => r.encode(nested.buf), - Self::ServerCertTypes(ref r) => r.encode(nested.buf), - Self::TransportParameters(ref r) | Self::TransportParametersDraft(ref r) => { + Self::SessionTicket(ClientSessionTicket::Offer(r)) => r.encode(nested.buf), + Self::Protocols(r) => r.encode(nested.buf), + Self::SupportedVersions(r) => r.encode(nested.buf), + Self::KeyShare(r) => r.encode(nested.buf), + Self::PresharedKeyModes(r) => r.encode(nested.buf), + Self::PresharedKey(r) => r.encode(nested.buf), + Self::Cookie(r) => r.encode(nested.buf), + Self::CertificateStatusRequest(r) => r.encode(nested.buf), + Self::ClientCertTypes(r) => r.encode(nested.buf), + Self::ServerCertTypes(r) => r.encode(nested.buf), + Self::TransportParameters(r) | Self::TransportParametersDraft(r) => { nested.buf.extend_from_slice(r); } - Self::CertificateCompressionAlgorithms(ref r) => r.encode(nested.buf), - Self::EncryptedClientHello(ref r) => r.encode(nested.buf), - Self::EncryptedClientHelloOuterExtensions(ref r) => r.encode(nested.buf), - Self::AuthorityNames(ref r) => r.encode(nested.buf), - Self::Unknown(ref r) => r.encode(nested.buf), + Self::CertificateCompressionAlgorithms(r) => r.encode(nested.buf), + Self::EncryptedClientHello(r) => r.encode(nested.buf), + Self::EncryptedClientHelloOuterExtensions(r) => r.encode(nested.buf), + Self::AuthorityNames(r) => r.encode(nested.buf), + Self::Unknown(r) => r.encode(nested.buf), } } @@ -750,7 +750,7 @@ pub enum ServerExtension { impl ServerExtension { pub(crate) fn ext_type(&self) -> ExtensionType { - match *self { + match self { Self::EcPointFormats(_) => ExtensionType::ECPointFormats, Self::ServerNameAck => ExtensionType::ServerName, Self::SessionTicketAck => ExtensionType::SessionTicket, @@ -767,7 +767,7 @@ impl ServerExtension { Self::TransportParametersDraft(_) => ExtensionType::TransportParametersDraft, Self::EarlyData => ExtensionType::EarlyData, Self::EncryptedClientHello(_) => ExtensionType::EncryptedClientHello, - Self::Unknown(ref r) => r.typ, + Self::Unknown(r) => r.typ, } } } @@ -777,25 +777,25 @@ impl Codec<'_> for ServerExtension { self.ext_type().encode(bytes); let nested = LengthPrefixedBuffer::new(ListLength::U16, bytes); - match *self { - Self::EcPointFormats(ref r) => r.encode(nested.buf), + match self { + Self::EcPointFormats(r) => r.encode(nested.buf), Self::ServerNameAck | Self::SessionTicketAck | Self::ExtendedMasterSecretAck | Self::CertificateStatusAck | Self::EarlyData => {} - Self::RenegotiationInfo(ref r) => r.encode(nested.buf), - Self::Protocols(ref r) => r.encode(nested.buf), - Self::KeyShare(ref r) => r.encode(nested.buf), + Self::RenegotiationInfo(r) => r.encode(nested.buf), + Self::Protocols(r) => r.encode(nested.buf), + Self::KeyShare(r) => r.encode(nested.buf), Self::PresharedKey(r) => r.encode(nested.buf), Self::ClientCertType(r) => r.encode(nested.buf), Self::ServerCertType(r) => r.encode(nested.buf), - Self::SupportedVersions(ref r) => r.encode(nested.buf), - Self::TransportParameters(ref r) | Self::TransportParametersDraft(ref r) => { + Self::SupportedVersions(r) => r.encode(nested.buf), + Self::TransportParameters(r) | Self::TransportParametersDraft(r) => { nested.buf.extend_from_slice(r); } - Self::EncryptedClientHello(ref r) => r.encode(nested.buf), - Self::Unknown(ref r) => r.encode(nested.buf), + Self::EncryptedClientHello(r) => r.encode(nested.buf), + Self::Unknown(r) => r.encode(nested.buf), } } @@ -985,7 +985,7 @@ impl ClientHelloPayload { pub(crate) fn sni_extension(&self) -> Option<&[ServerName]> { let ext = self.find_extension(ExtensionType::ServerName)?; - match *ext { + match ext { // Does this comply with RFC6066? // // [RFC6066][] specifies that literal IP addresses are illegal in @@ -996,7 +996,7 @@ impl ClientHelloPayload { // but then act like the client sent no `server_name` extension. // // [RFC6066]: https://datatracker.ietf.org/doc/html/rfc6066#section-3 - ClientExtension::ServerName(ref req) + ClientExtension::ServerName(req) if !req .iter() .any(|name| matches!(name.payload, ServerNamePayload::IpAddress(_))) => @@ -1009,16 +1009,16 @@ impl ClientHelloPayload { pub fn sigalgs_extension(&self) -> Option<&[SignatureScheme]> { let ext = self.find_extension(ExtensionType::SignatureAlgorithms)?; - match *ext { - ClientExtension::SignatureAlgorithms(ref req) => Some(req), + match ext { + ClientExtension::SignatureAlgorithms(req) => Some(req), _ => None, } } pub(crate) fn namedgroups_extension(&self) -> Option<&[NamedGroup]> { let ext = self.find_extension(ExtensionType::EllipticCurves)?; - match *ext { - ClientExtension::NamedGroups(ref req) => Some(req), + match ext { + ClientExtension::NamedGroups(req) => Some(req), _ => None, } } @@ -1026,8 +1026,8 @@ impl ClientHelloPayload { #[cfg(feature = "tls12")] pub(crate) fn ecpoints_extension(&self) -> Option<&[ECPointFormat]> { let ext = self.find_extension(ExtensionType::ECPointFormats)?; - match *ext { - ClientExtension::EcPointFormats(ref req) => Some(req), + match ext { + ClientExtension::EcPointFormats(req) => Some(req), _ => None, } } @@ -1050,8 +1050,8 @@ impl ClientHelloPayload { pub(crate) fn alpn_extension(&self) -> Option<&Vec> { let ext = self.find_extension(ExtensionType::ALProtocolNegotiation)?; - match *ext { - ClientExtension::Protocols(ref req) => Some(req), + match ext { + ClientExtension::Protocols(req) => Some(req), _ => None, } } @@ -1060,9 +1060,9 @@ impl ClientHelloPayload { let ext = self .find_extension(ExtensionType::TransportParameters) .or_else(|| self.find_extension(ExtensionType::TransportParametersDraft))?; - match *ext { - ClientExtension::TransportParameters(ref bytes) - | ClientExtension::TransportParametersDraft(ref bytes) => Some(bytes.to_vec()), + match ext { + ClientExtension::TransportParameters(bytes) + | ClientExtension::TransportParametersDraft(bytes) => Some(bytes.to_vec()), _ => None, } } @@ -1074,16 +1074,16 @@ impl ClientHelloPayload { pub(crate) fn versions_extension(&self) -> Option<&[ProtocolVersion]> { let ext = self.find_extension(ExtensionType::SupportedVersions)?; - match *ext { - ClientExtension::SupportedVersions(ref vers) => Some(vers), + match ext { + ClientExtension::SupportedVersions(vers) => Some(vers), _ => None, } } pub fn keyshare_extension(&self) -> Option<&[KeyShareEntry]> { let ext = self.find_extension(ExtensionType::KeyShare)?; - match *ext { - ClientExtension::KeyShare(ref shares) => Some(shares), + match ext { + ClientExtension::KeyShare(shares) => Some(shares), _ => None, } } @@ -1102,8 +1102,8 @@ impl ClientHelloPayload { pub(crate) fn psk(&self) -> Option<&PresharedKeyOffer> { let ext = self.find_extension(ExtensionType::PreSharedKey)?; - match *ext { - ClientExtension::PresharedKey(ref psk) => Some(psk), + match ext { + ClientExtension::PresharedKey(psk) => Some(psk), _ => None, } } @@ -1116,8 +1116,8 @@ impl ClientHelloPayload { pub(crate) fn psk_modes(&self) -> Option<&[PSKKeyExchangeMode]> { let ext = self.find_extension(ExtensionType::PSKKeyExchangeModes)?; - match *ext { - ClientExtension::PresharedKeyModes(ref psk_modes) => Some(psk_modes), + match ext { + ClientExtension::PresharedKeyModes(psk_modes) => Some(psk_modes), _ => None, } } @@ -1150,8 +1150,8 @@ impl ClientHelloPayload { &self, ) -> Option<&[CertificateCompressionAlgorithm]> { let ext = self.find_extension(ExtensionType::CompressCertificate)?; - match *ext { - ClientExtension::CertificateCompressionAlgorithms(ref algs) => Some(algs), + match ext { + ClientExtension::CertificateCompressionAlgorithms(algs) => Some(algs), _ => None, } } @@ -1183,12 +1183,12 @@ pub(crate) enum HelloRetryExtension { impl HelloRetryExtension { pub(crate) fn ext_type(&self) -> ExtensionType { - match *self { + match self { Self::KeyShare(_) => ExtensionType::KeyShare, Self::Cookie(_) => ExtensionType::Cookie, Self::SupportedVersions(_) => ExtensionType::SupportedVersions, Self::EchHelloRetryRequest(_) => ExtensionType::EncryptedClientHello, - Self::Unknown(ref r) => r.typ, + Self::Unknown(r) => r.typ, } } } @@ -1198,14 +1198,14 @@ impl Codec<'_> for HelloRetryExtension { self.ext_type().encode(bytes); let nested = LengthPrefixedBuffer::new(ListLength::U16, bytes); - match *self { - Self::KeyShare(ref r) => r.encode(nested.buf), - Self::Cookie(ref r) => r.encode(nested.buf), - Self::SupportedVersions(ref r) => r.encode(nested.buf), - Self::EchHelloRetryRequest(ref r) => { + match self { + Self::KeyShare(r) => r.encode(nested.buf), + Self::Cookie(r) => r.encode(nested.buf), + Self::SupportedVersions(r) => r.encode(nested.buf), + Self::EchHelloRetryRequest(r) => { nested.buf.extend_from_slice(r); } - Self::Unknown(ref r) => r.encode(nested.buf), + Self::Unknown(r) => r.encode(nested.buf), } } @@ -1292,32 +1292,32 @@ impl HelloRetryRequest { pub fn requested_key_share_group(&self) -> Option { let ext = self.find_extension(ExtensionType::KeyShare)?; - match *ext { - HelloRetryExtension::KeyShare(grp) => Some(grp), + match ext { + HelloRetryExtension::KeyShare(grp) => Some(*grp), _ => None, } } pub(crate) fn cookie(&self) -> Option<&PayloadU16> { let ext = self.find_extension(ExtensionType::Cookie)?; - match *ext { - HelloRetryExtension::Cookie(ref ck) => Some(ck), + match ext { + HelloRetryExtension::Cookie(ck) => Some(ck), _ => None, } } pub(crate) fn supported_versions(&self) -> Option { let ext = self.find_extension(ExtensionType::SupportedVersions)?; - match *ext { - HelloRetryExtension::SupportedVersions(ver) => Some(ver), + match ext { + HelloRetryExtension::SupportedVersions(ver) => Some(*ver), _ => None, } } pub(crate) fn ech(&self) -> Option<&Vec> { let ext = self.find_extension(ExtensionType::EncryptedClientHello)?; - match *ext { - HelloRetryExtension::EchHelloRetryRequest(ref ech) => Some(ech), + match ext { + HelloRetryExtension::EchHelloRetryRequest(ech) => Some(ech), _ => None, } } @@ -1406,24 +1406,24 @@ impl HasServerExtensions for ServerHelloPayload { impl ServerHelloPayload { pub(crate) fn key_share(&self) -> Option<&KeyShareEntry> { let ext = self.find_extension(ExtensionType::KeyShare)?; - match *ext { - ServerExtension::KeyShare(ref share) => Some(share), + match ext { + ServerExtension::KeyShare(share) => Some(share), _ => None, } } pub(crate) fn psk_index(&self) -> Option { let ext = self.find_extension(ExtensionType::PreSharedKey)?; - match *ext { - ServerExtension::PresharedKey(ref index) => Some(*index), + match ext { + ServerExtension::PresharedKey(index) => Some(*index), _ => None, } } pub(crate) fn ecpoints_extension(&self) -> Option<&[ECPointFormat]> { let ext = self.find_extension(ExtensionType::ECPointFormats)?; - match *ext { - ServerExtension::EcPointFormats(ref fmts) => Some(fmts), + match ext { + ServerExtension::EcPointFormats(fmts) => Some(fmts), _ => None, } } @@ -1436,8 +1436,8 @@ impl ServerHelloPayload { pub(crate) fn supported_versions(&self) -> Option { let ext = self.find_extension(ExtensionType::SupportedVersions)?; - match *ext { - ServerExtension::SupportedVersions(vers) => Some(vers), + match ext { + ServerExtension::SupportedVersions(vers) => Some(*vers), _ => None, } } @@ -1521,15 +1521,15 @@ pub(crate) enum CertificateExtension<'a> { impl CertificateExtension<'_> { pub(crate) fn ext_type(&self) -> ExtensionType { - match *self { + match self { Self::CertificateStatus(_) => ExtensionType::StatusRequest, - Self::Unknown(ref r) => r.typ, + Self::Unknown(r) => r.typ, } } pub(crate) fn cert_status(&self) -> Option<&[u8]> { - match *self { - Self::CertificateStatus(ref cs) => Some(cs.ocsp_response.0.bytes()), + match self { + Self::CertificateStatus(cs) => Some(cs.ocsp_response.0.bytes()), _ => None, } } @@ -1547,9 +1547,9 @@ impl<'a> Codec<'a> for CertificateExtension<'a> { self.ext_type().encode(bytes); let nested = LengthPrefixedBuffer::new(ListLength::U16, bytes); - match *self { - Self::CertificateStatus(ref r) => r.encode(nested.buf), - Self::Unknown(ref r) => r.encode(nested.buf), + match self { + Self::CertificateStatus(r) => r.encode(nested.buf), + Self::Unknown(r) => r.encode(nested.buf), } } @@ -2025,9 +2025,9 @@ impl From for ServerKeyExchangePayload { impl Codec<'_> for ServerKeyExchangePayload { fn encode(&self, bytes: &mut Vec) { - match *self { - Self::Known(ref x) => x.encode(bytes), - Self::Unknown(ref x) => x.encode(bytes), + match self { + Self::Known(x) => x.encode(bytes), + Self::Unknown(x) => x.encode(bytes), } } @@ -2041,7 +2041,7 @@ impl Codec<'_> for ServerKeyExchangePayload { impl ServerKeyExchangePayload { #[cfg(feature = "tls12")] pub(crate) fn unwrap_given_kxa(&self, kxa: KeyExchangeAlgorithm) -> Option { - if let Self::Unknown(ref unk) = *self { + if let Self::Unknown(unk) = self { let mut rd = Reader::init(unk.bytes()); let result = ServerKeyExchange { @@ -2085,8 +2085,8 @@ pub(crate) trait HasServerExtensions { fn alpn_protocol(&self) -> Option<&[u8]> { let ext = self.find_extension(ExtensionType::ALProtocolNegotiation)?; - match *ext { - ServerExtension::Protocols(ref protos) => protos.as_single_slice(), + match ext { + ServerExtension::Protocols(protos) => protos.as_single_slice(), _ => None, } } @@ -2111,9 +2111,9 @@ pub(crate) trait HasServerExtensions { let ext = self .find_extension(ExtensionType::TransportParameters) .or_else(|| self.find_extension(ExtensionType::TransportParametersDraft))?; - match *ext { - ServerExtension::TransportParameters(ref bytes) - | ServerExtension::TransportParametersDraft(ref bytes) => Some(bytes.to_vec()), + match ext { + ServerExtension::TransportParameters(bytes) + | ServerExtension::TransportParametersDraft(bytes) => Some(bytes.to_vec()), _ => None, } } @@ -2219,11 +2219,11 @@ pub(crate) enum CertReqExtension { impl CertReqExtension { pub(crate) fn ext_type(&self) -> ExtensionType { - match *self { + match self { Self::SignatureAlgorithms(_) => ExtensionType::SignatureAlgorithms, Self::AuthorityNames(_) => ExtensionType::CertificateAuthorities, Self::CertificateCompressionAlgorithms(_) => ExtensionType::CompressCertificate, - Self::Unknown(ref r) => r.typ, + Self::Unknown(r) => r.typ, } } } @@ -2233,11 +2233,11 @@ impl Codec<'_> for CertReqExtension { self.ext_type().encode(bytes); let nested = LengthPrefixedBuffer::new(ListLength::U16, bytes); - match *self { - Self::SignatureAlgorithms(ref r) => r.encode(nested.buf), - Self::AuthorityNames(ref r) => r.encode(nested.buf), - Self::CertificateCompressionAlgorithms(ref r) => r.encode(nested.buf), - Self::Unknown(ref r) => r.encode(nested.buf), + match self { + Self::SignatureAlgorithms(r) => r.encode(nested.buf), + Self::AuthorityNames(r) => r.encode(nested.buf), + Self::CertificateCompressionAlgorithms(r) => r.encode(nested.buf), + Self::Unknown(r) => r.encode(nested.buf), } } @@ -2305,16 +2305,16 @@ impl CertificateRequestPayloadTls13 { pub(crate) fn sigalgs_extension(&self) -> Option<&[SignatureScheme]> { let ext = self.find_extension(ExtensionType::SignatureAlgorithms)?; - match *ext { - CertReqExtension::SignatureAlgorithms(ref sa) => Some(sa), + match ext { + CertReqExtension::SignatureAlgorithms(sa) => Some(sa), _ => None, } } pub(crate) fn authorities_extension(&self) -> Option<&[DistinguishedName]> { let ext = self.find_extension(ExtensionType::CertificateAuthorities)?; - match *ext { - CertReqExtension::AuthorityNames(ref an) => Some(an), + match ext { + CertReqExtension::AuthorityNames(an) => Some(an), _ => None, } } @@ -2323,8 +2323,8 @@ impl CertificateRequestPayloadTls13 { &self, ) -> Option<&[CertificateCompressionAlgorithm]> { let ext = self.find_extension(ExtensionType::CompressCertificate)?; - match *ext { - CertReqExtension::CertificateCompressionAlgorithms(ref comps) => Some(comps), + match ext { + CertReqExtension::CertificateCompressionAlgorithms(comps) => Some(comps), _ => None, } } @@ -2376,9 +2376,9 @@ pub(crate) enum NewSessionTicketExtension { impl NewSessionTicketExtension { pub(crate) fn ext_type(&self) -> ExtensionType { - match *self { + match self { Self::EarlyData(_) => ExtensionType::EarlyData, - Self::Unknown(ref r) => r.typ, + Self::Unknown(r) => r.typ, } } } @@ -2388,9 +2388,9 @@ impl Codec<'_> for NewSessionTicketExtension { self.ext_type().encode(bytes); let nested = LengthPrefixedBuffer::new(ListLength::U16, bytes); - match *self { + match self { Self::EarlyData(r) => r.encode(nested.buf), - Self::Unknown(ref r) => r.encode(nested.buf), + Self::Unknown(r) => r.encode(nested.buf), } } @@ -2449,8 +2449,8 @@ impl NewSessionTicketPayloadTls13 { pub(crate) fn max_early_data_size(&self) -> Option { let ext = self.find_extension(ExtensionType::EarlyData)?; - match *ext { - NewSessionTicketExtension::EarlyData(ref sz) => Some(*sz), + match ext { + NewSessionTicketExtension::EarlyData(sz) => Some(*sz), _ => None, } } @@ -2598,27 +2598,27 @@ pub enum HandshakePayload<'a> { impl HandshakePayload<'_> { fn encode(&self, bytes: &mut Vec) { use self::HandshakePayload::*; - match *self { + match self { HelloRequest | ServerHelloDone | EndOfEarlyData => {} - ClientHello(ref x) => x.encode(bytes), - ServerHello(ref x) => x.encode(bytes), - HelloRetryRequest(ref x) => x.encode(bytes), - Certificate(ref x) => x.encode(bytes), - CertificateTls13(ref x) => x.encode(bytes), - CompressedCertificate(ref x) => x.encode(bytes), - ServerKeyExchange(ref x) => x.encode(bytes), - ClientKeyExchange(ref x) => x.encode(bytes), - CertificateRequest(ref x) => x.encode(bytes), - CertificateRequestTls13(ref x) => x.encode(bytes), - CertificateVerify(ref x) => x.encode(bytes), - NewSessionTicket(ref x) => x.encode(bytes), - NewSessionTicketTls13(ref x) => x.encode(bytes), - EncryptedExtensions(ref x) => x.encode(bytes), - KeyUpdate(ref x) => x.encode(bytes), - Finished(ref x) => x.encode(bytes), - CertificateStatus(ref x) => x.encode(bytes), - MessageHash(ref x) => x.encode(bytes), - Unknown(ref x) => x.encode(bytes), + 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), } } @@ -2775,8 +2775,8 @@ impl<'a> HandshakeMessagePayload<'a> { } pub(crate) fn total_binder_length(&self) -> usize { - match self.payload { - HandshakePayload::ClientHello(ref ch) => match ch.extensions.last() { + match &self.payload { + HandshakePayload::ClientHello(ch) => match ch.extensions.last() { Some(ClientExtension::PresharedKey(offer)) => { let mut binders_encoding = Vec::new(); offer @@ -2999,8 +2999,8 @@ pub enum EchConfigExtension { impl EchConfigExtension { pub(crate) fn ext_type(&self) -> ExtensionType { - match *self { - Self::Unknown(ref r) => r.typ, + match self { + Self::Unknown(r) => r.typ, } } } @@ -3010,8 +3010,8 @@ impl Codec<'_> for EchConfigExtension { self.ext_type().encode(bytes); let nested = LengthPrefixedBuffer::new(ListLength::U16, bytes); - match *self { - Self::Unknown(ref r) => r.encode(nested.buf), + match self { + Self::Unknown(r) => r.encode(nested.buf), } } diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index 9e5a7b8f98b..63aeee7e851 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -749,7 +749,7 @@ fn can_clone_all_server_extensions() { #[test] fn can_round_trip_all_tls12_handshake_payloads() { - for ref hm in all_tls12_handshake_payloads().iter() { + for hm in all_tls12_handshake_payloads().iter() { println!("{:?}", hm.typ); let bytes = hm.get_encoding(); let mut rd = Reader::init(&bytes); @@ -813,7 +813,7 @@ fn can_detect_truncation_of_all_tls12_handshake_payloads() { #[test] fn can_round_trip_all_tls13_handshake_payloads() { - for ref hm in all_tls13_handshake_payloads().iter() { + for hm in all_tls13_handshake_payloads().iter() { println!("{:?}", hm.typ); let bytes = hm.get_encoding(); let mut rd = Reader::init(&bytes); diff --git a/rustls/src/msgs/message/outbound.rs b/rustls/src/msgs/message/outbound.rs index 8dc924c156d..7345e54b37e 100644 --- a/rustls/src/msgs/message/outbound.rs +++ b/rustls/src/msgs/message/outbound.rs @@ -282,8 +282,8 @@ pub(crate) fn read_opaque_message_header( let version = ProtocolVersion::read(r).map_err(|_| MessageError::TooShortForHeader)?; // Accept only versions 0x03XX for any XX. - match version { - ProtocolVersion::Unknown(ref v) if (v & 0xff00) != 0x0300 => { + match &version { + ProtocolVersion::Unknown(v) if (v & 0xff00) != 0x0300 => { return Err(MessageError::UnknownProtocolVersion); } _ => {} diff --git a/rustls/src/msgs/persist.rs b/rustls/src/msgs/persist.rs index c5e67ad0903..8fb21e09341 100644 --- a/rustls/src/msgs/persist.rs +++ b/rustls/src/msgs/persist.rs @@ -313,7 +313,7 @@ pub struct ServerSessionValue { impl Codec<'_> for ServerSessionValue { fn encode(&self, bytes: &mut Vec) { - if let Some(ref sni) = self.sni { + if let Some(sni) = &self.sni { 1u8.encode(bytes); let sni_bytes: &str = sni.as_ref(); PayloadU8::new(Vec::from(sni_bytes)).encode(bytes); @@ -324,13 +324,13 @@ impl Codec<'_> for ServerSessionValue { self.cipher_suite.encode(bytes); self.master_secret.encode(bytes); (u8::from(self.extended_ms)).encode(bytes); - if let Some(ref chain) = self.client_cert_chain { + if let Some(chain) = &self.client_cert_chain { 1u8.encode(bytes); chain.encode(bytes); } else { 0u8.encode(bytes); } - if let Some(ref alpn) = self.alpn { + if let Some(alpn) = &self.alpn { 1u8.encode(bytes); alpn.encode(bytes); } else { diff --git a/rustls/src/server/hs.rs b/rustls/src/server/hs.rs index aafa2be1f63..3378e78d025 100644 --- a/rustls/src/server/hs.rs +++ b/rustls/src/server/hs.rs @@ -92,7 +92,7 @@ impl ExtensionProcessing { .iter() .find(|protocol| their_protocols.contains(&protocol.as_slice())) .cloned(); - if let Some(ref selected_protocol) = cx.common.alpn_protocol { + if let Some(selected_protocol) = &cx.common.alpn_protocol { debug!("Chosen ALPN protocol {:?}", selected_protocol); self.exts .push(ServerExtension::make_alpn(&[selected_protocol])); diff --git a/rustls/src/server/server_conn.rs b/rustls/src/server/server_conn.rs index 8108701e146..42cfa808cf2 100644 --- a/rustls/src/server/server_conn.rs +++ b/rustls/src/server/server_conn.rs @@ -1087,9 +1087,7 @@ impl EarlyDataState { #[cfg(read_buf)] fn read_buf(&mut self, cursor: core::io::BorrowedCursor<'_>) -> io::Result<()> { match self { - Self::Accepted { - ref mut received, .. - } => received.read_buf(cursor), + Self::Accepted { received, .. } => received.read_buf(cursor), _ => Err(io::Error::from(io::ErrorKind::BrokenPipe)), } } diff --git a/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index 89137bc30cc..b0908ca2e14 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -324,7 +324,7 @@ mod client_hello { self.send_tickets = self.config.send_tls13_tickets; } - if let Some(ref resume) = resumedata { + if let Some(resume) = &resumedata { cx.data.received_resumption_data = Some(resume.application_data.0.clone()); cx.common .peer_certificates @@ -865,7 +865,7 @@ impl State for ExpectAndSkipRejectedEarlyData { * 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(ref skip_data) = m.payload { + 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); From 70e2b1c779f324a331ed7394693571f122e4d28d Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 14 Mar 2025 09:46:53 +0000 Subject: [PATCH 096/403] Add warning about server-side cross-config resumption --- rustls/src/server/server_conn.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/rustls/src/server/server_conn.rs b/rustls/src/server/server_conn.rs index 42cfa808cf2..7b568a79a68 100644 --- a/rustls/src/server/server_conn.rs +++ b/rustls/src/server/server_conn.rs @@ -242,6 +242,31 @@ impl<'a> ClientHello<'a> { /// * [`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)] @@ -268,9 +293,15 @@ pub struct ServerConfig { pub max_fragment_size: Option, /// How to store client sessions. + /// + /// See [ServerConfig#sharing-resumption-storage-between-serverconfigs] + /// for a warning related to this field. pub session_storage: Arc, /// How to produce tickets. + /// + /// See [ServerConfig#sharing-resumption-storage-between-serverconfigs] + /// for a warning related to this field. pub ticketer: Arc, /// How to choose a server cert and key. This is usually set by From 3ab8a8ef9359cba2e711c4b07dfe8444e5f66f29 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Sat, 15 Mar 2025 13:45:14 +0000 Subject: [PATCH 097/403] Prepare 0.23.24 --- Cargo.lock | 56 +++++++++++++++++++++++------------------------ fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4278deee4ab..31765614dfa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -494,7 +494,7 @@ dependencies = [ "base64", "env_logger", "nix", - "rustls 0.23.23", + "rustls 0.23.24", "rustls-post-quantum", ] @@ -1362,7 +1362,7 @@ dependencies = [ "ipnet", "once_cell", "rand 0.9.0", - "rustls 0.23.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.23.23", "thiserror 2.0.12", "tinyvec", "tokio", @@ -1387,7 +1387,7 @@ dependencies = [ "parking_lot", "rand 0.9.0", "resolv-conf", - "rustls 0.23.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.23.23", "smallvec", "thiserror 2.0.12", "tokio", @@ -2581,6 +2581,21 @@ dependencies = [ [[package]] name = "rustls" version = "0.23.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.8", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls" +version = "0.23.24" dependencies = [ "aws-lc-rs", "base64", @@ -2609,27 +2624,12 @@ dependencies = [ "zlib-rs", ] -[[package]] -name = "rustls" -version = "0.23.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" -dependencies = [ - "log", - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki 0.102.8", - "subtle", - "zeroize", -] - [[package]] name = "rustls-bench" version = "0.1.0" dependencies = [ "clap", - "rustls 0.23.23", + "rustls 0.23.24", "rustls-post-quantum", "tikv-jemallocator", ] @@ -2646,7 +2646,7 @@ dependencies = [ "fxhash", "itertools 0.14.0", "rayon", - "rustls 0.23.23", + "rustls 0.23.24", "tikv-jemallocator", ] @@ -2657,7 +2657,7 @@ dependencies = [ "hickory-resolver", "regex", "ring", - "rustls 0.23.23", + "rustls 0.23.24", "tokio", ] @@ -2672,7 +2672,7 @@ dependencies = [ "log", "mio", "rcgen", - "rustls 0.23.23", + "rustls 0.23.24", "serde", "tokio", "webpki-roots", @@ -2683,7 +2683,7 @@ name = "rustls-fuzzing-provider" version = "0.1.0" dependencies = [ "env_logger", - "rustls 0.23.23", + "rustls 0.23.24", ] [[package]] @@ -2695,7 +2695,7 @@ dependencies = [ "num-bigint", "once_cell", "openssl", - "rustls 0.23.23", + "rustls 0.23.24", ] [[package]] @@ -2710,7 +2710,7 @@ version = "0.2.2" dependencies = [ "criterion", "env_logger", - "rustls 0.23.23", + "rustls 0.23.24", "webpki-roots", ] @@ -2731,7 +2731,7 @@ dependencies = [ "rand_core 0.6.4", "rcgen", "rsa", - "rustls 0.23.23", + "rustls 0.23.24", "sha2", "signature", "webpki-roots", @@ -2743,7 +2743,7 @@ name = "rustls-provider-test" version = "0.1.0" dependencies = [ "hex", - "rustls 0.23.23", + "rustls 0.23.24", "rustls-provider-example", "serde", "serde_json", @@ -3160,7 +3160,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "rustls 0.23.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.23.23", "tokio", ] diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 7b7af1ae2e6..14a1bd47d5c 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -224,7 +224,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.23" +version = "0.23.24" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 221a7990c07..dc416d3ae10 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.23" +version = "0.23.24" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From 317c5bfcf0dd61edfdc9d45c2fd2e4bcf8fe69dc Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Mon, 17 Mar 2025 13:36:16 +0100 Subject: [PATCH 098/403] Map webpki RequiredEkuNotFound error to InvalidPurpose --- rustls/src/webpki/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rustls/src/webpki/mod.rs b/rustls/src/webpki/mod.rs index 55566e978e8..65412d14ffa 100644 --- a/rustls/src/webpki/mod.rs +++ b/rustls/src/webpki/mod.rs @@ -91,6 +91,8 @@ fn pki_error(error: webpki::Error) -> Error { CertRevocationListError::BadSignature.into() } + RequiredEkuNotFound => CertificateError::InvalidPurpose.into(), + _ => CertificateError::Other(OtherError( #[cfg(feature = "std")] Arc::new(error), From 1e2b4f3c946ad159ee9774a14dec23c544603a49 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 17 Mar 2025 12:59:48 +0000 Subject: [PATCH 099/403] Prepare 0.23.25 --- Cargo.lock | 22 +++++++++++----------- fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 31765614dfa..bee92188adc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -494,7 +494,7 @@ dependencies = [ "base64", "env_logger", "nix", - "rustls 0.23.24", + "rustls 0.23.25", "rustls-post-quantum", ] @@ -2595,7 +2595,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.24" +version = "0.23.25" dependencies = [ "aws-lc-rs", "base64", @@ -2629,7 +2629,7 @@ name = "rustls-bench" version = "0.1.0" dependencies = [ "clap", - "rustls 0.23.24", + "rustls 0.23.25", "rustls-post-quantum", "tikv-jemallocator", ] @@ -2646,7 +2646,7 @@ dependencies = [ "fxhash", "itertools 0.14.0", "rayon", - "rustls 0.23.24", + "rustls 0.23.25", "tikv-jemallocator", ] @@ -2657,7 +2657,7 @@ dependencies = [ "hickory-resolver", "regex", "ring", - "rustls 0.23.24", + "rustls 0.23.25", "tokio", ] @@ -2672,7 +2672,7 @@ dependencies = [ "log", "mio", "rcgen", - "rustls 0.23.24", + "rustls 0.23.25", "serde", "tokio", "webpki-roots", @@ -2683,7 +2683,7 @@ name = "rustls-fuzzing-provider" version = "0.1.0" dependencies = [ "env_logger", - "rustls 0.23.24", + "rustls 0.23.25", ] [[package]] @@ -2695,7 +2695,7 @@ dependencies = [ "num-bigint", "once_cell", "openssl", - "rustls 0.23.24", + "rustls 0.23.25", ] [[package]] @@ -2710,7 +2710,7 @@ version = "0.2.2" dependencies = [ "criterion", "env_logger", - "rustls 0.23.24", + "rustls 0.23.25", "webpki-roots", ] @@ -2731,7 +2731,7 @@ dependencies = [ "rand_core 0.6.4", "rcgen", "rsa", - "rustls 0.23.24", + "rustls 0.23.25", "sha2", "signature", "webpki-roots", @@ -2743,7 +2743,7 @@ name = "rustls-provider-test" version = "0.1.0" dependencies = [ "hex", - "rustls 0.23.24", + "rustls 0.23.25", "rustls-provider-example", "serde", "serde_json", diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 14a1bd47d5c..5669575568c 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -224,7 +224,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.24" +version = "0.23.25" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index dc416d3ae10..fa9930bb7f3 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.24" +version = "0.23.25" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From e889744103d499fca1a599af64749d7abceea6ba Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Thu, 20 Mar 2025 11:49:17 +0100 Subject: [PATCH 100/403] Upgrade to hickory-resolver 0.25 --- Cargo.lock | 35 +++++++++++++++++----------------- Cargo.toml | 2 +- connect-tests/tests/ech.rs | 9 +++++++-- examples/src/bin/ech-client.rs | 6 ++++-- 4 files changed, 30 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bee92188adc..34bab480f8e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -772,6 +772,12 @@ dependencies = [ "itertools 0.10.5", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + [[package]] name = "crossbeam-channel" version = "0.5.14" @@ -1343,14 +1349,15 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hickory-proto" -version = "0.25.0-alpha.5" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d00147af6310f4392a31680db52a3ed45a2e0f68eb18e8c3fe5537ecc96d9e2" +checksum = "6d844af74f7b799e41c78221be863bade11c430d46042c3b49ca8ae0c6d27287" dependencies = [ "async-recursion", "async-trait", "bytes", "cfg-if", + "critical-section", "data-encoding", "enum-as-inner", "futures-channel", @@ -1362,6 +1369,7 @@ dependencies = [ "ipnet", "once_cell", "rand 0.9.0", + "ring", "rustls 0.23.23", "thiserror 2.0.12", "tinyvec", @@ -1374,9 +1382,9 @@ dependencies = [ [[package]] name = "hickory-resolver" -version = "0.25.0-alpha.5" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5762f69ebdbd4ddb2e975cd24690bf21fe6b2604039189c26acddbc427f12887" +checksum = "a128410b38d6f931fcc6ca5c107a3b02cabd6c05967841269a4ad65d23c44331" dependencies = [ "cfg-if", "futures-util", @@ -2025,6 +2033,10 @@ name = "once_cell" version = "1.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +dependencies = [ + "critical-section", + "portable-atomic", +] [[package]] name = "oorandom" @@ -2584,9 +2596,9 @@ version = "0.23.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" dependencies = [ + "aws-lc-rs", "log", "once_cell", - "ring", "rustls-pki-types", "rustls-webpki 0.102.8", "subtle", @@ -2755,6 +2767,7 @@ version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -3184,21 +3197,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", - "tracing-attributes", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.99", -] - [[package]] name = "tracing-core" version = "0.1.33" diff --git a/Cargo.toml b/Cargo.toml index 6d94452d556..7825d1bf955 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,7 +57,7 @@ env_logger = "0.11" fxhash = "0.2.1" hashbrown = { version = "0.15", default-features = false, features = ["default-hasher", "inline-more"] } hex = "0.4" -hickory-resolver = { version = "0.25.0-alpha.5", features = ["dns-over-https-rustls", "webpki-roots"] } +hickory-resolver = { version = "0.25", features = ["https-aws-lc-rs", "webpki-roots"] } hmac = "0.12" hpke-rs = "0.2" hpke-rs-crypto = "0.2" diff --git a/connect-tests/tests/ech.rs b/connect-tests/tests/ech.rs index 134eb8a610b..9b56eac2f28 100644 --- a/connect-tests/tests/ech.rs +++ b/connect-tests/tests/ech.rs @@ -1,5 +1,6 @@ mod ech_config { - use hickory_resolver::config::{ResolverConfig, ResolverOpts}; + use hickory_resolver::config::ResolverConfig; + use hickory_resolver::name_server::TokioConnectionProvider; use hickory_resolver::proto::rr::rdata::svcb::{SvcParamKey, SvcParamValue}; use hickory_resolver::proto::rr::{RData, RecordType}; use hickory_resolver::{Resolver, TokioResolver}; @@ -24,7 +25,11 @@ mod ech_config { /// Lookup the ECH config list for a domain and deserialize it. async fn test_deserialize_ech_config_list(domain: &str) { - let resolver = Resolver::tokio(ResolverConfig::google_https(), ResolverOpts::default()); + let resolver = Resolver::builder_with_config( + ResolverConfig::google_https(), + TokioConnectionProvider::default(), + ) + .build(); let tls_encoded_list = lookup_ech(&resolver, domain).await; let parsed_configs = Vec::::read(&mut Reader::init(&tls_encoded_list)) .expect("failed to deserialize ECH config list"); diff --git a/examples/src/bin/ech-client.rs b/examples/src/bin/ech-client.rs index 46cabdc1c7d..a8bf9896398 100644 --- a/examples/src/bin/ech-client.rs +++ b/examples/src/bin/ech-client.rs @@ -35,7 +35,8 @@ use std::net::{TcpStream, ToSocketAddrs}; use std::sync::Arc; use clap::Parser; -use hickory_resolver::config::{ResolverConfig, ResolverOpts}; +use hickory_resolver::config::ResolverConfig; +use hickory_resolver::name_server::TokioConnectionProvider; use hickory_resolver::proto::rr::rdata::svcb::{SvcParamKey, SvcParamValue}; use hickory_resolver::proto::rr::{RData, RecordType}; use hickory_resolver::{ResolveError, Resolver, TokioResolver}; @@ -68,7 +69,8 @@ async fn main() -> Result<(), Box> { ResolverConfig::google_https() }; lookup_ech_configs( - &Resolver::tokio(resolver_config, ResolverOpts::default()), + &Resolver::builder_with_config(resolver_config, TokioConnectionProvider::default()) + .build(), &args.inner_hostname, args.port, ) From 4ec06b638c427b333401af8b96f014a293e236df Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 20 Mar 2025 13:51:55 +0000 Subject: [PATCH 101/403] Pin cargo-hack@0.6.33 for now --- .github/workflows/daily-tests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/daily-tests.yml b/.github/workflows/daily-tests.yml index f3f52c1c66b..c6866d44385 100644 --- a/.github/workflows/daily-tests.yml +++ b/.github/workflows/daily-tests.yml @@ -145,7 +145,9 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: Install cargo hack - uses: taiki-e/install-action@cargo-hack + uses: taiki-e/install-action@v2 + with: + tool: cargo-hack@0.6.33 - name: Check feature powerset run: > From 293f05e9d1011132a749b8b6e0435f701421fd01 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 20 Mar 2025 18:12:51 +0000 Subject: [PATCH 102/403] Revert "Pin cargo-hack@0.6.33 for now" This reverts commit 4ec06b638c427b333401af8b96f014a293e236df. --- .github/workflows/daily-tests.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/daily-tests.yml b/.github/workflows/daily-tests.yml index c6866d44385..f3f52c1c66b 100644 --- a/.github/workflows/daily-tests.yml +++ b/.github/workflows/daily-tests.yml @@ -145,9 +145,7 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: Install cargo hack - uses: taiki-e/install-action@v2 - with: - tool: cargo-hack@0.6.33 + uses: taiki-e/install-action@cargo-hack - name: Check feature powerset run: > From bdb303696dea02ecc6b5de3907880e181899d717 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 24 Mar 2025 01:41:04 +0000 Subject: [PATCH 103/403] chore(deps): lock file maintenance --- Cargo.lock | 401 ++++++++++++++++++++++++------------------------ fuzz/Cargo.lock | 122 +++++++++++++-- 2 files changed, 307 insertions(+), 216 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 34bab480f8e..80e552f0aad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -150,9 +150,9 @@ dependencies = [ [[package]] name = "asn1-rs" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "607495ec7113b178fbba7a6166a27f99e774359ef4823adbefd756b5b81d7970" +checksum = "56624a96882bb8c26d61312ae18cb45868e5a9992ea73c58e45c3101e56a1e60" dependencies = [ "asn1-rs-derive", "asn1-rs-impl", @@ -172,7 +172,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "synstructure", ] @@ -184,7 +184,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -195,7 +195,7 @@ checksum = "67c7e14dc2fafd01c4c68c054e128b770d5a4a07b04d76bfaedca40dce3cb2c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -297,14 +297,14 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] name = "async-std" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" +checksum = "730294c1c08c2e0f85759590518f6333f0d5a0a766a27d519c1b244c3dfd8a24" dependencies = [ "async-attributes", "async-channel 1.9.0", @@ -335,13 +335,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.87" +version = "0.1.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d556ec1359574147ec0c4fc5eb525f3f23263a592b1a9c07e0a75b427de55c97" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -358,43 +358,40 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-fips-sys" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29003a681b2b9465c1139bfb726da452a841a8b025f35953f3bce71139f10b21" +checksum = "7c6f97c07b7eb57063d9f62cbb5638bcdf699888f8e9febd07a88b156c4b05bb" dependencies = [ "bindgen", "cc", "cmake", "dunce", "fs_extra", - "paste", "regex", ] [[package]] name = "aws-lc-rs" -version = "1.12.5" +version = "1.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e4e8200b9a4a5801a769d50eeabc05670fec7e959a8cb7a63a93e4e519942ae" +checksum = "dabb68eb3a7aa08b46fddfd59a3d55c978243557a90ab804769f7e20e67d2b01" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", - "paste", "zeroize", ] [[package]] name = "aws-lc-sys" -version = "0.26.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f9dd2e03ee80ca2822dd6ea431163d2ef259f2066a4d6ccaca6d9dcb386aa43" +checksum = "77926887776171ced7d662120a75998e444d3750c951abfe07f90da130514b1f" dependencies = [ "bindgen", "cc", "cmake", "dunce", "fs_extra", - "paste", ] [[package]] @@ -426,9 +423,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.6.0" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" [[package]] name = "bencher" @@ -455,7 +452,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.99", + "syn 2.0.100", "which", ] @@ -545,9 +542,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.16" +version = "1.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" dependencies = [ "jobserver", "libc", @@ -650,9 +647,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.31" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767" +checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83" dependencies = [ "clap_builder", "clap_derive", @@ -660,9 +657,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.31" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863" +checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8" dependencies = [ "anstream", "anstyle", @@ -672,14 +669,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.28" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" +checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -872,7 +869,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -907,9 +904,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.11" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "28cfac68e08048ae1883171632c2aef3ebc555621ae56fbccce1cbf22dd7f058" dependencies = [ "powerfmt", ] @@ -934,7 +931,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -992,7 +989,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -1007,14 +1004,14 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.6" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" +checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" dependencies = [ "anstream", "anstyle", "env_filter", - "humantime", + "jiff", "log", ] @@ -1069,9 +1066,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "ff" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ "rand_core 0.6.4", "subtle", @@ -1091,9 +1088,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "foreign-types" @@ -1203,7 +1200,7 @@ dependencies = [ "libc", "log", "rustversion", - "windows", + "windows 0.58.0", ] [[package]] @@ -1230,14 +1227,14 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" dependencies = [ "cfg-if", "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets 0.52.6", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] @@ -1306,9 +1303,9 @@ dependencies = [ [[package]] name = "half" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +checksum = "7db2ff139bba50379da6aa0766b52fdcb62cb5b263009b09ed58ba604e14bbd1" dependencies = [ "cfg-if", "crunchy", @@ -1370,7 +1367,7 @@ dependencies = [ "once_cell", "rand 0.9.0", "ring", - "rustls 0.23.23", + "rustls 0.23.25 (registry+https://github.com/rust-lang/crates.io-index)", "thiserror 2.0.12", "tinyvec", "tokio", @@ -1395,7 +1392,7 @@ dependencies = [ "parking_lot", "rand 0.9.0", "resolv-conf", - "rustls 0.23.23", + "rustls 0.23.25 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec", "thiserror 2.0.12", "tokio", @@ -1433,13 +1430,13 @@ dependencies = [ [[package]] name = "hostname" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" dependencies = [ + "cfg-if", "libc", - "match_cfg", - "winapi", + "windows 0.52.0", ] [[package]] @@ -1482,21 +1479,15 @@ dependencies = [ [[package]] name = "http" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", "itoa", ] -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "icu_collections" version = "1.5.0" @@ -1612,7 +1603,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -1638,9 +1629,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" dependencies = [ "equivalent", "hashbrown", @@ -1723,6 +1714,30 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "jiff" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c102670231191d07d37a35af3eb77f1f0dbf7a71be51a962dcd57ea607be7260" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cdde31a9d349f1b1f51a0b3714a5940ac022976f4b49485fc04be052b183b4c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + [[package]] name = "jobserver" version = "0.1.32" @@ -1768,9 +1783,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.170" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "libloading" @@ -1848,12 +1863,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8dd856d451cc0da70e2ef2ce95a18e39a93b7558bedf10201ad28503f918568" -[[package]] -name = "match_cfg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" - [[package]] name = "matchers" version = "0.1.0" @@ -2030,9 +2039,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" dependencies = [ "critical-section", "portable-atomic", @@ -2040,9 +2049,9 @@ dependencies = [ [[package]] name = "oorandom" -version = "11.1.4" +version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "opaque-debug" @@ -2073,7 +2082,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2289,6 +2298,15 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" +[[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" @@ -2297,21 +2315,21 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.7.35", + "zerocopy", ] [[package]] name = "prettyplease" -version = "0.2.30" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1ccf34da56fc294e7d4ccf69a85992b7dfb826b7cf57bac6a70bba3494cc08a" +checksum = "5316f57387668042f561aae71480de936257848f9c43ce528e311d89a07cadeb" dependencies = [ "proc-macro2", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2332,21 +2350,21 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - [[package]] name = "quote" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" +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 = "rand" version = "0.8.5" @@ -2365,7 +2383,7 @@ checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", - "zerocopy 0.8.23", + "zerocopy", ] [[package]] @@ -2403,7 +2421,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.1", + "getrandom 0.3.2", ] [[package]] @@ -2494,12 +2512,11 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "resolv-conf" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +checksum = "48375394603e3dd4b2d64371f7148fd8c7baa2680e28741f2cb8d23b59e3d4c4" dependencies = [ "hostname", - "quick-error", ] [[package]] @@ -2514,9 +2531,9 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.13" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", @@ -2528,9 +2545,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" +checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" dependencies = [ "const-oid", "digest", @@ -2590,21 +2607,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "rustls" -version = "0.23.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" -dependencies = [ - "aws-lc-rs", - "log", - "once_cell", - "rustls-pki-types", - "rustls-webpki 0.102.8", - "subtle", - "zeroize", -] - [[package]] name = "rustls" version = "0.23.25" @@ -2624,7 +2626,7 @@ dependencies = [ "rcgen", "ring", "rustls-pki-types", - "rustls-webpki 0.103.0", + "rustls-webpki", "rustversion", "serde", "serde_json", @@ -2636,6 +2638,21 @@ dependencies = [ "zlib-rs", ] +[[package]] +name = "rustls" +version = "0.23.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" +dependencies = [ + "aws-lc-rs", + "log", + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-bench" version = "0.1.0" @@ -2761,18 +2778,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "rustls-webpki" -version = "0.102.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" -dependencies = [ - "aws-lc-rs", - "ring", - "rustls-pki-types", - "untrusted", -] - [[package]] name = "rustls-webpki" version = "0.103.0" @@ -2840,22 +2845,22 @@ checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2978,9 +2983,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.99" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -2995,7 +3000,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3030,7 +3035,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3041,7 +3046,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3076,9 +3081,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.39" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad298b01a40a23aac4580b67e3dbedb7cc8402f3592d7f49469de2ea4aecdd8" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", @@ -3091,15 +3096,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.20" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", @@ -3142,9 +3147,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.43.0" +version = "1.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" +checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" dependencies = [ "backtrace", "bytes", @@ -3164,7 +3169,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3173,15 +3178,15 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "rustls 0.23.23", + "rustls 0.23.25 (registry+https://github.com/rust-lang/crates.io-index)", "tokio", ] [[package]] name = "tokio-util" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" +checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" dependencies = [ "bytes", "futures-core", @@ -3298,11 +3303,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.15.1" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" +checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" dependencies = [ - "getrandom 0.3.1", + "getrandom 0.3.2", ] [[package]] @@ -3347,9 +3352,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi" -version = "0.13.3+wasi-0.2.2" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] @@ -3376,7 +3381,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "wasm-bindgen-shared", ] @@ -3411,7 +3416,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3458,9 +3463,9 @@ dependencies = [ [[package]] name = "widestring" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" +checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d" [[package]] name = "winapi" @@ -3493,13 +3498,32 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core 0.52.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows" version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" dependencies = [ - "windows-core", + "windows-core 0.58.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ "windows-targets 0.52.6", ] @@ -3524,7 +3548,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3535,7 +3559,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3717,9 +3741,9 @@ dependencies = [ [[package]] name = "wit-bindgen-rt" -version = "0.33.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ "bitflags", ] @@ -3794,49 +3818,28 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "synstructure", ] [[package]] name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive 0.7.35", -] - -[[package]] -name = "zerocopy" -version = "0.8.23" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" dependencies = [ - "zerocopy-derive 0.8.23", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.99", + "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.23" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3856,7 +3859,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "synstructure", ] @@ -3877,7 +3880,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3899,7 +3902,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 5669575568c..0d246d9d5d7 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -69,9 +69,9 @@ checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" [[package]] name = "cc" -version = "1.2.16" +version = "1.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" dependencies = [ "jobserver", "libc", @@ -102,14 +102,14 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.6" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" +checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" dependencies = [ "anstream", "anstyle", "env_filter", - "humantime", + "jiff", "log", ] @@ -124,18 +124,36 @@ dependencies = [ "wasi", ] -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "is_terminal_polyfill" version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "jiff" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c102670231191d07d37a35af3eb77f1f0dbf7a71be51a962dcd57ea607be7260" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cdde31a9d349f1b1f51a0b3714a5940ac022976f4b49485fc04be052b183b4c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "jobserver" version = "0.1.32" @@ -147,9 +165,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.170" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "libfuzzer-sys" @@ -175,9 +193,42 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" + +[[package]] +name = "portable-atomic" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" + +[[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 = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +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 = "regex" @@ -210,9 +261,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "ring" -version = "0.17.13" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", @@ -268,6 +319,26 @@ dependencies = [ "untrusted", ] +[[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 = "shlex" version = "1.3.0" @@ -280,6 +351,23 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "syn" +version = "2.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[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" From e1cffa0c8b0769e2441218838cd4255415908108 Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Tue, 1 Apr 2025 15:30:58 -0400 Subject: [PATCH 104/403] Cargo: update aws-lc-fips-sys 0.13.4 -> 0.13.5 --- Cargo.lock | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 80e552f0aad..87810deb2a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -358,9 +358,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-fips-sys" -version = "0.13.4" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c6f97c07b7eb57063d9f62cbb5638bcdf699888f8e9febd07a88b156c4b05bb" +checksum = "2d9c2e952a1f57e8cbc78b058a968639e70c4ce8b9c0a5e6363d4e5670eed795" dependencies = [ "bindgen", "cc", @@ -442,7 +442,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools 0.10.5", "lazy_static", "lazycell", "log", @@ -1028,7 +1028,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -1672,7 +1672,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ "hermit-abi 0.5.0", "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -1690,15 +1690,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.14.0" @@ -1794,7 +1785,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] @@ -2604,7 +2595,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -3489,7 +3480,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] From 249519230b15eb05eed27be72e3afeb80d1cf34b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 1 Apr 2025 20:27:06 +0000 Subject: [PATCH 105/403] chore(deps): update rust crate zlib-rs to 0.5 --- Cargo.lock | 14 +++++++------- Cargo.toml | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 87810deb2a6..8d5b132b4a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1028,7 +1028,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1672,7 +1672,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ "hermit-abi 0.5.0", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1785,7 +1785,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -2595,7 +2595,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3480,7 +3480,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -3898,6 +3898,6 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b20717f0917c908dc63de2e44e97f1e6b126ca58d0e391cee86d504eb8fbd05" +checksum = "868b928d7949e09af2f6086dfc1e01936064cc7a819253bce650d4e2a2d63ba8" diff --git a/Cargo.toml b/Cargo.toml index 7825d1bf955..61e177c9bc3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -91,7 +91,7 @@ webpki-roots = "0.26" x25519-dalek = "2" x509-parser = "0.17" zeroize = "1.7" -zlib-rs = "0.4" +zlib-rs = "0.5" [profile.bench] codegen-units = 1 From beb8390053751ad023c69650d99017d88ab634ff Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 2 Apr 2025 06:01:02 +0000 Subject: [PATCH 106/403] chore(deps): update dependency go to v1.24.2 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 30e2985de8c..c38542c6039 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -68,7 +68,7 @@ jobs: if: runner.os == 'MacOS' uses: actions/setup-go@v5 with: - go-version: "1.24.1" + go-version: "1.24.2" - name: cargo build (debug; default features) run: cargo build --locked From 66e4c27ffbc47e73c2d4677620a7b6ef5dc5c378 Mon Sep 17 00:00:00 2001 From: xixishidibei Date: Wed, 2 Apr 2025 22:02:44 +0800 Subject: [PATCH 107/403] chore: fix some typos Signed-off-by: xixishidibei --- .clippy.toml | 4 ++-- rustls/src/lib.rs | 2 +- rustls/tests/api.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.clippy.toml b/.clippy.toml index 779a21d1dd9..6b6a85a00c8 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -2,6 +2,6 @@ upper-case-acronyms-aggressive = true # only intended to affect main rustls crate - need to allow disallowed-types in all other crates in Clippy CI job disallowed-types = [ - { path = "std::sync::Arc", reason = "must use Arc from sync module to support downstream forks targetting architectures without atomic ptrs" }, - { path = "std::sync::Weak", reason = "must use Weak from sync module to support downstream forks targetting architectures without atomic ptrs" }, + { path = "std::sync::Arc", reason = "must use Arc from sync module to support downstream forks targeting architectures without atomic ptrs" }, + { path = "std::sync::Weak", reason = "must use Weak from sync module to support downstream forks targeting architectures without atomic ptrs" }, ] diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 74bb61e1d19..9fad5db7b3a 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -416,7 +416,7 @@ mod log { mod test_macros; /// This internal `sync` module aliases the `Arc` implementation to allow downstream forks -/// of rustls targetting architectures without atomic pointers to replace the implementation +/// 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)] diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 168256178f5..91b24a6cc0d 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -401,7 +401,7 @@ mod test_raw_keys { } Payload::new(parsed.get_encoding()) } else { - panic!("Expected to succesfully encode handshake message"); + panic!("Expected to successfully encode handshake message"); }; // // Re-encrypt From 75ab55b9e44766c7af399c57436808d6961db265 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Thu, 3 Apr 2025 09:59:01 +0200 Subject: [PATCH 108/403] Add cargo deny check in CI --- .github/workflows/build.yml | 6 ++++++ bogo/Cargo.toml | 1 + deny.toml | 10 ++++++++++ rustls-bench/Cargo.toml | 1 + 4 files changed, 18 insertions(+) create mode 100644 deny.toml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c38542c6039..c346bb17e25 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -590,3 +590,9 @@ jobs: run: cargo test --locked -- --include-ignored env: RUST_BACKTRACE: 1 + + audit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: EmbarkStudios/cargo-deny-action@v2 diff --git a/bogo/Cargo.toml b/bogo/Cargo.toml index f8831396c82..4393b17e464 100644 --- a/bogo/Cargo.toml +++ b/bogo/Cargo.toml @@ -2,6 +2,7 @@ name = "bogo" version = "0.1.0" edition = "2021" +publish = false [dependencies] base64 = { workspace = true } diff --git a/deny.toml b/deny.toml new file mode 100644 index 00000000000..71198518908 --- /dev/null +++ b/deny.toml @@ -0,0 +1,10 @@ +[licenses] +version = 2 +allow = ["Apache-2.0", "BSD-3-Clause", "ISC", "MIT", "MPL-2.0", "OpenSSL", "Unicode-3.0", "Zlib"] +private = { ignore = true } + +[advisories] +ignore = [ + "RUSTSEC-2023-0071", # Marvin Attack on rsa, dev-dependency only + "RUSTSEC-2024-0436", # Unmaintained paste via macro_rules_attributes; dev-dependency only +] diff --git a/rustls-bench/Cargo.toml b/rustls-bench/Cargo.toml index 989c75ba807..36f70198b1d 100644 --- a/rustls-bench/Cargo.toml +++ b/rustls-bench/Cargo.toml @@ -2,6 +2,7 @@ name = "rustls-bench" version = "0.1.0" edition = "2021" +publish = false [dependencies] clap = { workspace = true } From d3b810d6b68a2bb2c06dde4fc62b2c2b276b9503 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 20:55:25 +0000 Subject: [PATCH 109/403] build(deps): bump openssl from 0.10.71 to 0.10.72 Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.71 to 0.10.72. - [Release notes](https://github.com/sfackler/rust-openssl/releases) - [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.71...openssl-v0.10.72) --- updated-dependencies: - dependency-name: openssl dependency-version: 0.10.72 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8d5b132b4a3..87a06aac176 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2052,9 +2052,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.71" +version = "0.10.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" +checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" dependencies = [ "bitflags", "cfg-if", @@ -2078,9 +2078,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.106" +version = "0.9.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" +checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" dependencies = [ "cc", "libc", From c1fc0f424c5600998dd3503fd512ff8a4af8de07 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 7 Apr 2025 12:06:17 +0100 Subject: [PATCH 110/403] Take semver-compatible updates --- Cargo.lock | 108 +++++++++++++++++++++++++++++------------------------ 1 file changed, 59 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 87a06aac176..47ceeaf42be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -372,9 +372,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.12.6" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dabb68eb3a7aa08b46fddfd59a3d55c978243557a90ab804769f7e20e67d2b01" +checksum = "19b756939cb2f8dc900aa6dcd505e6e2428e9cae7ff7b028c49e3946efa70878" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", @@ -383,9 +383,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.27.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77926887776171ced7d662120a75998e444d3750c951abfe07f90da130514b1f" +checksum = "b9f7720b74ed28ca77f90769a71fd8c637a0137f6fae4ae947e1050229cff57f" dependencies = [ "bindgen", "cc", @@ -442,7 +442,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "itertools 0.10.5", + "itertools 0.12.1", "lazy_static", "lazycell", "log", @@ -542,9 +542,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.17" +version = "1.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" +checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c" dependencies = [ "jobserver", "libc", @@ -647,9 +647,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.32" +version = "4.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83" +checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944" dependencies = [ "clap_builder", "clap_derive", @@ -657,9 +657,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.32" +version = "4.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8" +checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9" dependencies = [ "anstream", "anstyle", @@ -904,9 +904,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.4.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cfac68e08048ae1883171632c2aef3ebc555621ae56fbccce1cbf22dd7f058" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", ] @@ -1004,9 +1004,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.7" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" dependencies = [ "anstream", "anstyle", @@ -1023,9 +1023,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", "windows-sys 0.59.0", @@ -1050,9 +1050,9 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ "event-listener 5.4.0", "pin-project-lite", @@ -1529,9 +1529,9 @@ dependencies = [ [[package]] name = "icu_locid_transform_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" +checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" [[package]] name = "icu_normalizer" @@ -1553,9 +1553,9 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" [[package]] name = "icu_properties" @@ -1574,9 +1574,9 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" [[package]] name = "icu_provider" @@ -1629,9 +1629,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown", @@ -1690,6 +1690,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.14.0" @@ -1731,10 +1740,11 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ + "getrandom 0.3.2", "libc", ] @@ -1818,9 +1828,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" dependencies = [ "value-bag", ] @@ -1877,9 +1887,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430" dependencies = [ "adler2", ] @@ -2030,9 +2040,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.1" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" dependencies = [ "critical-section", "portable-atomic", @@ -2315,9 +2325,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.31" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5316f57387668042f561aae71480de936257848f9c43ce528e311d89a07cadeb" +checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" dependencies = [ "proc-macro2", "syn 2.0.100", @@ -2450,9 +2460,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" dependencies = [ "bitflags", ] @@ -2771,9 +2781,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.0" +version = "0.103.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa4eeac2588ffff23e9d7a7e9b3f971c5fb5b7ebc9452745e0c232c64f83b2f" +checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" dependencies = [ "aws-lc-rs", "ring", @@ -2913,15 +2923,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" [[package]] name = "socket2" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3138,9 +3148,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.44.1" +version = "1.44.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" +checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" dependencies = [ "backtrace", "bytes", @@ -3309,9 +3319,9 @@ checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "value-bag" -version = "1.10.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" +checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" [[package]] name = "vcpkg" From 68d6ef21eba3b518c44e3b27de9b06fadfbf819d Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 8 Apr 2025 12:53:58 +0100 Subject: [PATCH 111/403] Use tlswg name for draft-kwiatkowski-tls-ecdhe-mlkem --- rustls/src/crypto/aws_lc_rs/pq/mod.rs | 2 +- rustls/src/manual/defaults.rs | 2 +- rustls/src/manual/features.rs | 2 +- website/content/perf/2024-12-17-pq-kx/index.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rustls/src/crypto/aws_lc_rs/pq/mod.rs b/rustls/src/crypto/aws_lc_rs/pq/mod.rs index 86bd686259c..ecb5ab3bf83 100644 --- a/rustls/src/crypto/aws_lc_rs/pq/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/pq/mod.rs @@ -7,7 +7,7 @@ mod mlkem; /// This is the [X25519MLKEM768] key exchange. /// -/// [X25519MLKEM768]: +/// [X25519MLKEM768]: pub static X25519MLKEM768: &dyn SupportedKxGroup = &hybrid::Hybrid { classical: kx_group::X25519, post_quantum: MLKEM768, diff --git a/rustls/src/manual/defaults.rs b/rustls/src/manual/defaults.rs index 746bf2aed23..f6f70dc05f5 100644 --- a/rustls/src/manual/defaults.rs +++ b/rustls/src/manual/defaults.rs @@ -59,7 +59,7 @@ by default out of conservatism. do not currently exist, and may never exist, but current traffic could be captured now and attacked later. -[X25519MLKEM768]: +[X25519MLKEM768]: [`X25519MLKEM768`]: crate::crypto::aws_lc_rs::kx_group::X25519MLKEM768 [`MLKEM768`]: crate::crypto::aws_lc_rs::kx_group::MLKEM768 [FIPS203]: diff --git a/rustls/src/manual/features.rs b/rustls/src/manual/features.rs index d8b85d61402..69daf48ace5 100644 --- a/rustls/src/manual/features.rs +++ b/rustls/src/manual/features.rs @@ -12,7 +12,7 @@ APIs ([`CryptoProvider`] for example). * 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-kwiatkowski-tls-ecdhe-mlkem/) [^2] `*` +* 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 diff --git a/website/content/perf/2024-12-17-pq-kx/index.md b/website/content/perf/2024-12-17-pq-kx/index.md index 29da8f00f4f..2c2ae277492 100644 --- a/website/content/perf/2024-12-17-pq-kx/index.md +++ b/website/content/perf/2024-12-17-pq-kx/index.md @@ -78,7 +78,7 @@ It's therefore advantageous for a client to avoid `HelloRetryRequest`s, by: [draft-ietf-tls-key-share-prediction]: https://datatracker.ietf.org/doc/draft-ietf-tls-key-share-prediction/ [X25519]: https://datatracker.ietf.org/doc/html/rfc7748 [ML-KEM]: https://csrc.nist.gov/pubs/fips/203/final -[X25519MLKEM768]: https://datatracker.ietf.org/doc/draft-kwiatkowski-tls-ecdhe-mlkem/02/ +[X25519MLKEM768]: https://datatracker.ietf.org/doc/draft-ietf-tls-ecdhe-mlkem/ [Xeon E-2386G]: https://www.intel.com/content/www/us/en/products/sku/214806/intel-xeon-e2386g-processor-12m-cache-3-50-ghz/specifications.html [draft-ietf-tls-hybrid-design]: https://www.ietf.org/archive/id/draft-ietf-tls-hybrid-design-11.html#name-transmitting-public-keys-an From 334760fb0682d86dc2559f6a9b95bd95f69b09c2 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 8 Apr 2025 14:13:04 +0100 Subject: [PATCH 112/403] Invert working of `SignatureScheme::supported_in_tls13` This was previously an allow-list, which stands in the way of people shipping providers for other algorithms that are not specifically outlawed in RFC8446. --- rustls/src/enums.rs | 73 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/rustls/src/enums.rs b/rustls/src/enums.rs index 0dc0e356666..a2997ec56e3 100644 --- a/rustls/src/enums.rs +++ b/rustls/src/enums.rs @@ -1,6 +1,7 @@ #![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 @@ -542,17 +543,35 @@ impl SignatureScheme { /// 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. + /// See RFC8446 s4.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 { - matches!( - *self, - Self::ECDSA_NISTP521_SHA512 - | Self::ECDSA_NISTP384_SHA384 - | Self::ECDSA_NISTP256_SHA256 - | Self::RSA_PSS_SHA512 - | Self::RSA_PSS_SHA384 - | Self::RSA_PSS_SHA256 - | Self::ED25519 + 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 ) } } @@ -617,4 +636,38 @@ mod tests { CertificateCompressionAlgorithm::Zstd, ); } + + #[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()); + } } From 99db311d7e80b14528031b1cbb40e03515fdf6c8 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 9 Apr 2025 14:51:28 +0100 Subject: [PATCH 113/403] Replace hand-written encodings with `encoding` module --- rustls/tests/api.rs | 37 +++++++++++++++++++++++++++++++------ rustls/tests/common/mod.rs | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 91b24a6cc0d..c17e5f85eb7 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -6450,7 +6450,11 @@ fn test_client_rejects_illegal_tls13_ccs() { fn corrupt_ccs(msg: &mut Message) -> Altered { if let MessagePayload::ChangeCipherSpec(_) = &mut msg.payload { println!("seen CCS {:?}", msg); - return Altered::Raw(vec![0x14, 0x03, 0x03, 0x00, 0x02, 0x01, 0x02]); + return Altered::Raw(encoding::message_framing( + ContentType::ChangeCipherSpec, + ProtocolVersion::TLSv1_2, + vec![0x01, 0x02], + )); } Altered::InPlace } @@ -6706,7 +6710,14 @@ fn test_acceptor() { let mut acceptor = Acceptor::default(); // Minimal valid 1-byte application data message is not a handshake message acceptor - .read_tls(&mut [0x17, 0x03, 0x03, 0x00, 0x01, 0x00].as_ref()) + .read_tls( + &mut encoding::message_framing( + ContentType::ApplicationData, + ProtocolVersion::TLSv1_2, + vec![0x00], + ) + .as_slice(), + ) .unwrap(); let (err, mut alert) = acceptor.accept().unwrap_err(); assert!(matches!(err, Error::InappropriateMessage { .. })); @@ -6717,7 +6728,14 @@ fn test_acceptor() { let mut acceptor = Acceptor::default(); // Minimal 1-byte ClientHello message is not a legal handshake message acceptor - .read_tls(&mut [0x16, 0x03, 0x03, 0x00, 0x05, 0x01, 0x00, 0x00, 0x01, 0x00].as_ref()) + .read_tls( + &mut encoding::message_framing( + ContentType::Handshake, + ProtocolVersion::TLSv1_2, + encoding::handshake_framing(HandshakeType::ClientHello, vec![0x00]), + ) + .as_slice(), + ) .unwrap(); let (err, mut alert) = acceptor.accept().unwrap_err(); assert!(matches!( @@ -7261,9 +7279,16 @@ fn test_client_removes_tls12_session_if_server_sends_undecryptable_first_message fn inject_corrupt_finished_message(msg: &mut Message) -> Altered { if let MessagePayload::ChangeCipherSpec(_) = msg.payload { // interdict "real" ChangeCipherSpec with its encoding, plus a faulty encrypted Finished. - let mut raw_change_cipher_spec = [0x14u8, 0x03, 0x03, 0x00, 0x01, 0x01].to_vec(); - let mut corrupt_finished = [0x16, 0x03, 0x03, 0x00, 0x28].to_vec(); - corrupt_finished.extend([0u8; 0x28]); + let mut raw_change_cipher_spec = encoding::message_framing( + ContentType::ChangeCipherSpec, + ProtocolVersion::TLSv1_2, + vec![0x01], + ); + let mut corrupt_finished = encoding::message_framing( + ContentType::Handshake, + ProtocolVersion::TLSv1_2, + vec![0u8; 0x28], + ); let mut both = vec![]; both.append(&mut raw_change_cipher_spec); diff --git a/rustls/tests/common/mod.rs b/rustls/tests/common/mod.rs index dd84391c7c4..044256b6881 100644 --- a/rustls/tests/common/mod.rs +++ b/rustls/tests/common/mod.rs @@ -1477,3 +1477,40 @@ mod plaintext { } } } + +/// Deeply inefficient, test-only TLS encoding helpers +pub mod encoding { + use rustls::{ContentType, HandshakeType, ProtocolVersion}; + + /// Apply handshake framing to `body`. + /// + /// This does not do fragmentation. + pub fn handshake_framing(ty: HandshakeType, body: Vec) -> Vec { + let mut body = len_u24(body); + body.splice(0..0, ty.to_array()); + body + } + + /// Apply message framing to `body`. + pub fn message_framing(ty: ContentType, vers: ProtocolVersion, body: Vec) -> Vec { + let mut body = len_u16(body); + body.splice(0..0, vers.to_array()); + body.splice(0..0, ty.to_array()); + body + } + + /// Prefix with u16 length + pub fn len_u16(mut body: Vec) -> Vec { + body.splice(0..0, (body.len() as u16).to_be_bytes()); + body + } + + /// Prefix with u24 length + pub fn len_u24(mut body: Vec) -> Vec { + let len = (body.len() as u32).to_be_bytes(); + body.insert(0, len[1]); + body.insert(1, len[2]); + body.insert(2, len[3]); + body + } +} From 0f3c823f7569c962c6b3c5f16593be122134e051 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 9 Apr 2025 15:01:06 +0100 Subject: [PATCH 114/403] Rework SNI tests to use new test-only TLS encoder --- rustls/src/lib.rs | 4 +- rustls/tests/api.rs | 130 ++++++++------------------------- rustls/tests/common/mod.rs | 144 ++++++++++++++++++++++++++++++++++++- 3 files changed, 176 insertions(+), 102 deletions(-) diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 9fad5db7b3a..72d57e7d15b 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -476,8 +476,8 @@ pub mod internal { } pub mod enums { pub use crate::msgs::enums::{ - AlertLevel, CertificateType, Compression, EchVersion, HpkeAead, HpkeKdf, HpkeKem, - NamedGroup, + AlertLevel, CertificateType, Compression, EchVersion, ExtensionType, HpkeAead, + HpkeKdf, HpkeKem, NamedGroup, }; } pub mod fragmenter { diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index c17e5f85eb7..013106acd61 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -15,10 +15,10 @@ use rustls::client::{ResolvesClientCert, Resumption, verify_server_cert_signed_b use rustls::crypto::{ActiveKeyExchange, CryptoProvider, SharedSecret, SupportedKxGroup}; use rustls::internal::msgs::base::Payload; use rustls::internal::msgs::codec::Codec; -use rustls::internal::msgs::enums::{AlertLevel, CertificateType, Compression}; +use rustls::internal::msgs::enums::{AlertLevel, CertificateType, Compression, ExtensionType}; use rustls::internal::msgs::handshake::{ ClientExtension, ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, Random, - ServerExtension, ServerName as ServerNameExtensionItem, SessionId, + ServerExtension, SessionId, }; use rustls::internal::msgs::message::{Message, MessagePayload, PlainMessage}; use rustls::server::{ClientHello, ParsedCertificate, ResolvesServerCert}; @@ -1518,87 +1518,39 @@ fn client_trims_terminating_dot() { #[test] fn server_ignores_sni_with_ip_address() { - fn insert_ip_address_server_name(msg: &mut Message) -> Altered { - alter_sni_extension( - msg, - |snr| { - snr.clear(); - snr.push(ServerNameExtensionItem::read_bytes(b"\x00\x00\x071.1.1.1").unwrap()); - }, - |parsed, _encoded| Payload::new(parsed.get_encoding()), - ) - } - check_sni_error( - insert_ip_address_server_name, + encoding::Extension::new_sni(b"1.1.1.1"), Error::General("no server certificate chain resolved".to_string()), ); } #[test] fn server_rejects_sni_with_illegal_dns_name() { - fn insert_illegal_server_name(msg: &mut Message) -> Altered { - alter_sni_extension( - msg, - |_| (), - |_, encoded| { - // replace "localhost" with invalid DNS name - let mut altered = encoded.clone().into_vec(); - let needle = b"localhost"; - let index = altered - .windows(needle.len()) - .position(|window| window == needle) - .unwrap(); - altered[index..index + needle.len()].copy_from_slice(b"ab@cd.com"); - Payload::new(altered) - }, - ) - } - check_sni_error( - insert_illegal_server_name, + encoding::Extension::new_sni(b"ab@cd.com"), Error::InvalidMessage(InvalidMessage::InvalidServerName), ); } -fn alter_sni_extension( - msg: &mut Message, - alter_inner: impl Fn(&mut Vec), - alter_encoding: impl Fn(&mut HandshakeMessagePayload, &mut Payload) -> Payload<'static>, -) -> Altered { - if let MessagePayload::Handshake { parsed, encoded } = &mut msg.payload { - if let HandshakePayload::ClientHello(ch) = &mut parsed.payload { - for mut ext in ch.extensions.iter_mut() { - if let ClientExtension::ServerName(snr) = &mut ext { - alter_inner(snr); - } - } - *encoded = alter_encoding(parsed, encoded); - } - } - - Altered::InPlace -} - -fn check_sni_error(alteration: impl Fn(&mut Message) -> Altered, expected_error: Error) { +fn check_sni_error(sni_extension: encoding::Extension, expected_error: Error) { for kt in ALL_KEY_TYPES { - let client_config = make_client_config(*kt); let mut server_config = make_server_config(*kt); - server_config.cert_resolver = Arc::new(ServerCheckNoSni {}); - let client = - ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); - let server = ServerConnection::new(Arc::new(server_config)).unwrap(); - let (mut client, mut server) = (client.into(), server.into()); + let mut server = ServerConnection::new(Arc::new(server_config)).unwrap(); + server + .read_tls( + &mut encoding::message_framing( + ContentType::Handshake, + ProtocolVersion::TLSv1_2, + encoding::basic_client_hello(vec![sni_extension.clone()]), + ) + .as_slice(), + ) + .unwrap(); - transfer_altered(&mut client, &alteration, &mut server); assert_eq!(server.process_new_packets(), Err(expected_error.clone()),); - - let rustls::Connection::Server(server_inner) = server else { - unreachable!(); - }; - assert_eq!(None, server_inner.server_name()); + assert_eq!(None, server.server_name()); } } @@ -6305,45 +6257,25 @@ fn connection_types_are_not_huge() { #[test] fn test_server_rejects_duplicate_sni_names() { - fn duplicate_sni_payload(msg: &mut Message) -> Altered { - alter_sni_extension( - msg, - |snr| { - snr.push(snr[0].clone()); - }, - |parsed, _encoded| Payload::new(parsed.get_encoding()), - ) - } - - let (client, server) = make_pair(KeyType::Rsa2048); - let (mut client, mut server) = (client.into(), server.into()); - transfer_altered(&mut client, duplicate_sni_payload, &mut server); - assert_eq!( - server.process_new_packets(), - Err(Error::PeerMisbehaved( - PeerMisbehaved::DuplicateServerNameTypes - )) + let mut body = encoding::Extension::sni_dns_hostname(b"example.com"); + body.extend_from_slice(&encoding::Extension::sni_dns_hostname(b"example.com")); + check_sni_error( + encoding::Extension { + typ: ExtensionType::ServerName, + body: encoding::len_u16(body), + }, + Error::PeerMisbehaved(PeerMisbehaved::DuplicateServerNameTypes), ); } #[test] fn test_server_rejects_empty_sni_extension() { - fn empty_sni_payload(msg: &mut Message) -> Altered { - alter_sni_extension( - msg, - |snr| snr.clear(), - |parsed, _encoded| Payload::new(parsed.get_encoding()), - ) - } - - let (client, server) = make_pair(KeyType::Rsa2048); - let (mut client, mut server) = (client.into(), server.into()); - transfer_altered(&mut client, empty_sni_payload, &mut server); - assert_eq!( - server.process_new_packets(), - Err(Error::PeerMisbehaved( - PeerMisbehaved::ServerNameMustContainOneHostName - )) + check_sni_error( + encoding::Extension { + typ: ExtensionType::ServerName, + body: encoding::len_u16(vec![]), + }, + Error::PeerMisbehaved(PeerMisbehaved::ServerNameMustContainOneHostName), ); } diff --git a/rustls/tests/common/mod.rs b/rustls/tests/common/mod.rs index 044256b6881..01af3e37f6a 100644 --- a/rustls/tests/common/mod.rs +++ b/rustls/tests/common/mod.rs @@ -1480,7 +1480,64 @@ mod plaintext { /// Deeply inefficient, test-only TLS encoding helpers pub mod encoding { - use rustls::{ContentType, HandshakeType, ProtocolVersion}; + use rustls::internal::msgs::codec::Codec; + use rustls::internal::msgs::enums::ExtensionType; + use rustls::{ + CipherSuite, ContentType, HandshakeType, NamedGroup, ProtocolVersion, SignatureScheme, + }; + + /// Return a client hello with mandatory extensions added to `extensions` + /// + /// The returned bytes are handshake-framed, but not message-framed. + pub fn basic_client_hello(mut extensions: Vec) -> Vec { + extensions.push(Extension::new_kx_groups()); + extensions.push(Extension::new_sig_algs()); + extensions.push(Extension::new_versions()); + extensions.push(Extension::new_dummy_key_share()); + client_hello_with_extensions(extensions) + } + + /// Return a client hello with exactly `extensions` + /// + /// The returned bytes are handshake-framed, but not message-framed. + pub fn client_hello_with_extensions(extensions: Vec) -> Vec { + client_hello( + ProtocolVersion::TLSv1_2, + &[0u8; 32], + &[0], + vec![ + CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + CipherSuite::TLS13_AES_128_GCM_SHA256, + ], + extensions, + ) + } + + pub fn client_hello( + legacy_version: ProtocolVersion, + random: &[u8; 32], + session_id: &[u8], + cipher_suites: Vec, + extensions: Vec, + ) -> Vec { + let mut out = vec![]; + + legacy_version.encode(&mut out); + out.extend_from_slice(random); + out.extend_from_slice(session_id); + cipher_suites.to_vec().encode(&mut out); + out.extend_from_slice(&[0x01, 0x00]); // only null compression + + let mut exts = vec![]; + for e in extensions { + e.typ.encode(&mut exts); + exts.extend_from_slice(&(e.body.len() as u16).to_be_bytes()); + exts.extend_from_slice(&e.body); + } + + out.extend(len_u16(exts)); + handshake_framing(HandshakeType::ClientHello, out) + } /// Apply handshake framing to `body`. /// @@ -1499,6 +1556,81 @@ pub mod encoding { body } + #[derive(Clone)] + pub struct Extension { + pub typ: ExtensionType, + pub body: Vec, + } + + impl Extension { + pub fn new_sni(name: &[u8]) -> Self { + let body = Self::sni_dns_hostname(name); + let body = len_u16(body); + Self { + typ: ExtensionType::ServerName, + body, + } + } + + pub fn sni_dns_hostname(name: &[u8]) -> Vec { + const SNI_HOSTNAME_TYPE: u8 = 0; + + let mut out = len_u16(name.to_vec()); + out.insert(0, SNI_HOSTNAME_TYPE); + out + } + + pub fn new_sig_algs() -> Extension { + Extension { + typ: ExtensionType::SignatureAlgorithms, + body: len_u16( + SignatureScheme::RSA_PKCS1_SHA256 + .to_array() + .to_vec(), + ), + } + } + + pub fn new_kx_groups() -> Extension { + Extension { + typ: ExtensionType::EllipticCurves, + body: len_u16(vector_of([NamedGroup::secp256r1].into_iter())), + } + } + + pub fn new_versions() -> Extension { + Extension { + typ: ExtensionType::SupportedVersions, + body: len_u8(vector_of( + [ProtocolVersion::TLSv1_3, ProtocolVersion::TLSv1_2].into_iter(), + )), + } + } + + pub fn new_dummy_key_share() -> Extension { + const SOME_POINT_ON_P256: &[u8] = &[ + 4, 41, 39, 177, 5, 18, 186, 227, 237, 220, 254, 70, 120, 40, 18, 139, 173, 41, 3, + 38, 153, 25, 247, 8, 96, 105, 200, 196, 223, 108, 115, 40, 56, 199, 120, 121, 100, + 234, 172, 0, 229, 146, 31, 177, 73, 138, 96, 244, 96, 103, 102, 179, 217, 104, 80, + 1, 85, 141, 26, 151, 78, 115, 65, 81, 62, + ]; + + let mut share = len_u16(SOME_POINT_ON_P256.to_vec()); + share.splice(0..0, NamedGroup::secp256r1.to_array()); + + Extension { + typ: ExtensionType::KeyShare, + body: len_u16(share), + } + } + } + + /// Prefix with u8 length + pub fn len_u8(mut body: Vec) -> Vec { + body.splice(0..0, [body.len() as u8]); + body + } + /// Prefix with u16 length pub fn len_u16(mut body: Vec) -> Vec { body.splice(0..0, (body.len() as u16).to_be_bytes()); @@ -1513,4 +1645,14 @@ pub mod encoding { body.insert(2, len[3]); body } + + /// Encode each of `items` + pub fn vector_of<'a, T: Codec<'a>>(items: impl Iterator) -> Vec { + let mut body = Vec::new(); + + for i in items { + i.encode(&mut body); + } + body + } } From d71046e992c5582fd5c8fa14eec3209b17a3e3ff Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 9 Apr 2025 15:06:34 +0100 Subject: [PATCH 115/403] Rework QUIC tests to use new encoding module --- rustls/tests/api.rs | 91 +++------------------------------------------ 1 file changed, 6 insertions(+), 85 deletions(-) diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 013106acd61..e170f2aca5f 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -5272,7 +5272,6 @@ mod test_quic { } #[test] - #[cfg(feature = "ring")] // uses ring APIs directly fn test_quic_server_no_params_received() { let server_config = make_server_config_with_versions(KeyType::Ed25519, &[&rustls::version::TLS13]); @@ -5285,48 +5284,7 @@ mod test_quic { ) .unwrap(); - use rustls::internal::msgs::enums::{Compression, NamedGroup}; - use rustls::internal::msgs::handshake::{ - ClientHelloPayload, HandshakeMessagePayload, KeyShareEntry, Random, SessionId, - }; - use rustls::{CipherSuite, HandshakeType, SignatureScheme}; - - let provider = provider::default_provider(); - let mut random = [0; 32]; - provider - .secure_random - .fill(&mut random) - .unwrap(); - let random = Random::from(random); - - let rng = ring::rand::SystemRandom::new(); - let kx = ring::agreement::EphemeralPrivateKey::generate(&ring::agreement::ECDH_P256, &rng) - .unwrap() - .compute_public_key() - .unwrap(); - - let client_hello = MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::ClientHello, - payload: HandshakePayload::ClientHello(ClientHelloPayload { - client_version: ProtocolVersion::TLSv1_3, - random, - session_id: SessionId::random(provider.secure_random).unwrap(), - cipher_suites: vec![CipherSuite::TLS13_AES_128_GCM_SHA256], - compression_methods: vec![Compression::Null], - extensions: vec![ - ClientExtension::SupportedVersions(vec![ProtocolVersion::TLSv1_3]), - ClientExtension::NamedGroups(vec![NamedGroup::secp256r1]), - ClientExtension::SignatureAlgorithms(vec![SignatureScheme::ED25519]), - ClientExtension::KeyShare(vec![KeyShareEntry::new( - NamedGroup::secp256r1, - kx.as_ref(), - )]), - ], - }), - }); - - let mut buf = Vec::with_capacity(512); - client_hello.encode(&mut buf); + let buf = encoding::basic_client_hello(vec![]); assert_eq!( server.read_hs(buf.as_slice()).err(), Some(Error::PeerMisbehaved( @@ -5336,33 +5294,12 @@ mod test_quic { } #[test] - #[cfg(feature = "ring")] // uses ring APIs directly fn test_quic_server_no_tls12() { let mut server_config = make_server_config_with_versions(KeyType::Ed25519, &[&rustls::version::TLS13]); server_config.alpn_protocols = vec!["foo".into()]; let server_config = Arc::new(server_config); - use rustls::internal::msgs::enums::{Compression, NamedGroup}; - use rustls::internal::msgs::handshake::{ - ClientHelloPayload, HandshakeMessagePayload, KeyShareEntry, Random, SessionId, - }; - use rustls::{CipherSuite, HandshakeType, SignatureScheme}; - - let provider = provider::default_provider(); - let mut random = [0; 32]; - provider - .secure_random - .fill(&mut random) - .unwrap(); - let random = Random::from(random); - - let rng = ring::rand::SystemRandom::new(); - let kx = ring::agreement::EphemeralPrivateKey::generate(&ring::agreement::X25519, &rng) - .unwrap() - .compute_public_key() - .unwrap(); - let mut server = quic::ServerConnection::new( server_config, quic::Version::V1, @@ -5370,27 +5307,11 @@ mod test_quic { ) .unwrap(); - let client_hello = MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::ClientHello, - payload: HandshakePayload::ClientHello(ClientHelloPayload { - client_version: ProtocolVersion::TLSv1_2, - random, - session_id: SessionId::random(provider.secure_random).unwrap(), - cipher_suites: vec![CipherSuite::TLS13_AES_128_GCM_SHA256], - compression_methods: vec![Compression::Null], - extensions: vec![ - ClientExtension::NamedGroups(vec![NamedGroup::X25519]), - ClientExtension::SignatureAlgorithms(vec![SignatureScheme::ED25519]), - ClientExtension::KeyShare(vec![KeyShareEntry::new( - NamedGroup::X25519, - kx.as_ref(), - )]), - ], - }), - }); - - let mut buf = Vec::with_capacity(512); - client_hello.encode(&mut buf); + let buf = encoding::client_hello_with_extensions(vec![ + encoding::Extension::new_sig_algs(), + encoding::Extension::new_dummy_key_share(), + encoding::Extension::new_kx_groups(), + ]); assert_eq!( server.read_hs(buf.as_slice()).err(), Some(Error::PeerIncompatible( From c5b9b10147d8c448f251cbb77192daf9770e309e Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 9 Apr 2025 15:10:41 +0100 Subject: [PATCH 116/403] Rework further tests to use encoding module --- rustls/tests/api.rs | 86 +++++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 54 deletions(-) diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index e170f2aca5f..e3ff2c80090 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -15,11 +15,8 @@ use rustls::client::{ResolvesClientCert, Resumption, verify_server_cert_signed_b use rustls::crypto::{ActiveKeyExchange, CryptoProvider, SharedSecret, SupportedKxGroup}; use rustls::internal::msgs::base::Payload; use rustls::internal::msgs::codec::Codec; -use rustls::internal::msgs::enums::{AlertLevel, CertificateType, Compression, ExtensionType}; -use rustls::internal::msgs::handshake::{ - ClientExtension, ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, Random, - ServerExtension, SessionId, -}; +use rustls::internal::msgs::enums::{AlertLevel, CertificateType, ExtensionType}; +use rustls::internal::msgs::handshake::{ClientExtension, HandshakePayload, ServerExtension}; use rustls::internal::msgs::message::{Message, MessagePayload, PlainMessage}; use rustls::server::{ClientHello, ParsedCertificate, ResolvesServerCert}; use rustls::{ @@ -6202,27 +6199,27 @@ fn test_server_rejects_empty_sni_extension() { #[test] fn test_server_rejects_clients_without_any_kx_groups() { - fn delete_kx_groups(msg: &mut Message) -> Altered { - if let MessagePayload::Handshake { parsed, encoded } = &mut msg.payload { - if let HandshakePayload::ClientHello(ch) = &mut parsed.payload { - for mut ext in ch.extensions.iter_mut() { - if let ClientExtension::NamedGroups(ngs) = &mut ext { - ngs.clear(); - } - if let ClientExtension::KeyShare(ks) = &mut ext { - ks.clear(); - } - } - } - - *encoded = Payload::new(parsed.get_encoding()); - } - Altered::InPlace - } - - let (client, server) = make_pair(KeyType::Rsa2048); - let (mut client, mut server) = (client.into(), server.into()); - transfer_altered(&mut client, delete_kx_groups, &mut server); + let (_, mut server) = make_pair(KeyType::Rsa2048); + server + .read_tls( + &mut encoding::message_framing( + ContentType::Handshake, + ProtocolVersion::TLSv1_2, + encoding::client_hello_with_extensions(vec![ + encoding::Extension::new_sig_algs(), + encoding::Extension { + typ: ExtensionType::EllipticCurves, + body: encoding::len_u16(vec![]), + }, + encoding::Extension { + typ: ExtensionType::KeyShare, + body: encoding::len_u16(vec![]), + }, + ]), + ) + .as_slice(), + ) + .unwrap(); assert_eq!( server.process_new_packets(), Err(Error::PeerIncompatible( @@ -7838,13 +7835,10 @@ fn test_illegal_server_renegotiation_attempt_after_tls13_handshake() { let msg = PlainMessage { typ: ContentType::Handshake, version: ProtocolVersion::TLSv1_3, - payload: Payload::new( - HandshakeMessagePayload { - typ: HandshakeType::HelloRequest, - payload: HandshakePayload::HelloRequest, - } - .get_encoding(), - ), + payload: Payload::new(encoding::handshake_framing( + HandshakeType::HelloRequest, + vec![], + )), }; raw_server.encrypt_and_send(&msg, &mut client); let err = client @@ -7875,13 +7869,10 @@ fn test_illegal_server_renegotiation_attempt_after_tls12_handshake() { let msg = PlainMessage { typ: ContentType::Handshake, version: ProtocolVersion::TLSv1_3, - payload: Payload::new( - HandshakeMessagePayload { - typ: HandshakeType::HelloRequest, - payload: HandshakePayload::HelloRequest, - } - .get_encoding(), - ), + payload: Payload::new(encoding::handshake_framing( + HandshakeType::HelloRequest, + vec![], + )), }; // one is allowed (and elicits a warning alert) @@ -7917,20 +7908,7 @@ fn test_illegal_client_renegotiation_attempt_after_tls13_handshake() { let msg = PlainMessage { typ: ContentType::Handshake, version: ProtocolVersion::TLSv1_3, - payload: Payload::new( - HandshakeMessagePayload { - typ: HandshakeType::ClientHello, - payload: HandshakePayload::ClientHello(ClientHelloPayload { - client_version: ProtocolVersion::TLSv1_2, - random: Random::from([0u8; 32]), - session_id: SessionId::read_bytes(&[0u8]).unwrap(), - cipher_suites: vec![], - compression_methods: vec![Compression::Null], - extensions: vec![ClientExtension::ExtendedMasterSecretRequest], - }), - } - .get_encoding(), - ), + payload: Payload::new(encoding::basic_client_hello(vec![])), }; raw_client.encrypt_and_send(&msg, &mut server); let err = server From 0ab530f85dbb40f1703c4b2769655622ea114b32 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 9 Apr 2025 20:16:57 +0100 Subject: [PATCH 117/403] Detect and error on faulty `io::Write::write_vectored` --- rustls/src/vecbuf.rs | 17 +++++++++++++++-- rustls/tests/api.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/rustls/src/vecbuf.rs b/rustls/src/vecbuf.rs index ddc150d529e..8a4a1f3e4b8 100644 --- a/rustls/src/vecbuf.rs +++ b/rustls/src/vecbuf.rs @@ -200,8 +200,21 @@ impl ChunkVecBuffer { prefix = 0; } let len = cmp::min(bufs.len(), self.chunks.len()); - let used = wr.write_vectored(&bufs[..len])?; - assert!(used <= self.len(), "illegal write_vectored return value"); + 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 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) } diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index e3ff2c80090..bb0e53f97a2 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -2480,6 +2480,35 @@ fn client_respects_buffer_limit_post_handshake() { check_read(&mut server.reader(), b"01234567890123456789012345"); } +#[test] +fn client_detects_broken_write_vectored_impl() { + // see https://github.com/rustls/rustls/issues/2316 + let (mut client, _) = make_pair(KeyType::Rsa2048); + let err = client + .write_tls(&mut BrokenWriteVectored) + .unwrap_err(); + assert_eq!(err.kind(), io::ErrorKind::Other); + assert!(format!("{err:?}").starts_with( + "Custom { kind: Other, error: \"illegal write_vectored return value (9999 > " + )); + + struct BrokenWriteVectored; + + impl io::Write for BrokenWriteVectored { + fn write_vectored(&mut self, _bufs: &[IoSlice<'_>]) -> io::Result { + Ok(9999) + } + + fn write(&mut self, _buf: &[u8]) -> io::Result { + unreachable!() + } + + fn flush(&mut self) -> io::Result<()> { + unreachable!() + } + } +} + #[test] fn buf_read() { let (mut client, mut server) = make_pair(KeyType::Rsa2048); From 88dccec476595321af9a32708ffbf63200701a98 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 10 Apr 2025 09:50:34 +0100 Subject: [PATCH 118/403] Prepare 0.23.26 --- Cargo.lock | 56 +++++++++++++++++++++++------------------------ fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 47ceeaf42be..69e856ec4e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -491,7 +491,7 @@ dependencies = [ "base64", "env_logger", "nix", - "rustls 0.23.25", + "rustls 0.23.26", "rustls-post-quantum", ] @@ -1367,7 +1367,7 @@ dependencies = [ "once_cell", "rand 0.9.0", "ring", - "rustls 0.23.25 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.23.25", "thiserror 2.0.12", "tinyvec", "tokio", @@ -1392,7 +1392,7 @@ dependencies = [ "parking_lot", "rand 0.9.0", "resolv-conf", - "rustls 0.23.25 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.23.25", "smallvec", "thiserror 2.0.12", "tokio", @@ -2611,6 +2611,21 @@ dependencies = [ [[package]] name = "rustls" version = "0.23.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" +dependencies = [ + "aws-lc-rs", + "log", + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls" +version = "0.23.26" dependencies = [ "aws-lc-rs", "base64", @@ -2639,27 +2654,12 @@ dependencies = [ "zlib-rs", ] -[[package]] -name = "rustls" -version = "0.23.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" -dependencies = [ - "aws-lc-rs", - "log", - "once_cell", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - [[package]] name = "rustls-bench" version = "0.1.0" dependencies = [ "clap", - "rustls 0.23.25", + "rustls 0.23.26", "rustls-post-quantum", "tikv-jemallocator", ] @@ -2676,7 +2676,7 @@ dependencies = [ "fxhash", "itertools 0.14.0", "rayon", - "rustls 0.23.25", + "rustls 0.23.26", "tikv-jemallocator", ] @@ -2687,7 +2687,7 @@ dependencies = [ "hickory-resolver", "regex", "ring", - "rustls 0.23.25", + "rustls 0.23.26", "tokio", ] @@ -2702,7 +2702,7 @@ dependencies = [ "log", "mio", "rcgen", - "rustls 0.23.25", + "rustls 0.23.26", "serde", "tokio", "webpki-roots", @@ -2713,7 +2713,7 @@ name = "rustls-fuzzing-provider" version = "0.1.0" dependencies = [ "env_logger", - "rustls 0.23.25", + "rustls 0.23.26", ] [[package]] @@ -2725,7 +2725,7 @@ dependencies = [ "num-bigint", "once_cell", "openssl", - "rustls 0.23.25", + "rustls 0.23.26", ] [[package]] @@ -2740,7 +2740,7 @@ version = "0.2.2" dependencies = [ "criterion", "env_logger", - "rustls 0.23.25", + "rustls 0.23.26", "webpki-roots", ] @@ -2761,7 +2761,7 @@ dependencies = [ "rand_core 0.6.4", "rcgen", "rsa", - "rustls 0.23.25", + "rustls 0.23.26", "sha2", "signature", "webpki-roots", @@ -2773,7 +2773,7 @@ name = "rustls-provider-test" version = "0.1.0" dependencies = [ "hex", - "rustls 0.23.25", + "rustls 0.23.26", "rustls-provider-example", "serde", "serde_json", @@ -3179,7 +3179,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "rustls 0.23.25 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.23.25", "tokio", ] diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 0d246d9d5d7..bb99b94f202 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.25" +version = "0.23.26" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index fa9930bb7f3..9a1267466e4 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.25" +version = "0.23.26" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From 4bdacf893eaca287868e26febff288c6d4e3c4fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Apr 2025 14:45:00 +0000 Subject: [PATCH 119/403] build(deps): bump crossbeam-channel from 0.5.14 to 0.5.15 Bumps [crossbeam-channel](https://github.com/crossbeam-rs/crossbeam) from 0.5.14 to 0.5.15. - [Release notes](https://github.com/crossbeam-rs/crossbeam/releases) - [Changelog](https://github.com/crossbeam-rs/crossbeam/blob/master/CHANGELOG.md) - [Commits](https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-channel-0.5.14...crossbeam-channel-0.5.15) --- updated-dependencies: - dependency-name: crossbeam-channel dependency-version: 0.5.15 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 69e856ec4e8..316a133daca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -777,9 +777,9 @@ checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "crossbeam-channel" -version = "0.5.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] From 4f757a8b346a8213fde03f8fdaaacb375ed45096 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 14 Apr 2025 13:55:16 +0100 Subject: [PATCH 120/403] Detect and reject empty TLS1.3 ticket values This field is required to be non-empty in TLS1.3. --- rustls/src/error.rs | 2 ++ rustls/src/msgs/handshake.rs | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/rustls/src/error.rs b/rustls/src/error.rs index 91288b6a460..56751acab24 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -184,6 +184,8 @@ pub enum InvalidMessage { UnsupportedCurveType, /// A peer sent an unsupported key exchange algorithm. UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm), + /// A server sent an empty ticket + EmptyTicketValue, } impl From for Error { diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index f5abbf6987d..9b025a4c2ef 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -2472,6 +2472,10 @@ impl Codec<'_> for NewSessionTicketPayloadTls13 { let ticket = Arc::new(PayloadU16::read(r)?); let exts = Vec::read(r)?; + if ticket.0.is_empty() { + return Err(InvalidMessage::EmptyTicketValue); + } + Ok(Self { lifetime, age_add, From d7066997bd63b84f908083642e240f7c8be09a18 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 14 Apr 2025 13:16:01 +0100 Subject: [PATCH 121/403] Take new bogo version Upstream there are now tests for PAKE, TrustAnchor, cross-SNI resumption, and TLS flags. These are disabled but ready to use if we want to experiment with those. --- bogo/config.json.in | 32 +++++++++++++++++++------------- bogo/fetch-and-build | 2 +- bogo/src/main.rs | 5 +++++ 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index ad19c3ea6f7..bb677e5c959 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -122,6 +122,9 @@ "*EarlyKeyingMaterial-Client-*": "early exporter NYI", "QUICTransportParams-*": "Bogo assumes this can be tested over TLS1.3 framing -- could make this work with some effort", "QUICCompatibilityMode": "", + "PAKE-*": "no PAKE draft support", + "TrustAnchors-*": "no TrustAnchor draft support", + "TLS13-Client-*TicketFlags*": "no flags extension support (on tickets or elsewhere)", "Ed25519DefaultDisable-NoAccept": "not implemented (ed25519 accepted by default)", "Ed25519DefaultDisable-NoAdvertise": "not implemented (ed25519 advertised by default)", "Server-VerifyDefault-Ed25519-TLS13": "ed25519 accepted by default", @@ -144,17 +147,19 @@ "*-QUIC": "" }, "ErrorMap": { - ":HTTP_REQUEST:": ":GARBAGE:", - ":HTTPS_PROXY_REQUEST:": ":GARBAGE:", - ":WRONG_VERSION_NUMBER:": ":GARBAGE:", - ":PEER_DID_NOT_RETURN_A_CERTIFICATE:": ":NO_CERTS:", - ":UNEXPECTED_RECORD:": ":UNEXPECTED_MESSAGE:", - ":NO_RENEGOTIATION:": ":UNEXPECTED_MESSAGE:", - ":DIGEST_CHECK_FAILED:": ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:", - ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:": ":UNEXPECTED_MESSAGE:", - ":ENCRYPTED_LENGTH_TOO_LONG:": ":GARBAGE:" + ":HTTP_REQUEST:": [":GARBAGE:"], + ":HTTPS_PROXY_REQUEST:": [":GARBAGE:"], + ":WRONG_VERSION_NUMBER:": [":GARBAGE:"], + ":PEER_DID_NOT_RETURN_A_CERTIFICATE:": [":NO_CERTS:"], + ":UNEXPECTED_RECORD:": [":UNEXPECTED_MESSAGE:"], + ":NO_RENEGOTIATION:": [":UNEXPECTED_MESSAGE:"], + ":DIGEST_CHECK_FAILED:": [":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:"], + ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:": [":UNEXPECTED_MESSAGE:"], + ":ENCRYPTED_LENGTH_TOO_LONG:": [":GARBAGE:"] }, "TestErrorMap": { + "AppDataBeforeTLS13KeyChange": ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:", + "AppDataBeforeTLS13KeyChange-Empty": ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:", "EchoTLS13CompatibilitySessionID": ":PEER_MISBEHAVIOUR:", "EmptyCertificateList": ":NO_CERTS:", "SendInvalidRecordType": ":GARBAGE:", @@ -206,7 +211,7 @@ "NoNullCompression-TLS13": ":INCOMPATIBLE:", "InvalidCompressionMethod": ":PEER_MISBEHAVIOUR:", "TLS13-InvalidCompressionMethod": ":PEER_MISBEHAVIOUR:", - "TLS13-WrongOuterRecord": ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:", + "TLS13-WrongOuterRecord-TLS": ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:", "TLS-TLS13-ECDHE_ECDSA_WITH_AES_128_GCM_SHA256-server": ":INCOMPATIBLE:", "TLS-TLS13-ECDHE_ECDSA_WITH_AES_128_GCM_SHA256-client": ":PEER_MISBEHAVIOUR:", "TLS-TLS13-ECDHE_ECDSA_WITH_AES_256_GCM_SHA384-server": ":INCOMPATIBLE:", @@ -342,8 +347,8 @@ "ServerCipherFilter-RSA": ":INCOMPATIBLE:", "ServerCipherFilter-ECDSA": ":INCOMPATIBLE:", "ServerCipherFilter-Ed25519": ":INCOMPATIBLE:", - "TLS13-OnlyPadding": ":PEER_MISBEHAVIOUR:", - "TLS13-EmptyRecords": ":PEER_MISBEHAVIOUR:", + "TLS13-OnlyPadding-TLS": ":PEER_MISBEHAVIOUR:", + "TLS13-EmptyRecords-TLS": ":PEER_MISBEHAVIOUR:", "TLS13-DuplicateTicketEarlyDataSupport": ":PEER_MISBEHAVIOUR:", "SupportedVersionSelection-TLS12": ":PEER_MISBEHAVIOUR:", "HelloRetryRequest-CipherChange-TLS13": ":PEER_MISBEHAVIOUR:", @@ -359,7 +364,7 @@ "ExtendedMasterSecret-YesToNo-Server": ":PEER_MISBEHAVIOUR:", "ExtendedMasterSecret-YesToNo-Client": ":PEER_MISBEHAVIOUR:", "ServerAcceptsEarlyDataOnHRR-Client-TLS13": ":PEER_MISBEHAVIOUR:", - "Downgrade-TLS12-Client": ":PEER_MISBEHAVIOUR:", + "Downgrade-TLS12-Client-TLS": ":PEER_MISBEHAVIOUR:", "Downgrade-TLS10-Client": ":HANDSHAKE_FAILURE:", "Downgrade-TLS10-Server": ":INCOMPATIBLE:", "ECDSACurveMismatch-Verify-TLS13": ":BAD_SIGNATURE:", @@ -370,6 +375,7 @@ "EarlyData-CipherMismatch-Client-TLS13": ":PEER_MISBEHAVIOUR:", "EarlyDataWithoutResume-Client-TLS13": ":PEER_MISBEHAVIOUR:", "EarlyDataVersionDowngrade-Client-TLS13": ":PEER_MISBEHAVIOUR:", + "EarlyDataVersionDowngrade-Client-TLS13-WarningAlert": ":PEER_MISBEHAVIOUR:", "EarlyData-SkipEndOfEarlyData-TLS13": ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:", "CertCompressionTooLargeClient-TLS13": ":GARBAGE:", "SkipEarlyData-Interleaved-TLS13": ":PEER_MISBEHAVIOUR:", diff --git a/bogo/fetch-and-build b/bogo/fetch-and-build index 67e2214abb8..928e701199f 100755 --- a/bogo/fetch-and-build +++ b/bogo/fetch-and-build @@ -15,7 +15,7 @@ util/testresult EOF # fix on a tested point of rustls-testing branch -COMMIT=018edfaaaeea43bf35a16e9f7ba24510c0c003bb +COMMIT=92b3d4e221b4b4690dc9c3f8ada7e92df843e987 git fetch --depth=1 https://github.com/rustls/boringssl.git $COMMIT git checkout $COMMIT (cd ssl/test/runner && go test -c) diff --git a/bogo/src/main.rs b/bogo/src/main.rs index 5f237de56ea..09feb39a315 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -883,6 +883,7 @@ fn handle_err(opts: &Options, err: Error) -> ! { Error::InvalidMessage( InvalidMessage::TrailingData("ChangeCipherSpecPayload") | InvalidMessage::InvalidCcs, ) => quit(":BAD_CHANGE_CIPHER_SPEC:"), + Error::InvalidMessage(InvalidMessage::EmptyTicketValue) => quit(":DECODE_ERROR:"), Error::InvalidMessage( InvalidMessage::InvalidKeyUpdate | InvalidMessage::MissingData(_) @@ -1688,8 +1689,12 @@ pub fn main() { "-cnsa-202407" | "-srtp-profiles" | "-permute-extensions" | + "-use-ticket-aead-callback" | "-signed-cert-timestamps" | "-on-initial-expect-peer-cert-file" | + "-resumption-across-names-enabled" | + "-expect-resumable-across-names" | + "-expect-not-resumable-across-names" | "-use-custom-verify-callback" => { println!("NYI option {:?}", arg); process::exit(BOGO_NACK); From ffb9610c9f7a698d97e27fcc553ad6bc61f21f07 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 14 Apr 2025 14:22:11 +0100 Subject: [PATCH 122/403] bogo: run extension permutation tests --- bogo/config.json.in | 1 + bogo/src/main.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index bb677e5c959..e6874328fb9 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -23,6 +23,7 @@ "DuplicateCertCompressionExt*-TLS12": "RFC8879: if TLS 1.2 or earlier is negotiated, the peers MUST ignore this extension", #if defined(RING) "TLS-ECH-*": "*ring* has no HPKE provider for ECH", + "AllExtensions-Client-Permute-ECH-HelloRetryRequest-TLS-TLS13": "requires ECH", #elif defined(AWS_LC_RS) && defined(FIPS) "TLS-ECH-*": "ECH test suites use non-FIPS approved algos", #else diff --git a/bogo/src/main.rs b/bogo/src/main.rs index 09feb39a315..7ba5696b83c 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -1629,6 +1629,7 @@ pub fn main() { "-handoff" | "-ipv6" | "-decline-alpn" | + "-permute-extensions" | "-expect-no-session" | "-expect-ticket-renewal" | "-enable-ocsp-stapling" | @@ -1688,7 +1689,6 @@ pub fn main() { "-wpa-202304" | "-cnsa-202407" | "-srtp-profiles" | - "-permute-extensions" | "-use-ticket-aead-callback" | "-signed-cert-timestamps" | "-on-initial-expect-peer-cert-file" | From 0f5b44d5fafbf06aab1844baa6d45144685a62a4 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 14 Apr 2025 16:29:19 +0100 Subject: [PATCH 123/403] bogo: fix TLS12-NoTicket-NoOffer Support -resume-with-tickets-disabled for clients. --- bogo/config.json.in | 1 - bogo/src/main.rs | 17 ++++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index e6874328fb9..f6343913d98 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -161,7 +161,6 @@ "TestErrorMap": { "AppDataBeforeTLS13KeyChange": ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:", "AppDataBeforeTLS13KeyChange-Empty": ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:", - "EchoTLS13CompatibilitySessionID": ":PEER_MISBEHAVIOUR:", "EmptyCertificateList": ":NO_CERTS:", "SendInvalidRecordType": ":GARBAGE:", "NoSharedCipher": ":HANDSHAKE_FAILURE:", diff --git a/bogo/src/main.rs b/bogo/src/main.rs index 7ba5696b83c..8cbcd854a19 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -19,7 +19,7 @@ use nix::unistd::Pid; use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; use rustls::client::{ ClientConfig, ClientConnection, EchConfig, EchGreaseConfig, EchMode, EchStatus, Resumption, - WebPkiServerVerifier, + Tls12Resumption, WebPkiServerVerifier, }; use rustls::crypto::aws_lc_rs::hpke; use rustls::crypto::hpke::{Hpke, HpkePublicKey}; @@ -816,7 +816,11 @@ fn make_client_cfg(opts: &Options) -> Arc { }); } - cfg.resumption = Resumption::store(ClientCacheWithoutKxHints::new(opts.resumption_delay)); + cfg.resumption = Resumption::store(ClientCacheWithoutKxHints::new(opts.resumption_delay)) + .tls12_resumption(match opts.tickets { + true => Tls12Resumption::SessionIdOrTickets, + false => Tls12Resumption::SessionIdOnly, + }); cfg.enable_sni = opts.use_sni; cfg.max_fragment_size = opts.max_fragment; cfg.require_ems = opts.require_ems; @@ -952,6 +956,9 @@ fn handle_err(opts: &Options, err: Error) -> ! { Error::PeerMisbehaved(PeerMisbehaved::TooManyKeyUpdateRequests) => { quit(":TOO_MANY_KEY_UPDATES:") } + Error::PeerMisbehaved(PeerMisbehaved::ServerEchoedCompatibilitySessionId) => { + quit(":SERVER_ECHOED_INVALID_SESSION_ID:") + } Error::PeerMisbehaved(PeerMisbehaved::TooManyEmptyFragments) => { quit(":TOO_MANY_EMPTY_FRAGMENTS:") } @@ -1762,7 +1769,11 @@ pub fn main() { exec(&opts, sess, i); if opts.resume_with_tickets_disabled { opts.tickets = false; - server_cfg = Some(make_server_cfg(&opts)); + + match opts.side { + Side::Server => server_cfg = Some(make_server_cfg(&opts)), + Side::Client => client_cfg = Some(make_client_cfg(&opts)), + }; } if opts.on_resume_ech_config_list.is_some() { opts.ech_config_list From 1b64a92ca06bce4c3969ca00d589b3f47c8a0fc2 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 11 Apr 2025 11:44:57 +0100 Subject: [PATCH 124/403] Add `prefer-post-quantum` to default features This enables, for dependents who use default-features, X25519MLKEM768 as the most-preferred key exchange. --- rustls/Cargo.toml | 2 +- rustls/src/lib.rs | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 9a1267466e4..aad7b604e0d 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -15,7 +15,7 @@ exclude = ["src/testdata", "tests/**"] build = "build.rs" [features] -default = ["aws_lc_rs", "logging", "std", "tls12"] +default = ["aws_lc_rs", "logging", "prefer-post-quantum", "std", "tls12"] aws-lc-rs = ["aws_lc_rs"] # Alias because Cargo features commonly use `-` aws_lc_rs = ["dep:aws-lc-rs", "webpki/aws-lc-rs", "aws-lc-rs/aws-lc-sys", "aws-lc-rs/prebuilt-nasm"] diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 72d57e7d15b..d19183ef47c 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -296,11 +296,10 @@ //! //! See [manual::_06_fips] for more details. //! -//! - `prefer-post-quantum`: 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`. We expect to add this feature -//! to the default set in a future minor release. See [the manual][x25519mlkem768-manual] -//! 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`. From 44c70f8b6bc7f0e85e3da7b98bb80c9f3695557b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:27:04 +0100 Subject: [PATCH 125/403] Support non-empty TLS vectors --- rustls/src/error.rs | 4 ++++ rustls/src/msgs/codec.rs | 27 +++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/rustls/src/error.rs b/rustls/src/error.rs index 56751acab24..fa022769338 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -186,6 +186,10 @@ pub enum InvalidMessage { 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), } impl From for Error { diff --git a/rustls/src/msgs/codec.rs b/rustls/src/msgs/codec.rs index 0a7ae21507e..a58ff7d150b 100644 --- a/rustls/src/msgs/codec.rs +++ b/rustls/src/msgs/codec.rs @@ -227,7 +227,15 @@ impl<'a, T: Codec<'a> + TlsListElement + Debug> Codec<'a> for Vec { fn read(r: &mut Reader<'a>) -> Result { let len = match T::SIZE_LEN { ListLength::U8 => usize::from(u8::read(r)?), + ListLength::NonZeroU8 { empty_error } => match usize::from(u8::read(r)?) { + 0 => return Err(empty_error), + len => len, + }, ListLength::U16 => usize::from(u16::read(r)?), + ListLength::NonZeroU16 { empty_error } => match usize::from(u16::read(r)?) { + 0 => return Err(empty_error), + len => len, + }, ListLength::U24 { max, error } => match usize::from(u24::read(r)?) { len if len > max => return Err(error), len => len, @@ -260,8 +268,19 @@ pub(crate) trait TlsListElement { /// 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, perhaps empty U8, + + /// 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 }, } @@ -280,8 +299,8 @@ impl<'a> LengthPrefixedBuffer<'a> { pub(crate) fn new(size_len: ListLength, buf: &'a mut Vec) -> Self { let len_offset = buf.len(); buf.extend(match size_len { - ListLength::U8 => &[0xff][..], - ListLength::U16 => &[0xff, 0xff], + ListLength::U8 | ListLength::NonZeroU8 { .. } => &[0xff][..], + ListLength::U16 | ListLength::NonZeroU16 { .. } => &[0xff, 0xff], ListLength::U24 { .. } => &[0xff, 0xff, 0xff], }); @@ -297,12 +316,12 @@ 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::U8 => { + ListLength::U8 | 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::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]) From 83b873d98ea1e13f8ecb4788406112720cca091b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:30:28 +0100 Subject: [PATCH 126/403] Require non-empty list of `ECPointFormats` --- rustls/src/msgs/handshake.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 9b025a4c2ef..60af4921262 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -206,8 +206,11 @@ impl UnknownExtension { } } +/// RFC8422: `ECPointFormat ec_point_format_list<1..2^8-1>` impl TlsListElement for ECPointFormat { - const SIZE_LEN: ListLength = ListLength::U8; + const SIZE_LEN: ListLength = ListLength::NonZeroU8 { + empty_error: InvalidMessage::IllegalEmptyList("ECPointFormats"), + }; } impl TlsListElement for NamedGroup { From 26d4ad0dd1491223b3c007fada46f0d1d295eaf7 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:31:09 +0100 Subject: [PATCH 127/403] Require non-empty list of `NamedGroups` --- rustls/src/msgs/handshake.rs | 5 ++++- rustls/tests/api.rs | 6 +++--- rustls/tests/api_ffdhe.rs | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 60af4921262..af290ebd1ce 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -213,8 +213,11 @@ impl TlsListElement for ECPointFormat { }; } +/// RFC8422: `NamedCurve named_curve_list<2..2^16-1>` impl TlsListElement for NamedGroup { - const SIZE_LEN: ListLength = ListLength::U16; + const SIZE_LEN: ListLength = ListLength::NonZeroU16 { + empty_error: InvalidMessage::IllegalEmptyList("NamedGroups"), + }; } impl TlsListElement for SignatureScheme { diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index bb0e53f97a2..4ee6427f6fc 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -6251,9 +6251,9 @@ fn test_server_rejects_clients_without_any_kx_groups() { .unwrap(); assert_eq!( server.process_new_packets(), - Err(Error::PeerIncompatible( - PeerIncompatible::NoKxGroupsInCommon - )) + Err(Error::InvalidMessage(InvalidMessage::IllegalEmptyList( + "NamedGroups" + ))) ); } diff --git a/rustls/tests/api_ffdhe.rs b/rustls/tests/api_ffdhe.rs index 31b7f9864a3..f915f9d39e8 100644 --- a/rustls/tests/api_ffdhe.rs +++ b/rustls/tests/api_ffdhe.rs @@ -79,6 +79,7 @@ fn server_picks_ffdhe_group_when_clienthello_has_no_ffdhe_group_in_groups_ext() for mut ext in ch.extensions.iter_mut() { if let ClientExtension::NamedGroups(ngs) = &mut ext { ngs.clear(); + ngs.push(NamedGroup::X448); } } } From c2ffa7aa0569df223c1f09a9f3e768e45e6f6e7b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:31:24 +0100 Subject: [PATCH 128/403] Require non-empty list of `SignatureSchemes` --- rustls/src/msgs/handshake.rs | 5 ++++- rustls/tests/server_cert_verifier.rs | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index af290ebd1ce..d0f09234c92 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -220,8 +220,11 @@ impl TlsListElement for NamedGroup { }; } +/// RFC8446: `SignatureScheme supported_signature_algorithms<2..2^16-2>;` impl TlsListElement for SignatureScheme { - const SIZE_LEN: ListLength = ListLength::U16; + const SIZE_LEN: ListLength = ListLength::NonZeroU16 { + empty_error: InvalidMessage::NoSignatureSchemes, + }; } #[derive(Clone, Debug)] diff --git a/rustls/tests/server_cert_verifier.rs b/rustls/tests/server_cert_verifier.rs index e00e1cee57c..1f0a6bb7d29 100644 --- a/rustls/tests/server_cert_verifier.rs +++ b/rustls/tests/server_cert_verifier.rs @@ -159,10 +159,10 @@ fn client_can_override_certificate_verification_and_offer_no_signature_schemes() assert_eq!( errs, Err(vec![ - ErrorFromPeer::Server(Error::PeerIncompatible( - rustls::PeerIncompatible::NoSignatureSchemesInCommon + ErrorFromPeer::Server(Error::InvalidMessage( + rustls::InvalidMessage::NoSignatureSchemes )), - ErrorFromPeer::Client(Error::AlertReceived(AlertDescription::HandshakeFailure)), + ErrorFromPeer::Client(Error::AlertReceived(AlertDescription::DecodeError)), ]) ); } From 845cc9dc118d8e926b2377dc81bfd84913819f40 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:32:38 +0100 Subject: [PATCH 129/403] Require non-empty list of `ServerNames` --- rustls/src/msgs/handshake.rs | 5 ++++- rustls/tests/api.rs | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index d0f09234c92..c63cb3291ff 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -292,8 +292,11 @@ impl Codec<'_> for ServerName { } } +/// RFC6066: `ServerName server_name_list<1..2^16-1>` impl TlsListElement for ServerName { - const SIZE_LEN: ListLength = ListLength::U16; + const SIZE_LEN: ListLength = ListLength::NonZeroU16 { + empty_error: InvalidMessage::IllegalEmptyList("ServerNames"), + }; } pub(crate) trait ConvertServerNameList { diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 4ee6427f6fc..4b11090d5db 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -6222,7 +6222,7 @@ fn test_server_rejects_empty_sni_extension() { typ: ExtensionType::ServerName, body: encoding::len_u16(vec![]), }, - Error::PeerMisbehaved(PeerMisbehaved::ServerNameMustContainOneHostName), + Error::InvalidMessage(InvalidMessage::IllegalEmptyList("ServerNames")), ); } From 4a6d922b901b3f86f2f6a05401491d9235d8ab31 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:33:03 +0100 Subject: [PATCH 130/403] Require non-empty list of ALPN protocols --- rustls/src/msgs/handshake.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index c63cb3291ff..eb99a3c72eb 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -327,8 +327,11 @@ impl ConvertServerNameList for [ServerName] { wrapped_payload!(pub struct ProtocolName, PayloadU8,); +/// RFC7301: `ProtocolName protocol_name_list<2..2^16-1>` impl TlsListElement for ProtocolName { - const SIZE_LEN: ListLength = ListLength::U16; + const SIZE_LEN: ListLength = ListLength::NonZeroU16 { + empty_error: InvalidMessage::IllegalEmptyList("ProtocolNames"), + }; } pub(crate) trait ConvertProtocolNameList { From 88fbe31fb933f2f3fc82708035db38a6417ee5a6 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:33:47 +0100 Subject: [PATCH 131/403] Require non-empty list of TLS1.3 `PskIdentities` --- rustls/src/msgs/handshake.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index eb99a3c72eb..39df4eb4916 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -430,8 +430,11 @@ impl Codec<'_> for PresharedKeyIdentity { } } +/// RFC8446: `PskIdentity identities<7..2^16-1>;` impl TlsListElement for PresharedKeyIdentity { - const SIZE_LEN: ListLength = ListLength::U16; + const SIZE_LEN: ListLength = ListLength::NonZeroU16 { + empty_error: InvalidMessage::IllegalEmptyList("PskIdentities"), + }; } wrapped_payload!(pub(crate) struct PresharedKeyBinder, PayloadU8,); From a705ac5b5f10e488c8964998c180ac794fe28e6e Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:34:30 +0100 Subject: [PATCH 132/403] Require non-empty list of TLS1.3 PSK binders --- bogo/config.json.in | 2 -- bogo/src/main.rs | 4 +++- rustls/src/msgs/handshake.rs | 5 ++++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index f6343913d98..2b82f7e940d 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -254,13 +254,11 @@ "SecondClientHelloWrongCurve-TLS13": ":PEER_MISBEHAVIOUR:", "SecondClientHelloMissingKeyShare-TLS13": ":INCOMPATIBLE:", "Resume-Server-BinderWrongLength-SecondBinder": ":PEER_MISBEHAVIOUR:", - "Resume-Server-NoPSKBinder-SecondBinder": ":PEER_MISBEHAVIOUR:", "Resume-Server-ExtraPSKBinder-SecondBinder": ":PEER_MISBEHAVIOUR:", "Resume-Server-ExtraIdentityNoBinder-SecondBinder": ":PEER_MISBEHAVIOUR:", "Resume-Server-InvalidPSKBinder-SecondBinder": ":PEER_MISBEHAVIOUR:", "Resume-Server-PSKBinderFirstExtension-SecondBinder": ":PEER_MISBEHAVIOUR:", "Resume-Server-BinderWrongLength": ":PEER_MISBEHAVIOUR:", - "Resume-Server-NoPSKBinder": ":PEER_MISBEHAVIOUR:", "Resume-Server-ExtraPSKBinder": ":PEER_MISBEHAVIOUR:", "Resume-Server-ExtraIdentityNoBinder": ":PEER_MISBEHAVIOUR:", "Resume-Server-InvalidPSKBinder": ":PEER_MISBEHAVIOUR:", diff --git a/bogo/src/main.rs b/bogo/src/main.rs index 8cbcd854a19..f9c08d661e8 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -887,7 +887,9 @@ fn handle_err(opts: &Options, err: Error) -> ! { Error::InvalidMessage( InvalidMessage::TrailingData("ChangeCipherSpecPayload") | InvalidMessage::InvalidCcs, ) => quit(":BAD_CHANGE_CIPHER_SPEC:"), - Error::InvalidMessage(InvalidMessage::EmptyTicketValue) => quit(":DECODE_ERROR:"), + Error::InvalidMessage( + InvalidMessage::EmptyTicketValue | InvalidMessage::IllegalEmptyList(_), + ) => quit(":DECODE_ERROR:"), Error::InvalidMessage( InvalidMessage::InvalidKeyUpdate | InvalidMessage::MissingData(_) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 39df4eb4916..f57b753a466 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -439,8 +439,11 @@ impl TlsListElement for PresharedKeyIdentity { wrapped_payload!(pub(crate) struct PresharedKeyBinder, PayloadU8,); +/// RFC8446: `PskBinderEntry binders<33..2^16-1>;` impl TlsListElement for PresharedKeyBinder { - const SIZE_LEN: ListLength = ListLength::U16; + const SIZE_LEN: ListLength = ListLength::NonZeroU16 { + empty_error: InvalidMessage::IllegalEmptyList("PskBinders"), + }; } #[derive(Clone, Debug)] From 707acdfea4feb470775b6492e7daeb13403712c2 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:34:50 +0100 Subject: [PATCH 133/403] Note that list of OCSP responders can be empty --- rustls/src/msgs/handshake.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index f57b753a466..a5b4c8dc2d4 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -479,6 +479,7 @@ impl Codec<'_> for PresharedKeyOffer { // --- 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; } From 1867705a5bfea923a0a681f3944630946bd77b7f Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:35:22 +0100 Subject: [PATCH 134/403] Require non-empty list of `PskKeyExchangeModes` --- rustls/src/msgs/handshake.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index a5b4c8dc2d4..6fe14a59541 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -550,8 +550,11 @@ impl CertificateStatusRequest { // --- +/// RFC8446: `PskKeyExchangeMode ke_modes<1..255>;` impl TlsListElement for PSKKeyExchangeMode { - const SIZE_LEN: ListLength = ListLength::U8; + const SIZE_LEN: ListLength = ListLength::NonZeroU8 { + empty_error: InvalidMessage::IllegalEmptyList("PskKeyExchangeModes"), + }; } impl TlsListElement for KeyShareEntry { From f68bbb51733a95a5e988889323fd93a4d9fbedfa Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:35:59 +0100 Subject: [PATCH 135/403] Note that client may send empty list of key shares --- rustls/src/msgs/handshake.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 6fe14a59541..d933d2edfc7 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -557,6 +557,7 @@ impl TlsListElement for PSKKeyExchangeMode { }; } +/// RFC8446: `KeyShareEntry client_shares<0..2^16-1>;` impl TlsListElement for KeyShareEntry { const SIZE_LEN: ListLength = ListLength::U16; } From d93479234afda15cd33e62d1456f993acd2c7fc3 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:36:37 +0100 Subject: [PATCH 136/403] Require non-empty list of `ProtocolVersions` --- rustls/src/msgs/handshake.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index d933d2edfc7..14b468b434b 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -562,8 +562,11 @@ impl TlsListElement for KeyShareEntry { const SIZE_LEN: ListLength = ListLength::U16; } +/// RFC8446: `ProtocolVersion versions<2..254>;` impl TlsListElement for ProtocolVersion { - const SIZE_LEN: ListLength = ListLength::U8; + const SIZE_LEN: ListLength = ListLength::NonZeroU8 { + empty_error: InvalidMessage::IllegalEmptyList("ProtocolVersions"), + }; } impl TlsListElement for CertificateType { From 6d789b5e50b478528035332395ff570800116f39 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:37:23 +0100 Subject: [PATCH 137/403] Require non-empty list of `CertificateTypes` --- rustls/src/msgs/handshake.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 14b468b434b..4f41e87d021 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -569,8 +569,13 @@ impl TlsListElement for ProtocolVersion { }; } +/// 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::U8; + const SIZE_LEN: ListLength = ListLength::NonZeroU8 { + empty_error: InvalidMessage::IllegalEmptyList("CertificateTypes"), + }; } impl TlsListElement for CertificateCompressionAlgorithm { From 315424792740274ae703df1de72d515f3ec200aa Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:37:37 +0100 Subject: [PATCH 138/403] Require non-empty list of `CertificateCompressionAlgorithms` --- rustls/src/msgs/handshake.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 4f41e87d021..6e7b3d1b151 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -578,8 +578,11 @@ impl TlsListElement for CertificateType { }; } +/// RFC8879: `CertificateCompressionAlgorithm algorithms<2..2^8-2>;` impl TlsListElement for CertificateCompressionAlgorithm { - const SIZE_LEN: ListLength = ListLength::U8; + const SIZE_LEN: ListLength = ListLength::NonZeroU8 { + empty_error: InvalidMessage::IllegalEmptyList("CertificateCompressionAlgorithms"), + }; } #[derive(Clone, Debug)] From 94f0e46f92171a87bad6072e9d05b414b2ed3775 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:38:47 +0100 Subject: [PATCH 139/403] Require non-empty list of offered ciphersuites --- rustls/src/msgs/handshake.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 6e7b3d1b151..7ebbbd32472 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -925,8 +925,11 @@ impl Codec<'_> for ClientHelloPayload { } } +/// RFC8446: `CipherSuite cipher_suites<2..2^16-2>;` impl TlsListElement for CipherSuite { - const SIZE_LEN: ListLength = ListLength::U16; + const SIZE_LEN: ListLength = ListLength::NonZeroU16 { + empty_error: InvalidMessage::IllegalEmptyList("CipherSuites"), + }; } impl TlsListElement for Compression { From e9046bd8163edbf09a47f0af8fa7e5360cb0b52c Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:39:10 +0100 Subject: [PATCH 140/403] Require non-empty list of `Compressions` --- rustls/src/msgs/handshake.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 7ebbbd32472..8ce42d440da 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -932,8 +932,11 @@ impl TlsListElement for CipherSuite { }; } +/// RFC5246: `CompressionMethod compression_methods<1..2^8-1>;` impl TlsListElement for Compression { - const SIZE_LEN: ListLength = ListLength::U8; + const SIZE_LEN: ListLength = ListLength::NonZeroU8 { + empty_error: InvalidMessage::IllegalEmptyList("Compressions"), + }; } impl TlsListElement for ClientExtension { From 1a0f228ee37ae3f05b0e51b3a1762c58a1250da0 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:39:33 +0100 Subject: [PATCH 141/403] Require non-empty list of ECH compressed extensions --- rustls/src/msgs/handshake.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 8ce42d440da..0fe84ddb886 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -943,8 +943,11 @@ impl TlsListElement for ClientExtension { const SIZE_LEN: ListLength = ListLength::U16; } +/// draft-ietf-tls-esni-17: `ExtensionType OuterExtensions<2..254>;` impl TlsListElement for ExtensionType { - const SIZE_LEN: ListLength = ListLength::U8; + const SIZE_LEN: ListLength = ListLength::NonZeroU8 { + empty_error: InvalidMessage::IllegalEmptyList("ExtensionTypes"), + }; } impl ClientHelloPayload { From 01805e795e506eae8c44e164b226ee768832945c Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:39:58 +0100 Subject: [PATCH 142/403] Require non-empty list of `ClientCertificateTypes` --- rustls/src/msgs/handshake.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 0fe84ddb886..3586dc16f94 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -2184,8 +2184,11 @@ impl HasServerExtensions for Vec { } } +/// RFC5246: `ClientCertificateType certificate_types<1..2^8-1>;` impl TlsListElement for ClientCertificateType { - const SIZE_LEN: ListLength = ListLength::U8; + const SIZE_LEN: ListLength = ListLength::NonZeroU8 { + empty_error: InvalidMessage::IllegalEmptyList("ClientCertificateTypes"), + }; } wrapped_payload!( From c69266ce2c194f9e88af77f257b2a5260757e3d5 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:05:24 +0100 Subject: [PATCH 143/403] Require non-empty list for `HpkeSymmetricCipherSuite` --- rustls/src/msgs/handshake.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 3586dc16f94..bf5689bd664 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -2908,8 +2908,11 @@ impl Codec<'_> for HpkeSymmetricCipherSuite { } } +/// draft-ietf-tls-esni-24: `HpkeSymmetricCipherSuite cipher_suites<4..2^16-4>;` impl TlsListElement for HpkeSymmetricCipherSuite { - const SIZE_LEN: ListLength = ListLength::U16; + const SIZE_LEN: ListLength = ListLength::NonZeroU16 { + empty_error: InvalidMessage::IllegalEmptyList("HpkeSymmetricCipherSuites"), + }; } #[derive(Clone, Debug, PartialEq)] From 11e069af46614aadc1236d0e4f41ce1a4cac4825 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:48:53 +0100 Subject: [PATCH 144/403] Drop unused `ListLength::U8` for TLS vectors --- rustls/src/msgs/codec.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/rustls/src/msgs/codec.rs b/rustls/src/msgs/codec.rs index a58ff7d150b..b73e713c432 100644 --- a/rustls/src/msgs/codec.rs +++ b/rustls/src/msgs/codec.rs @@ -226,7 +226,6 @@ impl<'a, T: Codec<'a> + TlsListElement + Debug> Codec<'a> for Vec { fn read(r: &mut Reader<'a>) -> Result { let len = match T::SIZE_LEN { - ListLength::U8 => usize::from(u8::read(r)?), ListLength::NonZeroU8 { empty_error } => match usize::from(u8::read(r)?) { 0 => return Err(empty_error), len => len, @@ -268,9 +267,6 @@ pub(crate) trait TlsListElement { /// 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, perhaps empty - U8, - /// U8 but non-empty NonZeroU8 { empty_error: InvalidMessage }, @@ -299,7 +295,7 @@ impl<'a> LengthPrefixedBuffer<'a> { pub(crate) fn new(size_len: ListLength, buf: &'a mut Vec) -> Self { let len_offset = buf.len(); buf.extend(match size_len { - ListLength::U8 | ListLength::NonZeroU8 { .. } => &[0xff][..], + ListLength::NonZeroU8 { .. } => &[0xff][..], ListLength::U16 | ListLength::NonZeroU16 { .. } => &[0xff, 0xff], ListLength::U24 { .. } => &[0xff, 0xff, 0xff], }); @@ -316,7 +312,7 @@ 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::U8 | ListLength::NonZeroU8 { .. } => { + ListLength::NonZeroU8 { .. } => { let len = self.buf.len() - self.len_offset - 1; debug_assert!(len <= 0xff); self.buf[self.len_offset] = len as u8; From d881c656c0590b0eb17b147ee457851e8434ed29 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 17:40:20 +0100 Subject: [PATCH 145/403] Manually check non-emptiness in TLS1.3 `Vec` Unfortunately attaching the emptiness or not to `Vec` doesn't work here, because the requirement changes based on context. --- rustls/src/msgs/handshake.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index bf5689bd664..f3f8cc1257d 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -722,7 +722,13 @@ impl Codec<'_> for ClientExtension { ExtensionType::EncryptedClientHelloOuterExtensions => { Self::EncryptedClientHelloOuterExtensions(Vec::read(&mut sub)?) } - ExtensionType::CertificateAuthorities => Self::AuthorityNames(Vec::read(&mut sub)?), + ExtensionType::CertificateAuthorities => Self::AuthorityNames({ + let items = Vec::read(&mut sub)?; + if items.is_empty() { + return Err(InvalidMessage::IllegalEmptyList("DistinguishedNames")); + } + items + }), _ => Self::Unknown(UnknownExtension::read(typ, &mut sub)), }; @@ -2222,6 +2228,8 @@ impl DistinguishedName { } } +/// 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; } @@ -2305,6 +2313,9 @@ impl Codec<'_> for CertReqExtension { } ExtensionType::CertificateAuthorities => { let cas = Vec::read(&mut sub)?; + if cas.is_empty() { + return Err(InvalidMessage::IllegalEmptyList("DistinguishedNames")); + } Self::AuthorityNames(cas) } ExtensionType::CompressCertificate => { From 61936f70c2bd56d0272fc790b5eae26073137a34 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 14:58:13 +0100 Subject: [PATCH 146/403] Introduce lower bounds for `PayloadU8` type This allows `PayloadU8` to be specialised for non-emptiness. --- rustls/src/error.rs | 2 ++ rustls/src/msgs/base.rs | 44 +++++++++++++++++++++++++------ rustls/src/msgs/handshake.rs | 14 ++++++---- rustls/src/msgs/handshake_test.rs | 10 +++---- rustls/src/msgs/message_test.rs | 7 +++-- rustls/src/msgs/persist.rs | 8 +++--- 6 files changed, 61 insertions(+), 24 deletions(-) diff --git a/rustls/src/error.rs b/rustls/src/error.rs index fa022769338..73cdcf10298 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -190,6 +190,8 @@ pub enum InvalidMessage { /// /// The argument names the context. IllegalEmptyList(&'static str), + /// A peer sent an empty value, but a non-empty value is required. + IllegalEmptyValue, } impl From for Error { diff --git a/rustls/src/msgs/base.rs b/rustls/src/msgs/base.rs index cbdad0a7b67..0171cff9f78 100644 --- a/rustls/src/msgs/base.rs +++ b/rustls/src/msgs/base.rs @@ -1,5 +1,6 @@ use alloc::vec::Vec; use core::fmt; +use core::marker::PhantomData; use pki_types::CertificateDer; use zeroize::Zeroize; @@ -148,50 +149,77 @@ impl fmt::Debug for PayloadU16 { } /// An arbitrary, unknown-content, u8-length-prefixed payload +/// +/// `C` controls the minimum length accepted when decoding. #[derive(Clone, Eq, PartialEq)] -pub struct PayloadU8(pub(crate) Vec); +pub struct PayloadU8(pub(crate) Vec, PhantomData); -impl PayloadU8 { +impl PayloadU8 { pub(crate) fn encode_slice(slice: &[u8], bytes: &mut Vec) { (slice.len() as u8).encode(bytes); bytes.extend_from_slice(slice); } pub(crate) fn new(bytes: Vec) -> Self { - Self(bytes) + debug_assert!(bytes.len() >= C::MIN); + Self(bytes, PhantomData) } +} +impl PayloadU8 { pub(crate) fn empty() -> Self { - Self(Vec::new()) + Self(Vec::new(), PhantomData) } } -impl Codec<'_> for PayloadU8 { +impl Codec<'_> for PayloadU8 { fn encode(&self, bytes: &mut Vec) { + 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 { 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)) + Ok(Self(body, PhantomData)) } } -impl Zeroize for PayloadU8 { +impl Zeroize for PayloadU8 { fn zeroize(&mut self) { self.0.zeroize(); } } -impl fmt::Debug for PayloadU8 { +impl fmt::Debug for PayloadU8 { 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<'_>, diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index f3f8cc1257d..1e06eb1da07 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -19,7 +19,7 @@ use crate::error::InvalidMessage; #[cfg(feature = "tls12")] use crate::ffdhe_groups::FfdheGroup; use crate::log::warn; -use crate::msgs::base::{Payload, PayloadU8, PayloadU16, PayloadU24}; +use crate::msgs::base::{MaybeEmpty, Payload, PayloadU8, PayloadU16, PayloadU24}; use crate::msgs::codec::{self, Codec, LengthPrefixedBuffer, ListLength, Reader, TlsListElement}; use crate::msgs::enums::{ CertificateStatusType, CertificateType, ClientCertificateType, Compression, ECCurveType, @@ -2989,7 +2989,7 @@ impl Codec<'_> for EchConfigContents { self.key_config.encode(bytes); self.maximum_name_length.encode(bytes); let dns_name = &self.public_name.borrow(); - PayloadU8::encode_slice(dns_name.as_ref().as_ref(), bytes); + PayloadU8::::encode_slice(dns_name.as_ref().as_ref(), bytes); self.extensions.encode(bytes); } @@ -2998,9 +2998,13 @@ impl Codec<'_> for EchConfigContents { key_config: HpkeKeyConfig::read(r)?, maximum_name_length: u8::read(r)?, public_name: { - DnsName::try_from(PayloadU8::read(r)?.0.as_slice()) - .map_err(|_| InvalidMessage::InvalidServerName)? - .to_owned() + DnsName::try_from( + PayloadU8::::read(r)? + .0 + .as_slice(), + ) + .map_err(|_| InvalidMessage::InvalidServerName)? + .to_owned() }, extensions: Vec::read(r)?, }) diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index 63aeee7e851..a60454a4973 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -1014,7 +1014,7 @@ fn sample_server_hello_payload() -> ServerHelloPayload { ServerExtension::EcPointFormats(ECPointFormat::SUPPORTED.to_vec()), ServerExtension::ServerNameAck, ServerExtension::SessionTicketAck, - ServerExtension::RenegotiationInfo(PayloadU8(vec![0])), + ServerExtension::RenegotiationInfo(PayloadU8::new(vec![0])), ServerExtension::Protocols(vec![ProtocolName::from(vec![0])]), ServerExtension::KeyShare(KeyShareEntry::new(NamedGroup::X25519, &[1, 2, 3][..])), ServerExtension::PresharedKey(3), @@ -1209,7 +1209,7 @@ fn all_tls13_handshake_payloads() -> Vec> { fn sample_certificate_payload_tls13() -> CertificatePayloadTls13<'static> { CertificatePayloadTls13 { - context: PayloadU8(vec![1, 2, 3]), + context: PayloadU8::new(vec![1, 2, 3]), entries: vec![CertificateEntry { cert: CertificateDer::from(vec![3, 4, 5]), exts: vec![ @@ -1240,7 +1240,7 @@ fn sample_ecdhe_server_key_exchange_payload() -> ServerKeyExchangePayload { curve_type: ECCurveType::NamedCurve, named_group: NamedGroup::X25519, }, - public: PayloadU8(vec![1, 2, 3]), + public: PayloadU8::new(vec![1, 2, 3]), }), dss: DigitallySignedStruct::new(SignatureScheme::RSA_PSS_SHA256, vec![1, 2, 3]), }) @@ -1271,7 +1271,7 @@ fn sample_certificate_request_payload() -> CertificateRequestPayload { fn sample_certificate_request_payload_tls13() -> CertificateRequestPayloadTls13 { CertificateRequestPayloadTls13 { - context: PayloadU8(vec![1, 2, 3]), + context: PayloadU8::new(vec![1, 2, 3]), extensions: vec![ CertReqExtension::SignatureAlgorithms(vec![SignatureScheme::ECDSA_NISTP256_SHA256]), CertReqExtension::AuthorityNames(vec![DistinguishedName::from(vec![1, 2, 3])]), @@ -1294,7 +1294,7 @@ fn sample_new_session_ticket_payload_tls13() -> NewSessionTicketPayloadTls13 { NewSessionTicketPayloadTls13 { lifetime: 123, age_add: 1234, - nonce: PayloadU8(vec![1, 2, 3]), + nonce: PayloadU8::new(vec![1, 2, 3]), ticket: Arc::new(PayloadU16(vec![4, 5, 6])), exts: vec![NewSessionTicketExtension::Unknown(UnknownExtension { typ: ExtensionType::Unknown(12345), diff --git a/rustls/src/msgs/message_test.rs b/rustls/src/msgs/message_test.rs index 672fdddde42..e21e9d7cd44 100644 --- a/rustls/src/msgs/message_test.rs +++ b/rustls/src/msgs/message_test.rs @@ -8,7 +8,7 @@ use super::codec::Reader; use super::enums::AlertLevel; use super::message::{Message, OutboundOpaqueMessage, PlainMessage}; use crate::enums::{AlertDescription, HandshakeType}; -use crate::msgs::base::{PayloadU8, PayloadU16, PayloadU24}; +use crate::msgs::base::{NonEmpty, PayloadU8, PayloadU16, PayloadU24}; #[test] fn test_read_fuzz_corpus() { @@ -100,7 +100,10 @@ fn construct_all_types() { #[test] fn debug_payload() { assert_eq!("01020304", format!("{:?}", Payload::new(vec![1, 2, 3, 4]))); - assert_eq!("01020304", format!("{:?}", PayloadU8(vec![1, 2, 3, 4]))); + assert_eq!( + "01020304", + format!("{:?}", PayloadU8::::new(vec![1, 2, 3, 4])) + ); assert_eq!("01020304", format!("{:?}", PayloadU16(vec![1, 2, 3, 4]))); assert_eq!( "01020304", diff --git a/rustls/src/msgs/persist.rs b/rustls/src/msgs/persist.rs index 8fb21e09341..b7708ffe5fa 100644 --- a/rustls/src/msgs/persist.rs +++ b/rustls/src/msgs/persist.rs @@ -7,7 +7,7 @@ use zeroize::Zeroizing; use crate::client::ResolvesClientCert; use crate::enums::{CipherSuite, ProtocolVersion}; use crate::error::InvalidMessage; -use crate::msgs::base::{PayloadU8, PayloadU16}; +use crate::msgs::base::{MaybeEmpty, PayloadU8, PayloadU16}; use crate::msgs::codec::{Codec, Reader}; use crate::msgs::handshake::CertificateChain; #[cfg(feature = "tls12")] @@ -239,7 +239,7 @@ impl ClientSessionCommon { ) -> Self { Self { ticket, - secret: Zeroizing::new(PayloadU8(secret.to_vec())), + 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), @@ -316,7 +316,7 @@ impl Codec<'_> for ServerSessionValue { if let Some(sni) = &self.sni { 1u8.encode(bytes); let sni_bytes: &str = sni.as_ref(); - PayloadU8::new(Vec::from(sni_bytes)).encode(bytes); + PayloadU8::::encode_slice(sni_bytes.as_bytes(), bytes); } else { 0u8.encode(bytes); } @@ -345,7 +345,7 @@ impl Codec<'_> for ServerSessionValue { fn read(r: &mut Reader<'_>) -> Result { let has_sni = u8::read(r)?; let sni = if has_sni == 1 { - let dns_name = PayloadU8::read(r)?; + let dns_name = PayloadU8::::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), From 4b7bbbfe5e0474d7b895f09bbf2c83b90175d021 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 14:59:47 +0100 Subject: [PATCH 147/403] Use `PayloadU8` for `ClientEcdhParams` --- rustls/src/msgs/handshake.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 1e06eb1da07..deb78320cb7 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -19,7 +19,7 @@ use crate::error::InvalidMessage; #[cfg(feature = "tls12")] use crate::ffdhe_groups::FfdheGroup; use crate::log::warn; -use crate::msgs::base::{MaybeEmpty, Payload, PayloadU8, PayloadU16, PayloadU24}; +use crate::msgs::base::{MaybeEmpty, NonEmpty, Payload, PayloadU8, PayloadU16, PayloadU24}; use crate::msgs::codec::{self, Codec, LengthPrefixedBuffer, ListLength, Reader, TlsListElement}; use crate::msgs::enums::{ CertificateStatusType, CertificateType, ClientCertificateType, Compression, ECCurveType, @@ -1893,7 +1893,8 @@ impl KxDecode<'_> for ClientKeyExchangeParams { #[cfg(feature = "tls12")] #[derive(Debug)] pub(crate) struct ClientEcdhParams { - pub(crate) public: PayloadU8, + /// RFC4492: `opaque point <1..2^8-1>;` + pub(crate) public: PayloadU8, } #[cfg(feature = "tls12")] From 5e0d5ea47332aa07aa72d1ec638d08cde4200fd5 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 15:17:50 +0100 Subject: [PATCH 148/403] Use `PayloadU8` for ALPN `ProtocolName` --- bogo/config.json.in | 8 ++++---- bogo/src/main.rs | 1 + rustls/src/msgs/handshake.rs | 9 ++++++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index 2b82f7e940d..6953fce9c62 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -196,10 +196,10 @@ "VersionTooLow": ":INCOMPATIBLE:", "ALPNClient-RejectUnknown-TLS-TLS12": ":PEER_MISBEHAVIOUR:", "ALPNClient-RejectUnknown-TLS-TLS13": ":PEER_MISBEHAVIOUR:", - "ALPNClient-EmptyProtocolName-TLS-TLS12": ":PEER_MISBEHAVIOUR:", - "ALPNClient-EmptyProtocolName-TLS-TLS13": ":PEER_MISBEHAVIOUR:", - "ALPNServer-EmptyProtocolName-TLS-TLS12": ":PEER_MISBEHAVIOUR:", - "ALPNServer-EmptyProtocolName-TLS-TLS13": ":PEER_MISBEHAVIOUR:", + "ALPNClient-EmptyProtocolName-TLS-TLS12": ":ILLEGAL_EMPTY_VALUE:", + "ALPNClient-EmptyProtocolName-TLS-TLS13": ":ILLEGAL_EMPTY_VALUE:", + "ALPNServer-EmptyProtocolName-TLS-TLS12": ":ILLEGAL_EMPTY_VALUE:", + "ALPNServer-EmptyProtocolName-TLS-TLS13": ":ILLEGAL_EMPTY_VALUE:", "Verify-ClientAuth-SignatureType": ":BAD_SIGNATURE:", "Verify-ServerAuth-SignatureType-TLS13": ":BAD_SIGNATURE:", "Verify-ClientAuth-SignatureType-TLS13": ":BAD_SIGNATURE:", diff --git a/bogo/src/main.rs b/bogo/src/main.rs index f9c08d661e8..59429a4cf14 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -890,6 +890,7 @@ fn handle_err(opts: &Options, err: Error) -> ! { Error::InvalidMessage( InvalidMessage::EmptyTicketValue | InvalidMessage::IllegalEmptyList(_), ) => quit(":DECODE_ERROR:"), + Error::InvalidMessage(InvalidMessage::IllegalEmptyValue) => quit(":ILLEGAL_EMPTY_VALUE:"), Error::InvalidMessage( InvalidMessage::InvalidKeyUpdate | InvalidMessage::MissingData(_) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index deb78320cb7..1c759f258bb 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -37,10 +37,10 @@ use crate::x509::wrap_in_sequence; /// 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,) => { + ($(#[$comment:meta])* $vis:vis struct $name:ident, $inner:ident$(<$inner_ty:ty>)?,) => { $(#[$comment])* #[derive(Clone, Debug)] - $vis struct $name($inner); + $vis struct $name($inner$(<$inner_ty>)?); impl From> for $name { fn from(v: Vec) -> Self { @@ -325,7 +325,10 @@ impl ConvertServerNameList for [ServerName] { } } -wrapped_payload!(pub struct ProtocolName, PayloadU8,); +wrapped_payload!( + /// RFC7301: `opaque ProtocolName<1..2^8-1>;` + pub struct ProtocolName, PayloadU8, +); /// RFC7301: `ProtocolName protocol_name_list<2..2^16-1>` impl TlsListElement for ProtocolName { From a218b11d99a31aeaebbf033022aec36a24e98c51 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 15:22:25 +0100 Subject: [PATCH 149/403] Use `PayloadU8` for PSK binder --- rustls/src/msgs/handshake.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 1c759f258bb..6c714ab513e 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -440,7 +440,10 @@ impl TlsListElement for PresharedKeyIdentity { }; } -wrapped_payload!(pub(crate) struct PresharedKeyBinder, PayloadU8,); +wrapped_payload!( + /// RFC8446: `opaque PskBinderEntry<32..255>;` + pub(crate) struct PresharedKeyBinder, PayloadU8, +); /// RFC8446: `PskBinderEntry binders<33..2^16-1>;` impl TlsListElement for PresharedKeyBinder { From 20aba84467cd87f41cd457a6cf2745d523a0aaff Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 15:23:28 +0100 Subject: [PATCH 150/403] Use `PayloadU8` for `ServerEcdhParams` --- rustls/src/msgs/handshake.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 6c714ab513e..d5c26a34bb3 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -1937,7 +1937,8 @@ impl Codec<'_> for ClientDhParams { #[derive(Debug)] pub(crate) struct ServerEcdhParams { pub(crate) curve_params: EcParameters, - pub(crate) public: PayloadU8, + /// RFC4492: `opaque point <1..2^8-1>;` + pub(crate) public: PayloadU8, } impl ServerEcdhParams { From 831d8966f13e4e3ea53311b207e4a366ce0499ff Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 15:42:31 +0100 Subject: [PATCH 151/403] Introduce lower bounds for `PayloadU16` type --- rustls/src/client/ech.rs | 4 ++-- rustls/src/msgs/base.rs | 32 ++++++++++++++++++------------- rustls/src/msgs/handshake.rs | 2 +- rustls/src/msgs/handshake_test.rs | 14 +++++++------- rustls/src/msgs/message_test.rs | 7 +++++-- rustls/src/msgs/persist.rs | 4 ++-- rustls/tests/api.rs | 2 +- 7 files changed, 37 insertions(+), 28 deletions(-) diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index 8a2bd9a86c1..fb2d992493f 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -219,7 +219,7 @@ impl EchGreaseConfig { key_config: HpkeKeyConfig { config_id: config_id[0], kem_id: HpkeKem::DHKEM_P256_HKDF_SHA256, - public_key: PayloadU16(self.placeholder_key.0.clone()), + public_key: PayloadU16::new(self.placeholder_key.0.clone()), symmetric_cipher_suites: vec![suite.sym], }, maximum_name_length: 0, @@ -255,7 +255,7 @@ impl EchGreaseConfig { EncryptedClientHello::Outer(EncryptedClientHelloOuter { cipher_suite: suite.sym, config_id: config_id[0], - enc: PayloadU16(grease_state.enc.0), + enc: PayloadU16::new(grease_state.enc.0), payload: PayloadU16::new(payload), }), )) diff --git a/rustls/src/msgs/base.rs b/rustls/src/msgs/base.rs index 0171cff9f78..3a1b43f4981 100644 --- a/rustls/src/msgs/base.rs +++ b/rustls/src/msgs/base.rs @@ -111,38 +111,44 @@ impl fmt::Debug for PayloadU24<'_> { } /// 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(pub Vec); +pub struct PayloadU16(pub(crate) Vec, PhantomData); -impl PayloadU16 { +impl PayloadU16 { pub fn new(bytes: Vec) -> Self { - Self(bytes) + debug_assert!(bytes.len() >= C::MIN); + Self(bytes, PhantomData) } +} - pub fn empty() -> Self { +impl PayloadU16 { + pub(crate) fn empty() -> Self { Self::new(Vec::new()) } - - pub fn encode_slice(slice: &[u8], bytes: &mut Vec) { - (slice.len() as u16).encode(bytes); - bytes.extend_from_slice(slice); - } } -impl Codec<'_> for PayloadU16 { +impl Codec<'_> for PayloadU16 { fn encode(&self, bytes: &mut Vec) { - Self::encode_slice(&self.0, bytes); + 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 { 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)) + Ok(Self(body, PhantomData)) } } -impl fmt::Debug for PayloadU16 { +impl fmt::Debug for PayloadU16 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { hex(f, &self.0) } diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index d5c26a34bb3..6b8fe1ac4bc 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -3275,7 +3275,7 @@ mod tests { key_config: HpkeKeyConfig { config_id: 0, kem_id: HpkeKem::DHKEM_P256_HKDF_SHA256, - public_key: PayloadU16(b"xxx".into()), + public_key: PayloadU16::new(b"xxx".into()), symmetric_cipher_suites: vec![HpkeSymmetricCipherSuite { kdf_id: HpkeKdf::HKDF_SHA256, aead_id: HpkeAead::AES_128_GCM, diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index a60454a4973..654e1c17b0a 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -946,7 +946,7 @@ fn sample_hello_retry_request() -> HelloRetryRequest { cipher_suite: CipherSuite::TLS_NULL_WITH_NULL_NULL, extensions: vec![ HelloRetryExtension::KeyShare(NamedGroup::X25519), - HelloRetryExtension::Cookie(PayloadU16(vec![0])), + HelloRetryExtension::Cookie(PayloadU16::new(vec![0])), HelloRetryExtension::SupportedVersions(ProtocolVersion::TLSv1_2), HelloRetryExtension::Unknown(UnknownExtension { typ: ExtensionType::Unknown(12345), @@ -984,7 +984,7 @@ fn sample_client_hello_payload() -> ClientHelloPayload { PresharedKeyBinder::from(vec![3, 4, 5]), ], }), - ClientExtension::Cookie(PayloadU16(vec![1, 2, 3])), + ClientExtension::Cookie(PayloadU16::new(vec![1, 2, 3])), ClientExtension::ExtendedMasterSecretRequest, ClientExtension::CertificateStatusRequest(CertificateStatusRequest::build_ocsp()), ClientExtension::ServerCertTypes(vec![CertificateType::RawPublicKey]), @@ -1249,9 +1249,9 @@ fn sample_ecdhe_server_key_exchange_payload() -> ServerKeyExchangePayload { fn sample_dhe_server_key_exchange_payload() -> ServerKeyExchangePayload { ServerKeyExchangePayload::Known(ServerKeyExchange { params: ServerKeyExchangeParams::Dh(ServerDhParams { - dh_p: PayloadU16(vec![1, 2, 3]), - dh_g: PayloadU16(vec![2]), - dh_Ys: PayloadU16(vec![1, 2]), + 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]), }) @@ -1286,7 +1286,7 @@ fn sample_certificate_request_payload_tls13() -> CertificateRequestPayloadTls13 fn sample_new_session_ticket_payload() -> NewSessionTicketPayload { NewSessionTicketPayload { lifetime_hint: 1234, - ticket: Arc::new(PayloadU16(vec![1, 2, 3])), + ticket: Arc::new(PayloadU16::new(vec![1, 2, 3])), } } @@ -1295,7 +1295,7 @@ fn sample_new_session_ticket_payload_tls13() -> NewSessionTicketPayloadTls13 { lifetime: 123, age_add: 1234, nonce: PayloadU8::new(vec![1, 2, 3]), - ticket: Arc::new(PayloadU16(vec![4, 5, 6])), + ticket: Arc::new(PayloadU16::new(vec![4, 5, 6])), exts: vec![NewSessionTicketExtension::Unknown(UnknownExtension { typ: ExtensionType::Unknown(12345), payload: Payload::Borrowed(&[1, 2, 3]), diff --git a/rustls/src/msgs/message_test.rs b/rustls/src/msgs/message_test.rs index e21e9d7cd44..c52fde58575 100644 --- a/rustls/src/msgs/message_test.rs +++ b/rustls/src/msgs/message_test.rs @@ -8,7 +8,7 @@ use super::codec::Reader; use super::enums::AlertLevel; use super::message::{Message, OutboundOpaqueMessage, PlainMessage}; use crate::enums::{AlertDescription, HandshakeType}; -use crate::msgs::base::{NonEmpty, PayloadU8, PayloadU16, PayloadU24}; +use crate::msgs::base::{MaybeEmpty, NonEmpty, PayloadU8, PayloadU16, PayloadU24}; #[test] fn test_read_fuzz_corpus() { @@ -104,7 +104,10 @@ fn debug_payload() { "01020304", format!("{:?}", PayloadU8::::new(vec![1, 2, 3, 4])) ); - assert_eq!("01020304", format!("{:?}", PayloadU16(vec![1, 2, 3, 4]))); + assert_eq!( + "01020304", + format!("{:?}", PayloadU16::::new(vec![1, 2, 3, 4])) + ); assert_eq!( "01020304", format!("{:?}", PayloadU24(Payload::new(vec![1, 2, 3, 4]))) diff --git a/rustls/src/msgs/persist.rs b/rustls/src/msgs/persist.rs index b7708ffe5fa..9179eedfd52 100644 --- a/rustls/src/msgs/persist.rs +++ b/rustls/src/msgs/persist.rs @@ -104,7 +104,7 @@ impl Tls13ClientSessionValue { server_cert_verifier, client_creds, ), - quic_params: PayloadU16(Vec::new()), + quic_params: PayloadU16::new(Vec::new()), } } @@ -129,7 +129,7 @@ impl Tls13ClientSessionValue { } pub fn set_quic_params(&mut self, quic_params: &[u8]) { - self.quic_params = PayloadU16(quic_params.to_vec()); + self.quic_params = PayloadU16::new(quic_params.to_vec()); } pub fn quic_params(&self) -> Vec { diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 4b11090d5db..2f4e32c6df5 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -7283,7 +7283,7 @@ fn test_client_fips_service_indicator_includes_ech_hpke_suite() { key_config: HpkeKeyConfig { config_id: 10, kem_id: suite_id.kem, - public_key: PayloadU16(public_key.0.clone()), + public_key: PayloadU16::new(public_key.0.clone()), symmetric_cipher_suites: vec![HpkeSymmetricCipherSuite { kdf_id: suite_id.sym.kdf_id, aead_id: suite_id.sym.aead_id, From c667f79f72a06057976eae0a3a7aca345c15575d Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 15:44:49 +0100 Subject: [PATCH 152/403] Use `PayloadU16` for `KeyShareEntry` --- rustls/src/msgs/handshake.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 6b8fe1ac4bc..081383690e0 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -373,7 +373,8 @@ impl ConvertProtocolNameList for Vec { #[derive(Clone, Debug)] pub struct KeyShareEntry { pub(crate) group: NamedGroup, - pub(crate) payload: PayloadU16, + /// RFC8446: `opaque key_exchange<1..2^16-1>;` + pub(crate) payload: PayloadU16, } impl KeyShareEntry { From 2ff1c7ad0cb12a4418350b6d6fd0e221fe12ac9c Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 15:48:33 +0100 Subject: [PATCH 153/403] Use `PayloadU16` for `ClientDhParams` --- rustls/src/msgs/handshake.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 081383690e0..2f3d8dda1d5 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -1919,7 +1919,8 @@ impl Codec<'_> for ClientEcdhParams { #[cfg(feature = "tls12")] #[derive(Debug)] pub(crate) struct ClientDhParams { - pub(crate) public: PayloadU16, + /// RFC5246: `opaque dh_Yc<1..2^16-1>;` + pub(crate) public: PayloadU16, } #[cfg(feature = "tls12")] From d282f1999b6e87e649476e64cef143fdc26827e9 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 15:50:29 +0100 Subject: [PATCH 154/403] Use `PayloadU16` for `ServerDhParams` --- rustls/src/msgs/handshake.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 2f3d8dda1d5..106ae284eec 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -1976,9 +1976,12 @@ impl Codec<'_> for ServerEcdhParams { #[derive(Debug)] #[allow(non_snake_case)] pub(crate) struct ServerDhParams { - pub(crate) dh_p: PayloadU16, - pub(crate) dh_g: PayloadU16, - pub(crate) dh_Ys: PayloadU16, + /// RFC5246: `opaque dh_p<1..2^16-1>;` + pub(crate) dh_p: PayloadU16, + /// RFC5246: `opaque dh_g<1..2^16-1>;` + pub(crate) dh_g: PayloadU16, + /// RFC5246: `opaque dh_Ys<1..2^16-1>;` + pub(crate) dh_Ys: PayloadU16, } impl ServerDhParams { From 3aad0a0ebc9acdba4ba9cc22b0d778617de9e442 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 16:03:51 +0100 Subject: [PATCH 155/403] Use `PayloadU16` for `DistinguishedName` --- rustls/src/msgs/handshake.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 106ae284eec..84ed9868306 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -2223,8 +2223,10 @@ wrapped_payload!( /// 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, + PayloadU16, ); impl DistinguishedName { From f7522b7800d954579188e7d5802002f00637858e Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 16:04:49 +0100 Subject: [PATCH 156/403] Use `PayloadU16` for decoding TLS1.3 tickets This is a minor refactor of the existing emptiness check. It does not change the underlying type of tickets as this is shared with TLS1.2. --- rustls/src/msgs/handshake.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 84ed9868306..60c17f4388d 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -2544,13 +2544,14 @@ impl Codec<'_> for NewSessionTicketPayloadTls13 { let lifetime = u32::read(r)?; let age_add = u32::read(r)?; let nonce = PayloadU8::read(r)?; - let ticket = Arc::new(PayloadU16::read(r)?); + // nb. RFC8446: `opaque ticket<1..2^16-1>;` + let ticket = Arc::new(match PayloadU16::::read(r) { + Err(InvalidMessage::IllegalEmptyValue) => Err(InvalidMessage::EmptyTicketValue), + Err(err) => Err(err), + Ok(pl) => Ok(PayloadU16::new(pl.0)), + }?); let exts = Vec::read(r)?; - if ticket.0.is_empty() { - return Err(InvalidMessage::EmptyTicketValue); - } - Ok(Self { lifetime, age_add, From 66ac54f941ea93af7f3be2d8f86eb2b9c0371225 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 16:32:32 +0100 Subject: [PATCH 157/403] Use `PayloadU16` for PSK identity --- rustls/src/msgs/handshake.rs | 3 ++- rustls/src/msgs/handshake_test.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 60c17f4388d..bc6d77f8a68 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -407,7 +407,8 @@ impl Codec<'_> for KeyShareEntry { // --- TLS 1.3 PresharedKey offers --- #[derive(Clone, Debug)] pub(crate) struct PresharedKeyIdentity { - pub(crate) identity: PayloadU16, + /// RFC8446: `opaque identity<1..2^16-1>;` + pub(crate) identity: PayloadU16, pub(crate) obfuscated_ticket_age: u32, } diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index 654e1c17b0a..fdb90fa9702 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -267,7 +267,7 @@ fn rejects_truncated_sni() { #[test] fn can_round_trip_psk_identity() { - let bytes = [0, 0, 0x11, 0x22, 0x33, 0x44]; + 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); From 8dc9af93b35a9bbae1b794a4bdd0637656cfae4b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 16:41:35 +0100 Subject: [PATCH 158/403] Use `PayloadU16` for HPKE public key --- rustls/src/msgs/handshake.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index bc6d77f8a68..39492df1a53 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -2947,7 +2947,8 @@ impl TlsListElement for HpkeSymmetricCipherSuite { pub struct HpkeKeyConfig { pub config_id: u8, pub kem_id: HpkeKem, - pub public_key: PayloadU16, + /// draft-ietf-tls-esni-24: `opaque HpkePublicKey<1..2^16-1>;` + pub public_key: PayloadU16, pub symmetric_cipher_suites: Vec, } From d7146e4ef867c1a55b2a10dbaeaa5f1efe761d7e Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 16:41:53 +0100 Subject: [PATCH 159/403] Use `PayloadU16` for ECH HPKE encrypted payload --- rustls/src/msgs/handshake.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 39492df1a53..adce5314522 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -3177,7 +3177,7 @@ pub struct EncryptedClientHelloOuter { /// 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, + pub payload: PayloadU16, } impl Codec<'_> for EncryptedClientHelloOuter { From b7acce1356df9aba91db5fac90fb91cc3fad811b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 15 Apr 2025 16:54:21 +0100 Subject: [PATCH 160/403] Use `PayloadU16` for TLS1.3 cookies --- bogo/config.json.in | 2 +- rustls/src/msgs/handshake.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index 6953fce9c62..0b1d4092d28 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -287,7 +287,7 @@ "UnknownCurve-HelloRetryRequest-TLS13": ":PEER_MISBEHAVIOUR:", "DisabledCurve-HelloRetryRequest-TLS13": ":PEER_MISBEHAVIOUR:", "HelloRetryRequest-Empty-TLS13": ":PEER_MISBEHAVIOUR:", - "HelloRetryRequest-EmptyCookie-TLS13": ":PEER_MISBEHAVIOUR:", + "HelloRetryRequest-EmptyCookie-TLS13": ":ILLEGAL_EMPTY_VALUE:", "TrailingDataWithFinished-Client-TLS12": ":PEER_MISBEHAVIOUR:", "TrailingDataWithFinished-Resume-Client-TLS12": ":PEER_MISBEHAVIOUR:", "TrailingDataWithFinished-Server-TLS12": ":PEER_MISBEHAVIOUR:", diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index adce5314522..56c87425e87 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -605,7 +605,7 @@ pub enum ClientExtension { KeyShare(Vec), PresharedKeyModes(Vec), PresharedKey(PresharedKeyOffer), - Cookie(PayloadU16), + Cookie(PayloadU16), ExtendedMasterSecretRequest, CertificateStatusRequest(CertificateStatusRequest), ServerCertTypes(Vec), @@ -1235,7 +1235,7 @@ impl ClientHelloPayload { #[derive(Clone, Debug)] pub(crate) enum HelloRetryExtension { KeyShare(NamedGroup), - Cookie(PayloadU16), + Cookie(PayloadU16), SupportedVersions(ProtocolVersion), EchHelloRetryRequest(Vec), Unknown(UnknownExtension), @@ -1358,7 +1358,7 @@ impl HelloRetryRequest { } } - pub(crate) fn cookie(&self) -> Option<&PayloadU16> { + pub(crate) fn cookie(&self) -> Option<&PayloadU16> { let ext = self.find_extension(ExtensionType::Cookie)?; match ext { HelloRetryExtension::Cookie(ck) => Some(ck), From fdf470d58d2933151dbf349c34abe819c540f5eb Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 17 Apr 2025 08:15:07 +0100 Subject: [PATCH 161/403] Rename private enum type `PSKKeyExchangeMode` --- rustls/src/client/hs.rs | 4 ++-- rustls/src/msgs/enums.rs | 10 +++++----- rustls/src/msgs/handshake.rs | 10 +++++----- rustls/src/msgs/handshake_test.rs | 4 ++-- rustls/src/server/tls13.rs | 4 ++-- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 66ea8c67faf..ed0b8f375c1 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -27,7 +27,7 @@ use crate::hash_hs::HandshakeHashBuffer; use crate::log::{debug, trace}; use crate::msgs::base::Payload; use crate::msgs::enums::{ - CertificateType, Compression, ECPointFormat, ExtensionType, PSKKeyExchangeMode, + CertificateType, Compression, ECPointFormat, ExtensionType, PskKeyExchangeMode, }; use crate::msgs::handshake::{ CertificateStatusRequest, ClientExtension, ClientHelloPayload, ClientSessionTicket, @@ -348,7 +348,7 @@ fn emit_client_hello_for_retry( if support_tls13 { // We could support PSK_KE here too. Such connections don't // have forward secrecy, and are similar to TLS1.2 resumption. - let psk_modes = vec![PSKKeyExchangeMode::PSK_DHE_KE]; + let psk_modes = vec![PskKeyExchangeMode::PSK_DHE_KE]; exts.push(ClientExtension::PresharedKeyModes(psk_modes)); } diff --git a/rustls/src/msgs/enums.rs b/rustls/src/msgs/enums.rs index 2e03e85593e..6bf255781c5 100644 --- a/rustls/src/msgs/enums.rs +++ b/rustls/src/msgs/enums.rs @@ -281,11 +281,11 @@ enum_builder! { } enum_builder! { - /// The `PSKKeyExchangeMode` TLS protocol enum. Values in this enum are taken + /// 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 { + pub enum PskKeyExchangeMode { PSK_KE => 0x00, PSK_DHE_KE => 0x01, } @@ -445,9 +445,9 @@ pub(crate) mod tests { HeartbeatMode::PeerNotAllowedToSend, ); test_enum8::(ECCurveType::ExplicitPrime, ECCurveType::NamedCurve); - test_enum8::( - PSKKeyExchangeMode::PSK_KE, - PSKKeyExchangeMode::PSK_DHE_KE, + test_enum8::( + PskKeyExchangeMode::PSK_KE, + PskKeyExchangeMode::PSK_DHE_KE, ); test_enum8::( KeyUpdateRequest::UpdateNotRequested, diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 56c87425e87..152e9a891aa 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -24,7 +24,7 @@ use crate::msgs::codec::{self, Codec, LengthPrefixedBuffer, ListLength, Reader, use crate::msgs::enums::{ CertificateStatusType, CertificateType, ClientCertificateType, Compression, ECCurveType, ECPointFormat, EchVersion, ExtensionType, HpkeAead, HpkeKdf, HpkeKem, KeyUpdateRequest, - NamedGroup, PSKKeyExchangeMode, ServerNameType, + NamedGroup, PskKeyExchangeMode, ServerNameType, }; use crate::rand; use crate::sync::Arc; @@ -559,7 +559,7 @@ impl CertificateStatusRequest { // --- /// RFC8446: `PskKeyExchangeMode ke_modes<1..255>;` -impl TlsListElement for PSKKeyExchangeMode { +impl TlsListElement for PskKeyExchangeMode { const SIZE_LEN: ListLength = ListLength::NonZeroU8 { empty_error: InvalidMessage::IllegalEmptyList("PskKeyExchangeModes"), }; @@ -603,7 +603,7 @@ pub enum ClientExtension { Protocols(Vec), SupportedVersions(Vec), KeyShare(Vec), - PresharedKeyModes(Vec), + PresharedKeyModes(Vec), PresharedKey(PresharedKeyOffer), Cookie(PayloadU16), ExtendedMasterSecretRequest, @@ -1174,7 +1174,7 @@ impl ClientHelloPayload { .is_some_and(|ext| ext.ext_type() == ExtensionType::PreSharedKey) } - pub(crate) fn psk_modes(&self) -> Option<&[PSKKeyExchangeMode]> { + pub(crate) fn psk_modes(&self) -> Option<&[PskKeyExchangeMode]> { let ext = self.find_extension(ExtensionType::PSKKeyExchangeModes)?; match ext { ClientExtension::PresharedKeyModes(psk_modes) => Some(psk_modes), @@ -1182,7 +1182,7 @@ impl ClientHelloPayload { } } - pub(crate) fn psk_mode_offered(&self, mode: PSKKeyExchangeMode) -> bool { + pub(crate) fn psk_mode_offered(&self, mode: PskKeyExchangeMode) -> bool { self.psk_modes() .map(|modes| modes.contains(&mode)) .unwrap_or(false) diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index fdb90fa9702..ecb0af34166 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -7,7 +7,7 @@ use super::base::{Payload, PayloadU8, PayloadU16, PayloadU24}; use super::codec::{Codec, Reader, put_u16}; use super::enums::{ CertificateType, ClientCertificateType, Compression, ECCurveType, ECPointFormat, ExtensionType, - KeyUpdateRequest, NamedGroup, PSKKeyExchangeMode, ServerNameType, + KeyUpdateRequest, NamedGroup, PskKeyExchangeMode, ServerNameType, }; use super::handshake::{ CertReqExtension, CertificateChain, CertificateEntry, CertificateExtension, @@ -973,7 +973,7 @@ fn sample_client_hello_payload() -> ClientHelloPayload { ClientExtension::Protocols(vec![ProtocolName::from(vec![0])]), ClientExtension::SupportedVersions(vec![ProtocolVersion::TLSv1_3]), ClientExtension::KeyShare(vec![KeyShareEntry::new(NamedGroup::X25519, &[1, 2, 3][..])]), - ClientExtension::PresharedKeyModes(vec![PSKKeyExchangeMode::PSK_DHE_KE]), + ClientExtension::PresharedKeyModes(vec![PskKeyExchangeMode::PSK_DHE_KE]), ClientExtension::PresharedKey(PresharedKeyOffer { identities: vec![ PresharedKeyIdentity::new(vec![3, 4, 5], 123456), diff --git a/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index b0908ca2e14..32f27780db4 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -43,7 +43,7 @@ mod client_hello { use crate::enums::SignatureScheme; use crate::msgs::base::{Payload, PayloadU8}; use crate::msgs::ccs::ChangeCipherSpecPayload; - use crate::msgs::enums::{Compression, NamedGroup, PSKKeyExchangeMode}; + use crate::msgs::enums::{Compression, NamedGroup, PskKeyExchangeMode}; use crate::msgs::handshake::{ CertReqExtension, CertificatePayloadTls13, CertificateRequestPayloadTls13, ClientHelloPayload, HelloRetryExtension, HelloRetryRequest, KeyShareEntry, Random, @@ -315,7 +315,7 @@ mod client_hello { } } - if !client_hello.psk_mode_offered(PSKKeyExchangeMode::PSK_DHE_KE) { + if !client_hello.psk_mode_offered(PskKeyExchangeMode::PSK_DHE_KE) { debug!("Client unwilling to resume, DHE_KE not offered"); self.send_tickets = 0; chosen_psk_index = None; From 841a1602755a512bca92b4d7a11e1271a7390dd9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 20 Apr 2025 06:06:14 +0000 Subject: [PATCH 162/403] Update Rust crate brotli to v8 --- Cargo.lock | 18 ++++++++++++++---- Cargo.toml | 2 +- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 316a133daca..4eb981ac01b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -497,13 +497,13 @@ dependencies = [ [[package]] name = "brotli" -version = "7.0.0" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" +checksum = "cf19e729cdbd51af9a397fb9ef8ac8378007b797f8273cfbfdf45dcaa316167b" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", - "brotli-decompressor", + "brotli-decompressor 5.0.0", ] [[package]] @@ -516,6 +516,16 @@ dependencies = [ "alloc-stdlib", ] +[[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 = "bumpalo" version = "3.17.0" @@ -2631,7 +2641,7 @@ dependencies = [ "base64", "bencher", "brotli", - "brotli-decompressor", + "brotli-decompressor 4.0.2", "env_logger", "hashbrown", "hex", diff --git a/Cargo.toml b/Cargo.toml index 61e177c9bc3..2be5488f9b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,7 @@ async-trait = "0.1.74" aws-lc-rs = { version = "1.12", default-features = false } base64 = "0.22" bencher = "0.1.5" -brotli = { version = "7", default-features = false, features = ["std"] } +brotli = { version = "8", default-features = false, features = ["std"] } brotli-decompressor = "4.0.1" # 4.0.1 required for panic fix byteorder = "1.4.3" chacha20poly1305 = { version = "0.10", default-features = false, features = ["alloc"] } From 7f26c4067b3a7d19ba6f0415c9d70d2dfe627c03 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 20 Apr 2025 10:43:10 +0000 Subject: [PATCH 163/403] Update Rust crate brotli-decompressor to v5 --- Cargo.lock | 14 ++------------ Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4eb981ac01b..4b212f6d681 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -503,17 +503,7 @@ checksum = "cf19e729cdbd51af9a397fb9ef8ac8378007b797f8273cfbfdf45dcaa316167b" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", - "brotli-decompressor 5.0.0", -] - -[[package]] -name = "brotli-decompressor" -version = "4.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74fa05ad7d803d413eb8380983b092cbbaf9a85f151b871360e7b00cd7060b37" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", + "brotli-decompressor", ] [[package]] @@ -2641,7 +2631,7 @@ dependencies = [ "base64", "bencher", "brotli", - "brotli-decompressor 4.0.2", + "brotli-decompressor", "env_logger", "hashbrown", "hex", diff --git a/Cargo.toml b/Cargo.toml index 2be5488f9b1..fb9df5b0599 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ aws-lc-rs = { version = "1.12", default-features = false } base64 = "0.22" bencher = "0.1.5" brotli = { version = "8", default-features = false, features = ["std"] } -brotli-decompressor = "4.0.1" # 4.0.1 required for panic fix +brotli-decompressor = "5.0.0" byteorder = "1.4.3" chacha20poly1305 = { version = "0.10", default-features = false, features = ["alloc"] } clap = { version = "4.3.21", features = ["derive", "env"] } From 72902db6e1cb6618e447138babdcb3c5c7684962 Mon Sep 17 00:00:00 2001 From: Eric Lagergren Date: Wed, 16 Apr 2025 10:49:45 -0700 Subject: [PATCH 164/403] add clarifying comments For #2424 Signed-off-by: Eric Lagergren --- rustls/src/client/hs.rs | 24 ++++++++-- rustls/src/client/tls13.rs | 2 + rustls/src/server/hs.rs | 3 ++ rustls/src/tls13/key_schedule.rs | 82 +++++++++++++++++++++++++++++--- 4 files changed, 99 insertions(+), 12 deletions(-) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index ed0b8f375c1..aed2b2c37b8 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -198,6 +198,13 @@ pub(super) fn start_handshake( 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_key_schedule: Option, offered_key_share: Option>, suite: Option, @@ -222,6 +229,11 @@ struct ClientHelloInput { prev_ech_ext: Option, } +/// 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>, @@ -593,7 +605,12 @@ fn emit_client_hello_for_retry( }) } -/// Prepare resumption with the session state retrieved from storage. +/// 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 /// @@ -602,10 +619,7 @@ fn emit_client_hello_for_retry( /// (c) send a request for 1.3 early data if allowed and /// (d) send a 1.3 preshared key if we have one. /// -/// For resumption to work, the currently negotiated cipher suite (if available) must be -/// able to resume from the resuming session's cipher suite. -/// -/// If 1.3 resumption can continue, returns the 1.3 session value for further processing. +/// It returns the TLS 1.3 PSKs, if any, for further processing. fn prepare_resumption<'a>( resuming: &'a Option>, exts: &mut Vec, diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index 94378d68d4c..5ab899e0748 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -63,6 +63,8 @@ static DISALLOWED_TLS13_EXTS: &[ExtensionType] = &[ ExtensionType::ExtendedMasterSecret, ]; +/// `early_key_schedule` is `Some` if we sent the "early_data" +/// extension to the server. pub(super) fn handle_server_hello( config: Arc, cx: &mut ClientContext<'_>, diff --git a/rustls/src/server/hs.rs b/rustls/src/server/hs.rs index 3378e78d025..2453a86f3ab 100644 --- a/rustls/src/server/hs.rs +++ b/rustls/src/server/hs.rs @@ -48,6 +48,9 @@ pub(super) fn can_resume( // 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 diff --git a/rustls/src/tls13/key_schedule.rs b/rustls/src/tls13/key_schedule.rs index 833720a864e..d5d179000e2 100644 --- a/rustls/src/tls13/key_schedule.rs +++ b/rustls/src/tls13/key_schedule.rs @@ -78,7 +78,13 @@ struct KeySchedule { // with an empty or trivial secret, or extract the wrong kind of secrets // at a given point. -/// KeySchedule for early data stage. +/// 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, } @@ -90,6 +96,15 @@ impl KeyScheduleEarly { } } + /// 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, @@ -132,21 +147,47 @@ impl KeyScheduleEarly { } } -/// Pre-handshake key schedule +/// The "early secret" stage of the key schedule. /// -/// The inner `KeySchedule` is either constructed without any secrets based on the HKDF algorithm -/// or is extracted from a `KeyScheduleEarly`. This can then be used to derive the `KeyScheduleHandshakeStart`. +/// Call [`KeySchedulePreHandshake::new`] to create it without +/// a PSK, or use [`From`] 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, @@ -157,6 +198,7 @@ impl KeySchedulePreHandshake { } } +/// Creates a key schedule with a PSK. impl From for KeySchedulePreHandshake { fn from(KeyScheduleEarly { ks }: KeyScheduleEarly) -> Self { Self { ks } @@ -164,6 +206,8 @@ impl From for KeySchedulePreHandshake { } /// KeySchedule during handshake. +/// +/// Created by [`KeySchedulePreHandshake`]. pub(crate) struct KeyScheduleHandshakeStart { ks: KeySchedule, } @@ -641,6 +685,7 @@ impl KeySchedule { self.suite.aead_alg.decrypter(key, iv) } + /// Creates a key schedule without a PSK. fn new_with_empty_secret(suite: &'static Tls13CipherSuite) -> Self { Self { current: suite @@ -651,6 +696,10 @@ impl KeySchedule { } /// 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 @@ -669,6 +718,12 @@ impl KeySchedule { } /// 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) } @@ -692,9 +747,18 @@ impl KeySchedule { } /// Derive a secret of given `kind` using the hash of the empty string - /// for the handshake hash. Useful only for - /// `SecretKind::ResumptionPSKBinderKey` and - /// `SecretKind::DerivedSecret`. + /// 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 empty_hash = self .suite @@ -707,12 +771,16 @@ impl KeySchedule { /// 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 From f8eaf8336bff8ffe97a78359b55388625af2dcbb Mon Sep 17 00:00:00 2001 From: Eric Lagergren Date: Wed, 16 Apr 2025 10:53:19 -0700 Subject: [PATCH 165/403] clarify some field and parameter identifiers For #2424 Signed-off-by: Eric Lagergren --- rustls/src/client/hs.rs | 59 +++++++++++++++++++------------------- rustls/src/client/tls13.rs | 8 +++--- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index aed2b2c37b8..1c55a87c342 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -205,7 +205,7 @@ struct ExpectServerHello { // Otherwise, it is thrown away. // // If this is `None` then we do not support early data. - early_key_schedule: Option, + early_data_key_schedule: Option, offered_key_share: Option>, suite: Option, ech_state: Option, @@ -515,7 +515,7 @@ fn emit_client_hello_for_retry( payload: HandshakePayload::ClientHello(chp_payload), }; - let early_key_schedule = match (ech_state.as_mut(), tls13_session) { + 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 @@ -562,37 +562,38 @@ fn emit_client_hello_for_retry( cx.common.send_msg(ch, false); // Calculate the hash of ClientHello and use it to derive EarlyTrafficSecret - let early_key_schedule = early_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), - }; + let early_data_key_schedule = + tls13_early_data_key_schedule.map(|(resuming_suite, schedule)| { + if !cx.data.early_data.is_enabled() { + return schedule; + } - tls13::derive_early_traffic_secret( - &*config.key_log, - cx, - resuming_suite, - &schedule, - &mut input.sent_tls13_fake_ccs, - transcript_buffer, - random, - ); - 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, + &schedule, + &mut input.sent_tls13_fake_ccs, + transcript_buffer, + random, + ); + schedule + }); let next = ExpectServerHello { input, transcript_buffer, - early_key_schedule, + early_data_key_schedule, offered_key_share: key_share, suite, ech_state, @@ -915,7 +916,7 @@ impl State for ExpectServerHello { randoms, suite, transcript, - self.early_key_schedule, + self.early_data_key_schedule, self.input.hello, // We always send a key share when TLS 1.3 is enabled. self.offered_key_share.unwrap(), diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index 5ab899e0748..98fd747025b 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -63,8 +63,8 @@ static DISALLOWED_TLS13_EXTS: &[ExtensionType] = &[ ExtensionType::ExtendedMasterSecret, ]; -/// `early_key_schedule` is `Some` if we sent the "early_data" -/// extension to the server. +/// `early_data_key_schedule` is `Some` if we sent the +/// "early_data" extension to the server. pub(super) fn handle_server_hello( config: Arc, cx: &mut ClientContext<'_>, @@ -74,7 +74,7 @@ pub(super) fn handle_server_hello( mut randoms: ConnectionRandoms, suite: &'static Tls13CipherSuite, mut transcript: HandshakeHash, - early_key_schedule: Option, + early_data_key_schedule: Option, mut hello: ClientHelloDetails, our_key_share: Box, mut sent_tls13_fake_ccs: bool, @@ -100,7 +100,7 @@ pub(super) fn handle_server_hello( ) })?; - let key_schedule_pre_handshake = match (server_hello.psk_index(), early_key_schedule) { + let key_schedule_pre_handshake = match (server_hello.psk_index(), early_data_key_schedule) { (Some(selected_psk), Some(early_key_schedule)) => { match &resuming_session { Some(resuming) => { From df8c684d58d9cc418e976f5eaca77e1dbce8075c Mon Sep 17 00:00:00 2001 From: Eric Lagergren Date: Wed, 16 Apr 2025 10:56:25 -0700 Subject: [PATCH 166/403] remove unused field Signed-off-by: Eric Lagergren --- rustls/src/client/client_conn.rs | 2 -- rustls/src/client/tls13.rs | 1 - 2 files changed, 3 deletions(-) diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index 39c9d8dca0a..6dd8611df4f 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -969,7 +969,6 @@ impl std::error::Error for EarlyDataError {} #[derive(Debug)] pub struct ClientConnectionData { pub(super) early_data: EarlyData, - pub(super) resumption_ciphersuite: Option, pub(super) ech_status: EchStatus, } @@ -977,7 +976,6 @@ impl ClientConnectionData { fn new() -> Self { Self { early_data: EarlyData::new(), - resumption_ciphersuite: None, ech_status: EchStatus::NotOffered, } } diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index 98fd747025b..c37cc9ef10a 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -341,7 +341,6 @@ pub(super) fn prepare_resumption( ) { let resuming_suite = resuming_session.suite(); cx.common.suite = Some(resuming_suite.into()); - cx.data.resumption_ciphersuite = 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(); From 486de063dd4e72d7850eeed1edd667f4feeac99d Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Wed, 23 Apr 2025 10:37:57 +0200 Subject: [PATCH 167/403] Add support for connection-level ALPN protocol configuration Co-authored-by: CodeMan62 --- rustls/src/client/client_conn.rs | 38 ++++++++++++++++++++++++++++---- rustls/src/client/common.rs | 4 +++- rustls/src/client/hs.rs | 24 +++++++++++--------- rustls/src/client/tls13.rs | 2 +- rustls/src/quic.rs | 25 ++++++++++++++++++++- rustls/tests/api.rs | 30 +++++++++++++++++++++++++ 6 files changed, 106 insertions(+), 17 deletions(-) diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index 6dd8611df4f..1fefadfc980 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -702,11 +702,25 @@ mod connection { /// we behave in the TLS protocol, `name` is the /// name of the server we want to talk to. pub fn new(config: Arc, name: ServerName<'static>) -> Result { + Self::new_with_alpn(Arc::clone(&config), name, config.alpn_protocols.clone()) + } + + /// Make a new ClientConnection with custom ALPN protocols. + pub fn new_with_alpn( + config: Arc, + name: ServerName<'static>, + alpn_protocols: Vec>, + ) -> Result { Ok(Self { - inner: ConnectionCore::for_client(config, name, Vec::new(), Protocol::Tcp)?.into(), + inner: ConnectionCommon::from(ConnectionCore::for_client( + config, + name, + alpn_protocols, + Vec::new(), + 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. /// @@ -821,6 +835,7 @@ impl ConnectionCore { pub(crate) fn for_client( config: Arc, name: ServerName<'static>, + alpn_protocols: Vec>, extra_exts: Vec, proto: Protocol, ) -> Result { @@ -838,7 +853,7 @@ impl ConnectionCore { sendable_plaintext: None, }; - let state = hs::start_handshake(name, extra_exts, config, &mut cx)?; + let state = hs::start_handshake(name, alpn_protocols, extra_exts, config, &mut cx)?; Ok(Self::new(state, data, common_state)) } @@ -859,8 +874,23 @@ 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, name: ServerName<'static>) -> Result { + Self::new_with_alpn(Arc::clone(&config), name, config.alpn_protocols.clone()) + } + + /// Make a new UnbufferedClientConnection with custom ALPN protocols. + pub fn new_with_alpn( + config: Arc, + name: ServerName<'static>, + alpn_protocols: Vec>, + ) -> Result { Ok(Self { - inner: ConnectionCore::for_client(config, name, Vec::new(), Protocol::Tcp)?.into(), + inner: UnbufferedConnectionCommon::from(ConnectionCore::for_client( + config, + name, + alpn_protocols, + Vec::new(), + Protocol::Tcp, + )?), }) } diff --git a/rustls/src/client/common.rs b/rustls/src/client/common.rs index 048b77a640f..74803a866e9 100644 --- a/rustls/src/client/common.rs +++ b/rustls/src/client/common.rs @@ -35,14 +35,16 @@ impl<'a> ServerCertDetails<'a> { } pub(super) struct ClientHelloDetails { + pub(super) alpn_protocols: Vec>, pub(super) sent_extensions: Vec, pub(super) extension_order_seed: u16, pub(super) offered_cert_compression: bool, } impl ClientHelloDetails { - pub(super) fn new(extension_order_seed: u16) -> Self { + pub(super) fn new(alpn_protocols: Vec>, extension_order_seed: u16) -> Self { Self { + alpn_protocols, sent_extensions: Vec::new(), extension_order_seed, offered_cert_compression: false, diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 1c55a87c342..35bd5114581 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -100,6 +100,7 @@ fn find_session( pub(super) fn start_handshake( server_name: ServerName<'static>, + alpn_protocols: Vec>, extra_exts: Vec, config: Arc, cx: &mut ClientContext<'_>, @@ -185,7 +186,7 @@ pub(super) fn start_handshake( #[cfg(feature = "tls12")] using_ems: false, sent_tls13_fake_ccs: false, - hello: ClientHelloDetails::new(extension_order_seed), + hello: ClientHelloDetails::new(alpn_protocols, extension_order_seed), session_id, server_name, prev_ech_ext: None, @@ -364,9 +365,11 @@ fn emit_client_hello_for_retry( exts.push(ClientExtension::PresharedKeyModes(psk_modes)); } - if !config.alpn_protocols.is_empty() { + // Add ALPN extension if we have any protocols + if !input.hello.alpn_protocols.is_empty() { exts.push(ClientExtension::Protocols(Vec::from_slices( - &config + &input + .hello .alpn_protocols .iter() .map(|proto| &proto[..]) @@ -677,16 +680,13 @@ fn prepare_resumption<'a>( pub(super) fn process_alpn_protocol( common: &mut CommonState, - config: &ClientConfig, + offered_protocols: &[Vec], proto: Option<&[u8]>, ) -> Result<(), Error> { common.alpn_protocol = proto.map(ToOwned::to_owned); if let Some(alpn_protocol) = &common.alpn_protocol { - if !config - .alpn_protocols - .contains(alpn_protocol) - { + if !offered_protocols.contains(alpn_protocol) { return Err(common.send_fatal_alert( AlertDescription::IllegalParameter, PeerMisbehaved::SelectedUnofferedApplicationProtocol, @@ -700,7 +700,7 @@ pub(super) fn process_alpn_protocol( // 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() && !config.alpn_protocols.is_empty() { + if common.is_quic() && common.alpn_protocol.is_none() && !offered_protocols.is_empty() { return Err(common.send_fatal_alert( AlertDescription::NoApplicationProtocol, Error::NoApplicationProtocol, @@ -838,7 +838,11 @@ impl State for ExpectServerHello { // Extract ALPN protocol if !cx.common.is_tls13() { - process_alpn_protocol(cx.common, config, server_hello.alpn_protocol())?; + process_alpn_protocol( + cx.common, + &self.input.hello.alpn_protocols, + server_hello.alpn_protocol(), + )?; } // If ECPointFormats extension is supplied by the server, it must contain diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index c37cc9ef10a..70b7d0e7c9d 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -473,7 +473,7 @@ impl State for ExpectEncryptedExtensions { self.transcript.add_message(&m); validate_encrypted_extensions(cx.common, &self.hello, exts)?; - hs::process_alpn_protocol(cx.common, &self.config, exts.alpn_protocol())?; + hs::process_alpn_protocol(cx.common, &self.hello.alpn_protocols, exts.alpn_protocol())?; hs::process_client_cert_type_extension(cx.common, &self.config, exts.client_cert_type())?; hs::process_server_cert_type_extension(cx.common, &self.config, exts.server_cert_type())?; diff --git a/rustls/src/quic.rs b/rustls/src/quic.rs index 69c2fc49ab9..df806eca0c4 100644 --- a/rustls/src/quic.rs +++ b/rustls/src/quic.rs @@ -163,6 +163,23 @@ mod connection { quic_version: Version, name: ServerName<'static>, params: Vec, + ) -> Result { + Self::new_with_alpn( + Arc::clone(&config), + quic_version, + name, + params, + config.alpn_protocols.clone(), + ) + } + + /// Make a new QUIC ClientConnection with custom ALPN protocols. + pub fn new_with_alpn( + config: Arc, + quic_version: Version, + name: ServerName<'static>, + params: Vec, + alpn_protocols: Vec>, ) -> Result { if !config.supports_version(ProtocolVersion::TLSv1_3) { return Err(Error::General( @@ -181,7 +198,13 @@ mod connection { Version::V1 | Version::V2 => ClientExtension::TransportParameters(params), }; - let mut inner = ConnectionCore::for_client(config, name, vec![ext], Protocol::Quic)?; + let mut inner = ConnectionCore::for_client( + config, + name, + alpn_protocols, + vec![ext], + Protocol::Quic, + )?; inner.common_state.quic.version = quic_version; Ok(Self { inner: inner.into(), diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 2f4e32c6df5..4d797308d3d 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -510,6 +510,36 @@ fn alpn() { ); } +#[test] +fn connection_level_alpn_protocols() { + let mut server_config = make_server_config(KeyType::Rsa2048); + server_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()]; + let server_config = Arc::new(server_config); + + // Config specifies `h2` + let mut client_config = make_client_config(KeyType::Rsa2048); + client_config.alpn_protocols = vec![b"h2".to_vec()]; + let client_config = Arc::new(client_config); + + // Client relies on config-specified `h2`, server agrees + let mut client = + ClientConnection::new(client_config.clone(), server_name("localhost")).unwrap(); + let mut server = ServerConnection::new(server_config.clone()).unwrap(); + do_handshake_until_error(&mut client, &mut server).unwrap(); + assert_eq!(client.alpn_protocol(), Some(&b"h2"[..])); + + // Specify `http/1.1` for the connection, server agrees + let mut client = ClientConnection::new_with_alpn( + client_config, + server_name("localhost"), + vec![b"http/1.1".to_vec()], + ) + .unwrap(); + let mut server = ServerConnection::new(server_config).unwrap(); + do_handshake_until_error(&mut client, &mut server).unwrap(); + assert_eq!(client.alpn_protocol(), Some(&b"http/1.1"[..])); +} + fn version_test( client_versions: &[&'static rustls::SupportedProtocolVersion], server_versions: &[&'static rustls::SupportedProtocolVersion], From 53580f7890a1a6217397f71d00cd3389878f1632 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 4 Apr 2025 11:07:16 +0100 Subject: [PATCH 168/403] Externalise copy of `end_entity_ocsp` return value --- rustls/src/client/tls13.rs | 2 +- rustls/src/msgs/handshake.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index 70b7d0e7c9d..ca7c1500f50 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -1084,7 +1084,7 @@ impl State for ExpectCertificate { PeerMisbehaved::BadCertChainExtensions, )); } - let end_entity_ocsp = cert_chain.end_entity_ocsp(); + let end_entity_ocsp = cert_chain.end_entity_ocsp().to_vec(); let server_cert = ServerCertDetails::new( cert_chain .into_certificate_chain() diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 152e9a891aa..31c0736f92a 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -1794,11 +1794,10 @@ impl<'a> CertificatePayloadTls13<'a> { false } - pub(crate) fn end_entity_ocsp(&self) -> Vec { + pub(crate) fn end_entity_ocsp(&self) -> &[u8] { self.entries .first() .and_then(CertificateEntry::ocsp_response) - .map(|resp| resp.to_vec()) .unwrap_or_default() } From 14ff4f37694e9cd627b29c229a4bde8eed70e604 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 28 Apr 2025 11:10:26 +0100 Subject: [PATCH 169/403] Extract reading of `ListLength` --- rustls/src/msgs/codec.rs | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/rustls/src/msgs/codec.rs b/rustls/src/msgs/codec.rs index b73e713c432..17cf35c65c2 100644 --- a/rustls/src/msgs/codec.rs +++ b/rustls/src/msgs/codec.rs @@ -225,22 +225,7 @@ impl<'a, T: Codec<'a> + TlsListElement + Debug> Codec<'a> for Vec { } fn read(r: &mut Reader<'a>) -> Result { - let len = match T::SIZE_LEN { - ListLength::NonZeroU8 { empty_error } => match usize::from(u8::read(r)?) { - 0 => return Err(empty_error), - len => len, - }, - ListLength::U16 => usize::from(u16::read(r)?), - ListLength::NonZeroU16 { empty_error } => match usize::from(u16::read(r)?) { - 0 => return Err(empty_error), - len => len, - }, - ListLength::U24 { max, error } => match usize::from(u24::read(r)?) { - len if len > max => return Err(error), - len => len, - }, - }; - + let len = T::SIZE_LEN.read(r)?; let mut sub = r.sub(len)?; let mut ret = Self::new(); while sub.any_left() { @@ -280,6 +265,26 @@ pub(crate) enum ListLength { U24 { max: usize, error: InvalidMessage }, } +impl ListLength { + pub(crate) fn read(&self, r: &mut Reader<'_>) -> Result { + 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, From 2caa30488178ebd08a4cfd6763d659df34c81dd9 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 28 Apr 2025 11:18:38 +0100 Subject: [PATCH 170/403] Optimize client's SupportedVersions ext repr --- rustls/src/client/hs.rs | 57 +++++++++++-------------- rustls/src/msgs/handshake.rs | 69 +++++++++++++++++++++++++++++-- rustls/src/msgs/handshake_test.rs | 8 +++- rustls/src/server/hs.rs | 4 +- 4 files changed, 97 insertions(+), 41 deletions(-) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 35bd5114581..47a788798b8 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -29,6 +29,7 @@ use crate::msgs::base::Payload; use crate::msgs::enums::{ CertificateType, Compression, ECPointFormat, ExtensionType, PskKeyExchangeMode, }; +use crate::msgs::handshake::SupportedProtocolVersions; use crate::msgs::handshake::{ CertificateStatusRequest, ClientExtension, ClientHelloPayload, ClientSessionTicket, ConvertProtocolNameList, HandshakeMessagePayload, HandshakePayload, HasServerExtensions, @@ -249,31 +250,21 @@ fn emit_client_hello_for_retry( // 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 support_tls12 = config.supports_version(ProtocolVersion::TLSv1_2) && !forbids_tls12; - let support_tls13 = config.supports_version(ProtocolVersion::TLSv1_3); - let mut supported_versions = Vec::new(); - if support_tls13 { - supported_versions.push(ProtocolVersion::TLSv1_3); - } - - if support_tls12 { - supported_versions.push(ProtocolVersion::TLSv1_2); - } + 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.is_empty()); + assert!(supported_versions.any(|_| true)); // offer groups which are usable for any offered version let offered_groups = config .provider .kx_groups .iter() - .filter(|skxg| { - supported_versions - .iter() - .any(|v| skxg.usable_for_version(*v)) - }) + .filter(|skxg| supported_versions.any(|v| skxg.usable_for_version(v))) .map(|skxg| skxg.name()) .collect(); @@ -289,7 +280,7 @@ fn emit_client_hello_for_retry( ClientExtension::CertificateStatusRequest(CertificateStatusRequest::build_ocsp()), ]; - if support_tls13 { + if supported_versions.tls13 { if let Some(cas_extension) = config.verifier.root_hint_subjects() { exts.push(ClientExtension::AuthorityNames(cas_extension.to_owned())); } @@ -327,7 +318,7 @@ fn emit_client_hello_for_retry( }; if let Some(key_share) = &key_share { - debug_assert!(support_tls13); + debug_assert!(supported_versions.tls13); let mut shares = vec![KeyShareEntry::new(key_share.group(), key_share.pub_key())]; if !retryreq @@ -358,7 +349,7 @@ fn emit_client_hello_for_retry( exts.push(ClientExtension::Cookie(cookie.clone())); } - if support_tls13 { + 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. let psk_modes = vec![PskKeyExchangeMode::PSK_DHE_KE]; @@ -377,19 +368,19 @@ fn emit_client_hello_for_retry( ))); } - input.hello.offered_cert_compression = if support_tls13 && !config.cert_decompressors.is_empty() - { - exts.push(ClientExtension::CertificateCompressionAlgorithms( - config - .cert_decompressors - .iter() - .map(|dec| dec.algorithm()) - .collect(), - )); - true - } else { - false - }; + input.hello.offered_cert_compression = + if supported_versions.tls13 && !config.cert_decompressors.is_empty() { + exts.push(ClientExtension::CertificateCompressionAlgorithms( + config + .cert_decompressors + .iter() + .map(|dec| dec.algorithm()) + .collect(), + )); + true + } else { + false + }; if config .client_auth_cert_resolver @@ -602,7 +593,7 @@ fn emit_client_hello_for_retry( ech_state, }; - Ok(if support_tls13 && retryreq.is_none() { + Ok(if supported_versions.tls13 && retryreq.is_none() { Box::new(ExpectServerHelloOrHelloRetryRequest { next, extra_exts }) } else { Box::new(next) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 31c0736f92a..b91ba5567ce 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -570,7 +570,66 @@ 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 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) { + 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 { + let len = Self::LIST_LENGTH.read(reader)?; + let mut sub = reader.sub(len)?; + + let mut tls12 = false; + let mut tls13 = false; + + while sub.any_left() { + match ProtocolVersion::read(&mut sub)? { + 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"), @@ -601,7 +660,7 @@ pub enum ClientExtension { ServerName(Vec), SessionTicket(ClientSessionTicket), Protocols(Vec), - SupportedVersions(Vec), + SupportedVersions(SupportedProtocolVersions), KeyShare(Vec), PresharedKeyModes(Vec), PresharedKey(PresharedKeyOffer), @@ -705,7 +764,9 @@ impl Codec<'_> for ClientExtension { } } ExtensionType::ALProtocolNegotiation => Self::Protocols(Vec::read(&mut sub)?), - ExtensionType::SupportedVersions => Self::SupportedVersions(Vec::read(&mut sub)?), + ExtensionType::SupportedVersions => { + Self::SupportedVersions(SupportedProtocolVersions::read(&mut sub)?) + } ExtensionType::KeyShare => Self::KeyShare(Vec::read(&mut sub)?), ExtensionType::PSKKeyExchangeModes => Self::PresharedKeyModes(Vec::read(&mut sub)?), ExtensionType::PreSharedKey => Self::PresharedKey(PresharedKeyOffer::read(&mut sub)?), @@ -1132,10 +1193,10 @@ impl ClientHelloPayload { self.find_extension(ExtensionType::SessionTicket) } - pub(crate) fn versions_extension(&self) -> Option<&[ProtocolVersion]> { + pub(crate) fn versions_extension(&self) -> Option { let ext = self.find_extension(ExtensionType::SupportedVersions)?; match ext { - ClientExtension::SupportedVersions(vers) => Some(vers), + ClientExtension::SupportedVersions(vers) => Some(*vers), _ => None, } } diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index ecb0af34166..5b43086733f 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -19,7 +19,8 @@ use super::handshake::{ NewSessionTicketExtension, NewSessionTicketPayload, NewSessionTicketPayloadTls13, PresharedKeyBinder, PresharedKeyIdentity, PresharedKeyOffer, ProtocolName, Random, ServerDhParams, ServerEcdhParams, ServerExtension, ServerHelloPayload, ServerKeyExchange, - ServerKeyExchangeParams, ServerKeyExchangePayload, SessionId, UnknownExtension, + ServerKeyExchangeParams, ServerKeyExchangePayload, SessionId, SupportedProtocolVersions, + UnknownExtension, }; use crate::enums::{ CertificateCompressionAlgorithm, CipherSuite, HandshakeType, ProtocolVersion, SignatureScheme, @@ -971,7 +972,10 @@ fn sample_client_hello_payload() -> ClientHelloPayload { ClientExtension::SessionTicket(ClientSessionTicket::Request), ClientExtension::SessionTicket(ClientSessionTicket::Offer(Payload::Borrowed(&[]))), ClientExtension::Protocols(vec![ProtocolName::from(vec![0])]), - ClientExtension::SupportedVersions(vec![ProtocolVersion::TLSv1_3]), + ClientExtension::SupportedVersions(SupportedProtocolVersions { + tls13: true, + ..Default::default() + }), ClientExtension::KeyShare(vec![KeyShareEntry::new(NamedGroup::X25519, &[1, 2, 3][..])]), ClientExtension::PresharedKeyModes(vec![PskKeyExchangeMode::PSK_DHE_KE]), ClientExtension::PresharedKey(PresharedKeyOffer { diff --git a/rustls/src/server/hs.rs b/rustls/src/server/hs.rs index 2453a86f3ab..43f0b568a9a 100644 --- a/rustls/src/server/hs.rs +++ b/rustls/src/server/hs.rs @@ -348,9 +348,9 @@ impl ExpectClientHello { // Are we doing TLS1.3? let maybe_versions_ext = client_hello.versions_extension(); let version = if let Some(versions) = maybe_versions_ext { - if versions.contains(&ProtocolVersion::TLSv1_3) && tls13_enabled { + if versions.tls13 && tls13_enabled { ProtocolVersion::TLSv1_3 - } else if !versions.contains(&ProtocolVersion::TLSv1_2) || !tls12_enabled { + } else if !versions.tls12 || !tls12_enabled { return Err(cx.common.send_fatal_alert( AlertDescription::ProtocolVersion, PeerIncompatible::Tls12NotOfferedOrEnabled, From 17ef9e3a8fb6171ea9f7f9d1df026c6f77893997 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 28 Apr 2025 11:39:51 +0100 Subject: [PATCH 171/403] Simplify ALPN server extension representation --- rustls/src/msgs/handshake.rs | 53 ++++++++++++++++++++++++------- rustls/src/msgs/handshake_test.rs | 8 ++--- rustls/src/server/hs.rs | 6 ++-- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index b91ba5567ce..5b36b16743e 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -340,7 +340,6 @@ impl TlsListElement for ProtocolName { pub(crate) trait ConvertProtocolNameList { fn from_slices(names: &[&[u8]]) -> Self; fn to_slices(&self) -> Vec<&[u8]>; - fn as_single_slice(&self) -> Option<&[u8]>; } impl ConvertProtocolNameList for Vec { @@ -359,16 +358,48 @@ impl ConvertProtocolNameList for Vec { .map(|proto| proto.as_ref()) .collect::>() } +} + +/// RFC7301 encodes a single protocol name as `Vec` +#[derive(Clone, Debug)] +pub struct SingleProtocolName(ProtocolName); + +impl SingleProtocolName { + pub(crate) fn new(bytes: Vec) -> Self { + Self(ProtocolName::from(bytes)) + } + + const SIZE_LEN: ListLength = ListLength::NonZeroU16 { + empty_error: InvalidMessage::IllegalEmptyList("ProtocolNames"), + }; +} + +impl Codec<'_> for SingleProtocolName { + fn encode(&self, bytes: &mut Vec) { + let body = LengthPrefixedBuffer::new(Self::SIZE_LEN, bytes); + self.0.encode(body.buf); + } - fn as_single_slice(&self) -> Option<&[u8]> { - if self.len() == 1 { - Some(self[0].as_ref()) + fn read(reader: &mut Reader<'_>) -> Result { + 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 { - None + Ok(Self(item)) } } } +impl AsRef<[u8]> for SingleProtocolName { + fn as_ref(&self) -> &[u8] { + self.0.as_ref() + } +} + // --- TLS 1.3 Key shares --- #[derive(Clone, Debug)] pub struct KeyShareEntry { @@ -845,7 +876,7 @@ pub enum ServerExtension { ServerNameAck, SessionTicketAck, RenegotiationInfo(PayloadU8), - Protocols(Vec), + Protocols(SingleProtocolName), KeyShare(KeyShareEntry), PresharedKey(u16), ExtendedMasterSecretAck, @@ -922,7 +953,9 @@ impl Codec<'_> for ServerExtension { ExtensionType::SessionTicket => Self::SessionTicketAck, ExtensionType::StatusRequest => Self::CertificateStatusAck, ExtensionType::RenegotiationInfo => Self::RenegotiationInfo(PayloadU8::read(&mut sub)?), - ExtensionType::ALProtocolNegotiation => Self::Protocols(Vec::read(&mut sub)?), + ExtensionType::ALProtocolNegotiation => { + Self::Protocols(SingleProtocolName::read(&mut sub)?) + } ExtensionType::ClientCertificateType => { Self::ClientCertType(CertificateType::read(&mut sub)?) } @@ -952,10 +985,6 @@ impl Codec<'_> for ServerExtension { } impl ServerExtension { - pub(crate) fn make_alpn(proto: &[&[u8]]) -> Self { - Self::Protocols(Vec::from_slices(proto)) - } - #[cfg(feature = "tls12")] pub(crate) fn make_empty_renegotiation_info() -> Self { let empty = Vec::new(); @@ -2212,7 +2241,7 @@ pub(crate) trait HasServerExtensions { fn alpn_protocol(&self) -> Option<&[u8]> { let ext = self.find_extension(ExtensionType::ALProtocolNegotiation)?; match ext { - ServerExtension::Protocols(protos) => protos.as_single_slice(), + ServerExtension::Protocols(protos) => Some(protos.as_ref()), _ => None, } } diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index 5b43086733f..6d6813897f6 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -19,8 +19,8 @@ use super::handshake::{ NewSessionTicketExtension, NewSessionTicketPayload, NewSessionTicketPayloadTls13, PresharedKeyBinder, PresharedKeyIdentity, PresharedKeyOffer, ProtocolName, Random, ServerDhParams, ServerEcdhParams, ServerExtension, ServerHelloPayload, ServerKeyExchange, - ServerKeyExchangeParams, ServerKeyExchangePayload, SessionId, SupportedProtocolVersions, - UnknownExtension, + ServerKeyExchangeParams, ServerKeyExchangePayload, SessionId, SingleProtocolName, + SupportedProtocolVersions, UnknownExtension, }; use crate::enums::{ CertificateCompressionAlgorithm, CipherSuite, HandshakeType, ProtocolVersion, SignatureScheme, @@ -340,7 +340,6 @@ fn can_round_trip_multi_proto() { ClientExtension::Protocols(prot) => { assert_eq!(2, prot.len()); assert_eq!(vec![b"hi", b"lo"], prot.to_slices()); - assert_eq!(prot.as_single_slice(), None); } _ => unreachable!(), } @@ -359,7 +358,6 @@ fn can_round_trip_single_proto() { ClientExtension::Protocols(prot) => { assert_eq!(1, prot.len()); assert_eq!(vec![b"hi"], prot.to_slices()); - assert_eq!(prot.as_single_slice(), Some(&b"hi"[..])); } _ => unreachable!(), } @@ -1019,7 +1017,7 @@ fn sample_server_hello_payload() -> ServerHelloPayload { ServerExtension::ServerNameAck, ServerExtension::SessionTicketAck, ServerExtension::RenegotiationInfo(PayloadU8::new(vec![0])), - ServerExtension::Protocols(vec![ProtocolName::from(vec![0])]), + ServerExtension::Protocols(SingleProtocolName::new(vec![0])), ServerExtension::KeyShare(KeyShareEntry::new(NamedGroup::X25519, &[1, 2, 3][..])), ServerExtension::PresharedKey(3), ServerExtension::ExtendedMasterSecretAck, diff --git a/rustls/src/server/hs.rs b/rustls/src/server/hs.rs index 43f0b568a9a..9f7d384cd2c 100644 --- a/rustls/src/server/hs.rs +++ b/rustls/src/server/hs.rs @@ -22,7 +22,7 @@ use crate::msgs::enums::{CertificateType, Compression, ExtensionType, NamedGroup use crate::msgs::handshake::SessionId; use crate::msgs::handshake::{ ClientHelloPayload, ConvertProtocolNameList, ConvertServerNameList, HandshakePayload, - KeyExchangeAlgorithm, Random, ServerExtension, + KeyExchangeAlgorithm, Random, ServerExtension, SingleProtocolName, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; @@ -98,7 +98,9 @@ impl ExtensionProcessing { if let Some(selected_protocol) = &cx.common.alpn_protocol { debug!("Chosen ALPN protocol {:?}", selected_protocol); self.exts - .push(ServerExtension::make_alpn(&[selected_protocol])); + .push(ServerExtension::Protocols(SingleProtocolName::new( + selected_protocol.clone(), + ))); } else if !our_protocols.is_empty() { return Err(cx.common.send_fatal_alert( AlertDescription::NoApplicationProtocol, From 2fb28bbd896bdc07b99eb8d578831d58f410a36d Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 28 Apr 2025 11:51:07 +0100 Subject: [PATCH 172/403] Eliminate `ConvertProtocolNameList` Now a given decoded `ProtocolName` cannot be empty, there is no need to check that manually. --- rustls/src/client/hs.rs | 13 +++++++------ rustls/src/msgs/handshake.rs | 23 ----------------------- rustls/src/msgs/handshake_test.rs | 26 ++++++++++++++++++-------- rustls/src/server/hs.rs | 19 +++++++------------ 4 files changed, 32 insertions(+), 49 deletions(-) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 47a788798b8..e59cba279f7 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -29,11 +29,12 @@ use crate::msgs::base::Payload; use crate::msgs::enums::{ CertificateType, Compression, ECPointFormat, ExtensionType, PskKeyExchangeMode, }; +use crate::msgs::handshake::ProtocolName; use crate::msgs::handshake::SupportedProtocolVersions; use crate::msgs::handshake::{ CertificateStatusRequest, ClientExtension, ClientHelloPayload, ClientSessionTicket, - ConvertProtocolNameList, HandshakeMessagePayload, HandshakePayload, HasServerExtensions, - HelloRetryRequest, KeyShareEntry, Random, SessionId, + HandshakeMessagePayload, HandshakePayload, HasServerExtensions, HelloRetryRequest, + KeyShareEntry, Random, SessionId, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; @@ -358,14 +359,14 @@ fn emit_client_hello_for_retry( // Add ALPN extension if we have any protocols if !input.hello.alpn_protocols.is_empty() { - exts.push(ClientExtension::Protocols(Vec::from_slices( - &input + exts.push(ClientExtension::Protocols( + input .hello .alpn_protocols .iter() - .map(|proto| &proto[..]) + .map(|proto| ProtocolName::from(proto.clone())) .collect::>(), - ))); + )); } input.hello.offered_cert_compression = diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 5b36b16743e..1969f9a05ac 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -337,29 +337,6 @@ impl TlsListElement for ProtocolName { }; } -pub(crate) trait ConvertProtocolNameList { - fn from_slices(names: &[&[u8]]) -> Self; - fn to_slices(&self) -> Vec<&[u8]>; -} - -impl ConvertProtocolNameList for Vec { - fn from_slices(names: &[&[u8]]) -> Self { - let mut ret = Self::new(); - - for name in names { - ret.push(ProtocolName::from(name.to_vec())); - } - - ret - } - - fn to_slices(&self) -> Vec<&[u8]> { - self.iter() - .map(|proto| proto.as_ref()) - .collect::>() - } -} - /// RFC7301 encodes a single protocol name as `Vec` #[derive(Clone, Debug)] pub struct SingleProtocolName(ProtocolName); diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index 6d6813897f6..21f038a141c 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -13,12 +13,12 @@ use super::handshake::{ CertReqExtension, CertificateChain, CertificateEntry, CertificateExtension, CertificatePayloadTls13, CertificateRequestPayload, CertificateRequestPayloadTls13, CertificateStatus, CertificateStatusRequest, ClientExtension, ClientHelloPayload, - ClientSessionTicket, CompressedCertificatePayload, ConvertProtocolNameList, - ConvertServerNameList, DistinguishedName, EcParameters, HandshakeMessagePayload, - HandshakePayload, HasServerExtensions, HelloRetryExtension, HelloRetryRequest, KeyShareEntry, - NewSessionTicketExtension, NewSessionTicketPayload, NewSessionTicketPayloadTls13, - PresharedKeyBinder, PresharedKeyIdentity, PresharedKeyOffer, ProtocolName, Random, - ServerDhParams, ServerEcdhParams, ServerExtension, ServerHelloPayload, ServerKeyExchange, + ClientSessionTicket, CompressedCertificatePayload, ConvertServerNameList, DistinguishedName, + EcParameters, HandshakeMessagePayload, HandshakePayload, HasServerExtensions, + HelloRetryExtension, HelloRetryRequest, KeyShareEntry, NewSessionTicketExtension, + NewSessionTicketPayload, NewSessionTicketPayloadTls13, PresharedKeyBinder, + PresharedKeyIdentity, PresharedKeyOffer, ProtocolName, Random, ServerDhParams, + ServerEcdhParams, ServerExtension, ServerHelloPayload, ServerKeyExchange, ServerKeyExchangeParams, ServerKeyExchangePayload, SessionId, SingleProtocolName, SupportedProtocolVersions, UnknownExtension, }; @@ -339,7 +339,12 @@ fn can_round_trip_multi_proto() { match ext { ClientExtension::Protocols(prot) => { assert_eq!(2, prot.len()); - assert_eq!(vec![b"hi", b"lo"], prot.to_slices()); + assert_eq!( + vec![b"hi", b"lo"], + prot.iter() + .map(|p| p.as_ref()) + .collect::>() + ); } _ => unreachable!(), } @@ -357,7 +362,12 @@ fn can_round_trip_single_proto() { match ext { ClientExtension::Protocols(prot) => { assert_eq!(1, prot.len()); - assert_eq!(vec![b"hi"], prot.to_slices()); + assert_eq!( + vec![b"hi"], + prot.iter() + .map(|p| p.as_ref()) + .collect::>() + ); } _ => unreachable!(), } diff --git a/rustls/src/server/hs.rs b/rustls/src/server/hs.rs index 9f7d384cd2c..faae4832223 100644 --- a/rustls/src/server/hs.rs +++ b/rustls/src/server/hs.rs @@ -21,8 +21,8 @@ use crate::msgs::enums::{CertificateType, Compression, ExtensionType, NamedGroup #[cfg(feature = "tls12")] use crate::msgs::handshake::SessionId; use crate::msgs::handshake::{ - ClientHelloPayload, ConvertProtocolNameList, ConvertServerNameList, HandshakePayload, - KeyExchangeAlgorithm, Random, ServerExtension, SingleProtocolName, + ClientHelloPayload, ConvertServerNameList, HandshakePayload, KeyExchangeAlgorithm, Random, + ServerExtension, SingleProtocolName, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; @@ -82,18 +82,13 @@ impl ExtensionProcessing { let our_protocols = &config.alpn_protocols; let maybe_their_protocols = hello.alpn_extension(); if let Some(their_protocols) = maybe_their_protocols { - let their_protocols = their_protocols.to_slices(); - - if their_protocols - .iter() - .any(|protocol| protocol.is_empty()) - { - return Err(PeerMisbehaved::OfferedEmptyApplicationProtocol.into()); - } - cx.common.alpn_protocol = our_protocols .iter() - .find(|protocol| their_protocols.contains(&protocol.as_slice())) + .find(|ours| { + their_protocols + .iter() + .any(|theirs| theirs.as_ref() == ours.as_slice()) + }) .cloned(); if let Some(selected_protocol) = &cx.common.alpn_protocol { debug!("Chosen ALPN protocol {:?}", selected_protocol); From ffac73a071248807bc96cc84230518aaa38b5b3f Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 28 Apr 2025 12:23:12 +0100 Subject: [PATCH 173/403] Simplify SNI client extension representation Retire `Vec`, as in practice there can never be more than one value: unknown name types (and everything that follows them) cannot be decoded, and only one value of each name type is allowed. Eliminates `ServerName` type which was confusingly overlapping with `rustls-pki-types::ServerName`. --- rustls/src/client/ech.rs | 6 +- rustls/src/client/hs.rs | 6 +- rustls/src/lib.rs | 2 +- rustls/src/msgs/handshake.rs | 211 +++++++++++++++--------------- rustls/src/msgs/handshake_test.rs | 68 +++------- rustls/src/server/hs.rs | 36 ++--- rustls/tests/api.rs | 4 +- 7 files changed, 153 insertions(+), 180 deletions(-) diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index fb2d992493f..dec0f6ef821 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -19,7 +19,7 @@ use crate::msgs::handshake::{ ClientExtension, ClientHelloPayload, EchConfigContents, EchConfigPayload, Encoding, EncryptedClientHello, EncryptedClientHelloOuter, HandshakeMessagePayload, HandshakePayload, HelloRetryRequest, HpkeKeyConfig, HpkeSymmetricCipherSuite, PresharedKeyBinder, - PresharedKeyOffer, Random, ServerHelloPayload, + PresharedKeyOffer, Random, ServerHelloPayload, ServerNamePayload, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; @@ -620,7 +620,9 @@ impl EchState { if let Some(sni_value) = inner_sni { inner_hello .extensions - .push(ClientExtension::make_sni(&sni_value.borrow())); + .push(ClientExtension::ServerName(ServerNamePayload::from( + sni_value, + ))); } // We don't want to add, or compress, the SNI from the outer hello. continue; diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index e59cba279f7..5e10682c589 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -304,13 +304,15 @@ fn emit_client_hello_for_retry( // 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), _) => exts.push(ClientExtension::make_sni(&ech_state.outer_name)), + (Some(ech_state), _) => { + exts.push(ClientExtension::ServerName((&ech_state.outer_name).into())) + } // If we have no ECH state, and SNI is enabled, try to use the input server_name // for the SNI domain name. (None, true) => { if let ServerName::DnsName(dns_name) = &input.server_name { - exts.push(ClientExtension::make_sni(dns_name)) + exts.push(ClientExtension::ServerName(dns_name.into())); } } diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index d19183ef47c..8dec9a50fd0 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -487,7 +487,7 @@ pub mod internal { CertificateChain, ClientExtension, ClientHelloPayload, DistinguishedName, EchConfigContents, EchConfigPayload, HandshakeMessagePayload, HandshakePayload, HpkeKeyConfig, HpkeSymmetricCipherSuite, KeyShareEntry, Random, ServerExtension, - ServerName, SessionId, + SessionId, }; } pub mod message { diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 1969f9a05ac..453de5b7d1b 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -228,100 +228,131 @@ impl TlsListElement for SignatureScheme { } #[derive(Clone, Debug)] -pub(crate) enum ServerNamePayload { - HostName(DnsName<'static>), - IpAddress(PayloadU16), - Unknown(Payload<'static>), -} +pub enum ServerNamePayload<'a> { + /// A successfully decoded value: + SingleDnsName(DnsName<'a>), -impl ServerNamePayload { - pub(crate) fn new_hostname(hostname: DnsName<'static>) -> Self { - Self::HostName(hostname) - } + /// A DNS name which was actually an IP address + IpAddress, - fn read_hostname(r: &mut Reader<'_>) -> Result { - use pki_types::ServerName; - let raw = PayloadU16::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(_) => { - warn!( - "Illegal SNI hostname received {:?}", - String::from_utf8_lossy(&raw.0) - ); - Err(InvalidMessage::InvalidServerName) - } - } - } + /// A successfully decoded, but syntactically-invalid value. + Invalid, +} - fn encode(&self, bytes: &mut Vec) { +impl ServerNamePayload<'_> { + fn into_owned(self) -> ServerNamePayload<'static> { match self { - Self::HostName(name) => { - (name.as_ref().len() as u16).encode(bytes); - bytes.extend_from_slice(name.as_ref().as_bytes()); - } - Self::IpAddress(r) => r.encode(bytes), - Self::Unknown(r) => r.encode(bytes), + Self::SingleDnsName(d) => ServerNamePayload::SingleDnsName(d.to_owned()), + Self::IpAddress => ServerNamePayload::IpAddress, + Self::Invalid => ServerNamePayload::Invalid, } } -} -#[derive(Clone, Debug)] -pub struct ServerName { - pub(crate) typ: ServerNameType, - pub(crate) payload: ServerNamePayload, + /// RFC6066: `ServerName server_name_list<1..2^16-1>` + const SIZE_LEN: ListLength = ListLength::NonZeroU16 { + empty_error: InvalidMessage::IllegalEmptyList("ServerNames"), + }; } -impl Codec<'_> for ServerName { +/// 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) { - self.typ.encode(bytes); - self.payload.encode(bytes); + 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<'_>) -> Result { - let typ = ServerNameType::read(r)?; + fn read(r: &mut Reader<'a>) -> Result { + let mut found = None; - let payload = match typ { - ServerNameType::HostName => ServerNamePayload::read_hostname(r)?, - _ => ServerNamePayload::Unknown(Payload::read(r).into_owned()), - }; + 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; + } + }; - Ok(Self { typ, payload }) + // "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)) } } -/// RFC6066: `ServerName server_name_list<1..2^16-1>` -impl TlsListElement for ServerName { - const SIZE_LEN: ListLength = ListLength::NonZeroU16 { - empty_error: InvalidMessage::IllegalEmptyList("ServerNames"), - }; +impl<'a> From<&DnsName<'a>> for ServerNamePayload<'static> { + fn from(value: &DnsName<'a>) -> Self { + Self::SingleDnsName(trim_hostname_trailing_dot_for_sni(value)) + } } -pub(crate) trait ConvertServerNameList { - fn has_duplicate_names_for_type(&self) -> bool; - fn single_hostname(&self) -> Option>; +#[derive(Clone, Debug)] +pub(crate) enum HostNamePayload { + HostName(DnsName<'static>), + IpAddress(PayloadU16), + Invalid(PayloadU16), } -impl ConvertServerNameList for [ServerName] { - /// RFC6066: "The ServerNameList MUST NOT contain more than one name of the same name_type." - fn has_duplicate_names_for_type(&self) -> bool { - has_duplicates::<_, _, u8>(self.iter().map(|name| name.typ)) - } +impl HostNamePayload { + fn read(r: &mut Reader<'_>) -> Result { + use pki_types::ServerName; + let raw = PayloadU16::::read(r)?; - fn single_hostname(&self) -> Option> { - fn only_dns_hostnames(name: &ServerName) -> Option> { - if let ServerNamePayload::HostName(dns) = &name.payload { - Some(dns.borrow()) - } else { - None - } + 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)), } - - self.iter() - .filter_map(only_dns_hostnames) - .next() } } @@ -665,7 +696,7 @@ pub enum ClientExtension { EcPointFormats(Vec), NamedGroups(Vec), SignatureAlgorithms(Vec), - ServerName(Vec), + ServerName(ServerNamePayload<'static>), SessionTicket(ClientSessionTicket), Protocols(Vec), SupportedVersions(SupportedProtocolVersions), @@ -762,7 +793,9 @@ impl Codec<'_> for ClientExtension { ExtensionType::ECPointFormats => Self::EcPointFormats(Vec::read(&mut sub)?), ExtensionType::EllipticCurves => Self::NamedGroups(Vec::read(&mut sub)?), ExtensionType::SignatureAlgorithms => Self::SignatureAlgorithms(Vec::read(&mut sub)?), - ExtensionType::ServerName => Self::ServerName(Vec::read(&mut sub)?), + ExtensionType::ServerName => { + Self::ServerName(ServerNamePayload::read(&mut sub)?.into_owned()) + } ExtensionType::SessionTicket => { if sub.any_left() { let contents = Payload::read(&mut sub).into_owned(); @@ -829,18 +862,6 @@ fn trim_hostname_trailing_dot_for_sni(dns_name: &DnsName<'_>) -> DnsName<'static } } -impl ClientExtension { - /// Make a basic SNI ServerNameRequest quoting `hostname`. - pub(crate) fn make_sni(dns_name: &DnsName<'_>) -> Self { - let name = ServerName { - typ: ServerNameType::HostName, - payload: ServerNamePayload::new_hostname(trim_hostname_trailing_dot_for_sni(dns_name)), - }; - - Self::ServerName(vec![name]) - } -} - #[derive(Clone, Debug)] pub enum ClientSessionTicket { Request, @@ -1110,26 +1131,10 @@ impl ClientHelloPayload { .find(|x| x.ext_type() == ext) } - pub(crate) fn sni_extension(&self) -> Option<&[ServerName]> { + pub(crate) fn sni_extension(&self) -> Option<&ServerNamePayload<'_>> { let ext = self.find_extension(ExtensionType::ServerName)?; match ext { - // Does this comply with RFC6066? - // - // [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 - ClientExtension::ServerName(req) - if !req - .iter() - .any(|name| matches!(name.payload, ServerNamePayload::IpAddress(_))) => - { - Some(req) - } + ClientExtension::ServerName(req) => Some(req), _ => None, } } diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index 21f038a141c..30b07dd0c3f 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -7,25 +7,25 @@ use super::base::{Payload, PayloadU8, PayloadU16, PayloadU24}; use super::codec::{Codec, Reader, put_u16}; use super::enums::{ CertificateType, ClientCertificateType, Compression, ECCurveType, ECPointFormat, ExtensionType, - KeyUpdateRequest, NamedGroup, PskKeyExchangeMode, ServerNameType, + KeyUpdateRequest, NamedGroup, PskKeyExchangeMode, }; use super::handshake::{ CertReqExtension, CertificateChain, CertificateEntry, CertificateExtension, CertificatePayloadTls13, CertificateRequestPayload, CertificateRequestPayloadTls13, CertificateStatus, CertificateStatusRequest, ClientExtension, ClientHelloPayload, - ClientSessionTicket, CompressedCertificatePayload, ConvertServerNameList, DistinguishedName, - EcParameters, HandshakeMessagePayload, HandshakePayload, HasServerExtensions, - HelloRetryExtension, HelloRetryRequest, KeyShareEntry, NewSessionTicketExtension, - NewSessionTicketPayload, NewSessionTicketPayloadTls13, PresharedKeyBinder, - PresharedKeyIdentity, PresharedKeyOffer, ProtocolName, Random, ServerDhParams, - ServerEcdhParams, ServerExtension, ServerHelloPayload, ServerKeyExchange, - ServerKeyExchangeParams, ServerKeyExchangePayload, SessionId, SingleProtocolName, - SupportedProtocolVersions, UnknownExtension, + ClientSessionTicket, CompressedCertificatePayload, DistinguishedName, EcParameters, + HandshakeMessagePayload, HandshakePayload, HasServerExtensions, HelloRetryExtension, + HelloRetryRequest, KeyShareEntry, NewSessionTicketExtension, NewSessionTicketPayload, + NewSessionTicketPayloadTls13, PresharedKeyBinder, PresharedKeyIdentity, PresharedKeyOffer, + ProtocolName, Random, ServerDhParams, ServerEcdhParams, ServerExtension, ServerHelloPayload, + ServerKeyExchange, ServerKeyExchangeParams, ServerKeyExchangePayload, SessionId, + SingleProtocolName, SupportedProtocolVersions, UnknownExtension, }; use crate::enums::{ CertificateCompressionAlgorithm, CipherSuite, HandshakeType, ProtocolVersion, SignatureScheme, }; use crate::error::InvalidMessage; +use crate::msgs::handshake::ServerNamePayload; use crate::sync::Arc; use crate::verify::DigitallySignedStruct; @@ -190,17 +190,6 @@ fn can_round_trip_mixed_case_sni() { assert_eq!(bytes.to_vec(), ext.get_encoding()); } -#[test] -fn can_round_trip_other_sni_name_types() { - let bytes = [0, 0, 0, 7, 0, 5, 1, 0, 2, 0x6c, 0x6f]; - let mut rd = Reader::init(&bytes); - let ext = ClientExtension::read(&mut rd).unwrap(); - println!("{:?}", ext); - - assert_eq!(ext.ext_type(), ExtensionType::ServerName); - assert_eq!(bytes.to_vec(), ext.get_encoding()); -} - #[test] fn single_hostname_returns_none_for_other_sni_name_types() { let bytes = [0, 0, 0, 7, 0, 5, 1, 0, 2, 0x6c, 0x6f]; @@ -209,37 +198,10 @@ fn single_hostname_returns_none_for_other_sni_name_types() { println!("{:?}", ext); assert_eq!(ext.ext_type(), ExtensionType::ServerName); - if let ClientExtension::ServerName(snr) = ext { - assert!(!snr.has_duplicate_names_for_type()); - assert!(snr.single_hostname().is_none()); - } else { - unreachable!(); - } -} - -#[test] -fn can_round_trip_multi_name_sni() { - let bytes = [0, 0, 0, 12, 0, 10, 0, 0, 2, 0x68, 0x69, 0, 0, 2, 0x6c, 0x6f]; - let mut rd = Reader::init(&bytes); - let ext = ClientExtension::read(&mut rd).unwrap(); - println!("{:?}", ext); - - assert_eq!(ext.ext_type(), ExtensionType::ServerName); - assert_eq!(bytes.to_vec(), ext.get_encoding()); - match ext { - ClientExtension::ServerName(req) => { - assert_eq!(2, req.len()); - - assert!(req.has_duplicate_names_for_type()); - - let dns_name = req.single_hostname().unwrap(); - assert_eq!(dns_name.as_ref(), "hi"); - - assert_eq!(req[0].typ, ServerNameType::HostName); - assert_eq!(req[1].typ, ServerNameType::HostName); - } - _ => unreachable!(), - } + assert!(matches!( + ext, + ClientExtension::ServerName(ServerNamePayload::Invalid) + )); } #[test] @@ -976,7 +938,9 @@ fn sample_client_hello_payload() -> ClientHelloPayload { ClientExtension::EcPointFormats(ECPointFormat::SUPPORTED.to_vec()), ClientExtension::NamedGroups(vec![NamedGroup::X25519]), ClientExtension::SignatureAlgorithms(vec![SignatureScheme::ECDSA_NISTP256_SHA256]), - ClientExtension::make_sni(&DnsName::try_from("hello").unwrap()), + ClientExtension::ServerName(ServerNamePayload::from( + &DnsName::try_from("hello").unwrap(), + )), ClientExtension::SessionTicket(ClientSessionTicket::Request), ClientExtension::SessionTicket(ClientSessionTicket::Offer(Payload::Borrowed(&[]))), ClientExtension::Protocols(vec![ProtocolName::from(vec![0])]), diff --git a/rustls/src/server/hs.rs b/rustls/src/server/hs.rs index faae4832223..f426cff870c 100644 --- a/rustls/src/server/hs.rs +++ b/rustls/src/server/hs.rs @@ -21,8 +21,8 @@ use crate::msgs::enums::{CertificateType, Compression, ExtensionType, NamedGroup #[cfg(feature = "tls12")] use crate::msgs::handshake::SessionId; use crate::msgs::handshake::{ - ClientHelloPayload, ConvertServerNameList, HandshakePayload, KeyExchangeAlgorithm, Random, - ServerExtension, SingleProtocolName, + ClientHelloPayload, HandshakePayload, KeyExchangeAlgorithm, Random, ServerExtension, + ServerNamePayload, SingleProtocolName, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; @@ -699,23 +699,23 @@ pub(super) fn process_client_hello<'m>( // 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: Option> = match client_hello.sni_extension() { - Some(sni) => { - if sni.has_duplicate_names_for_type() { - return Err(cx.common.send_fatal_alert( - AlertDescription::DecodeError, - PeerMisbehaved::DuplicateServerNameTypes, - )); - } - - if let Some(hostname) = sni.single_hostname() { - Some(hostname.to_lowercase_owned()) - } else { - return Err(cx.common.send_fatal_alert( - AlertDescription::IllegalParameter, - PeerMisbehaved::ServerNameMustContainOneHostName, - )); - } + 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, }; diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 4d797308d3d..939c8f6750a 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -1555,7 +1555,7 @@ fn server_ignores_sni_with_ip_address() { fn server_rejects_sni_with_illegal_dns_name() { check_sni_error( encoding::Extension::new_sni(b"ab@cd.com"), - Error::InvalidMessage(InvalidMessage::InvalidServerName), + Error::PeerMisbehaved(PeerMisbehaved::ServerNameMustContainOneHostName), ); } @@ -6241,7 +6241,7 @@ fn test_server_rejects_duplicate_sni_names() { typ: ExtensionType::ServerName, body: encoding::len_u16(body), }, - Error::PeerMisbehaved(PeerMisbehaved::DuplicateServerNameTypes), + Error::InvalidMessage(InvalidMessage::InvalidServerName), ); } From 70ed532b33ef1691876209724f56108eede011ae Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 29 Apr 2025 15:45:36 +0000 Subject: [PATCH 174/403] Update Rust crate nix to 0.30 --- Cargo.lock | 4 ++-- bogo/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4b212f6d681..1244958a981 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1927,9 +1927,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +checksum = "537bc3c4a347b87fd52ac6c03a02ab1302962cfd93373c5d7a112cdc337854cc" dependencies = [ "bitflags", "cfg-if", diff --git a/bogo/Cargo.toml b/bogo/Cargo.toml index 4393b17e464..be08f06d38c 100644 --- a/bogo/Cargo.toml +++ b/bogo/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] base64 = { workspace = true } env_logger = { workspace = true } -nix = { version = "0.29", default-features = false, features = ["signal"] } +nix = { version = "0.30", default-features = false, features = ["signal"] } rustls = { path = "../rustls", features = ["aws_lc_rs", "ring", "tls12"] } rustls-post-quantum = { path = "../rustls-post-quantum", optional = true } From 26b8ee3f6508ccc758c6d9b60237fcb166a63ffd Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Thu, 1 May 2025 11:37:47 +0200 Subject: [PATCH 175/403] ci: skip push triggers for most branches --- .github/workflows/build.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c346bb17e25..b5ef058c601 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,8 +5,7 @@ permissions: on: push: - branches-ignore: - - 'gh-readonly-queue/**' + branches: ['main', 'rel-*', 'ci/*'] tags: - '**' pull_request: From 47ed0c66e46cbe55ce1012936034a1d8f13d8941 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Thu, 1 May 2025 11:38:14 +0200 Subject: [PATCH 176/403] ci: enable triggering CI workflow manually --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b5ef058c601..1ce8dcf4252 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,6 +12,7 @@ on: merge_group: schedule: - cron: '0 18 * * *' + workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }} From 35c44d26883d7c9e31b0a102499ca5ddaf11e350 Mon Sep 17 00:00:00 2001 From: Sean Lynch <42618346+swlynch99@users.noreply.github.com> Date: Wed, 9 Apr 2025 12:30:15 -0700 Subject: [PATCH 177/403] Extract tls13 expand_secret function out of extract_secrets --- rustls/src/tls13/key_schedule.rs | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/rustls/src/tls13/key_schedule.rs b/rustls/src/tls13/key_schedule.rs index d5d179000e2..2defeaaffda 100644 --- a/rustls/src/tls13/key_schedule.rs +++ b/rustls/src/tls13/key_schedule.rs @@ -578,26 +578,14 @@ impl KeyScheduleTraffic { .export_keying_material(&self.current_exporter_secret, out, label, context) } - pub(crate) fn extract_secrets(&self, side: Side) -> Result { - fn expand( - 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", &[]), - ) - } - let (client_key, client_iv) = expand( + pub(crate) fn extract_secrets(&self, side: Side) -> Result { + 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( + let (server_key, server_iv) = expand_secret( &self.current_server_traffic_secret, self.ks.suite.hkdf_provider, self.ks.suite.aead_alg.key_len(), @@ -621,6 +609,15 @@ impl KeyScheduleTraffic { } } +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", &[]), + ) +} + pub(crate) struct ResumptionSecret<'a> { kst: &'a KeyScheduleTraffic, resumption_master_secret: OkmBlock, From 5a12171558dc218b7cb85071fa117ed3cd4622ac Mon Sep 17 00:00:00 2001 From: Sean Lynch <42618346+swlynch99@users.noreply.github.com> Date: Thu, 6 Mar 2025 23:42:05 -0800 Subject: [PATCH 178/403] Add kernel connection API For kTLS we want to be able to interact with rustls in order to refresh traffic keys and save session tickets for future usage. The remaining parts of the TLS protocol are possible to implement externally provided that the user is willing to put in enough effort. This commit introduces a new API that provides exactly 3 capabilities to the user: 1. Refresh the TX traffic secrets. 2. Refresh the RX traffic secrets. 3. Handle a provided new_session_ticket message and save said session ticket for later use. That's it. Everything else needs to be implemented by the library user. --- rustls/src/client/client_conn.rs | 18 +++ rustls/src/client/tls12.rs | 28 +++- rustls/src/client/tls13.rs | 83 ++++++++-- rustls/src/common_state.rs | 5 + rustls/src/conn.rs | 47 +++++- rustls/src/conn/kernel.rs | 269 +++++++++++++++++++++++++++++++ rustls/src/lib.rs | 1 + rustls/src/server/server_conn.rs | 18 +++ rustls/src/server/tls12.rs | 27 +++- rustls/src/server/tls13.rs | 43 ++++- rustls/src/tls13/key_schedule.rs | 18 ++- 11 files changed, 531 insertions(+), 26 deletions(-) create mode 100644 rustls/src/conn/kernel.rs diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index 1fefadfc980..721db49cb5b 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -16,6 +16,7 @@ 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::ClientExtension; @@ -899,6 +900,23 @@ impl UnbufferedClientConnection { pub fn dangerous_extract_secrets(self) -> Result { 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), Error> { + self.inner + .core + .dangerous_into_kernel_connection() + } } impl Deref for UnbufferedClientConnection { diff --git a/rustls/src/client/tls12.rs b/rustls/src/client/tls12.rs index 9391c3d8de9..914ad526f92 100644 --- a/rustls/src/client/tls12.rs +++ b/rustls/src/client/tls12.rs @@ -9,11 +9,13 @@ 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}; @@ -23,8 +25,8 @@ use crate::msgs::base::{Payload, PayloadU8, PayloadU16}; use crate::msgs::ccs::ChangeCipherSpecPayload; use crate::msgs::handshake::{ CertificateChain, ClientDhParams, ClientEcdhParams, ClientKeyExchangeParams, - HandshakeMessagePayload, HandshakePayload, NewSessionTicketPayload, ServerKeyExchangeParams, - SessionId, + HandshakeMessagePayload, HandshakePayload, NewSessionTicketPayload, + NewSessionTicketPayloadTls13, ServerKeyExchangeParams, SessionId, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; @@ -1331,7 +1333,29 @@ impl State for ExpectTraffic { .extract_secrets(Side::Client) } + fn into_external_state(self: Box) -> Result, Error> { + Ok(self) + } + fn into_owned(self: Box) -> hs::NextState<'static> { self } } + +impl KernelState for ExpectTraffic { + fn update_secrets(&mut self, _: Direction) -> Result { + 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/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index ca7c1500f50..11830a7f3ea 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -15,6 +15,7 @@ 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::{ActiveKeyExchange, SharedSecret}; use crate::enums::{ AlertDescription, ContentType, HandshakeType, ProtocolVersion, SignatureScheme, @@ -45,7 +46,7 @@ use crate::tls13::{ Tls13CipherSuite, construct_client_verify_message, construct_server_verify_message, }; use crate::verify::{self, DigitallySignedStruct}; -use crate::{KeyLog, compress, crypto}; +use crate::{ConnectionTrafficSecrets, KeyLog, compress, crypto}; // Extensions we expect in plaintext in the ServerHello. static ALLOWED_PLAINTEXT_EXTS: &[ExtensionType] = &[ @@ -1460,16 +1461,13 @@ struct ExpectTraffic { } impl ExpectTraffic { - fn handle_new_ticket_tls13( + fn handle_new_ticket_impl( &mut self, - cx: &mut ClientContext<'_>, + cx: &mut KernelContext<'_>, nst: &NewSessionTicketPayloadTls13, ) -> Result<(), Error> { if nst.has_duplicate_extension() { - return Err(cx.common.send_fatal_alert( - AlertDescription::IllegalParameter, - PeerMisbehaved::DuplicateNewSessionTicketExtensions, - )); + return Err(PeerMisbehaved::DuplicateNewSessionTicketExtensions.into()); } let handshake_hash = self.transcript.current_hash(); @@ -1483,9 +1481,8 @@ impl ExpectTraffic { self.suite, Arc::clone(&nst.ticket), secret.as_ref(), - cx.common - .peer_certificates - .clone() + cx.peer_certificates + .cloned() .unwrap_or_default(), &self.config.verifier, &self.config.client_auth_cert_resolver, @@ -1496,14 +1493,14 @@ impl ExpectTraffic { .unwrap_or_default(), ); - if cx.common.is_quic() { + if cx.is_quic() { if let Some(sz) = nst.max_early_data_size() { if sz != 0 && sz != 0xffff_ffff { return Err(PeerMisbehaved::InvalidMaxEarlyDataSize.into()); } } - if let Some(quic_params) = &cx.common.quic.params { + if let Some(quic_params) = &cx.quic.params { value.set_quic_params(quic_params); } } @@ -1513,6 +1510,26 @@ impl ExpectTraffic { Ok(()) } + fn handle_new_ticket_tls13( + &mut self, + cx: &mut ClientContext<'_>, + nst: &NewSessionTicketPayloadTls13, + ) -> Result<(), Error> { + if nst.has_duplicate_extension() { + return Err(cx.common.send_fatal_alert( + AlertDescription::IllegalParameter, + PeerMisbehaved::DuplicateNewSessionTicketExtensions, + )); + } + + let mut kcx = KernelContext { + peer_certificates: cx.common.peer_certificates.as_ref(), + protocol: cx.common.protocol, + quic: &cx.common.quic, + }; + self.handle_new_ticket_impl(&mut kcx, nst) + } + fn handle_key_update( &mut self, common: &mut CommonState, @@ -1601,11 +1618,33 @@ impl State for ExpectTraffic { .extract_secrets(Side::Client) } + fn into_external_state(self: Box) -> Result, Error> { + Ok(self) + } + fn into_owned(self: Box) -> hs::NextState<'static> { self } } +impl KernelState for ExpectTraffic { + fn update_secrets(&mut self, dir: Direction) -> Result { + 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 for ExpectQuicTraffic { @@ -1637,7 +1676,27 @@ impl State for ExpectQuicTraffic { .export_keying_material(output, label, context) } + fn into_external_state(self: Box) -> Result, Error> { + Ok(self) + } + fn into_owned(self: Box) -> hs::NextState<'static> { self } } + +impl KernelState for ExpectQuicTraffic { + fn update_secrets(&mut self, _: Direction) -> Result { + 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/rustls/src/common_state.rs b/rustls/src/common_state.rs index 626e4b2277c..156eb0824cf 100644 --- a/rustls/src/common_state.rs +++ b/rustls/src/common_state.rs @@ -3,6 +3,7 @@ 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}; @@ -867,6 +868,10 @@ pub(crate) trait State: Send + Sync { fn handle_decrypt_error(&self) {} + fn into_external_state(self: Box) -> Result, Error> { + Err(Error::HandshakeNotComplete) + } + fn into_owned(self: Box) -> Box + 'static>; } diff --git a/rustls/src/conn.rs b/rustls/src/conn.rs index 1b370c242b8..790021bafc5 100644 --- a/rustls/src/conn.rs +++ b/rustls/src/conn.rs @@ -2,6 +2,7 @@ use alloc::boxed::Box; use core::fmt::Debug; use core::mem; use core::ops::{Deref, DerefMut, Range}; +use kernel::KernelConnection; #[cfg(feature = "std")] use std::io; @@ -15,9 +16,11 @@ 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, PartiallyExtractedSecrets}; +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")] @@ -1158,6 +1161,14 @@ impl ConnectionCore { } pub(crate) fn dangerous_extract_secrets(self) -> Result { + Ok(self + .dangerous_into_kernel_connection()? + .0) + } + + pub(crate) fn dangerous_into_kernel_connection( + self, + ) -> Result<(ExtractedSecrets, KernelConnection), Error> { if !self .common_state .enable_secret_extraction @@ -1165,14 +1176,34 @@ impl ConnectionCore { return Err(Error::General("Secret extraction is disabled".into())); } - let st = self.state?; + 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)?; - let record_layer = self.common_state.record_layer; - let PartiallyExtractedSecrets { tx, rx } = st.extract_secrets()?; - Ok(ExtractedSecrets { - tx: (record_layer.write_seq(), tx), - rx: (record_layer.read_seq(), rx), - }) + Ok((secrets, external)) } pub(crate) fn export_keying_material>( diff --git a/rustls/src/conn/kernel.rs b/rustls/src/conn/kernel.rs new file mode 100644 index 00000000000..f6982ce8857 --- /dev/null +++ b/rustls/src/conn/kernel.rs @@ -0,0 +1,269 @@ +//! 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 core::marker::PhantomData; + +use alloc::boxed::Box; + +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 { + state: Box, + + peer_certificates: Option>, + quic: Quic, + + negotiated_version: ProtocolVersion, + protocol: Protocol, + suite: SupportedCipherSuite, + + _data: PhantomData, +} + +impl KernelConnection { + pub(crate) fn new(state: Box, common: CommonState) -> Result { + 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 { + /// 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, typ: ContentType, message: &[u8]) -> Result<(), rustls::Error> { + /// let conn: &mut KernelConnection = // ... + /// # 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; + + /// 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/rustls/src/lib.rs b/rustls/src/lib.rs index 8dec9a50fd0..da044e3b317 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -545,6 +545,7 @@ pub mod unbuffered { // The public interface is: pub use crate::builder::{ConfigBuilder, ConfigSide, WantsVerifier, WantsVersions}; pub use crate::common_state::{CommonState, HandshakeKind, IoState, Side}; +pub use crate::conn::kernel; #[cfg(feature = "std")] pub use crate::conn::{Connection, Reader, Writer}; pub use crate::conn::{ConnectionCommon, SideData}; diff --git a/rustls/src/server/server_conn.rs b/rustls/src/server/server_conn.rs index 7b568a79a68..860a0abbf45 100644 --- a/rustls/src/server/server_conn.rs +++ b/rustls/src/server/server_conn.rs @@ -22,6 +22,7 @@ use crate::crypto; use crate::crypto::CryptoProvider; use crate::enums::{CipherSuite, ProtocolVersion, SignatureScheme}; use crate::error::Error; +use crate::kernel::KernelConnection; use crate::log::trace; use crate::msgs::base::Payload; use crate::msgs::enums::CertificateType; @@ -929,6 +930,23 @@ impl UnbufferedServerConnection { pub fn dangerous_extract_secrets(self) -> Result { 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), Error> { + self.inner + .core + .dangerous_into_kernel_connection() + } } impl Deref for UnbufferedServerConnection { diff --git a/rustls/src/server/tls12.rs b/rustls/src/server/tls12.rs index 5183b037678..8fc46de7382 100644 --- a/rustls/src/server/tls12.rs +++ b/rustls/src/server/tls12.rs @@ -13,6 +13,7 @@ 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}; @@ -23,14 +24,14 @@ use crate::msgs::ccs::ChangeCipherSpecPayload; use crate::msgs::codec::Codec; use crate::msgs::handshake::{ CertificateChain, ClientKeyExchangeParams, HandshakeMessagePayload, HandshakePayload, - NewSessionTicketPayload, SessionId, + 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::verify; +use crate::{ConnectionTrafficSecrets, verify}; mod client_hello { use pki_types::CertificateDer; @@ -998,7 +999,29 @@ impl State for ExpectTraffic { .extract_secrets(Side::Server) } + fn into_external_state(self: Box) -> Result, Error> { + Ok(self) + } + fn into_owned(self: Box) -> hs::NextState<'static> { self } } + +impl KernelState for ExpectTraffic { + fn update_secrets(&mut self, _: Direction) -> Result { + 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/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index 32f27780db4..4af77ddb611 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -13,6 +13,7 @@ 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; @@ -34,7 +35,7 @@ use crate::tls13::key_schedule::{ use crate::tls13::{ Tls13CipherSuite, construct_client_verify_message, construct_server_verify_message, }; -use crate::{compress, rand, verify}; +use crate::{ConnectionTrafficSecrets, compress, rand, verify}; mod client_hello { use super::*; @@ -1499,11 +1500,35 @@ impl State for ExpectTraffic { .request_key_update_and_update_encrypter(common) } + fn into_external_state(self: Box) -> Result, Error> { + Ok(self) + } + fn into_owned(self: Box) -> hs::NextState<'static> { self } } +impl KernelState for ExpectTraffic { + fn update_secrets(&mut self, dir: Direction) -> Result { + 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, @@ -1536,3 +1561,19 @@ impl State for ExpectQuicTraffic { self } } + +impl KernelState for ExpectQuicTraffic { + fn update_secrets(&mut self, _: Direction) -> Result { + 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/rustls/src/tls13/key_schedule.rs b/rustls/src/tls13/key_schedule.rs index 2defeaaffda..a96d9021ca7 100644 --- a/rustls/src/tls13/key_schedule.rs +++ b/rustls/src/tls13/key_schedule.rs @@ -10,7 +10,7 @@ use crate::crypto::{SharedSecret, hash, hmac}; use crate::error::Error; use crate::msgs::message::Message; use crate::suites::PartiallyExtractedSecrets; -use crate::{KeyLog, Tls13CipherSuite, quic}; +use crate::{ConnectionTrafficSecrets, KeyLog, Tls13CipherSuite, quic}; /// The kinds of secret we can extract from `KeySchedule`. #[derive(Debug, Clone, Copy, PartialEq)] @@ -578,6 +578,22 @@ impl KeyScheduleTraffic { .export_keying_material(&self.current_exporter_secret, out, label, context) } + pub(crate) fn refresh_traffic_secret( + &mut self, + side: Side, + ) -> Result { + 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 { let (client_key, client_iv) = expand_secret( From bf9e874384607dbc41cdb7d822c56e67c230d739 Mon Sep 17 00:00:00 2001 From: Sean Lynch <42618346+swlynch99@users.noreply.github.com> Date: Sat, 8 Mar 2025 14:11:45 -0800 Subject: [PATCH 179/403] Add test cases for KernelConnection key updates --- rustls/tests/common/mod.rs | 90 ++++++++++++++++++- rustls/tests/unbuffered.rs | 173 +++++++++++++++++++++++++++++++++++++ 2 files changed, 261 insertions(+), 2 deletions(-) diff --git a/rustls/tests/common/mod.rs b/rustls/tests/common/mod.rs index 01af3e37f6a..41fdc01e337 100644 --- a/rustls/tests/common/mod.rs +++ b/rustls/tests/common/mod.rs @@ -13,7 +13,8 @@ use pki_types::{ use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; use rustls::client::{ - AlwaysResolvesClientRawPublicKeys, ServerCertVerifierBuilder, WebPkiServerVerifier, + AlwaysResolvesClientRawPublicKeys, ServerCertVerifierBuilder, UnbufferedClientConnection, + WebPkiServerVerifier, }; use rustls::crypto::cipher::{InboundOpaqueMessage, MessageDecrypter, MessageEncrypter}; use rustls::crypto::{CryptoProvider, verify_tls13_signature_with_raw_key}; @@ -21,9 +22,13 @@ use rustls::internal::msgs::codec::{Codec, Reader}; use rustls::internal::msgs::message::{Message, OutboundOpaqueMessage, PlainMessage}; use rustls::server::danger::{ClientCertVerified, ClientCertVerifier}; use rustls::server::{ - AlwaysResolvesServerRawPublicKeys, ClientCertVerifierBuilder, WebPkiClientVerifier, + AlwaysResolvesServerRawPublicKeys, ClientCertVerifierBuilder, UnbufferedServerConnection, + WebPkiClientVerifier, }; use rustls::sign::CertifiedKey; +use rustls::unbuffered::{ + ConnectionState, EncodeError, UnbufferedConnectionCommon, UnbufferedStatus, +}; use rustls::{ ClientConfig, ClientConnection, Connection, ConnectionCommon, ContentType, DigitallySignedStruct, DistinguishedName, Error, InconsistentKeys, NamedGroup, ProtocolVersion, @@ -754,6 +759,87 @@ pub fn do_handshake( (to_server, to_client) } +// Drive a handshake using unbuffered connections. +// +// Note that this drives the connection beyond the handshake until both +// connections are idle and there is no pending data waiting to be processed +// by either. In practice this just means that session tickets are processed +// by the client. +pub fn do_unbuffered_handshake( + client: &mut UnbufferedClientConnection, + server: &mut UnbufferedServerConnection, +) { + fn is_idle(conn: &UnbufferedConnectionCommon, data: &[u8]) -> bool { + !conn.is_handshaking() && !conn.wants_write() && data.is_empty() + } + + let mut client_data = Vec::with_capacity(1024); + let mut server_data = Vec::with_capacity(1024); + + while !is_idle(client, &client_data) || !is_idle(server, &server_data) { + loop { + let UnbufferedStatus { discard, state } = client.process_tls_records(&mut client_data); + let state = state.unwrap(); + + match state { + ConnectionState::BlockedHandshake | ConnectionState::WriteTraffic(_) => { + client_data.drain(..discard); + break; + } + ConnectionState::Closed | ConnectionState::PeerClosed => unreachable!(), + ConnectionState::ReadEarlyData(_) => (), + ConnectionState::EncodeTlsData(mut data) => { + let required = match data.encode(&mut []) { + Err(EncodeError::InsufficientSize(err)) => err.required_size, + _ => unreachable!(), + }; + + let old_len = server_data.len(); + server_data.resize(old_len + required, 0); + data.encode(&mut server_data[old_len..]) + .unwrap(); + } + ConnectionState::TransmitTlsData(data) => data.done(), + st => unreachable!("unexpected connection state: {st:?}"), + } + + client_data.drain(..discard); + } + + loop { + let UnbufferedStatus { discard, state } = server.process_tls_records(&mut server_data); + let state = state.unwrap(); + + match state { + ConnectionState::BlockedHandshake | ConnectionState::WriteTraffic(_) => { + server_data.drain(..discard); + break; + } + ConnectionState::Closed | ConnectionState::PeerClosed => unreachable!(), + ConnectionState::ReadEarlyData(_) => unreachable!(), + ConnectionState::EncodeTlsData(mut data) => { + let required = match data.encode(&mut []) { + Err(EncodeError::InsufficientSize(err)) => err.required_size, + _ => unreachable!(), + }; + + let old_len = client_data.len(); + client_data.resize(old_len + required, 0); + data.encode(&mut client_data[old_len..]) + .unwrap(); + } + ConnectionState::TransmitTlsData(data) => data.done(), + _ => unreachable!(), + } + + server_data.drain(..discard); + } + } + + assert!(server_data.is_empty()); + assert!(client_data.is_empty()); +} + #[derive(PartialEq, Debug)] pub enum ErrorFromPeer { Client(Error), diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index 850f149bd03..a2946b78f79 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -1559,6 +1559,179 @@ fn test_secret_extraction_enabled() { } } +// Tests for the kernel API. +// +// We don't have anything set up to actually encrypt/decrypt the connection +// content so these tests all just check that the updated traffic secrets are +// equivalent on each side of the connection, if supported by the protocol +// version. + +#[test] +fn kernel_err_on_secret_extraction_not_enabled() { + let server_config = make_server_config(KeyType::Rsa2048); + let server_config = Arc::new(server_config); + + let client_config = make_client_config(KeyType::Rsa2048); + let client_config = Arc::new(client_config); + + let mut server = UnbufferedServerConnection::new(server_config).unwrap(); + let mut client = + UnbufferedClientConnection::new(client_config, "localhost".try_into().unwrap()).unwrap(); + + do_unbuffered_handshake(&mut client, &mut server); + + assert!( + client + .dangerous_into_kernel_connection() + .is_err() + ); + assert!( + server + .dangerous_into_kernel_connection() + .is_err() + ); +} + +#[test] +fn kernel_err_on_handshake_not_complete() { + let mut server_config = make_server_config(KeyType::Rsa2048); + server_config.enable_secret_extraction = true; + let server_config = Arc::new(server_config); + + let mut client_config = make_client_config(KeyType::Rsa2048); + client_config.enable_secret_extraction = true; + let client_config = Arc::new(client_config); + + let server = UnbufferedServerConnection::new(server_config).unwrap(); + let client = + UnbufferedClientConnection::new(client_config, "localhost".try_into().unwrap()).unwrap(); + + assert!(matches!( + client.dangerous_into_kernel_connection(), + Err(Error::HandshakeNotComplete) + )); + assert!(matches!( + server.dangerous_into_kernel_connection(), + Err(Error::HandshakeNotComplete) + )); +} + +#[test] +fn kernel_initial_traffic_secrets_match() { + let mut server_config = make_server_config(KeyType::Rsa2048); + server_config.enable_secret_extraction = true; + let server_config = Arc::new(server_config); + + let mut client_config = make_client_config(KeyType::Rsa2048); + client_config.enable_secret_extraction = true; + let client_config = Arc::new(client_config); + + let mut server = UnbufferedServerConnection::new(server_config).unwrap(); + let mut client = + UnbufferedClientConnection::new(client_config, "localhost".try_into().unwrap()).unwrap(); + + do_unbuffered_handshake(&mut client, &mut server); + + let (client_secrets, _) = client + .dangerous_into_kernel_connection() + .expect("failed to convert client connection to an KernelConnection"); + let (server_secrets, _) = server + .dangerous_into_kernel_connection() + .expect("failed to convert server connection to an KernelConnection"); + + assert_secrets_equal(client_secrets.tx, server_secrets.rx); + assert_secrets_equal(server_secrets.tx, client_secrets.rx); +} + +#[test] +fn kernel_key_updates_tls13() { + let mut server_config = make_server_config_with_versions(KeyType::Rsa2048, &[&TLS13]); + server_config.enable_secret_extraction = true; + let server_config = Arc::new(server_config); + + let mut client_config = make_client_config_with_versions(KeyType::Rsa2048, &[&TLS13]); + client_config.enable_secret_extraction = true; + let client_config = Arc::new(client_config); + + let mut server = UnbufferedServerConnection::new(server_config).unwrap(); + let mut client = + UnbufferedClientConnection::new(client_config, "localhost".try_into().unwrap()).unwrap(); + + do_unbuffered_handshake(&mut client, &mut server); + + let (_, mut client) = client + .dangerous_into_kernel_connection() + .expect("failed to convert client connection to an KernelConnection"); + let (_, mut server) = server + .dangerous_into_kernel_connection() + .expect("failed to convert server connection to an KernelConnection"); + + let new_client_tx = client.update_tx_secret().unwrap(); + let new_client_rx = client.update_rx_secret().unwrap(); + + let new_server_tx = server.update_tx_secret().unwrap(); + let new_server_rx = server.update_rx_secret().unwrap(); + + assert_secrets_equal(new_server_tx, new_client_rx); + assert_secrets_equal(new_server_rx, new_client_tx); +} + +#[test] +#[cfg(feature = "tls12")] +fn kernel_key_updates_tls12() { + use rustls::version::TLS12; + + let _ = env_logger::try_init(); + + let mut server_config = make_server_config_with_versions(KeyType::Rsa2048, &[&TLS12]); + server_config.enable_secret_extraction = true; + let server_config = Arc::new(server_config); + + let mut client_config = make_client_config_with_versions(KeyType::Rsa2048, &[&TLS12]); + client_config.enable_secret_extraction = true; + let client_config = Arc::new(client_config); + + let mut server = UnbufferedServerConnection::new(server_config).unwrap(); + let mut client = + UnbufferedClientConnection::new(client_config, "localhost".try_into().unwrap()).unwrap(); + + do_unbuffered_handshake(&mut client, &mut server); + + let (_, mut client) = client + .dangerous_into_kernel_connection() + .expect("failed to convert client connection to an KernelConnection"); + let (_, mut server) = server + .dangerous_into_kernel_connection() + .expect("failed to convert server connection to an KernelConnection"); + + // TLS 1.2 does not allow key updates so these should all error + assert!(client.update_tx_secret().is_err()); + assert!(client.update_rx_secret().is_err()); + + assert!(server.update_tx_secret().is_err()); + assert!(server.update_rx_secret().is_err()); +} + +fn assert_secrets_equal( + (l_seq, l_sec): (u64, ConnectionTrafficSecrets), + (r_seq, r_sec): (u64, ConnectionTrafficSecrets), +) { + assert_eq!(l_seq, r_seq); + assert_eq!(explode_secrets(&l_sec), explode_secrets(&r_sec)); +} + +// Comparing secrets for equality is something you should never have to +// do in production code, so ConnectionTrafficSecrets doesn't implement +// PartialEq/Eq on purpose. Instead, we have to get creative. +fn explode_secrets(s: &ConnectionTrafficSecrets) -> (&[u8], &[u8]) { + match s { + ConnectionTrafficSecrets::Aes128Gcm { key, iv } => (key.as_ref(), iv.as_ref()), + ConnectionTrafficSecrets::Aes256Gcm { key, iv } => (key.as_ref(), iv.as_ref()), + ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv } => (key.as_ref(), iv.as_ref()), + _ => panic!("unexpected secret type"), + } +} + const TLS12_CLIENT_TRANSCRIPT: &[&str] = &[ "EncodeTlsData", "TransmitTlsData", From 9509626f13be6046bf56f15639559ce4d5b41e53 Mon Sep 17 00:00:00 2001 From: Sean Lynch <42618346+swlynch99@users.noreply.github.com> Date: Fri, 4 Apr 2025 11:10:08 -0700 Subject: [PATCH 180/403] Deprecate dangerous_extract_secrets on unbuffered connections While dangerous_extract_secrets allows users to extract secrets from a connection there is more to implementing a TLS connection than just encryption and decryption. Just getting the ExtractedSecrets does not allow for handling TLS 1.3 key updates or session tickets. As such, this commit deprecates it in favour of dangerous_into_kernel_connection, which does support both of those things. --- rustls/src/client/client_conn.rs | 2 ++ rustls/src/server/server_conn.rs | 2 ++ rustls/tests/unbuffered.rs | 10 ++++++---- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index 721db49cb5b..305badfb736 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -897,6 +897,8 @@ impl UnbufferedClientConnection { /// 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 { self.inner.dangerous_extract_secrets() } diff --git a/rustls/src/server/server_conn.rs b/rustls/src/server/server_conn.rs index 860a0abbf45..47a84945616 100644 --- a/rustls/src/server/server_conn.rs +++ b/rustls/src/server/server_conn.rs @@ -927,6 +927,8 @@ impl UnbufferedServerConnection { /// 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 { self.inner.dangerous_extract_secrets() } diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index a2946b78f79..bb5292ae71b 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -1526,11 +1526,13 @@ fn test_secret_extraction_enabled() { // The handshake is finished, we're now able to extract traffic secrets let client_secrets = client - .dangerous_extract_secrets() - .unwrap(); + .dangerous_into_kernel_connection() + .unwrap() + .0; let server_secrets = server - .dangerous_extract_secrets() - .unwrap(); + .dangerous_into_kernel_connection() + .unwrap() + .0; // Comparing secrets for equality is something you should never have to // do in production code, so ConnectionTrafficSecrets doesn't implement From 06a704e3c819beefee70175c63d3da418271b0c2 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Sun, 13 Apr 2025 12:15:54 +0200 Subject: [PATCH 181/403] Update to webpki 0.103.2 --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- fuzz/Cargo.lock | 5 ++--- fuzz/Cargo.toml | 3 +++ rustls/src/webpki/mod.rs | 1 + 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1244958a981..2cb9c2ee2be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2781,9 +2781,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.1" +version = "0.103.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" +checksum = "7149975849f1abb3832b246010ef62ccc80d3a76169517ada7188252b9cfb437" dependencies = [ "aws-lc-rs", "ring", diff --git a/Cargo.toml b/Cargo.toml index fb9df5b0599..675b46e0c4e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,7 +86,7 @@ subtle = { version = "2.5.0", default-features = false } time = { version = "0.3.6", default-features = false } tikv-jemallocator = "0.6" tokio = { version = "1.34", features = ["io-util", "macros", "net", "rt"] } -webpki = { package = "rustls-webpki", version = "0.103", features = ["alloc"], default-features = false } +webpki = { package = "rustls-webpki", version = "0.103.2", features = ["alloc"], default-features = false } webpki-roots = "0.26" x25519-dalek = "2" x509-parser = "0.17" diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index bb99b94f202..079e5500ef7 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -310,9 +310,8 @@ checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" [[package]] name = "rustls-webpki" -version = "0.103.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa4eeac2588ffff23e9d7a7e9b3f971c5fb5b7ebc9452745e0c232c64f83b2f" +version = "0.103.2" +source = "git+https://github.com/rustls/webpki?branch=main#9cf30f67d6b8f91d87281cca0253dbc6950eb1f3" dependencies = [ "ring", "rustls-pki-types", diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index b2884a8e10e..eddc99062a0 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -49,3 +49,6 @@ path = "fuzzers/server_name.rs" [[bin]] name = "unbuffered" path = "fuzzers/unbuffered.rs" + +[patch."crates-io"] +rustls-webpki = { git = "https://github.com/rustls/webpki", branch = "main" } diff --git a/rustls/src/webpki/mod.rs b/rustls/src/webpki/mod.rs index 65412d14ffa..82aac89530f 100644 --- a/rustls/src/webpki/mod.rs +++ b/rustls/src/webpki/mod.rs @@ -91,6 +91,7 @@ fn pki_error(error: webpki::Error) -> Error { CertRevocationListError::BadSignature.into() } + #[allow(deprecated)] RequiredEkuNotFound => CertificateError::InvalidPurpose.into(), _ => CertificateError::Other(OtherError( From a70b0e6a2c10b951574f7933e6f5c41d5058adf8 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Sun, 13 Apr 2025 12:26:17 +0200 Subject: [PATCH 182/403] Handle webpki RequiredEkuNotFoundContext errors --- rustls/src/error.rs | 89 +++++++++++++++++++++++++++++++++++++++- rustls/src/lib.rs | 5 ++- rustls/src/webpki/mod.rs | 14 ++++++- rustls/tests/api.rs | 43 +++++++++++++++++-- 4 files changed, 143 insertions(+), 8 deletions(-) diff --git a/rustls/src/error.rs b/rustls/src/error.rs index 73cdcf10298..09a4244ed4a 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -2,10 +2,12 @@ use alloc::format; use alloc::string::String; use alloc::vec::Vec; use core::fmt; -use pki_types::{ServerName, UnixTime}; #[cfg(feature = "std")] use std::time::SystemTimeError; +use pki_types::{ServerName, UnixTime}; +use webpki::KeyUsage; + use crate::enums::{AlertDescription, ContentType, HandshakeType}; use crate::msgs::handshake::{EchConfigPayload, KeyExchangeAlgorithm}; use crate::rand; @@ -434,6 +436,17 @@ pub enum CertificateError { /// 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, + }, + /// The certificate is valid, but the handshake is rejected for other /// reasons. ApplicationVerificationFailure, @@ -495,6 +508,16 @@ impl PartialEq for CertificateError { }, ) => (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), (ApplicationVerificationFailure, ApplicationVerificationFailure) => true, (UnknownRevocationStatus, UnknownRevocationStatus) => true, (ExpiredRevocationList, ExpiredRevocationList) => true, @@ -538,7 +561,7 @@ impl From for AlertDescription { | ExpiredRevocationList | ExpiredRevocationListContext { .. } => Self::UnknownCA, BadSignature => Self::DecryptError, - InvalidPurpose => Self::UnsupportedCertificate, + InvalidPurpose | InvalidPurposeContext { .. } => Self::UnsupportedCertificate, ApplicationVerificationFailure => Self::AccessDenied, // RFC 5246/RFC 8446 // certificate_unknown @@ -622,6 +645,23 @@ impl fmt::Display for CertificateError { .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), } } @@ -634,6 +674,51 @@ impl From for Error { } } +/// 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` for human readability. + Other(Vec), +} + +impl ExtendedKeyPurpose { + pub(crate) fn for_values(values: impl Iterator) -> Self { + let values = values.collect::>(); + 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. diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index da044e3b317..51fa5741f3e 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -554,8 +554,9 @@ pub use crate::enums::{ ProtocolVersion, SignatureAlgorithm, SignatureScheme, }; pub use crate::error::{ - CertRevocationListError, CertificateError, EncryptedClientHelloError, Error, InconsistentKeys, - InvalidMessage, OtherError, PeerIncompatible, PeerMisbehaved, + CertRevocationListError, CertificateError, EncryptedClientHelloError, Error, + ExtendedKeyPurpose, InconsistentKeys, InvalidMessage, OtherError, PeerIncompatible, + PeerMisbehaved, }; pub use crate::key_log::{KeyLog, NoKeyLog}; #[cfg(feature = "std")] diff --git a/rustls/src/webpki/mod.rs b/rustls/src/webpki/mod.rs index 82aac89530f..c6c40916a7a 100644 --- a/rustls/src/webpki/mod.rs +++ b/rustls/src/webpki/mod.rs @@ -4,7 +4,9 @@ use core::fmt; use pki_types::CertificateRevocationListDer; use webpki::{CertRevocationList, InvalidNameContext, OwnedCertRevocationList}; -use crate::error::{CertRevocationListError, CertificateError, Error, OtherError}; +use crate::error::{ + CertRevocationListError, CertificateError, Error, ExtendedKeyPurpose, OtherError, +}; #[cfg(feature = "std")] use crate::sync::Arc; @@ -93,6 +95,16 @@ fn pki_error(error: webpki::Error) -> Error { #[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")] diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 939c8f6750a..95bc0cbf642 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -22,9 +22,10 @@ use rustls::server::{ClientHello, ParsedCertificate, ResolvesServerCert}; use rustls::{ AlertDescription, CertificateError, CipherSuite, ClientConfig, ClientConnection, ConnectionCommon, ConnectionTrafficSecrets, ContentType, DistinguishedName, Error, - HandshakeKind, HandshakeType, InconsistentKeys, InvalidMessage, KeyLog, NamedGroup, - PeerIncompatible, PeerMisbehaved, ProtocolVersion, ServerConfig, ServerConnection, SideData, - SignatureScheme, Stream, StreamOwned, SupportedCipherSuite, SupportedProtocolVersion, sign, + ExtendedKeyPurpose, HandshakeKind, HandshakeType, InconsistentKeys, InvalidMessage, KeyLog, + NamedGroup, PeerIncompatible, PeerMisbehaved, ProtocolVersion, RootCertStore, ServerConfig, + ServerConnection, SideData, SignatureScheme, Stream, StreamOwned, SupportedCipherSuite, + SupportedProtocolVersion, sign, }; #[cfg(feature = "aws_lc_rs")] use rustls::{ @@ -36,6 +37,7 @@ use rustls::{ }, pki_types::{DnsName, EchConfigListBytes}, }; +use webpki::anchor_from_trusted_cert; use super::*; @@ -1976,6 +1978,41 @@ fn client_check_server_certificate_helper_api() { } } +#[test] +fn client_check_server_valid_purpose() { + let chain = KeyType::EcdsaP256.get_client_chain(); + let trust_anchor = chain.last().unwrap(); + let roots = RootCertStore { + roots: vec![ + anchor_from_trusted_cert(trust_anchor) + .unwrap() + .to_owned(), + ], + }; + + let error = verify_server_cert_signed_by_trust_anchor( + &ParsedCertificate::try_from(chain.first().unwrap()).unwrap(), + &roots, + &[chain.get(1).unwrap().clone()], + UnixTime::now(), + webpki::ALL_VERIFICATION_ALGS, + ) + .unwrap_err(); + assert_eq!( + error, + Error::InvalidCertificate(CertificateError::InvalidPurposeContext { + required: ExtendedKeyPurpose::ServerAuth, + presented: vec![ExtendedKeyPurpose::ClientAuth], + }) + ); + + assert_eq!( + format!("{error}"), + "invalid peer certificate: certificate does not allow extended key usage for \ + server authentication, allows client authentication" + ); +} + #[derive(Debug)] struct ClientCheckCertResolve { query_count: AtomicUsize, From 260190933b0ac2408dc6b5939dd6273fe110de83 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Wed, 23 Apr 2025 09:57:55 +0200 Subject: [PATCH 183/403] Bump version to 0.23.27 --- Cargo.lock | 22 +++++++++++----------- fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2cb9c2ee2be..68dcfe40dc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -491,7 +491,7 @@ dependencies = [ "base64", "env_logger", "nix", - "rustls 0.23.26", + "rustls 0.23.27", "rustls-post-quantum", ] @@ -2625,7 +2625,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.26" +version = "0.23.27" dependencies = [ "aws-lc-rs", "base64", @@ -2659,7 +2659,7 @@ name = "rustls-bench" version = "0.1.0" dependencies = [ "clap", - "rustls 0.23.26", + "rustls 0.23.27", "rustls-post-quantum", "tikv-jemallocator", ] @@ -2676,7 +2676,7 @@ dependencies = [ "fxhash", "itertools 0.14.0", "rayon", - "rustls 0.23.26", + "rustls 0.23.27", "tikv-jemallocator", ] @@ -2687,7 +2687,7 @@ dependencies = [ "hickory-resolver", "regex", "ring", - "rustls 0.23.26", + "rustls 0.23.27", "tokio", ] @@ -2702,7 +2702,7 @@ dependencies = [ "log", "mio", "rcgen", - "rustls 0.23.26", + "rustls 0.23.27", "serde", "tokio", "webpki-roots", @@ -2713,7 +2713,7 @@ name = "rustls-fuzzing-provider" version = "0.1.0" dependencies = [ "env_logger", - "rustls 0.23.26", + "rustls 0.23.27", ] [[package]] @@ -2725,7 +2725,7 @@ dependencies = [ "num-bigint", "once_cell", "openssl", - "rustls 0.23.26", + "rustls 0.23.27", ] [[package]] @@ -2740,7 +2740,7 @@ version = "0.2.2" dependencies = [ "criterion", "env_logger", - "rustls 0.23.26", + "rustls 0.23.27", "webpki-roots", ] @@ -2761,7 +2761,7 @@ dependencies = [ "rand_core 0.6.4", "rcgen", "rsa", - "rustls 0.23.26", + "rustls 0.23.27", "sha2", "signature", "webpki-roots", @@ -2773,7 +2773,7 @@ name = "rustls-provider-test" version = "0.1.0" dependencies = [ "hex", - "rustls 0.23.26", + "rustls 0.23.27", "rustls-provider-example", "serde", "serde_json", diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 079e5500ef7..e6eb20cc0cd 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.26" +version = "0.23.27" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index aad7b604e0d..7d93128a7e2 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.26" +version = "0.23.27" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From 8d4651776e69beb2b0c2f8f2c93d26f7ef1c6bb4 Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Tue, 6 May 2025 10:55:22 -0400 Subject: [PATCH 184/403] fuzz: remove Cargo patch for webpki --- fuzz/Cargo.lock | 3 ++- fuzz/Cargo.toml | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index e6eb20cc0cd..dfa8f3f50e1 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -311,7 +311,8 @@ checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" [[package]] name = "rustls-webpki" version = "0.103.2" -source = "git+https://github.com/rustls/webpki?branch=main#9cf30f67d6b8f91d87281cca0253dbc6950eb1f3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7149975849f1abb3832b246010ef62ccc80d3a76169517ada7188252b9cfb437" dependencies = [ "ring", "rustls-pki-types", diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index eddc99062a0..b2884a8e10e 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -49,6 +49,3 @@ path = "fuzzers/server_name.rs" [[bin]] name = "unbuffered" path = "fuzzers/unbuffered.rs" - -[patch."crates-io"] -rustls-webpki = { git = "https://github.com/rustls/webpki", branch = "main" } From 5fd445f23126a9aee05353701e68bb4bce121f1a Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 7 May 2025 09:15:30 +0100 Subject: [PATCH 185/403] Update verifybench test data This was four years old, and the servo tests required a now-removed root. The process for this was: - delete all the old data - run admin/capture-certdata - adjust the time in verifybench.rs, and adjust chains that changed in length Document that in a head comment in verifybench.rs --- rustls/src/testdata/cert-arstechnica.0.der | Bin 1517 -> 1509 bytes rustls/src/testdata/cert-arstechnica.1.der | Bin 1101 -> 1122 bytes rustls/src/testdata/cert-arstechnica.3.der | Bin 1145 -> 0 bytes rustls/src/testdata/cert-duckduckgo.0.der | Bin 1741 -> 1776 bytes rustls/src/testdata/cert-duckduckgo.1.der | Bin 1218 -> 1228 bytes rustls/src/testdata/cert-duckduckgo.2.der | Bin 0 -> 914 bytes rustls/src/testdata/cert-github.0.der | Bin 1290 -> 1189 bytes rustls/src/testdata/cert-github.1.der | Bin 1055 -> 940 bytes rustls/src/testdata/cert-github.2.der | Bin 0 -> 983 bytes rustls/src/testdata/cert-google.0.der | Bin 1164 -> 1114 bytes rustls/src/testdata/cert-google.1.der | Bin 1434 -> 1295 bytes rustls/src/testdata/cert-hn.0.der | Bin 1740 -> 956 bytes rustls/src/testdata/cert-hn.1.der | Bin 1218 -> 1115 bytes rustls/src/testdata/cert-reddit.0.der | Bin 1730 -> 1764 bytes rustls/src/testdata/cert-reddit.1.der | Bin 1218 -> 1228 bytes rustls/src/testdata/cert-rustlang.0.der | Bin 1540 -> 1531 bytes rustls/src/testdata/cert-rustlang.1.der | Bin 1101 -> 1122 bytes rustls/src/testdata/cert-servo.0.der | Bin 1335 -> 932 bytes rustls/src/testdata/cert-servo.1.der | Bin 977 -> 675 bytes rustls/src/testdata/cert-servo.2.der | Bin 0 -> 894 bytes rustls/src/testdata/cert-stackoverflow.0.der | Bin 1785 -> 972 bytes rustls/src/testdata/cert-stackoverflow.1.der | Bin 1306 -> 1115 bytes rustls/src/testdata/cert-stackoverflow.2.der | Bin 1380 -> 0 bytes rustls/src/testdata/cert-twitter.0.der | Bin 1606 -> 985 bytes rustls/src/testdata/cert-twitter.1.der | Bin 1262 -> 1115 bytes rustls/src/testdata/cert-wapo.0.der | Bin 2211 -> 1731 bytes rustls/src/testdata/cert-wapo.1.der | Bin 1329 -> 1003 bytes rustls/src/testdata/cert-wikipedia.0.der | Bin 2086 -> 2126 bytes rustls/src/verifybench.rs | 28 ++++++++++++++++--- 29 files changed, 24 insertions(+), 4 deletions(-) delete mode 100644 rustls/src/testdata/cert-arstechnica.3.der create mode 100644 rustls/src/testdata/cert-duckduckgo.2.der create mode 100644 rustls/src/testdata/cert-github.2.der create mode 100644 rustls/src/testdata/cert-servo.2.der delete mode 100644 rustls/src/testdata/cert-stackoverflow.2.der diff --git a/rustls/src/testdata/cert-arstechnica.0.der b/rustls/src/testdata/cert-arstechnica.0.der index ac81cd85ec8d9eaddab3eedc92cfbf72ae643905..a0d033ae6ce70ebaadfb4cb033f3ccf49281afd8 100644 GIT binary patch delta 1252 zcmaFM{gm6lpo#UNK@-c#1R zK(48QrIE?Rez*En`BABf9BYn5xnD9}QFie4BAz-oui#p5D|S|oQ;C};jWtpa*nII^ zwEd3qQaz_8y~Kadr3;Lw?VV*ZRqym%mhd0k44ytuFa2AhowqJPtWEp!%RSqbKY8ht z&daxWopEWms+nKt`|3|{NKb86#8g5i1^Y1}OS&@zB`&VbCYpPhyo3=MR^>Od=M5!Gck=zzT{n(SR$?-k ze1J)GauAcgjWtNAJc|i13JezLEzoJx$|xx*u+rC0F3Qm>GRieD(n|zKS4mN6afx1X zey%=56evIW3X>Kqm^Yc3S+gFm>eM0w9*|YSjEw(Tm<$*Uniw0{xU|_ASs1TXGO;kR zG%*$caSme^Lpg)cM?aIj!9_kTY?6oj?W=@;Jl~qs-Z3ZFfVJiI(>66L1_s876ZIwS z85mfY89WT!m=qb-CDwoY`MCV|E;edt-4-Lk&M!U(8ltGs|h zSAE*i3@Ojg=N|m(;InLa6o0Vw$h2s+r)=B}Aq-^kbQ zz;Eijoy__-`Fiv!cR+0}2HWgz;L4=nxi4q=-SC!mf9iGGMdaD<2#fYg+k|@up8uR- zlC@4`hYrx^C#?vs zRO{V2&DYiK8Ed_i+#aCK4Hvx5Mf#fQRZCpXng59O@7oE{TNih4t&)2lFQF6@+JKf* znVT3H86pJ@7TX`(DdxLUb{+qx+%wNlDE#?8PhqL5!=x3DI_E7uwkKm|@gt-dAk4_{DB1%R6?Z4DzW}2mR9zDdi{|}GG?An%!ZIRc4n!~C$gk>>biAp?Dcag!X-SkuL2`jJM z|4!2xdYpgV`te}u`nl=zUraK4!l0CQ&M0KkiGpj7{^fBWR(=xekWo=HLCyKn{HNJ9 Wch=_f{d^F9?Nn%FrA~KA`+oq~%LAPN delta 1262 zcmaFL{g&Inpo#URK@-cx196X!KD zG&D4_GysDrAlJyy$jE$Rt6Tjn%Ql`zPF>|cm1S1tYk!`mZf8>$y+AJ5B<9E6c*VJ2 zwkVXX6utFu$=7)K`Oe4UHIHZIiRmb_XR9saKXr=DYhh^C)ZgL4yNVy*Yj^lw_ zn!|@%RiE!(Nfh z8y5C4{fpa!=33i|Ri@0ZmTl&_xb3FVilw$i>_JZXx##27?TB1{MBmUvci!Lq)vm7Z zy!%|f%&X~E`*N)Dt4+JB+QC;VU$gJObAaWuzkVwdGb01z;wGlw22D)g4dj7AC#%dN zVIbBZ61gOeEoedY)JZmrr?9I}D~bMTd%-{!q=1h_j74O!;L2wk8t)jmN==GR*#An@ zzgpOSvILXC1F8T=tgHeHj{%nf2OC>@BM&1JB6Vjxm&_j!8jw&Wy75SNq$o)#UcXOxAyD?sWT7LCp4qomj&1gN7BE!2I3WrT+hPD|sNxW^T znsNHkuG9bWI(TDtgv`&L9{yr6(8G==PHnue(}1LGd@g6 zn#T4GYH=#U!wR|4J;j%lP2#?vPbup=T(Bb8;NKjxM_L9ZTZ$~+uyS5vQb>NJR~#0* z>g>KnE4F@GZM&Q^_j>1=$ovI=Bd5D?O!)t4@Xq6=a=W-!r|b#rozmQ_ zX?ipwz|nV2eEmDo8#?=4gYP$*-P;!OCCdJB_XNIwqV0RX$EWM(Id*MR^h)Ss_BIYz z-x>9c@y-87MOu>IXJy~m`Td4HlQFaDO!lJARcB_bY?@Me!i9n1P4k+><7zYQB`q@5 uUFQlPv=z77IzxEVl!s4*1y^h_FSe8OYIt>gIdiYf;b1dSI5IObGBPzYFj_D?k&Yi7955ON162eA6B9vgVR~Us8=&b`m2~WZzksf+Dvj@$~C>J}cWt z1FhM4I0}MyWryX6`#bxKjt6>_S&R)uV+I-ZTmSV*0_BYS|0O!*_#c3&00{yf_!vw&dceX`FiVu;c9Gc+G>|KXlAYjDX;^JTm1&<{6&ug=Ubk2 z7vr(FsCF#g1Rp0}XR;4{#HY1DPCh8j$9L6%Rel6vy)>~ly3>@}R*^|Gn{Z4%|15)l zH69Q;xJD?DPHKPl>@5FwBr2q06Ft+hrKTpL5oQw`fCuU9?!{99NN=?WvYH@eBC$M$ ziKiHkqjcN_she$EP&vacW+9N1d;-+k0R$NkN^Mx delta 685 zcmV;e0#g0r2+as0FoFb0FoFXypaTK{0s<2Tf0S2+hv=+#-m+6NTfCWzRt=FNP98Be zF)%VRFfcGMFfdvd4Kg(`FflnWFfcGMFj_E1k&YiH6)+P9162eI6AV*ja&~2MAVWbQ zF+wp9FbxI+RRjYQ20?9MdT(x#${~NkP8Mg~&b(^KH(KmEFt8ow(GutqC`iocDZ#mJ zQ`MvE134PZcZc=?x!G{c&ufk2;{$PqnQhCalqyaW)~CG$>^@R@sN*RX2f1!g&--67_#L_fN@9rvu0BWd4=0i16d;B8`ss=_^ZAV8z$*-d!q`(4 z%V+S=h{`(A7jyMrn$*Q|9)1Dwm@s21s`7d*#o_`QhUGFo4!sey&peaw7f=wML&63s z;0JCjv#N%62}ON`s!Z=0)K0L-q*XZRl>>F$WXyFEI_1ZDBWiSn&K& zn2{&~PX%_j)9@R@=3dZdg%J-ffyNMlDgGc}Nb~aWgcDO`H5CzSf`3s!RaajawXh;S zt@2)@0pr87`O86C=2DTn%c9LcMVAp zC#5*8#1f;lqsU0J6$>8X;u+k;c2dZ^ia~gA*=?7zN{e_cUbGLROkm34N6UCE5*M*j Ti^@4Hy|pjGGXj>Y+5(h+w3#iu diff --git a/rustls/src/testdata/cert-arstechnica.3.der b/rustls/src/testdata/cert-arstechnica.3.der deleted file mode 100644 index 75df0cc7c0be230aca9aec4f9d5e958ea3b268ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1145 zcmXqLVktFfVvb$F%*4pV#L2Ln&&$W8X?wi^FB_*;n@8JsUPeZ4RtAF%Lv903Hs(+k zHesgFU_(^{We|r;SSGk6u_!GwH77+OBsDoBFFz+gJu|gfN5L~MSw_D3L6N5MA(J7f|K)0N{Ukwb5eYzHCKm)Z-)bolIh;O^CBy1|pF@brm-wq|5 z7mj4oZa8D&et+k^38}eE=XEA7TlV~3tAuAwn%`op+?8A3ndt4}W!_|WKI zv(GhNbagYDR?vQriOL92MMqM(_))}EJy(# zix`W@oOp)&s~E2vXj^nF+L7xu=ab;XW&?SUv@(l?fmnmc{`l<|&)t=8`w|_x=FWA2 zLwqYco*VeHacHwKva+%>GO{=uI2y>n_y&w^0vRPG1y=g{`Fh30MtY^i`UZ+{S*A8o zsB8sHwn8sCwa7pXWTQNbyn(EN^a9BR;&64vFm*+G$wfKf#3!r3!ezi=z{bWBDyzVN zoG5^q379At8I)xocZHv-eJNh)^HDDJ@0s8{J9qy3$3j1CVljK$ARl}r)90=P*H74Fd{#O_po!_n5B;yg30GLpeQe}7cz1c}bbpDRx%a+Lp2)GQ&Oztx!B@M> z<{7h<%kpy62j7)WS>2@mG4rZ#+`2Cd50@^FaMAr_Q!r!AuFP#y%j@|K<8=NkXt#3D z{7@PHMI>a&)HuNkp#=4F^ADB(R}L%Sm?WBn diff --git a/rustls/src/testdata/cert-duckduckgo.0.der b/rustls/src/testdata/cert-duckduckgo.0.der index 9f8267ca9259269393b3af3301adc69efbeee840..2f0fd204d98ebef9431eca5ba0ca1502efa12a6b 100644 GIT binary patch delta 1221 zcmX@h`+?WMpo#5`K@;nh1Ou>o;tcVpR4}uHq{-;AP{~YV&CO&dbQi z&B|a9IdP%rL{|YBV*^7r=1>-9VJ(-;^i1c}q7nu7ocyH390hlyiRrQ;rUu4_mIh!D zCC+PPYG`C=IdR6c`o4@mJ1z3ci=LQXyjJ-1%Y&t>WA`Mw3*L*7ns;~74Nn0HZvLWr zW>*o#tBXW)Kdfn)y>a`}4?D70PTbwF@EYU(LT{HK<2=nJN^76}l>0Vm8EgE-dI_(x z1X0^3+a|4ZOMg-sGI4jfZ@z{g$Nn2W!e8(7UX&^j-}Y?R?)@hgd=XZtKf>|mis$NspxZUuc~gJ_r&*{Z}jATSz078t=F%L$bM1eVN&?$K h z)k&R43VzF!+BLu2CA)o%Rp|`V1MBntU0}JE;{2dF{^iA6Dc$EMR>v*p4;Hc!;;2sK z%6C=P5^ar@V@YsP*s*->mwB((9rsti&cw{fz__@HdA30l^K=7wU?|Eevq%_-HHeh7 zHXKMhe&77w`MsLvtC(f?y*(>#APZ8!$0Eie^4{in96y)n2LHe6^)uI{ezvuIY&p4_ zNpEr%v%}<-Oa>zJK}zLW8mAjHPBHLU;I_b}&1v#mCPfZN%(xp(7G#m&%z;bkGowlg z6YYE}#kj8oTM^jOEhz{1SnX5hl4Ao@XU|E8Gvd(%a( zO{w8ZUDKF+#^L6=dD~_ly&IUN@nA2Lg5~#i39Z6%$+dOW7w$}Gn&wV|Z)heeDHX{h=j`7{YI#R(WK>ct248?UA;l1^fzkx7*o2fZF>4Y_Ge4 zE0ZF_{wc3nLq0d{FMMdexJ&Q%p_^wG_3T_H$az>!tTNr>&@Uzhp=5>dl-a*4#9g<) zE($qndh-0vyP7@kg_j?w>VLC(OCHeTXO|3<9m;zS3OKS|FRb5r?%*YdZ_`@Ze(!2G zlKm@Z-WLG1_$}OG1<~0`h6(}(dCez}-H4YK+YniQPLS=6#eLBy+tR#G3#0>`_U`G- z{0qhHGAfg|AGUwevnzD{$0H@rd*7FPGw2CUka~!g6`7kD85t^{@z=+)MsYA5=vi=q z>(BO;d;IhcoAeqgY`-#9@K*MNb$cw5m)W+(W^djk%z1J}Pb`C2%!g9Xm#5b)E&Ry& z?_Z?jbJe(;Ct6sRc-bk=OWXLpLjRb}*QZzJy=i@MVDVx5MTxhHoW=V$UF5xZX`)W` zG4^WhjZ=0n^<=(V^RDv4b?&vNPt}Quq|KwPz3)YoY0xGuifzAv@$Th1Zt ztYsgkzGAd6y!6)UdRzJB=9z7G&KF!v-t6I&8Wx?p>im3`&HPqkkr#f%Nmhqj^PC0% DW&r|_ delta 1204 zcmeysdzRP0po#6IK@;o71xtu~Lg@4SqR z+^h@+{u2#Ug)|M+*_cCFn1vNwGSf4iQ;SL_7Rt&R8X6gx8h}BRIIocrkZ)#WY-(w0 z8D)?&(Li+Kfr|P$i*k={jc5{Pi`dS$)kA9SOaA{)l;f%k_OAG^E|4o}H*1NdLTX^z zx8rFMq3^c^|7KmsbaK}x$7yTx*MDdIlN<7YN9&2`ftndR7TnUivf6^r+g6d=?{jvg z+noF222;1sV}E$c`y+Zv1~H!HCg{t&(=@bpb+WIe}9_KZV1q5N~N zId0L836-wdzTnN0O`&>M9yr-$U1wTiw{l^m>=lR8|3AN8v*C@jms$0uo-N8!TbU2- zUOsnn%lQp$YeMQ(etR9hs$}`OF@eG0$og-e>r(IUU0G52e8!V)OKz{e(4uipVO_A% z70&Zk1@#-Aq#G<$yjiep>u%4YbN)KwOw5c7jEkF?n+%$m>kQ<9;V7%jB4HrbAhJDs z(W@1!T6!v9ZMnriW7E;8WjntZ$buB`v52vVEZ<$S>7TvQ)OU#ogHjLjv#Xc62~Tci z(wqF5$v~tZq)eWrvE87t#lT^K-2$67tI6ifijxzVMR-m0l8bWSqKyzyRcd|?2L>o#Ri3wuQ03gdcwpEnA&V7bFioYO_G@G!=hDR#-Lfb@54MxOT`ai z#q*PwmOtGWUOOj&>&H*uShX0{*yAk>42-oM3RBiFFt9K)xEr`KDP%t@Sy8q2<;OLw zi_bIMpKOq*z?B^2m9N!s*Z-^h#;!L^iVUAy5?d_N1;id%#PL<6e&_Oddxy!a@0Xy= ztDsW{CK@m>lrcD-IJNP9y^@=kz_Eo^oKEd=eumxB%&%X2AJ6zOA!!=hH>kz8;1(+~ zEV;kN({O*>^O-9hyKc;h-x969&Z@iE+V4W_{0sH0e5FhZO8Ei7H!TY6Zda(TDw=WT zY3t77SgX7ITY1FQbp9v{x-yh9++P~EI-|*7K49CN%2R?Zfl8`8bPMg6Db$|-+y+t6|za}y&Y!`isy`jaoZ{$|~&T=|gg z^~sLBdQ1Nkwo*%;yBMwbGi}L{eBQ3 z$DwNN9jhN6_FOw{dBX9tbEV^4>wMPK-<4OV4pu3BaB&&J5Xe5ZiO%4C5V!rcufmmfVB7e5j4 zL@3~W(MPTwhCUm!JKDs)ok*=tX4qx7TCr8om*u-!mArGq(`H#|FD})Jl_uw+1ps9h B^cMgC diff --git a/rustls/src/testdata/cert-duckduckgo.1.der b/rustls/src/testdata/cert-duckduckgo.1.der index dd6a50f3273eab884f2245df8b0ad90967850380..b2b371600cef8d3a439ec441789b9ec9b916fe29 100644 GIT binary patch delta 705 zcmV;y0zUo13Csx}FoFcgFoFZHpaTK{0s;^W^}PlwRs!^TxKJ!3%GczzSFfcGMFj^N4GchnTGC49cH90joS}<9WFeMx_Ffj%LRRjYQDnw~#X+vdl zbRb7;Z(?C=AV)Hh>N$VR_Yh)Frn_Tr?T}Jd#cd~hdJYS`n$!xBryI~@5J+cm*W)m6iv&g5b_r4t0M3* zA`xL}kS4l#*_R*VeP*k5M3r;MtpD#_3W`}n;jFSc5A#U;*K2<_!DHOsM%LR!{(U3; zkmykd9#NxT?MX&de=LZ_^b?$y6+8pzp*h@X3^Kv57FSG^M?!p}$eexV)J;^cLYb(+ z1j2Wm)=1>e5#TC-nean!&p&o+(M(CJBwoS|g8fFQt8A0ZVp2kNlK7hXUS6`WVdWnm zxqk_m=so&_e@6mop_3y5EH!k6fWT(Q-#6aRy(u@U10BBY%@;5q1_M3Nq1405vGLvfqSAUT4aLXu{X_tI-{lNMr zdsC~e&1L<%oCchV*IGk|?M+NpU#-E#wFMw9S<(MW^`I))u$8UJE=oJsr}l4%Df}=$ zB!s)ew|kQZEU$-ab~Eh&RZ_B9p5(dE^WWzW{@wV*xe#)J2?Srym!2*%b&k)PSkhN9 zem4PuvSw{58h^2732o7Cko39wF98(ATvlWO*?otoI8&dCT}EwO#wUb<)P9VNqnlFa z#)#}Ud@B3!Ra!W55ZC|{&rEaMsy8*LDS>I6cD&vgdyv%1&+lgg{RCPe7P0^8Ki}Mf n_3QLmk|PZyDwQQn%At|w)VHjMbhGhoqnX?J)xCs3p8^M%vyetg delta 695 zcmV;o0!aPL3Bm~BB7Ve?A8;f?K`G%++VFfcGMFj^N4GchnUF*7nVH90joS};$MFeMTxFee5BRRjYQAVg_rX+vdl zbdmHqf5A($Wk+zl-A`EC?40exX5}9-6I88AW=0<@3hZPDt8 z9fFAE5mwtCpIE|C=PWc0F4B_WR?G2uU$eW1$|VDPno>b#5MWPN6G`ysH)n(2=hI7P zOd?UH-wv4&?N?EBCgOd^%3>}P8-F8+B~x#~e>7MCi-iC9zNc78B72stqKKOnyr6vF z=~1ZFumda`tvb(w{S}uiCDUTz4L1w>3+`(x>%f9)R5EtZ2i!fZMSiPThDC^S_#m5 z-o!)LDx}_?K_*|jkD1HeuHmR}pNIZ*w;vlItFceU^=DmOn>^|NY4>4l*4gv@HpZ)e z1BiCgOD=VW);#kc}WWi(!k&?-D2oKcxf=Te^cYY{6Al71cNit9EOLx<`r dW50Dj>)ylzy9zw_Fz@THO#F*B5OY2P^Q5mxM85z4 diff --git a/rustls/src/testdata/cert-duckduckgo.2.der b/rustls/src/testdata/cert-duckduckgo.2.der new file mode 100644 index 0000000000000000000000000000000000000000..1e927a7afe06c270670d6bc25c4d465db2e0a7e8 GIT binary patch literal 914 zcmXqLV(v3&Vk%p}%*4pVB*1L-@!4|0l?!%jq->Ps{Pom;myJ`a&7m8Ce;an;7{S44N3Zn3@aHzbQTHIERDpF(!1g)GQaJ{9Zplk- zye@a|@AU_#r!O{6V{hxNd-12ggQTEo);V)vP&-Tc!p2{-S^Rub$w8x&gcgr9D_VnJeCX{_;|J2P} zlz02&x_&wBDQX2hucLu6-|8C^Skma^IW)V_ne~}jhi)FnV1keK@Hao#ijU%z$=y=4>cw?qzQ zVDbWnG9yDmy2g}zK9A(rhIe13OI+=&wK>}DRsV9|ZEf-U8{&)0wTy%<8`GUyls~zq zo4)DT|D%6HB9Fdi`2qHg8zibR_3{p5LfoBYYm zyzW}IGxc}J?B04s;o;2qU^mg*8M8lpHn?hM_^7vK-s7%Yx2D;d3NMZS@UtMGz}-N8^%tYFG2u-sL@JUi+4LlJwK^__B94 Uy+>lhq8Hsv%iC;f{?uq20B`eLrT_o{ literal 0 HcmV?d00001 diff --git a/rustls/src/testdata/cert-github.0.der b/rustls/src/testdata/cert-github.0.der index 86d6fce22f2ac46e8eb07684d21a843addd541e6..59366fff02d41e90d1397594d8799b06c36207ee 100644 GIT binary patch literal 1189 zcmXqLVp(X=#Nx4lnTe5!NswW6THDs7>KCljnuHC6+C0A+aItY{wRxPgWnpGAXzVxS zHsEAq4rO5zW^#8jls1qAaX5s9+>25ZOHzvzd=vAMGg6CzOhW+!K9D54Fne%fPFj9Z zilKyo7)XRmm_Il*xg;|^U%@9cH?t%)#n9Zq6ePnetOt{Eb#_*8$n7#%)gPAI&X4Yc#kQ>l}~Spa0zLE=$+0(+#@j9lY<@t}Sk2`eV?< z^us_NXsfI;3((IEBHvoMtOeU1vefde;?}wJ?o3K`^*RGtkODpyF&2^F6ZQAz&G0+! zdu`9X)l=;ZY;7-|00*8dKO^IR7GTJ;HyH4MlnaCSOa=@P&8jS71|n=6+H8!htnAD{ zk3d;W2A&|r3M@_r4hAM{+(2O##!ZI6_+>XxHBg4BV`3B&&nPJ=D7MnqFNQ=2C~)+h z1A+}W*x1q=c^H`(4H{cu>KPeXDh$dD{9$|prZ#7gexUZ`q7pr1BcQPej6_HrBBBry zgOCVxcGLrEL^#NRu?_4Xpn>_x#RbSF8Z z%1&>J^7aLCLYBF5()NCeOmoUhj+)O~|MxwAOu_~xg`~g@ZrycW3mLi2|F7FqpHOoC zP*1JH_M$f#mvs~G7aU+HXOL{Wa$I9o{=Z$!`4w8ej1yO#(=9UOUw1CHz)@G#=lB(f zwUgh1t@SW)V^U;zx~B8voB7)fe=Rs7yHD)b_L7q+*H-)}65jCt;giJhV;6u*j{H+u zAW-YwQ6jjpZqI6|JvtV)FWt`Op5WOu@$xY@ZefNphSL_`MLTO+7P`boAH4hfWZtJ) zk!RhxGFe+UoEAAO67d}BUsbTh?gp+vQ?DdV`<}LdC)iW5>x_JblrPW)-(n6}S=i;Y98&EuRc3p0~Jx*@j# zCmVAp3!5-gXt1HUfhdT>CCulNnV#vKT2!K=;F*`KXJ~I=3zA?KHiJnhcx0w$C^!}u zmlh@FC8sKc_yj9>R3;T=rYN{NJ1YcxI2xInDHs_T87MeA8XCxn^BNf%7#o=yfI$?H zYh++-Y+z(;YH4a2WsrvI5McvBkbNA&T+WF(nQ8e&d6|iZVg@20L3Ux@;KV!yH;}!V z#mV`Gq6WecSM#`MmUxsVLEQ{BgISm>J+maEG)XTxKi41GU1(!^Z2x=+x%JZ*r z`fyhBytjcYNC6*<7>kJd#=7~t)n*3V_S2C5)wK^8d!nIQpONuD3os(t8z82tvVa1KLz|6}m6e?t=tC%r$)Ir~NWDBu<4S|ZWd?x@ z{1^DPd1sWA6j!ko=JQ*0{pkUI6#WE<8;c*O%Vn_@FBN!6Dpy&n0t{%_; zOe0MwHqs8{WCa#;15*QIHn#Le9$|VPIga$lAYGih+TJnZez_l}V9d-m?yu`adSFbBuiFub$Gzw(f4S?xU~q z$SgRZ4Z>ylGh&au8%#|9FzBmp9yNOCD>jM12>?(GZ=)tI2|R{v&Cq< zm)m`>HK#se<>h1;6j-PKDHEvV?$IA>_kPIOaC&vajt^H>1f?51U;M%P=eFIP z7nW`NcS;tyRAP2#FmPc~(0;W3P5yo@*CnPi%x#abEq#Jl?ARzWIW++r} zoHE5Qu|Fu$)ixV#<3&m66j-+;1pKtMU-AS*nGbT(6PYs%1H}-#TGJCtfGIAKZ%dh_ ztQAJ?9+Fy9#biNdTxv><$h#$8r0d;&*24$okU0)Xamgx&+uIosIVJY;Bq$)N_4BeY4 zj;in~gc!`Yzwp#I<-LsLCzR^ildrVC|9;aoy_U1`)ubJd(01eX#ss*{)=?8&p6bDF zxg}~}ytkS0r{bk&W@ou}dKC4;DB2CVvNB^nA&b9dD35Bw%S)N>9)_g4(6?2~2bP@# zqjDgLNFxl}W7@O&aFiHMdZ8=)y#9$B8k&nu!I+Gqe+fdiLpZibBc1*eTqaA5>&YSIeQTXSxN_*kWBz2Nys4rYLe_4Ifh~=G$~*%Q3o|p9kE5M;YyDr z^_CYEv7*=9ACyy-Qa=B{T#4x$pN|aA95?l zIhC$9t4t_?>3{$YXYLUM*kJEbhQoga?m>XZ;KGlOeQmGWG``8Ij`rZ%=E{lX*Ue6E z-|6hJj{1|o>Ss0=Li6_OjakgTeW!8Gk1@zzT-GXqz#;O8a;z_t8Jv{S#jR literal 1055 zcmXqLVv#mzVrE{z%*4pVB*2!=9KBoQZ}R#B*H#4k{S!0bW#iOp^Jx3d%gD&h%3zRV z$Zf#M#vIDRCd?EXY$$3V4B~JJ^SETDXF8`Al_+@TB^yc_h=YW=g$2sX%k@%#QprFm zz2y8{Lu~_1kQB495?qHzW_pH#V{vh5QDRR3;T= zrYN{NJ1YcxI2xInDHs_T835g3Xb=hXCp$14&e<|CvT=YJ%#7^JP7EyRd-Ffqyq>%7 z!nWr*!mF>(fBEgM=+piQuVw0{1W!D%PR{O1(aQ-QwNKAEA5oU&TKZZn`}oRD-qy~X zk`KSy`?>#J+{D;!(8SnmAOv)wtS}?ve-;h{HXy~s$Y3A~660eLV-X2RT(;nn=@CIK zgT=;6`r8U~7NXGgu{q7nmdkbC7>TnwBH92VFu zuxYb`nOBr!OqyXi1_mI*6j(G3)D1Y;*wPz$fax2~Vm4rBV+DyZ!i5;o(mHb!BO^nx zfc%NX4)L@3GAxJ1Zu@Y)>-jUK{g={(S@%5+`&{Oizl8oURQ_({I5u-P z$H5(jm+PnRV(73~nW6lC#>0jtXp?DLdKPo9YN)IHs|CA+>vXyI zzT#!9@tLx^?zoufg{7_~wdyTw>)gshE(`HnI=h=TW$;%Te%^E3H}&WAjHMTC#6DYp zVx0TfCN6Tn{`b3eGh~8!Uu9{%+20cvID0{2z0~(R3>P=A)wy=Js_a_%l4slu8-i`@ zyjthY`u#oS>CJ~P&+%tI3rG-UXn(lw=(onHep=24b$f)F9IEaa^oYwgUV9P}A!Q-> M;Idvuk6Di`04Uf~%K!iX diff --git a/rustls/src/testdata/cert-github.2.der b/rustls/src/testdata/cert-github.2.der new file mode 100644 index 0000000000000000000000000000000000000000..e987bd2e07c39fabc33a0874a53b0f42df098f16 GIT binary patch literal 983 zcmXqLV!mw9#I$<>GZP~dlR#LyEXynZnLhafjqZ_`N~aj`vTI}dwsVoq9q zQHr6Ifdoi|i$~BoKQ})mU%}Z?!6!2}vm`aeP|-jhB*)An;pph7;G9}il9`s73^Y?A zIJKxOGdZ=`Ku(<3(9*!z(8vG`qQrTPEDVi+d}C8fQ_CoW#ttOcg$5f68wi43C(PxS zTCU)gT2!1`X((bK1a_4$H$*_eIkTkFP|iRG>@s1|kc?D?&|ue~kf6}u5Cy-~lJfkb zY(qT*9kA zO3XW_Zv14>_#PaRvdSzH24W2&3k128?WTQXfAeU)=KH3l^%o45Y%!1pdPbIyMT|wn z>LF*_mGhE^rj?a=mfd+^dMr747C7Ey`577iv#UJ?yV=?dT zEHTr2zf_68xx{nQ@$UkMcr<@+-@B{+as1W!pH_Y;xw_-w<_(Qc9xhE@eC8EP#e}^5 F-vQIXQu_b^ literal 0 HcmV?d00001 diff --git a/rustls/src/testdata/cert-google.0.der b/rustls/src/testdata/cert-google.0.der index e8c41b21f57de6a6820185eb494897c042f5b666..729a331a8f7ccf4cbbe976575dbcb781f2524987 100644 GIT binary patch delta 1004 zcmeC-yv0#((8LmE(8O%FfSHMriAlhIee1VBCt_Z4wfs2#Y({^z0WTY;R+~rLcV0$D zZdL{ZYeQ}WPB!LH7B*p~&|pJ30~rv9OIXxBKR-PuRUxFPw75heIJKxOGdZ=`kjH=v zB+o3&93Et3AScdiWNKh+Y-nI%YGz~@1>|y@8kiXwgZTy%r^aQmL(t6X6&+~^@) zoKbqvM&l~aj@3LVSD)_LbMfCntHtaN^Onu~BGsyX?rBNff*hIc4lA|RUU;y6^2v2g z-b_CiH!(RHG%?vu7G<=nk2dh$u)X%U@s#3eEdus6(He(T9Sr1w4w6-7kuVTz5Vik-R2Va45VOe}MqHW?U1uyJU!F|x9eVBw(Mv8WF^~k=EyyBdAkf5DUS1A1ASYEXIX~Ax z7$l{@0t_$%4mP&*Mjl2cMgudDpgfDdfv$n}0?h^LZK_bilTqx~cMq-%G4wMDa4Jd% z+LL3@#K^+Nr9HWvNvOVz;k;njyQ_LN>p!CD=qRY>nvF2c4 zV4V7TVcBg41{P)pcLP@@MTX^HOb_^FuZ|9A3$wOMeJX6S#!CN`&T*A__Q}^puWm4B zQgA8PTdsBgpvvjXYA(i3O($n84zQMJc0A delta 1044 zcmcb`(ZgA9(8SVV(8OG@fSHMriAj**@KMes@;{xkxEL517}c0u40zc%wc0$|zVk9N za`T6NNsR|)QrNt!*!Kp=MnaQce3O+v0 zhQbDdAT`XwT<#&k3eJuShR((Ya^k#3hK7dXMwSM~#%9JQQ9!_4AX93-k)IGxgGeA)udLQf!!PY+wji$ke6^R9FvE30G8; z3{|g}l3HXS3381fi;#gp6JL3GIoQ0MRK4W7h3B*B>4R1{P)p zHv<NH=c;_OW(g+it&nY&KKcX-a_ z{d7-4LdIaN@`f`dA8y~CbcprT{-Q$+=EQH?#`0=1VNY_Erb8RlfOstAN_LY*MdJ)TyGe3dE3_+HiuoUWiNVs zUJ9sW`W%~mHV15+DmRp;EM(iNtnlRa7p?jqDpk||sQn6GHwi6W*E2UUGBT7;T&nT< z-LiS^W*clWf`ud6r6v`%^%fg_V|7S#W)qpja#H4#|7uBzoV3iCJB6p6{g+8875NwD zuX-$gVPEM+UiMQrF0xsc$v?OID<0a{;dFZSuYT~}Fw5si?neIjzQt(<>Rv5F)}eT zFgY+VFfdvd4Kg_}GBPkRG%zqQFj_D>F$*vW1_McbAX8;>c4=c}b1@7s3I+pJ1OpQTS5h*O+#!Fd|D1nC9&o5rpUT=#epd9$YtNC~@O3c`WqS#qH4$~O>vGpVkChoRd zWOjTM$1i%$s7$x?*$DjKha)v0sN!kjj7~qXS^8k29<#|HQyGHFHdAe2P3ZuU{C168 z2oDOv-0^>NYsC|83Qu~%@&X(#v}1$XG4?HWFtYor!fxBCzz(_jXVk+bS9I$IwCRqu z-YCt?dKBbw1ItZeE@4;28L11Hgc|61DcQ1(FaK9+X5h}Nm8dC}V{j5@9y;OMupx2R ze4hQP7jFJ5`#2XA(PpQwnzeAu$YX&zjKC_Xb~g>q;{pQ#00EaBFEUXK!z3FLE(1V{&vbD+U8q9UlZFFd{G@pdO$ch8k#ebZ|N^FJmrn zYiTZLZ*ONWaxZc*E@N_RFcSs?RUIG%3@{2X2nGgcfeZlx0Wb{)2`Yw2hJW`B0RamI z00V*o0RTmHi{&3XL=%=8t61?h$!|T<&@)PgGrCt%PwvDt+7=Q_zZ0Jg)Kuw6dB89{ zlqK>S^tv*Xwli`Ih3*LvB{Y=bZ$jIGn|psMnyLSPsnXs`Aj`A+0|U7D2L;+$k}nuW zn9i?qz9c5G9so_f2(6PrM1Kmq$JGIazmr$v-*ggF4iP2Oo7~>ZCvLOCxiexp!r(RG zTc-&w8OxC>c3kn_$|Hn8rEmY5LEyFTGSP*uuO$iaV#RL4$Zj(IxZ2{*N|8$Qg;h?m zb=F8TFK>j|5?r6uahPKzjcHs8Ykl%Tz397-ySna2HeY%#$NM8L_hnFlTj8Jtu$M?2LiOre91zVW$Wi|knP-V|UmfhN FTHU8)+#CP^ delta 1180 zcmeC@n#C<+(8M~;pozI|0W%XL6B92J^Pb?yY?I>>Ul{|^Cd$Xk8W>m@8XEwCiBXg| zuaUWdC71`|8n{g~FcJ|q5M*NxWnmWPat{esaCTHMbT*!NMX~;C$NlF?J#ywh%$+9G z=d@q=o!X@O_r>Y#CI53@Mkzm<`Az2KB<7jIHJn^sznrecg{iEnGH#K-_%d_%&XPCb zK4}?~%gsZB|5*z7Za3K-uUc+yEk5Oy&C|J8_Z;5h{913h`}++pg2^|wIJVw(H1L=# zy?^_+2d+$t52iVZpTDV{S|4V@uExT<;&1IKz4xy?YRrA@8Rj?Ne_z_7R~a7jCp=GT z+W$X2vzE==r+Tw~nhx7{K`o|+hS$jwHUXaPPrFXVOKL|>Yh+mPJMi|Ya&GRE)BN8T zcpi_*Rrot|%a%u{^veJ0-r?SsEzHv+sVzQj#?BAj-xjFv-uAdRuz&Bm)Cfx&)Uwp@W@T%bD^oM`s5@grTPpu4sA9@R#tXK zMwS?ZC<8SZ-+-}ADx;*Nz)D{~Ke@O-uOK^9FFij$T|d2~xX94J0IrUyO$DkBuB0fn zAYVT@wWy>RqFOH{waCB(7+13LEV>5T2AT`h7pS%=1GUwI%ug=LK{Fnz4Jcs{4$`K; z5@6tGV8O-(bSn$vwMr&dW&jbbDi<+Iqf@E@+_XcFlox;>vMrjyQ&^+KR>75lc6!#aml25#ik~ykBeQRwE~2M zeGdkkeRkqlAM&fOJXku#LS3A5Z^TLI8cW^i&*!eZoqk({c|T{ciu@rSmdY7wpAtU? z2mN*GkxtXL7hSmf|F_wX8)q@H6?U3xsN8+H_qC+%Lyyz8kg>>X*a` z$UX>iW0<>=1>+kVW!YvLoovp5Qj^c*C(|^y;#9DFS)3)paiCfS(wSy)Id(0*T~es)WF2h z+{Db#A_~m402&42nnxMP8_F6;gN$Jo7RgI3FV?F}&d*KC%u6iEFVX`t4I&MM+1SBO zU}A*2g_)6^*@=PWflG~es};x9zw#3@*S{C8-CP$G*=ruHwI$&LP#c@08gCNna!cpA7HD8l## zjBTPBB_#z``ueG+dii=eslf2n%P&edP=YIAY7;{!$wVm8huA9!vbPC)xC(L0|Nu& zv^jGtXEQLcFf+ItxH2g+oKa&w_)osc?N9SXjoDd=8h?Dwo!Mfyqu*`St=F|lVb_@y z@?)7fvMX~oK7AeAd?c3r)yEz!nWIjp_xx2#do+<-g$-!0&__R$y}?C3Eo_p9`|YcQ ze>~rs)ZQ^C*MPO<_0u*rE2zDFNcNuH^K#wgw5$D%?ZuAFCQR242^Gz_>1RJ{cHEA1hdFf8I%0@I>jV#+JV~dw;%ocm4F8lbf50FHOu?I@kZv6~SXZo)ef1 zSeIU!IK}t3{-T!l=i#k(IcnSPe5|sVBJn|U;iCHO6AfYneoYMT%YmW6p#z#8(0__n_8M$Mj4c$S}1HF2r`*N zn9DgaCo?U-C@(Y7P|QFCB*-qz8=RP@;8v8Fmz-IgoNp*?API4uP^5x$er{4`USdgp zkq*d-dWNzF(hxU_s2Ph73cw(22G4g$bM&JWngY%60d1ZH&BUZ`Et;C6HN0=4JU`|6l1rmVdtJGJ?m+JdTYpMn?gP5e>prCC|9 zC#KERh1!C@_gaQYa{a0@J6iu^v!8rU@pbnqUWVkOGUjfvJHp8(VrK4=}eG zfbt2{`Am#r(ohGMmzSfO?i>(oP!Chc$jDM`P-vh6;~OxxNkBE`Cl?o>=rr(zt72-i zh50`b`&q@b(vOT<-FrGC{H_YbEG zCzLxRDg{Mfc-1?Zv8z11R!ReCZ{Xq$U;i>z&I!xiVP4VCv!v>bwEF4q^E#Yn@&3Eg z&H5B#ud*?cy{i>goxb%zM72#U?CKGZT~j+Q9c+m+(fd%z0!-*^SK62q99{)S{$AF7 z^5gC;LGN1Eify?Sc7O7PHB0xls<fq+{~I?{(Ue$@?_)Q~76|{eAa`S0a;w zNtOWHACb@fQTgpwI?{|a)Ae_Xn}p9udg5O0`1)%tdch1VoERA#9;Th+k4gISjOnMX zpB&rk?o8YBtGe&(NKDT;8`N2Tb8F->Hr+WPkDE7b+%>gg=H%yhxZTU|H|2-*3QVqe zxynZM?saLV=L`zES47@Q&E0v0MNEJ0!%teGt1_Pks>$8E7vFGumRhuL*F4W9T3*ke zN6LRHb=1p#>u|}`d5g(S^_-fif@$B%tiBiA^X#2-=w?+yZ%f)T_tPzx{+H}s>|C7i zisSY)!Fdk4Ck|Z`-u!f_d829G?Fa9CMNjmUUpP2#p{JQ+*!S%!J66?SJ?*<(s;0KJ z&CY-2&smcX9TKctYi#=BT(I|M{Wd4&mbcf`9A#dam7Y|45clYU`*Z%=uQ;Bl1ONc$ Cv3B+V diff --git a/rustls/src/testdata/cert-hn.1.der b/rustls/src/testdata/cert-hn.1.der index dd6a50f3273eab884f2245df8b0ad90967850380..bbfc07a596e2953d85c84819c81b9d7b0ada6b27 100644 GIT binary patch literal 1115 zcmXqLVhJ~BVzOVr%*4pVB*@U*pObuUqh(JLTT-*=$-nmuc-c6$+C196^D;7WvoaX? z8*&?PvN4CUun9AT1{-P`sDn6M!U~>wC8~9oxkg6Drk19bQ3gh+ z7K#~&KrH0-Ni9(?R&dQrE~+djfhl4ZW^y$(C^HaXV+XqWoGlY08>@CB3xg7K5(5h_ zw^dhmV&As+cj6pI&}Zx;{8|WEEI= z47dz9*x1q=c^H`(!LchV&!S);XCSjcYJmi@?qp=$sL6!63Fr&?qPZrnPL8*hT-dZ} z$0aqN<$fk&QTTn=zuYs@Dd*Ps7)c53nE2<@lNX!Td=cNWtF^G%Xazw zL3^h?c;;!r_OjSj;a+}CU&7{}KK5G50>?ehtdE|0vh08KsUz>jB-EAn9Wk9V|NNo* z+>R6CEn=p|{MXCjs?U0Rx44ljBHzb)&Yj~?lfOR>cS#S87F<6=FpzP@osQ$z4SXYa zWG=b?v2RiX&)b>GX_;}SI{B|`+&uGBOyK>Tx6jvI|6gCl7e2MT{`thUNd`PW^q8e* z?5o)y+-7vRNIwj{1Pv=o_oO9vd8M`>HZLtZ=Xtp{=VD%eL82{ zS~=~2n2dSzRcEW^nI!PfDxdXH{@M2cN~t**}YLF;-0OWvLC zjp66K*EN1zl~NJ<&9qP4#!d9$l&0#V?snU=1trZ6G#$HZe?%&!V}hD!z>(#BNwJ{} Of5jI^{eSZ;MjZgt397FE literal 1218 zcmXqLV%cZV#Jp?)GZP~dlK|U|n=Dr&oZY^4=`Rmasykx9%f_kI=F#?@mywa1mBAp< zklTQhjX9KsO_(V(*ih6!7{uWc=5fhP&vZ^LDpByvOE#1=5C;i!3k#H&m+PefrILYC zddc~@h6)C9ASq^HakvimocyH39EG6#{1OFcM*}%=UL!*T6GIaNFo+W8H3o5wjf_n# zO)aAg{E2dcrhz)d9tF5PAwIzhLBWm+!5)rAre+F821W)z`wR`57?qH{$;isU+{DPw z02Jq9YGPz$IOx4O)xBWPUH^#NZ|1x`oc2`SP&j0*SDKr=4%eF$_NRJx?(F1Jczgfx zkqh%?t*nx5>Ub&`c3WaTe)I13Q>x6>vw|Gc1QPtig*`vK zFi&s3|NOFdx{p%evip291>S}SmZ&|dJ$@=lPguHMxkEKL|DZ_(LwC#nAN!U^cq&y- zTf3-Zw&qupEj)Z5jMYL{GDac%m&!zn*coeN$Rwx>e8&y!hm-EU9-C89geeTtC`&&{q} zuDwWIL3ry0TZhYv2JDkx&HT#5%*epFxQVd|7$S8BLcm~^6=r1o&%$BA2Ber684P4W zVtg!OEF#;p7rk1ss->s$)s|cQGd3NaTDJ3xfjmfBnMJ}ttU-kNUVv%XMW5Yi9~M87 zmOeavlkLS&13r)fevp|gz+~74F;A66%s_;VLz|6}m6e^D5zb;VD1)&X8CkLnG7MB; zd;`WdiHwqx0xNy}{N&;Sl$2-S09VD-W&%}}oCr#o#V88(VF?D3E{69aBG&V)7(#>x zJdBJ69BgbL22cpbVuG`nk<%$KI|9=wBSVAHxj62-c~QJv>mOcgIenn-S8KuBTd|vY zzH65{{A=a<_1Umudx5u9XT+|Cy`QsXU)G)H-W4$?^2&tEe{=p`n321^uqpa{E_W2? zh3b1poNs6?xi`;IEq-_Z%+q(*JzSALzx`jyc6n)q)f@efeNB&zoo(~-f9ChZoNG5f z|1~?dnz^IwlDA%I+v7hsLTl9y36|ftW7<~pd3AMFn_2#j?>8nFo^QKfZ1Agk^;@mT z6HYDGg5pv^pHK3M)GmrHO5auZHrze!=nf{YRFk;w3tBb`a{_1jJP(@pJzG$lcT%0~ oi>}vZV$SWaw37Fi+P}Vcgn2iY&3A+Muh;wh={6H6w)?yU0MuKve*gdg diff --git a/rustls/src/testdata/cert-reddit.0.der b/rustls/src/testdata/cert-reddit.0.der index 3a26d368ceee328890f4fb354327ed097b7bafea..626afb3a1865ed079169824c6494a6e8ef083a39 100644 GIT binary patch delta 1064 zcmX@a`-IoPpo#5)K@;nV1)S?mv_niEs#2f{8qlxLVvZe+`M&<@!5GBrQ zWNKhxWNKt=YH4a2Wsos(p`>|YPG(wuQC?=Ep_qXP$S8JU-r&SM1-GKayyVQ{ z17VOjmoQI|tBZ?gh>n7%pYz5Kj*M!P4Vswy4dj8cvdSzH24W2&C9Mqy(vIIZzjuDG zruiyn*?n)%icbz_(w5}W(kn_$Ny#kHOU}=2;zF<|$1poip2K7yG9P4&JWJzrgT^Ta z9t+$SxU@M&pmW>OjjfL@AB@+u1OA})* z5N9%`Gn6q1ee^Tg8(iem!X|mR-@Z!t$Mda8?HzM+4Om-VKW$U9VqjpL>SkK_lYxPS znZez_l}V9dW2u{&o6|g}tIrLu)fQh-7io@olU|r!Rr01FD`BnWYbFKu!^;<`?^!3g zKlR2_o~StPdLDKz@3Sln7Xz>E_Y`vd)4@>6@Ycrr+6%TrOBOMN-#)GK$b#{Hp#Iw< zZAT0E74B}gvwr}wxCrO~pv7(mE=&q?o6nUTTwZ5d6c+Sexe!@9s zSE8HBQzixbCyTF&H%aY%SAR}v@$ov36+e7Kl^P;v)vG^SqnfvG7BA4l&n_7zJCyev z6mVp_Ubyqz!AlO`rnR*F-qmg-`&Z7qF92$95t4@+-c8%^t@Xk7)hl}~K273}K0t9L<5 z?aWP#j0|jQ>;@J4MHkygH5u(Z_|H}2@Y&1z_norwJg)4=nG1y$=!cD?6sBCQJ%=fk8bA2#UJZcFur-eQ|DlEyq&7}p*v@; zU(&CbqV>bDySdlmb(3fBz4yKAGg%DxKK}Emm+hNw!4^N(1~ZEj3%B#LUUU69(^!yG z>$1V(7pdRVwoM3XX214#ecGgly@~sc3dKZ!d^OGp;Q4fRwN>NZsG&C?UH2{Msab6=M0}}%yBV$ub zQ_CoW^ogq_%^ZC^-TZ_6JRJ?i3`9T%unY4BJNhZO1v&aTdj>oE8;TeRfyB9lxr0(u zQZh>vJoAz_{&r+kt1)O|t}u`XO3Es;NEnDUh-}YZ^lHVbmY&L2TW;~s*mQJi+0HMM zlbEz6xr)GA^^)^*n|QSJ5WLCHm<&bwK}N{4G`1Twwiq}puv=i$W;I!xSy3^>CpakB zG1$Y=$kfcpz{tSa(NNb!FS#fOuBwz-Q4*)B$;+4=`Rmy@wAmP0S=kvGS&9t`C!b(e z=k&H*uShX0{*yAk>42(4ayKks7Ft9K)co?`bDKb2MKOt+g z<=0CcpS@N|t|@l6HqNbg@_K0=5u@B%cImb^P)XbJ^i?7SIYozzUx(c5WUA+RQ(_zE zy(RA6_Z1S_cZK(E1KJ$8c*EDfjFof3a(9?l^z$sKIwP%q`un^Nr&+xJu5`0Lh1$%E zWb;1jZ{l*xD{VXus+Nf>hHeeZSUz2`?!IxlZLQzaPc5-Pn>S3JpHdQi>)m%_4=vW) z&d;ZX@L5i(pLD5a_lp}zao_ZO7)lu&Pn_C#U&+l&;MhVdPN()bKf`Wm=GU*ik7s_yZ&BYQ=Tlh=OBU^_xwzo%xA2oqUh9tk`$TjZ`Dm1{_)AIKe((RNhkd8o|}0!66tyTaf^1RJolOrcy-%fu0NtupY}f& z*O@SVHOs0Pk85G;Zr|3k$@y0wFd;}s@?BK1*fFVVyq~1^78YEqDQ8Rgp(fcTyke5r zo19+(3YvyfFEP(prNDPNYDS8~j6SE=6_01izIKuo=iGjI>+G*xlE36*L`qd0GsN%D zHk_BR!czXbxdp2<%f1i(#jXyAlEP!S-rc$!^!<z>% diff --git a/rustls/src/testdata/cert-reddit.1.der b/rustls/src/testdata/cert-reddit.1.der index dd6a50f3273eab884f2245df8b0ad90967850380..b2b371600cef8d3a439ec441789b9ec9b916fe29 100644 GIT binary patch delta 705 zcmV;y0zUo13Csx}FoFcgFoFZHpaTK{0s;^W^}PlwRs!^TxKJ!3%GczzSFfcGMFj^N4GchnTGC49cH90joS}<9WFeMx_Ffj%LRRjYQDnw~#X+vdl zbRb7;Z(?C=AV)Hh>N$VR_Yh)Frn_Tr?T}Jd#cd~hdJYS`n$!xBryI~@5J+cm*W)m6iv&g5b_r4t0M3* zA`xL}kS4l#*_R*VeP*k5M3r;MtpD#_3W`}n;jFSc5A#U;*K2<_!DHOsM%LR!{(U3; zkmykd9#NxT?MX&de=LZ_^b?$y6+8pzp*h@X3^Kv57FSG^M?!p}$eexV)J;^cLYb(+ z1j2Wm)=1>e5#TC-nean!&p&o+(M(CJBwoS|g8fFQt8A0ZVp2kNlK7hXUS6`WVdWnm zxqk_m=so&_e@6mop_3y5EH!k6fWT(Q-#6aRy(u@U10BBY%@;5q1_M3Nq1405vGLvfqSAUT4aLXu{X_tI-{lNMr zdsC~e&1L<%oCchV*IGk|?M+NpU#-E#wFMw9S<(MW^`I))u$8UJE=oJsr}l4%Df}=$ zB!s)ew|kQZEU$-ab~Eh&RZ_B9p5(dE^WWzW{@wV*xe#)J2?Srym!2*%b&k)PSkhN9 zem4PuvSw{58h^2732o7Cko39wF98(ATvlWO*?otoI8&dCT}EwO#wUb<)P9VNqnlFa z#)#}Ud@B3!Ra!W55ZC|{&rEaMsy8*LDS>I6cD&vgdyv%1&+lgg{RCPe7P0^8Ki}Mf n_3QLmk|PZyDwQQn%At|w)VHjMbhGhoqnX?J)xCs3p8^M%vyetg delta 695 zcmV;o0!aPL3Bm~BB7Ve?A8;f?K`G%++VFfcGMFj^N4GchnUF*7nVH90joS};$MFeMTxFee5BRRjYQAVg_rX+vdl zbdmHqf5A($Wk+zl-A`EC?40exX5}9-6I88AW=0<@3hZPDt8 z9fFAE5mwtCpIE|C=PWc0F4B_WR?G2uU$eW1$|VDPno>b#5MWPN6G`ysH)n(2=hI7P zOd?UH-wv4&?N?EBCgOd^%3>}P8-F8+B~x#~e>7MCi-iC9zNc78B72stqKKOnyr6vF z=~1ZFumda`tvb(w{S}uiCDUTz4L1w>3+`(x>%f9)R5EtZ2i!fZMSiPThDC^S_#m5 z-o!)LDx}_?K_*|jkD1HeuHmR}pNIZ*w;vlItFceU^=DmOn>^|NY4>4l*4gv@HpZ)e z1BiCgOD=VW);#kc}WWi(!k&?-D2oKcxf=Te^cYY{6Al71cNit9EOLx<`r dW50Dj>)ylzy9zw_Fz@THO#F*B5OY2P^Q5mxM85z4 diff --git a/rustls/src/testdata/cert-rustlang.0.der b/rustls/src/testdata/cert-rustlang.0.der index 3af1cadfd8f23ad9eb304b9df27ba2166c3f9b02..e267909b64d434ef4cb7bd6f46faf2b63bb6c38a 100644 GIT binary patch delta 1224 zcmZqS`OR%$(8T)Ppo!)F0%j&gCME%xtu~Lg@4SqR z+^h@+HWLlx&14Lu*qB3En1zKMa}%rb^Av)D9TkiWOe_?94U7!r#CeTO49pCT4Zt7@ z$Tc-EH#C~q?^eG{ERSL4m2dVjbyGwm1me36L|8JmvJ;|aRvUemFR%h@`6Du?}a-G;W`%%W-S z4*HV>$|irD-lJZ0_tTU!^*5KQ7n-~6(!bX$9x&rDd%5#R7Q>=aW z%iPe8_gnbI{XY49l2v;!ftBwd`+3e~Zw<6kc#bu5E{m9DKJ~W8uBY#QJKdjZ*fUe3 z>1yC#rSb_fdOD#;;+dq)=1uV5)62xn$iTR`iCNg7iJ9L(9vF_Y$}AEFVhth(41>-_ z1srawDJeX6`sJLTRj->K8OVYZ@Ue)oh*V^VioD~z$6NQG|2Kot=~n+w42W1z*)E*T~}l=mDIaAdn)xbxh> zOAg>u&B=n*4!9q+WU3zGrg$ zWph`=|2n9>tbd#CvS^9B?;n26%GF--P~4lVE6@Ff-RHN_g_653ch=t7TKeol;#8em zGqx|k#M=G5-z0D4rvHm~g?&=+{~1hS z+>y0iag(oa-|BWS&fevS?@Ja7xAq5$_2N-K?54VG7K(fsVdvX8$@aj@1J~8sj+hB7 zKC|%Ot&Qp!O>Fi|~oRpJUhe`Y(_PnYTXupyofJCCewNEZcYR{5`f>*YB%edvR}U L`1g4lljSl1l<@!T delta 1231 zcmey(-NIvF(8R`I(8Tg$0W%XL6O#b@3*O}|pR(dM&(JOnQn;OBz{|#|)#lOmotKf3 zo0Y-9ZK8p^gQ$Tp8*?ZNw=hp|YEfBgk%F_Mf}xWkKTt7Hm|2+3F*mU)KhHo;oY%+3ypdEKw2AAjTc?4f@FHxn}>1LNW*W+8(nWeEW1f7)I!kOe8=V-aH!u~oBaQ=DEE!nOL-B3m_0z1gd@ z%qL4Qxlb-(@{uo2PBcu?O9V$iNl|HWiC%Jku0BLGxhQ9H9Fy4O2TYo*V3Emu%$oK1 zb(9$JfGiefWc<&mRv1&1@vBz5&7#OQ>I9TmvU|?Zpa5r#eQpmh2T`%M6en`SP2552M;tgN_GFHwB%iUpK(a*D_>WsAd>F@J8oM!RKVb z1DexwjwoD+<*1*%v_b1rt?>P;y15pX*S)`o>0HQD{0Fr7x@SXkTcNYbKK-MX@*fL% z>lbg8O5*q8+@V@ryRPkc8PH;~5_&Bu!)c z2DO+4VX<<^3+6_H@^b0b{U*)j2YyU#`|*Uy=xxyI*E8G9TOK{y#bCc|PstU@`f1C5uaWulpw{9| zlyCh7hkJ|s>K;6~&)! zxzEBcKK!M^Y%yu0dP0X$TFx=;Gl6%v{{D8Snk}&W>@1e6J(@BHEZ=^eXZEz%{r-$K zbMs%!l6oKFEg7+#!SwtL$r3w{Df7dke|?-kHM5~pX$Av_qRY!iZ)(0~y=%B^&XQ+q w{UB+fPOwbDo)I5IObGBPzYFj_D?k&Yi7955ON162eA6B9vgVR~Us8=&b`m2~WZzksf+Dvj@$~C>J}cWt z1FhM4I0}MyWryX6`#bxKjt6>_S&R)uV+I-ZTmSV*0_BYS|0O!*_#c3&00{yf_!vw&dceX`FiVu;c9Gc+G>|KXlAYjDX;^JTm1&<{6&ug=Ubk2 z7vr(FsCF#g1Rp0}XR;4{#HY1DPCh8j$9L6%Rel6vy)>~ly3>@}R*^|Gn{Z4%|15)l zH69Q;xJD?DPHKPl>@5FwBr2q06Ft+hrKTpL5oQw`fCuU9?!{99NN=?WvYH@eBC$M$ ziKiHkqjcN_she$EP&vacW+9N1d;-+k0R$NkN^Mx delta 685 zcmV;e0#g0r2+as0FoFb0FoFXypaTK{0s<2Tf0S2+hv=+#-m+6NTfCWzRt=FNP98Be zF)%VRFfcGMFfdvd4Kg(`FflnWFfcGMFj_E1k&YiH6)+P9162eI6AV*ja&~2MAVWbQ zF+wp9FbxI+RRjYQ20?9MdT(x#${~NkP8Mg~&b(^KH(KmEFt8ow(GutqC`iocDZ#mJ zQ`MvE134PZcZc=?x!G{c&ufk2;{$PqnQhCalqyaW)~CG$>^@R@sN*RX2f1!g&--67_#L_fN@9rvu0BWd4=0i16d;B8`ss=_^ZAV8z$*-d!q`(4 z%V+S=h{`(A7jyMrn$*Q|9)1Dwm@s21s`7d*#o_`QhUGFo4!sey&peaw7f=wML&63s z;0JCjv#N%62}ON`s!Z=0)K0L-q*XZRl>>F$WXyFEI_1ZDBWiSn&K& zn2{&~PX%_j)9@R@=3dZdg%J-ffyNMlDgGc}Nb~aWgcDO`H5CzSf`3s!RaajawXh;S zt@2)@0pr87`O86C=2DTn%c9LcMVAp zC#5*8#1f;lqsU0J6$>8X;u+k;c2dZ^ia~gA*=?7zN{e_cUbGLROkm34N6UCE5*M*j Ti^@4Hy|pjGGXj>Y+5(h+w3#iu diff --git a/rustls/src/testdata/cert-servo.0.der b/rustls/src/testdata/cert-servo.0.der index 0b6271ff545ded2d9e9ee2b7c439789809da1479..3dc2e824c118712fe4cb9ab593a9dd748c8edd54 100644 GIT binary patch literal 932 zcmXqLVqRd-#O%6&nTe5!Ns!^9#J1~MYfq&K?h;&D9(u>kfQyYotIgw_EekV~fwdvG z0Vf-CC<~h~Q)sZEoPi98!zC>0o}Ztdld2F>R9al35S&_6mYJMdY{&!D43uXUW)62X zG>{YLH8M3YF)%hVG%+_cjRJGc4UCM8OiWD;qYOk0g$x8B>N$&nM&#?|7o{6S8VIwo zgB`%c2z3cFBRjJb152uDpI!2IZCcNNd9TdI=$9+@1sHg)om!BV zRJ56WeLqk3*L+9D$ycv%`qreR_U{z=nR>Z0Y;hBlzd;j|w*eo}QdxdR#{VopKe9If zEd=saSwODm&}L&~Wo2h(G~fXV3WF3e888^gf_Qu^Vk{zy`dxc7%b%W^{P>>cq|B|W z=2^&YGmr;KE3-%#h&6~zD4%4Se&qj(Gb^7}-)yL?J~R2Jg+Uz5WJX4oAcFt{br|1( zu}wOoq@=(~Uq4^3AUjhp9T>9u#rox`hWZ9U=?1EBg-mUdP=%QYg+OI`$wegwiXaCF zvPc<7G$F#WiCaq#5wKuiDu8@xz`@3r-pIqq#Asj!(kIWNZ=h?Sy+Ct;dYdZLj${-& z^rNz~szM{YokPn*f%fGXG%>QUaRI}Mh4ES?6AKed<5!l(PYfRz${6n6Ib|~S`a?0+ z=TnV-9iRWhRwm&7Z3Zh5p)xL=HM>t}F)%Pr{d+C&5(5JZGlRQwVuG8J^HP3-UcL&R|l=n?K1eWx-jK9KpjbO*1DNJf2gs?*IC~ z_nao_xA+`iI~8beZKRyg!wRixnZ)#(xW7Lxw8w}n@S8esC$s)dz8<~G9Z-As!|he@ zv|L&mZey@k?AVv8qul=`_o=xV?w50aGqZZtQ@xWrPXS%_h_mt2W$WS(CC6+ZC&hT4 z@3@^X@$AZV|Nb4Br_<|a_6Iq$Fncl>xB>OFK6>(STFm`FGFqv zPB!LH7B*p~&|pJJ191?COIW};C%-f$Ehn)kRY$=yFImq}!9Wfq#Vjn2kOIjlxH>y4 zI6LYZ8_0?C8W|dx8JQS>K@^Z{1mqeU8Jk*~T1FX^qS_^FAP6#$Lzv4sF()%EzbG#= z(NN4l1SH5V%p07Tr{GqUn3tScoScu(VR8mC5Qm8t=Vj_8!`)q6oTHbVpKB0lAk4-N z_AnD8)aT5M?95IKERWe_BpM19wR7>e+$!P`%|Fi=DpGl4vc}(rPYdm?zFM}L;n4(^ zh?jTR?)JnoG-)lh6F6Zz>m<`x)4Bc@^-H;f7B?{$8#FQJ8^{A4AgjzGVIbBZvhmgHxdAg67GHj3wsB7ATP7jSX~%D|8(4s( z1z8LY^qa7IqKR8euQ;`+EMG6bD7}dj&NScy>Evf*{Lcc6P4)(eMXD^IVC2wdV`ODz zX9jv2%3?C81}T?kDKRKAFkfK0z_`sYqokz3N?$*@D92bYB{MxUIkl(+6m0s4SO!Ki zFpfb{tOrzvsnLW;jdmc*6zyM`oyjID?!o;lQD^3t&$WU&jwSp4 zdhTdl{pnA^zg%|)2F5Bok0&P>7+9DYJPh2J6dC$mzrVMuD~?fE$E~=Uox|q}12;<# zQ>)w7c)K7&%fmK6B{QGiK4`u1TH3*=^BG=ZK}<@S?#npxrnVp5F#C00NPja!8H19m zD|=+9O4u~}h58@A=e9jiR!d%cz`H*7SaVF?BYq~R#V^1XyBoLyP2GDy>ssg~J_)|b z>jW-)9@5<_`X@po>4&f!XIoy;x#b_26l&Uc-WH2|o%rI!<+@4t?(*54eBx{L>67yu z<;_Czzn-oK+Ut1Y)W-WtZe9Y%7FuySwa57xc1ttAe(ilc8x1_AW)TcmJjr z%k3YBsrlyT=dfMOe84p=I>=xDU-Gi!jo$xKU&}Hn1V^M6&J21|t?^>+1N9lk3b(5~ zHRTz69X5VkU?ZwADGj**WAzDhHd{?H rTCRNpdbn4tKYh)&8&?{H?b?;h4#=EJtQ2}+)c!Z)9+Ug*>(Z|QA@r~~ diff --git a/rustls/src/testdata/cert-servo.1.der b/rustls/src/testdata/cert-servo.1.der index 41c742136ce864a9d7a90253af5b9f1642672d5f..95399615ce617e226d37fd9e738a51e831776aff 100644 GIT binary patch literal 675 zcmXqLVw!Kz#H6}_nTe5!Nud6-WchR*C9g8kSmABgS|1y5v2kd%d7QIlVP-aPH{>?p zWMd9xVH0Kw4K`FVPylhbgeBec^V4%u6+((ii%S%OQ;W(nlT(Woe0-b@MGS;MYM6z& z-9v&Eg7WiA6oO0)EZ4^ip;GJhumX#N4WDl9E=ff zJtk@X{A$hHHt*SuH?Kat;GFAjQPU0MWw7 zBE}*zp?s2Q`jP)D&a8Y^eY2sm`po2?76$Sl6O~yc48$5l8hoz3F8S|iw)pCeKU?jN zW__3<+hbq?GoO)>MZ-YNKn2D(U}}@dC@Cqh($~+_E6C2&O9w`cevye@a#4waHpp0c z78L_v%q@^xAk!uVRho>X6rwl>7>Gc{3M{~|HQ-=lOK;?1WMV{44a^w~2B}Pj49}TX z2VVQ`JoQ}Zzl(xXuAXsltWw)|gXgo6uI+?%qWsDpLP7m@DV4(Ozb?~Z$_w4dWT4i0 zCWA5QdFSdn@fRZ3Tp5+}2=GPX>y$N#kefKB~0G*!1 A*#H0l literal 977 zcmXqLVm@oo#I$t*GZP~dlK_`_drDmVmL4U)ztV3-cx()K**LY@JlekVGBR?rG8jY| zavN~6F^96S2{U=R8VVT*fH+*joKA^3C7HSTMX83u27(|lZecFx%B0kykfPG!5$TL_^TCF>a~7|20v6GupaWE5PTofVuNb&U-o4TRa)fgU?& z%f!gW0cJ2WvNJm|uJH~+wF~f<3+6ixw*`u`X)lPy3=-aSj=vX@87@M_kE(< zk(0$&RQw;jlR1~OIj~Sa>zxlPXZhu#q$RVjFK%MYFlb^-F^~m1L6(n2j74PWIrCSq zHCN$=R=`s=2OK>IX#19_0NGK++PScAyZxse78E zhJl)a3XE^S*d~!tQc_^0ub-b>T%ebdnVy-PT2!K!oS$o81u{vV#n`~mK!1Vm0_`?U zsM6%39Agxv`u@3jnMJ_3GcqtT)dNZ! z`o}{aB5LmW^!t=f{%~0p@@MH#6E8KkYEL{ML{M8Wd;Il>_9J_ zvt?prW7TeCVNhaDVqp1PQoKB)J7Jyk4%4HJ2G!o4bAKO9JooIL+urP}i4vyk9PSo> z@0@55_1flLYt15uGV7JccDUcrdOm4lR`JV?MV9k5=P#OZIX*6;EtP*^ODfyNJKZOb z7oX_K(tmnn^+nmP#f|?B8vlU9M3$eC@jnX-Fu>akWPvV}Rb>$~5MkrcW@BV!WoKrD zvzQF{LDIq?<*WwGKnkLsk420{q`~Lf>yrPTW{a=h__NjSXx4`*vONa!Aoa>D5(Z)o zA_>)LQm(wyPjv?9*Rq^7S@HkRUvC35nBk0!ELsK{25K*Cqp1oQzOh1XG@4APiEjz`|p|Wx&D4 zmfpz2$i#@2l$e_s85ty;cJs4cV{V`J*gm*m)9$o<;>Ou>aeW`9cAwI9|FC94a$Vd0 zYfrK-U%SlM$J&)1vE%>uWi7m((gD%-R@|!GpM<(&E?0*4nl+vKuO_&Cec47v#^QkEtcP*I=j}ul!e768Wbd)`<37oYj9JP&JhH#-^%rg3`zmj-wA(p7 bru6m3YBN?{^}e*y?5LV`G=H~T$HAun$vi2+ literal 0 HcmV?d00001 diff --git a/rustls/src/testdata/cert-stackoverflow.0.der b/rustls/src/testdata/cert-stackoverflow.0.der index 68068a77c5ba02d9b45f91bbc9593d87b8e9c7b0..b42a06f60954d4f131c1f758271dc703834c89f5 100644 GIT binary patch delta 825 zcmey#dxl-tpo#ee5c@7*W@2Pw5@Nl?y*z^Njr{DUYp+@5SLp4FHQ-|7&}#EIXUoFO zJkh|Y-qqAVPMp`s)WF2pz|hRp(8Mwd%r!T%1amE-3}g(Y3?$f?Ls^)G1&d1(le6>7 zQj5}Z^2_y-^K%U%4TRa)!6q^>LXBo-WM_6_V7YUl+$LZ3wfec@$`of53_ zPQ24-T*!0vBdfu&d%+wgb|<~MHBQyX>bbu!l-c|@Gx4rxe@?$8T%?y@l&)`J z2+}LaqGh1bB&?-};n5~6eisI5QDEUQ;4PN?(80i(>^^%=_?@f%awIgAPeToUcOl{|A_EC6b`#NKf*hE1#5mOr`0YplndQ6ZgXjxQ>0UGI$AR&oaKx*Z{l;Q$~ zx||}2iV#4LiVYR9M+7S^f*uutvQ}^dx1#Z&WjmD4BoL+a-+cGocfaqxcjqA(H2}hD4%6VV;PC4UNrWu@P^U7t7n59fg-{#B;i2MIjEX z#fTjtLz+)#FcnHcTq3$FP9%^BQD&Sp3Bf?;561w>00{$40US4hFc1U^Q_!l7&6-#f z_TAARcme(~PtxU1XSG6hSWjP7Yi&;q)8U=hBtbn zeZXw^A@5F|_1lROK;un6Jy!Um>z@%EZjsF>_=WO*R>#F-G70%HnlZ&4$%r$yke&I?(bAaSvU-R;o z`mfolL$qzY%#5PJ$aAOGxZn9DJjw4cPb>WtFghJE{yHSv?NpFWVMkkDot*~UtFCq# z+U-;%O!Zt`QmfSL&)@15SRZhrRdF&Vw{SRUwKX;1YEw<9z;pMNmkTYBSL3V*{5$kkIOXkluHIZ9xReo-~dT_~wWCXKdFt>}PLTNH8j~7c*X0RlIQe?m+s1mbfFq2TFU~bB0uNd|a z+U9sDQ8}S3P>Gc~X&MgUK~*NiF$vZGi>(2irDZi8a07@Y2@=GFAB9SW%2jwHeS_Kd z%;uOgn`6yVDnlg+U+Jw0R7#Of$n?LXQ$HM>ru*9jGMPf(RbS5RHJ|e@Vir2cFg-CA zrl%P&;>hT;X?l}-oq&*GXRhtE&|0JtZcu_G7&U=k371VTqngJ zD;90pxiCXmtaedXNeV*t)4!LMJLko>Ec0a2^E&j%!-ocEoz} zd%tb+-SsPw3@lHr)1L74b<%E8oQx|=8K~R3r|3(Q(Xo(dH~!M-8=2FMIl9K{5H7CT zitXxbP7!%Oe!yK_<1<#8(5~87urKX7Q|tX*Uw2R$-fM=5c}#`h zCG_xt_LPzKX8O_o!#N*5p7UJ0R=|koQm)5kF?xV@e{6g}|s(PhqRcQ*>96ycsrU-R<(7fsiyX1(_$b0B8 cXHUm(SGA$NnYN#?TwI%sFE`HXAG}2R7mkFV)&Kwi diff --git a/rustls/src/testdata/cert-stackoverflow.1.der b/rustls/src/testdata/cert-stackoverflow.1.der index 2d66ea723ea4f983874b3ffacdf612bd90e150d7..bbfc07a596e2953d85c84819c81b9d7b0ada6b27 100644 GIT binary patch delta 790 zcmV+x1L^#l3fl-EFoFbEFoFUI$sbqk;G^fdTcC z0s>AHpDSO_JRwh=1h?%gEX2lei_+H(lVk!`6cYvmRUIG%3@{2X2nGgcfeZlx0h74` zDt`?I2`Yw2hW8Bt0Sg5H1A+np03ULlG(|!|+N993vbfSFOs7#LjY8V&Hb|DEx*DX& zW7zO7v(C$(XX&7x8S2yxid6%W%0q;mM)B3my5G9N0w{6!y8dm<8)VL`Ofni0xRLzw ziu5gL09*vherZpN90eAAi46y_VqSNjL`Sb44KDZ+wnmv-wOvDkBib zNX)NWmC1JhTgt@m78oZZzQi@0pU=YI3qg=yI9!!n|1N9_e`@XBbAbw2Z%jL!+{apz z_v2SYXH{Dfub2^00jS)F$Ja1TS-5GW-|>!;fDG-KBW7t{%83uuv9p=-Tv6X_?SJR4 z*Z+Td4p)_Tf9H{{VlWK&E(05wyLqE(a&3kCELb4>dU3YxVN*#6XUAHh#6y8tO4TwJ zd;GFIs#DCVftHOY)|GK&hzPTY6JOB3{^%;n*$HBO+pHAn8iv&74;bjR&fo!rygJp( zk5n}F@^ljY?z8uo30|!pD^Of$o`0VunxERc$Mz+RkOFumb7DISm-ILrkf`x z2JkA^fCO&bi?LVEORj#`~ UP{gN>VqH}L{THKJ|Lo>mC;umDKL7v# delta 982 zcmV;{11bF52$~8YFoFdZFoFX9paTK{0s;{Lkt+yF&kPu+Q})&_C8u9nksxInFfchV zG%zqQFfcG$7Y#BsFgYO;^@2P?sZMV7JHsy9jli&6^I16O?ayiOS_>P#z?38or@I0#*?%GR+AqB zDSsjc163U$1RF3JFbD<)XMqd>0s$}$1`8_&0R#bp-xC1=0Wb{)2`Yw2hW8Bt0Sg5H z1A+np0ENmr$4MUfq7$1J%;D$G~TCu$_zlUxsDu4eW zP8$Wo^%$4%UaZ5VxN7h&ygM_w?n~ax{N%5M3x+?yRYNxRXyG;&YL1!F|D`~uG`GOe zV>vZBb#C&ycF28VR>7tRa<*}Z}LpSNh#24%B?J$F<1j(G#E3NZ(DDnr;+mvY1@ z4)?@ePROoCgfQ3gg9Du|C{1WG)@NQGX`_?4^_`0^3(`_UraNykS7l8y zf!{b&gxk;1SKNl#73 zL{gR@JrxmQN>sv%N0kbU6)a3(BsVrTIO`YaHLTUzetqh8$~a7QeHi@9kthc*3o8$h*(; z>xh^i%o)0PNl$;_a4P!xVRc4&)b8Cn=BEM-gTGL*US4Q~u_wbYZ zDfms zEcV=m+^FFg`e)|yQi5C6h`@Q4@$l*LPTIw&l7Qk`QLOI#A(OH>amFlrRJNnMV5B%{ zeU3EqneWkEITQV7PjOatYiT1?-9y?Do5l8p`h{N}<4wvnp5)_`qh2R0Je6k_sc7@c z$}5C7k)*zYK~l@=-oWYeQ08%pW#7;rSLsX-j;pQoLHYH1)08YE+^gfa^NC-io&FN- zE$)T`-TV{%2UpEI-(FU?y*6eOGpxFzwQfT!qV_#=0Ij2wvJ?OGkIl9=BWOys9MT2< z+^7}N3KISAn@@(fGWG`_!!F*zCXX;7vKI90$nb12>9`I+QbfDTxBUA9$%kud-Bfow zt`-vQYYGX0)xD$__FZky>-VdD!|Eee7Y$^d%IswB`EKKK&5ZY}6x}U%3yQ0Lp?}mm zsK-(3vU4P7$!=0!)VO8h;ny2(4!Xo5`YS2(ykI__0O6oo6%+*-45z1 zV7;~Lu{7wita7e}-xX3sR^FX4skGXKWb0;KI((AmYpRjY%j7gc^X2g$wKYGxLp>+v zx>+8)H+>?{;f&IjORWv6(Bs!${@~;~*<1Z|tiOQM!Vwzk@OJYaWjIrz+O_~17) zu&>n3$uxN&6dyyk^POI#>IOpo5|%eTxf&W;U9@xeoh90|Om%Bnkj3Kk?3fy-J53w& detY&nbKg{?>MOX?eQGZsGWX76zZsnL`3L9%8WsQm diff --git a/rustls/src/testdata/cert-twitter.0.der b/rustls/src/testdata/cert-twitter.0.der index 36f4e06d476e3cb7570a58da95ac979b4915f503..ab71abd48a1307b182b1e37d510338d38aaad89b 100644 GIT binary patch literal 985 zcmXqLV!mq7#2mGNnTe5!Nr<&>-eoQCrxhn}zNy-@o<;h@69XuTN@;da;6QUUE@oK?zI|voMpZnSq=*uaT*Nsez%P zrIC@bVHB8aZfpSN8ble08HyMPfsA1m<}NAEEGbDX(o4?IHHb72W@882%)|(F0y85! zvl9c$3A0@bB)AtiaTd>c*Kp9_%%Pf?J-;+~beE@`yHL09$(I!oJIu>@pQhh$-1tZC z@w=WUr&u)NL^KQPlBHxQQvtpouBXfDdS`EI%XTe-;*ICiVscSrA{91>`Lb zZ8k<$R(58f)le3b0S`!87^IxZfB~YIk420{WP8tkO%tOa_Ct|%`PLKL{2y~P-!hN~ zDOP5YFc51HnXK+MgL!3OM&FEUN1QxvEANk(a>*bRW-=oqi>HCRfg+4=z}P05QBqQ1 zrLUiArkAgmlL`!0z5Jqd10}c;rZzEzl1zjWeFG}|XalQ)G z`{Q0xv+?>%gZF$+a$D;BR+%s`Fiz`jsuN~lU}0u(H*jTAWcag4>fL2s-{_3Ll4h&8 zBx`neMw&h^yK|w}NASwpcUw!C6w;-Gvo0~toguMfhvR&M6QRBuiAhx=+B465`?Rxu z;)kOQ%S|;(FI!`Hr}u7KSr>BPpAYW_h`qfB!S;F>xB>0G zpT1kHtXux z{Pyl>ODgx003Hj=#QVSaFC%9l=1c~IG$uoadl#1F6!*=!BY&GqKQtsFcv8fkTGooS z8XA_o*2(swbEK}GKH9u&QMTD%5xWh$e@OwgYz#4FpHfp+Tv7PqT(r!${(F{F*X-KO f_sh%ge%=qk>Z%WV=@6iLG1bWZ;gXLpuap_^vT5nXq$IUS2jn_ELlFZZ zi1WBhAmVz-`MCy7j7rG9Wn^VwZerwT0E%-lH8Cm3 z%4_NAPn}<%vrqJiU9dyq)M<%ZUg;0Szdz{Jx6&xkJ5tbozTjYP$&arKz9?1HE&6sf zbI-{Y(T=lT*}SPk5}dqGuWPJ-u~~SnZ_V)d$2#Sz062lj3bH5|$TcCyLKA;^dAS~PwD5t<;b&z0&%(mY#JT`t zt||*C&N;N%7+G1_nHk|MCWFRqka~HR#%6=Y1_QeVHVdrUEHX+;3as??lZ$eU^-_Qd zH5r&tL2<4ROP;{g2~3=jvQ8?P{^hzeFff*1O#VHcfq{jY!QH@>Ns-|d=d*7L zhX0O~N=#~8ZE(kM8>2|$#n*bWdrx}RPtjf$$D~kTwov2VGq%8FWERngw`$< z@Tdx#CRMi1w2pxdXs?p1D|=+9O4u~}h58@A=e9jiR!d%cz`H*7SaVF?BYq~Ry=#%| z-C!M1s=Z72`hL5t#dCID(_A~fwdy)o>w~f+ts766B~zIcl&?*hRKBCl*Lr@4rrY9q zf<8(tM>5~DtZ5B$=glxac>%eQ02YbBLV}T@zw{pO)|oELbWX1O%-h8JJHFtj@gd(? zfiXG?$!ls|Eg!gSPuAQx?-cK<)LS#=>!+WX@^t3+a+6Kw z9e?^aU;51=>?Qj^PxuU{uJF`lZ4uL*ll-$PeEx)FXO``Fc)e7AV)L{!%Q*ON%$&;B zF!2~q`Sz5<;`NQ;GK-_MHs4Cqo7?_aYU(eq@;jNGCu=917BA!A*fjI1^^wVcy7V2j zuhx8vb=t=i&{*NV`l7_wibHx=UukCU`6g(ll=Se|&wpIeEWMH^oWAEhjHm9IX`MPnRR%p)ung4-FM$SEb-v>e3r=M+D9K=FJ%J&gYZJ0 diff --git a/rustls/src/testdata/cert-twitter.1.der b/rustls/src/testdata/cert-twitter.1.der index 608f16c792172d34c2fe19cb77905975a6582521..67d933a8327620d3db96399972e27b6dfe20c8e6 100644 GIT binary patch literal 1115 zcmXqLVhJ~BVzOVr%*4pVB*?HK+-_p=boGMUTiQ=sxoTS&@Un4gwRyCC=VfH%W@Rw& zH{>?pWMd9xVH0Kw4K~y?PzQ0igcUsVN>YpRQcDzqQMi96N{2F6x@sQ zOA8D|4TM2TnT2^ggM-`^g7WiA6e0`_UfjmfyGK++PSc6FAmdIz-+nzpQENqbo`%uPUF)OJ^UDVT0zZR6<5 zo9Ab>zJcXPON_B3SEGmTv|aD7$Zl$w+;Chz?saWO;x zkfQpDKl?U!FF9s*l_Dr6|&F=9ui1nb~{F@2;Hyz>lwYPiceEG_i z$G9$P>bNg?C3#`#nF9HRa<89G3VgopJIAGD9%s*mNp`EY91Pm#Sn4*R?N0MuWv)<8 zu5}+$t2dvXJ*lL4^V>szB)5JQ^joC-lFvu~#P# z?b$hHU3=SPrNqKX)!VOn%>SwqFE}OoWY*cx zBBS?7(O1~BtL9DKwUFcBz4(69zsyS+e|P$nN835{GAw$rcc++5%jH$OSm$4umK{+R z|0lI=#Y2@W8*lrU2b9F0$UnC*3v!#b#VT=n&?%!QXZ5=CH`dq6{M#Fze#=~a!NMyh z`YH#O?SJp@8)4&TwdXdo9@D;uhkp6(IrMj(SW#l7r%>(vGq3l5&r>P7?$D|C?5~|L z^QPw)@6L9<{KxD6=XU3Che^Fx>Tg!hG_KS literal 1262 zcmXqLVtHlI#C&N1GZP~dlK__~$JH23ZN}OkYf}&Ke}7`Y%f_kI=F#?@mywa1mBAp< zklTQhjX9KsO_(V(*ih6!7{uWc=5fhP&vZ^LDpByvOE#1=5C;i!3k#H&m+PefrILYC zddc~@h6)C9ASq^HakvimocyH39EG6#{1OFcM*}%=ULykoOCu8lFo+W8H3o5wjf_n# zO)aAg{E2dcrhz)d9tF5PAwIzhLBWm+!5)rAre+F821W)z`wR`57?qH{$;isU+{DPw z02Jq9YGPz$IOx4O)xBWPUH^#NZ|1x`oc2`SP&j0*SDKr=4%eF$_NRJx?(F1Jczgfx zkqh%?t*nx5>Ub&`c3WaTe)I13Q>x6>vw|Gc1QPtig*`vK zFi&s3|NOFdx{p%evip291>S}SmZ&|dJ$@=lPguHMxkEKL|DZ_(LwC#nAN!U^cq&y- zTf3-Zw&qupEj)Z5jMYL{GDac%m&!zn*coeN$Rwx>e8&y!hm-EU9-C89geeTtC`&&{q} zuDwWIL3ry0TZhYv2JDkx&HT#5%*epFxQTHcFho`v$O3~^mXAe@MPz&SqE{MxHWR3-N|ry9)=GusmG+ z`l#o@zZXy5?^!>^RmV+hak8bt&v{-dQyfpMy!mKO2rJv^7@2(x()=r;{!8voJubFh zG3;(4>&ch>Gs^B~OJ6AB3D{|%S+zeQQXoy(N_UN@V2-Xb50f3M^}nYJ=RE4V-G1Hc zMci`_w%4nLW_?=UayYu#Yi48fYKDcUxNLkDsdj29Eno84*eAM2Pl{*LYs|GFwvR=t|su**2LYR|&*m-U$<+zj^R flQ#NB7q@c>Uzl^^leeXRP>bg>p9y~Q-?sn&!lt^k diff --git a/rustls/src/testdata/cert-wapo.0.der b/rustls/src/testdata/cert-wapo.0.der index 94d2cd97be27bcda15a55a85f778cfb72beddfe7..e868b1b3349ae264309e7afee111b165c807bf85 100644 GIT binary patch delta 939 zcmZ21c$in)powii5W6g3W@2Pw60rE>dPYJ~_(i_mr_;@xb#?|^Y#dr`9_MUXn3*T) zr7)UJoE)y;WgsWcYh+?zVPI)sXlP<;5e4L$0yz+_`D8A}Z}pJ|!ffndtxSwiGng6K znVlF|R5J~gMfy)|bBS!v*sffZmF2ZXvFg#^E7}wD?tBo+mk!Oze$=2J7NWh%{>Pg6 z{}nes3z9qG-cz$nv&~%1x5<2Q6Z1!dCg!&WJZ#LNvcimv|5=y}7z|`VJU$jN77_Me zvCWPGtII8x-;pmX(|GqK=!JfUfjmfFnMJ}ttU=`PPgmxBCw_9H?cYauq z2()>gaOVZ{2k%&aZR5LF6%r@$#9y!PP4TWfi|oZpBEuV!fHn(#^fTETT;$WjCV9Bu zzDoGV^Q}qk9dmLGSX*8{ZBw&iV5kTCIULF6lUruLIKKCC;L^&wiDwHY8Lx1$$%!<` z-S9diz48Lvx(7g;n}jF+xx>2NwfqwIx~;p`o;E*mX8Msk^I6uvRxr&>yu24VJ1}Q5 z7^E>7GMtUMQm}I`v*!lhd7d?HLDD>N^0WQrC;A+ivgG&vqRTlS(o5R+NruHty5u07 zscjVX8K`HD=HpM3&R!QX6K6OQbbnvznj^*aESdjPvd`bmeYo^&R)`^WRV&-eM9_dU<~wvvm~H$tIu z0Te1F7vfNWqH14V|Lq>nnIT3L;of!I1(FFWrXmN?dolp3cqC(e5MX7bd(t>?r8b!f zAp@E-8PEz^cqvjQWI+a#VQvM@#Y*5Wfe;uj)dM_&69Os%g@A|(0YL8AKiM%mp47U> zL>j!Tv_|Ene$ujU=<5nN*|NK=a+vb=M(PZ=@N8`-fjH=e3kWZH;s3&nUhheDxp*tK zK~?!(*mU7emEYeyUh`r3eGw^6Ivs9DN%l<)8rQwu(fGHZIqFqt>e$V-T}t!I$CM_x zGXF5#QKF6H+pdvcCrJ|Bx<|wo;pv62^JV_mwRiW%IF_pD6-jA}6iFb2t_E`!F+a=R z4ckpEbng*OO#SE>o#s~QHE(mq{t2nIxsoDcX}vqX`TGs!+xZjxRg{_!=7J5YC!Kv= zRzB-b8_M9A5nq{wkHq|u!!J&Rj-Cnql}#}Bgim^_oH0;GdU&wks0zga1QZFegHVVC zR@vk5K=Em_1mb!Ez(D^o6hko~c&Rwg!4Pr;;hySi(Mq=jPGhQho?G3fnn$dT@{N_X z&5BA5lr(xt2m+!a_G+{t2!=!0&<>^TaA$7bkOp%6$=4o&O>cEvy`LG7{$$aiN>Kf1P7dtaCWdu-j$aYFHjN;0Nb-@U*ZYqDow_r} zuVFe;?vZBiVJUa2_WwybCigA;n)-=5{2$jI?n3EE1^WPre_^zkH2B)NuFa6$Iz2cq z=~j)2{`mS&(RjW?4Y*I;EkI(+9%;_N`Xt4V|~)`=ysuvI%Z^{ggyr9=Vt&?MxV z$yz3QXP-CN-Lh_H$JO4+QTJ({%*^KYr*sYe57xvj0hg3D9_7S^ma8c1bEH)j1fkl# zq$`$TrWUd*(QN;RQ7CPbV`%ROo~*I=SX88Xjbyp1yyBAEuyIdkYWUoDf=h?qD!|3H zD(O<4y_(7O8dp1m`NXXj+1Q-kP|b_@2b2!-fZC@QOP7G_U;T3#oaL2;aMwS|K@dYm=AT*L` zVJW8ISj>oxyqIw4M8I(kXxL6@3oQvme~|+a&4&{K3fI9kpC_O|OE={3VZOK$(-tTZ z@WH1@0Kiorm8&rwsC81a^?g^hDZEim&Y<%*yAR$;;kSPY4L&wdFfB~;aagHesi)SP zne(PRH2fhr%bH82z+OC3PrAPNTnh%|+DH)P+4vi=r)ws*iT7NyKVWY~P9 zQ=m6W?|VF>EbqQy^qfP@)eMr^c0LW<)gQg3$H=L2yce%;?3C2DjcFtf%N0efOR9SC zaP_Q?T_MAbXC2~EZA4E<9#Wq-)$mS0+gd8$UZuvysk(QZquCQioAWnC3TKLav-{2j z)$a-MqXSQ&O}x$B73vLj+YUsM#iDlIQ2GdsryGA@vB343&w|!vMy5c5~85n_I&rGEj9PB e-jL1tO?`z4ot0K|YJTB|3{SDGc?`W`vhKe#zbl3S diff --git a/rustls/src/testdata/cert-wapo.1.der b/rustls/src/testdata/cert-wapo.1.der index 99ced211ba8a4465076a867f21a3b1792ff893d3..62ecaa439bd55331c688bd26dc4132d4fa6ba439 100644 GIT binary patch delta 516 zcmdnU^_pGJpo#f85a%plW@2Pw65wjS(qLCNKac?k0Iv7+RW|M2Yhnn;RN{ zxF$gEWG=>3Ml+z+@Om$UG6MlNcCfijjBKphjVugG%t;I^UmrdUpEX7N??w4H7Yx@N z{Ccledb_Qc*2iz&Q5P+e4`{wAeYek85X8LIk=45@$~~sqXUbZ7=a!ZV$?F=1G-(7pONuD z3k%TWY?D=)y@ZTGV)86H23iIh3)B{ z^RDLiiDIShGlZ>qCy341-}Ok{D0t?~!@sA=n0`-s+q2iR@RGCh!iA3&wUi51l-h2} zabru&mq>r2S+~jN;L&(axjYxYH;OYOL_NNQdT4Do*~0p`#DgbLne<}SGn29e!&U1mHK$daZWLLcdFwaJ&d6q$Rh<4?uIMn%ojt`cTX*64gHM^5 z85tNCH!*4h!$jSH4;a|8{EUqMSy+G(#bzK2;;XWV8HliPXtOc0va&NX!C8!xqnNyO zLGdFi&!TCdZlJnAd4Xb^d`3x0ft9{~a#4<6YFo~OUTTScx>0iC^?WR1 zEFy=$U)ZW;uy#G~M8yKjkh^<23yxbE$b-yMW|1%uYY@pQQmeWk_rCVIb!Om|oZk5p zgwj?c$0abS0OOL8VN3h*79}ao14}C2eD#;!(lR~2{N0uFk?U7DPt%u;xVP-HXtdr< z=Q%!3JH^EX*KXP9Sbsc?N2!f<`4*+$M>8_II*e`_>kXCV^;(B+P4-UNQBV`2dATX%>iMNp4ja$&HA#OEU{RLF(0f7u z*lNyIMZeDJn|A&=@Rp5v`~4o(@Q=UWYjoUf(m24vKcz8K`N2euqj6Vxu3u5Get+`E df&S%=XTx3ca?+FjwcLN6aO3^{D@t;_&jFXrR)_!q diff --git a/rustls/src/testdata/cert-wikipedia.0.der b/rustls/src/testdata/cert-wikipedia.0.der index 5452038166df37809be83013abcbb83471c6bc31..8703be78a6d8017e8da60d801718d8ab55228590 100644 GIT binary patch delta 730 zcmZ1`a85wppozoFpo#tb0%j&gCME%%lGsyE?IQ)O-!5{mIrH3VqI{;1iGih&nE@C? ziSrtn8X8QTHQz(?-*=|UlTBOITwb2s&t`YtbJ3+&{|rMO2j8uJuUM(PLgBicWy$^+ z{?_b;If1Pnhjs`GtT?RuREcBXYKQYSE_{od*rE)Y*uo|^GU}+d#T3QaKNQwe-6kS% z%$!3x@x#n2gC?f8Y|Npuf-Fr;Pk@{Un=di$VA5z3EYHl&Oe@VxF3HT#E7r>|N^cU@ z(!&s(9M0;<&j&JqpONuD3kx$7bI0UaEc+(UVBJ(N^wG~`Z*Y-M3!CKOe)}rnAJ4ZY zwRggEQe@TCr>Aa5 zbDy8T>dN(dvWoU|&qy;V2$~m#xq8V&)Ga@=g>lmC*JloYwD`z>$e=N6XZ_u2nL8QE z7-}QsgdSFC)mO_Trq{&%{c)i^Mr48C)OkCZ^>6a^=vD53SR8NxZn1)a=&gCr*X>#& zJIi#Q^Fk%LZC?X&?k_D->tEkho9*v+6X>)TA(b5yy>9n=8x+gVTIBQjO#imL3)Of1 zs&9C)haIoG2(_WUhRfR%M)cHO2<|$0b0D9xao11 zJ8z%+k>$I(Ed`K#`C8K}#sTSW*0qVILZ+zR}_JZ%W%#YW} p9E?1-{Z7Nat%uT?OU3w3{>;tW?6y$ld=;zt&6a1TX&N)jv;nsuE>!>k delta 690 zcmX>nuuMSSpov4tpox9?0%j&gCME%<+9}eSI=A(1{hTZ)5nN(7Q9e`1(9pop(f|yi z#CeU33=JpFn(y%%PgG zSsW%GVBJ)&S-J1SJWET(4`Idglb4o1-4|XvCxPq7Pv2Oz7}eP0Ees5dH8bP9{xLAH zFf+ItxH2gSYtO&3KQ^uTxTzIick%OAuN*J&*FR9b-JsMWv*h{0e@u!D&7o_r$TBPI z_(|nG`&-;EwSI!%Ke+&wlq3GPoOUW6WMU{|2wc43>tDvo`Z-~_JIpKkd6rb2kybzb zeO`ytEZ%=tx>=t>E&c|#Sdrn)+l{)*?DoX22KpT8V?~C4!oTde^<~x+vRw>HY2Lh3Me^F> zr%DU>g#%b}9vsi@V^Uyww1??m%(+RXg|E&@AKTES`Z%<*-tcd)=94M>Wv}G*47k`h zwAwt**|IP*GiNdwq%j#XoL%)oEM9^;?w-mXm$J``pUN#|mJF)<7p}wo@6q}#>2_I7 z9A@Vj6AZee7yAXM%im)H>goHfpi#H={C)WeGdY_#lo#Ybm|{OSvi4MtVy0f^r8E35 V*90G#d}z+K=4nrhEsJXB005Sf9ZvuN diff --git a/rustls/src/verifybench.rs b/rustls/src/verifybench.rs index a71c10f65a8..06213e7b532 100644 --- a/rustls/src/verifybench.rs +++ b/rustls/src/verifybench.rs @@ -1,5 +1,21 @@ -// This program does benchmarking of the functions in verify.rs, -// that do certificate chain validation and signature verification. +//! 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)] @@ -38,6 +54,7 @@ mod benchmarks { &[ 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()); @@ -52,7 +69,6 @@ mod benchmarks { include_bytes!("testdata/cert-arstechnica.0.der"), include_bytes!("testdata/cert-arstechnica.1.der"), include_bytes!("testdata/cert-arstechnica.2.der"), - include_bytes!("testdata/cert-arstechnica.3.der"), ], ); b.iter(|| ctx.verify_once()); @@ -66,6 +82,7 @@ mod benchmarks { &[ 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()); @@ -105,6 +122,7 @@ mod benchmarks { &[ 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()); @@ -144,6 +162,7 @@ mod benchmarks { &[ 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()); @@ -158,6 +177,7 @@ mod benchmarks { 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()); @@ -199,7 +219,7 @@ impl Context { .copied() .map(|bytes| CertificateDer::from(bytes.to_vec())) .collect(), - now: UnixTime::since_unix_epoch(Duration::from_secs(1_640_870_720)), + now: UnixTime::since_unix_epoch(Duration::from_secs(1_746_605_469)), verifier: WebPkiServerVerifier::new_without_revocation( roots, provider.signature_verification_algorithms, From bfa78bade301ac0e3bbf6dbd64b5ad7e7104447a Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Tue, 6 May 2025 19:52:12 -0400 Subject: [PATCH 186/403] ci: sync cargo-check-external-types toolchain Matches the nightly used by `cargo-check-external-types` v0.2.0: https://github.com/awslabs/cargo-check-external-types/releases/tag/v0.2.0 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1ce8dcf4252..9e615b8ada8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -518,7 +518,7 @@ jobs: - name: Install rust toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: nightly-2024-06-30 + toolchain: nightly-2025-05-04 # ^ sync with https://github.com/awslabs/cargo-check-external-types/blob/main/rust-toolchain.toml - name: Install cargo-check-external-types uses: taiki-e/cache-cargo-install-action@v2 From 26726e1fd5003aaabf0c522eeba654a273eb521e Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Wed, 7 May 2025 09:43:32 +0200 Subject: [PATCH 187/403] Update semver-compatible dependencies --- Cargo.lock | 329 ++++++++++++++++++++++++----------------------------- deny.toml | 12 +- 2 files changed, 157 insertions(+), 184 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68dcfe40dc0..36f34a97ca6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -134,15 +134,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "asn1" -version = "0.21.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c48ea2b435a08bc0fc63de853bda3d5dd1b794ce5f188edd036ad39a7c069d9" +checksum = "33fb74ca1da7780ced4ef36df6ea620b4e1debeff2b1ccde057583771e405e78" dependencies = [ "asn1_derive", "itoa", @@ -172,7 +172,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", "synstructure", ] @@ -184,18 +184,18 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] name = "asn1_derive" -version = "0.21.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c7e14dc2fafd01c4c68c054e128b770d5a4a07b04d76bfaedca40dce3cb2c0" +checksum = "0aa21886d7595227bbe0a5d53598aa295ef5f0d093936e2e76d4239d6d14ef22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -233,14 +233,15 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa" dependencies = [ "async-task", "concurrent-queue", "fastrand", "futures-lite", + "pin-project-lite", "slab", ] @@ -289,17 +290,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "async-recursion" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - [[package]] name = "async-std" version = "1.13.1" @@ -341,7 +331,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -358,9 +348,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-fips-sys" -version = "0.13.5" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d9c2e952a1f57e8cbc78b058a968639e70c4ce8b9c0a5e6363d4e5670eed795" +checksum = "e99d74bb793a19f542ae870a6edafbc5ecf0bc0ba01d4636b7f7e0aba9ee9bd3" dependencies = [ "bindgen", "cc", @@ -383,9 +373,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.28.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f7720b74ed28ca77f90769a71fd8c637a0137f6fae4ae947e1050229cff57f" +checksum = "bfa9b6986f250236c27e5a204062434a773a13243d2ffc2955f37bdba4c5c6a1" dependencies = [ "bindgen", "cc", @@ -396,9 +386,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", "cfg-if", @@ -452,7 +442,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.100", + "syn 2.0.101", "which", ] @@ -497,9 +487,9 @@ dependencies = [ [[package]] name = "brotli" -version = "8.0.0" +version = "8.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf19e729cdbd51af9a397fb9ef8ac8378007b797f8273cfbfdf45dcaa316167b" +checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -542,9 +532,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.18" +version = "1.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c" +checksum = "8691782945451c1c383942c4874dbe63814f61cb57ef773cda2972682b7bb3c0" dependencies = [ "jobserver", "libc", @@ -647,9 +637,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.35" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944" +checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" dependencies = [ "clap_builder", "clap_derive", @@ -657,9 +647,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.35" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9" +checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" dependencies = [ "anstream", "anstyle", @@ -676,7 +666,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -869,20 +859,20 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] name = "data-encoding" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "der" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", "zeroize", @@ -931,7 +921,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -989,7 +979,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -1200,7 +1190,7 @@ dependencies = [ "libc", "log", "rustversion", - "windows 0.58.0", + "windows", ] [[package]] @@ -1216,9 +1206,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", @@ -1284,9 +1274,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" +checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" dependencies = [ "atomic-waker", "bytes", @@ -1303,9 +1293,9 @@ dependencies = [ [[package]] name = "half" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db2ff139bba50379da6aa0766b52fdcb62cb5b263009b09ed58ba604e14bbd1" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" dependencies = [ "cfg-if", "crunchy", @@ -1313,9 +1303,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" dependencies = [ "foldhash", ] @@ -1334,9 +1324,9 @@ checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "hermit-abi" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" +checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" [[package]] name = "hex" @@ -1346,15 +1336,13 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hickory-proto" -version = "0.25.1" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d844af74f7b799e41c78221be863bade11c430d46042c3b49ca8ae0c6d27287" +checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" dependencies = [ - "async-recursion", "async-trait", "bytes", "cfg-if", - "critical-section", "data-encoding", "enum-as-inner", "futures-channel", @@ -1365,23 +1353,23 @@ dependencies = [ "idna", "ipnet", "once_cell", - "rand 0.9.0", + "rand 0.9.1", "ring", - "rustls 0.23.25", + "rustls 0.23.27 (registry+https://github.com/rust-lang/crates.io-index)", "thiserror 2.0.12", "tinyvec", "tokio", "tokio-rustls", "tracing", "url", - "webpki-roots", + "webpki-roots 0.26.11", ] [[package]] name = "hickory-resolver" -version = "0.25.1" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a128410b38d6f931fcc6ca5c107a3b02cabd6c05967841269a4ad65d23c44331" +checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" dependencies = [ "cfg-if", "futures-util", @@ -1390,15 +1378,15 @@ dependencies = [ "moka", "once_cell", "parking_lot", - "rand 0.9.0", + "rand 0.9.1", "resolv-conf", - "rustls 0.23.25", + "rustls 0.23.27 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec", "thiserror 2.0.12", "tokio", "tokio-rustls", "tracing", - "webpki-roots", + "webpki-roots 0.26.11", ] [[package]] @@ -1428,17 +1416,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "hostname" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" -dependencies = [ - "cfg-if", - "libc", - "windows 0.52.0", -] - [[package]] name = "hpke-rs" version = "0.2.0" @@ -1603,7 +1580,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -1670,7 +1647,7 @@ version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ - "hermit-abi 0.5.0", + "hermit-abi 0.5.1", "libc", "windows-sys 0.59.0", ] @@ -1716,9 +1693,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" -version = "0.2.5" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c102670231191d07d37a35af3eb77f1f0dbf7a71be51a962dcd57ea607be7260" +checksum = "f02000660d30638906021176af16b17498bd0d12813dbfe7b276d8bc7f3c0806" dependencies = [ "jiff-static", "log", @@ -1729,13 +1706,13 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.5" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cdde31a9d349f1b1f51a0b3714a5940ac022976f4b49485fc04be052b183b4c" +checksum = "f3c30758ddd7188629c6713fc45d1188af4f44c90582311d0c8d8c9907f60c48" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -1784,9 +1761,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.171" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libloading" @@ -1800,9 +1777,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "linux-raw-sys" @@ -1887,9 +1864,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", ] @@ -1927,9 +1904,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.30.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "537bc3c4a347b87fd52ac6c03a02ab1302962cfd93373c5d7a112cdc337854cc" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ "bitflags", "cfg-if", @@ -2083,14 +2060,14 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] name = "openssl-sys" -version = "0.9.107" +version = "0.9.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" +checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847" dependencies = [ "cc", "libc", @@ -2330,7 +2307,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" dependencies = [ "proc-macro2", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -2344,9 +2321,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -2378,13 +2355,12 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", - "zerocopy", ] [[package]] @@ -2413,7 +2389,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", ] [[package]] @@ -2460,9 +2436,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" +checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" dependencies = [ "bitflags", ] @@ -2513,12 +2489,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "resolv-conf" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48375394603e3dd4b2d64371f7148fd8c7baa2680e28741f2cb8d23b59e3d4c4" -dependencies = [ - "hostname", -] +checksum = "fc7c8f7f733062b66dc1c63f9db168ac0b97a9210e247fa90fdc9ad08f51b302" [[package]] name = "rfc6979" @@ -2538,7 +2511,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.15", + "getrandom 0.2.16", "libc", "untrusted", "windows-sys 0.52.0", @@ -2608,21 +2581,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "rustls" -version = "0.23.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" -dependencies = [ - "aws-lc-rs", - "log", - "once_cell", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - [[package]] name = "rustls" version = "0.23.27" @@ -2648,12 +2606,27 @@ dependencies = [ "serde_json", "subtle", "time", - "webpki-roots", + "webpki-roots 0.26.11", "x509-parser", "zeroize", "zlib-rs", ] +[[package]] +name = "rustls" +version = "0.23.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" +dependencies = [ + "aws-lc-rs", + "log", + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-bench" version = "0.1.0" @@ -2705,7 +2678,7 @@ dependencies = [ "rustls 0.23.27", "serde", "tokio", - "webpki-roots", + "webpki-roots 0.26.11", ] [[package]] @@ -2741,7 +2714,7 @@ dependencies = [ "criterion", "env_logger", "rustls 0.23.27", - "webpki-roots", + "webpki-roots 0.26.11", ] [[package]] @@ -2764,7 +2737,7 @@ dependencies = [ "rustls 0.23.27", "sha2", "signature", - "webpki-roots", + "webpki-roots 0.26.11", "x25519-dalek", ] @@ -2861,7 +2834,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -2878,9 +2851,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -2984,9 +2957,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.100" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -2995,13 +2968,13 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -3036,7 +3009,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -3047,7 +3020,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -3148,9 +3121,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.44.2" +version = "1.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" +checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" dependencies = [ "backtrace", "bytes", @@ -3170,7 +3143,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -3179,15 +3152,15 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "rustls 0.23.25", + "rustls 0.23.27 (registry+https://github.com/rust-lang/crates.io-index)", "tokio", ] [[package]] name = "tokio-util" -version = "0.7.14" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" dependencies = [ "bytes", "futures-core", @@ -3382,7 +3355,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", "wasm-bindgen-shared", ] @@ -3417,7 +3390,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3443,9 +3416,18 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.8" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.0", +] + +[[package]] +name = "webpki-roots" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" +checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" dependencies = [ "rustls-pki-types", ] @@ -3499,32 +3481,13 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" -dependencies = [ - "windows-core 0.52.0", - "windows-targets 0.52.6", -] - [[package]] name = "windows" version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" dependencies = [ - "windows-core 0.58.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ + "windows-core", "windows-targets 0.52.6", ] @@ -3549,7 +3512,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -3560,7 +3523,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -3819,28 +3782,28 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.24" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.24" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -3860,7 +3823,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", "synstructure", ] @@ -3881,7 +3844,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -3903,7 +3866,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] diff --git a/deny.toml b/deny.toml index 71198518908..b0559e7c6cd 100644 --- a/deny.toml +++ b/deny.toml @@ -1,6 +1,16 @@ [licenses] version = 2 -allow = ["Apache-2.0", "BSD-3-Clause", "ISC", "MIT", "MPL-2.0", "OpenSSL", "Unicode-3.0", "Zlib"] +allow = [ + "Apache-2.0", + "BSD-3-Clause", + "CDLA-Permissive-2.0", + "ISC", + "MIT", + "MPL-2.0", + "OpenSSL", + "Unicode-3.0", + "Zlib", +] private = { ignore = true } [advisories] From e3be538066657276e6a29d9ff88467ea48964592 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Wed, 7 May 2025 09:44:04 +0200 Subject: [PATCH 188/403] Upgrade to webpki-roots 1 --- Cargo.lock | 6 +++--- Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 36f34a97ca6..4f136c86274 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2606,7 +2606,7 @@ dependencies = [ "serde_json", "subtle", "time", - "webpki-roots 0.26.11", + "webpki-roots 1.0.0", "x509-parser", "zeroize", "zlib-rs", @@ -2678,7 +2678,7 @@ dependencies = [ "rustls 0.23.27", "serde", "tokio", - "webpki-roots 0.26.11", + "webpki-roots 1.0.0", ] [[package]] @@ -2737,7 +2737,7 @@ dependencies = [ "rustls 0.23.27", "sha2", "signature", - "webpki-roots 0.26.11", + "webpki-roots 1.0.0", "x25519-dalek", ] diff --git a/Cargo.toml b/Cargo.toml index 675b46e0c4e..73f1089a63d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -87,7 +87,7 @@ time = { version = "0.3.6", default-features = false } tikv-jemallocator = "0.6" tokio = { version = "1.34", features = ["io-util", "macros", "net", "rt"] } webpki = { package = "rustls-webpki", version = "0.103.2", features = ["alloc"], default-features = false } -webpki-roots = "0.26" +webpki-roots = "1" x25519-dalek = "2" x509-parser = "0.17" zeroize = "1.7" From 97a63bf860980f78e96f45c3b9786fd310108a2d Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Tue, 6 May 2025 19:41:59 -0400 Subject: [PATCH 189/403] manual: add a short howto debugging section Cover how to collect verbose logs with `RUST_LOG` and offer some starting point instructions on collecting a pcap and using `SSLKEYLOGFILE`. The new issue template for bug reports is updated to include a pointer to the new manual section. --- .github/ISSUE_TEMPLATE/bug_report.md | 2 + rustls/src/manual/howto.rs | 67 ++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 94b3292535d..67998e11163 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -27,3 +27,5 @@ A clear and concise description of what you expected to happen. **Additional context** Add any other context about the problem here. +For example, consider including verbose logs or a packet capture. For help +with this [see the manual](https://docs.rs/rustls/latest/rustls/manual/_03_howto/index.html#debugging). diff --git a/rustls/src/manual/howto.rs b/rustls/src/manual/howto.rs index 2e1959ae9b1..6c00c6957aa 100644 --- a/rustls/src/manual/howto.rs +++ b/rustls/src/manual/howto.rs @@ -54,4 +54,71 @@ messages are never delimited by the close of the TCP connection), it can uncondi ignore `UnexpectedEof` errors from rustls. [^2]: + +# 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 */ From 73339c2795aa80eada72e95c319e1f58198937a0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 7 May 2025 13:32:42 +0000 Subject: [PATCH 190/403] chore(deps): update dependency go to v1.24.3 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9e615b8ada8..bd21e1f8a60 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -68,7 +68,7 @@ jobs: if: runner.os == 'MacOS' uses: actions/setup-go@v5 with: - go-version: "1.24.2" + go-version: "1.24.3" - name: cargo build (debug; default features) run: cargo build --locked From b30fc9e5fa574d1db15423ff6ab3c3da85d2ad07 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 9 May 2025 17:02:56 +0100 Subject: [PATCH 191/403] SECURITY.md: temporal updates --- SECURITY.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 595d560d05a..417af4ca5ed 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -5,7 +5,7 @@ Security fixes will be backported only to the rustls versions for which the original semver-compatible release was published less than 2 years ago. -For example, as of 2024-04-18 the latest release is 0.23.4. +For example, as of 2025-05-09 the latest release is 0.23.27. * 0.23.0 was released in February of 2024 * 0.22.0 was released in December of 2023 @@ -13,7 +13,7 @@ For example, as of 2024-04-18 the latest release is 0.23.4. * 0.20.0 was released in September of 2021 * 0.19.0 was released in November of 2020 -Therefore 0.23.x, 0.22.x and 0.21.x will be updated, while 0.20.x and 0.19.x +Therefore 0.23.x and 0.22.x will be updated, while 0.21.x, 0.20.x and 0.19.x will not be. > [!NOTE] @@ -29,8 +29,8 @@ in the course of normal development, subject to these constraints: - Our MSRV will be no more recent than 9 versions old, or approximately 12 months. > [!TIP] -> At the time of writing, the most recent Rust release is 1.82.0. That means -> our MSRV could be as recent as 1.73.0. As it happens, it is 1.71.0. +> At the time of writing, the most recent Rust release is 1.85. That means +> our MSRV could be as recent as 1.76. As it happens, it is 1.71. - Our MSRV policy only covers the core library crate: it does not cover tests or example code, and is not binding on our dependencies. @@ -55,7 +55,7 @@ MSRV than this policy. > [!NOTE] > This is currently the case for our optional dependency on `zlib-rs`, which -> has a current MSRV of 1.75.0. +> has a current MSRV of 1.75. ## Reporting a Vulnerability From 4f0987013bbddeea7fa474edd80c097ecd0aec87 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Fri, 2 May 2025 13:59:26 +0200 Subject: [PATCH 192/403] Keep ClientHelloPayload impls together --- rustls/src/msgs/handshake.rs | 50 ++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 453de5b7d1b..6c3b63e0450 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -1027,31 +1027,6 @@ impl Codec<'_> for ClientHelloPayload { } } -/// 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"), - }; -} - -impl TlsListElement for ClientExtension { - const SIZE_LEN: ListLength = ListLength::U16; -} - -/// draft-ietf-tls-esni-17: `ExtensionType OuterExtensions<2..254>;` -impl TlsListElement for ExtensionType { - const SIZE_LEN: ListLength = ListLength::NonZeroU8 { - empty_error: InvalidMessage::IllegalEmptyList("ExtensionTypes"), - }; -} - impl ClientHelloPayload { pub(crate) fn ech_inner_encoding(&self, to_compress: Vec) -> Vec { let mut bytes = Vec::new(); @@ -1304,6 +1279,31 @@ impl ClientHelloPayload { } } +/// 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"), + }; +} + +impl TlsListElement for ClientExtension { + const SIZE_LEN: ListLength = ListLength::U16; +} + +/// draft-ietf-tls-esni-17: `ExtensionType OuterExtensions<2..254>;` +impl TlsListElement for ExtensionType { + const SIZE_LEN: ListLength = ListLength::NonZeroU8 { + empty_error: InvalidMessage::IllegalEmptyList("ExtensionTypes"), + }; +} + #[derive(Clone, Debug)] pub(crate) enum HelloRetryExtension { KeyShare(NamedGroup), From 7f8df8979e299ba15230ba1ecce319f56dc80571 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Fri, 2 May 2025 14:00:50 +0200 Subject: [PATCH 193/403] Reorder ClientHelloPayload impl blocks --- rustls/src/msgs/handshake.rs | 54 ++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 6c3b63e0450..6c3cb4027f5 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -1000,33 +1000,6 @@ pub struct ClientHelloPayload { pub extensions: Vec, } -impl Codec<'_> for ClientHelloPayload { - fn encode(&self, bytes: &mut Vec) { - self.payload_encode(bytes, Encoding::Standard) - } - - fn read(r: &mut Reader<'_>) -> Result { - let mut 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: Vec::new(), - }; - - if r.any_left() { - ret.extensions = Vec::read(r)?; - } - - match (r.any_left(), ret.extensions.is_empty()) { - (true, _) => Err(InvalidMessage::TrailingData("ClientHelloPayload")), - (_, true) => Err(InvalidMessage::MissingData("ClientHelloPayload")), - _ => Ok(ret), - } - } -} - impl ClientHelloPayload { pub(crate) fn ech_inner_encoding(&self, to_compress: Vec) -> Vec { let mut bytes = Vec::new(); @@ -1279,6 +1252,33 @@ impl ClientHelloPayload { } } +impl Codec<'_> for ClientHelloPayload { + fn encode(&self, bytes: &mut Vec) { + self.payload_encode(bytes, Encoding::Standard) + } + + fn read(r: &mut Reader<'_>) -> Result { + let mut 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: Vec::new(), + }; + + if r.any_left() { + ret.extensions = Vec::read(r)?; + } + + match (r.any_left(), ret.extensions.is_empty()) { + (true, _) => Err(InvalidMessage::TrailingData("ClientHelloPayload")), + (_, true) => Err(InvalidMessage::MissingData("ClientHelloPayload")), + _ => Ok(ret), + } + } +} + /// RFC8446: `CipherSuite cipher_suites<2..2^16-2>;` impl TlsListElement for CipherSuite { const SIZE_LEN: ListLength = ListLength::NonZeroU16 { From 0c0cd2e851ede2b4295353b5d0e9e90c471bcbff Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Thu, 15 May 2025 14:29:54 -0400 Subject: [PATCH 194/403] build: fix clippy::empty_line_after_doc_comments Of the form: ``` error: empty line after doc comment --> rustls/build.rs:4:1 | 4 | / /// See the comment in lib.rs to understand why we need this. 5 | | | |_^ 6 | #[cfg_attr(feature = "read_buf", rustversion::not(nightly))] 7 | fn main() {} | ------- the comment documents this function | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_doc_comments = note: `-D clippy::empty-line-after-doc-comments` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::empty_line_after_doc_comments)]` = help: if the empty line is unintentional, remove it help: if the comment should document the crate use an inner doc comment | 1 ~ //! This build script allows us to enable the `read_buf` language feature only 2 ~ //! for Rust Nightly. 3 ~ //! 4 ~ //! See the comment in lib.rs to understand why we need this. ``` --- rustls/build.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rustls/build.rs b/rustls/build.rs index 9c73252a655..8c0bd2aa64b 100644 --- a/rustls/build.rs +++ b/rustls/build.rs @@ -1,7 +1,7 @@ -/// 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. +//! 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() {} From 801591789e8bf876f5ec2d711ef0a8880c608ee4 Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Thu, 15 May 2025 14:54:39 -0400 Subject: [PATCH 195/403] ci-bench: fix clippy::io_other_error finding of the form: ``` error: this can be `std::io::Error::other(_)` --> ci-bench/src/util.rs:293:40 | 293 | return Poll::Ready(Err(io::Error::new( | ________________________________________^ 294 | | io::ErrorKind::Other, 295 | | "channel was closed", 296 | | ))); | |_________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#io_other_error = note: `-D clippy::io-other-error` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::io_other_error)]` help: use `std::io::Error::other` | 293 ~ return Poll::Ready(Err(io::Error::other( 294 ~ "channel was closed", | ``` --- ci-bench/src/util.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ci-bench/src/util.rs b/ci-bench/src/util.rs index 177663bc963..f45759ac310 100644 --- a/ci-bench/src/util.rs +++ b/ci-bench/src/util.rs @@ -290,10 +290,7 @@ pub mod async_io { fn poll(mut self: Pin<&mut Self>, _: &mut task::Context<'_>) -> Poll { if !self.writer.inner.open.get() { - return Poll::Ready(Err(io::Error::new( - io::ErrorKind::Other, - "channel was closed", - ))); + return Poll::Ready(Err(io::Error::other("channel was closed"))); } let mut pipe_buf = self.writer.inner.buf.borrow_mut(); From e3d67a7db0e9f32c9cbb8ca12354202c219f880c Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Thu, 15 May 2025 15:19:40 -0400 Subject: [PATCH 196/403] fix clippy::uninlined_format_args findings of the form: ``` error: variables can be used directly in the `format!` string --> rustls/src/server/tls13.rs:1347:9 | 1347 | trace!("sending new ticket {:?} (stateless: {})", t, stateless); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 1347 - trace!("sending new ticket {:?} (stateless: {})", t, stateless); 1347 + trace!("sending new ticket {t:?} (stateless: {stateless})"); | ``` Diff produced with `cargo clippy --fix --all-features --all-targets; cargo fmt`. --- examples/src/bin/simple_0rtt_client.rs | 9 ++-- examples/src/bin/simple_0rtt_server.rs | 2 +- examples/src/bin/tlsclient-mio.rs | 11 ++-- examples/src/bin/tlsserver-mio.rs | 24 ++++----- rustls/src/bs_debug.rs | 2 +- rustls/src/builder.rs | 2 +- rustls/src/client/common.rs | 2 +- rustls/src/client/ech.rs | 2 +- rustls/src/client/hs.rs | 10 ++-- rustls/src/client/tls12.rs | 2 +- rustls/src/client/tls13.rs | 4 +- rustls/src/common_state.rs | 2 +- rustls/src/conn/unbuffered.rs | 3 +- rustls/src/crypto/aws_lc_rs/sign.rs | 25 ++++----- rustls/src/crypto/aws_lc_rs/ticketer.rs | 2 +- rustls/src/crypto/ring/sign.rs | 21 ++++---- rustls/src/crypto/ring/ticketer.rs | 2 +- rustls/src/error.rs | 34 ++++++------- rustls/src/key_log_file.rs | 12 ++--- rustls/src/msgs/base.rs | 2 +- rustls/src/msgs/handshake.rs | 3 +- rustls/src/msgs/handshake_test.rs | 68 ++++++++++++------------- rustls/src/msgs/message/outbound.rs | 16 +++--- rustls/src/msgs/message_test.rs | 8 +-- rustls/src/msgs/persist.rs | 8 +-- rustls/src/server/hs.rs | 6 +-- rustls/src/server/tls12.rs | 8 +-- rustls/src/server/tls13.rs | 18 +++---- rustls/src/webpki/anchors.rs | 7 ++- rustls/src/webpki/client_verifier.rs | 24 ++++----- rustls/src/webpki/mod.rs | 2 +- rustls/src/webpki/server_verifier.rs | 10 ++-- rustls/tests/api.rs | 61 +++++++++++----------- rustls/tests/common/mod.rs | 13 ++--- rustls/tests/unbuffered.rs | 6 +-- 35 files changed, 199 insertions(+), 232 deletions(-) diff --git a/examples/src/bin/simple_0rtt_client.rs b/examples/src/bin/simple_0rtt_client.rs index 5ffbeb6ce88..7e875a83fb9 100644 --- a/examples/src/bin/simple_0rtt_client.rs +++ b/examples/src/bin/simple_0rtt_client.rs @@ -28,15 +28,14 @@ fn start_connection(config: &Arc, domain_name: &str, port: .expect("invalid DNS name") .to_owned(); let mut conn = rustls::ClientConnection::new(Arc::clone(config), server_name).unwrap(); - let mut sock = TcpStream::connect(format!("{}:{}", domain_name, port)).unwrap(); + let mut sock = TcpStream::connect(format!("{domain_name}:{port}")).unwrap(); sock.set_nodelay(true).unwrap(); let request = format!( "GET / HTTP/1.1\r\n\ - Host: {}\r\n\ + Host: {domain_name}\r\n\ Connection: close\r\n\ Accept-Encoding: identity\r\n\ - \r\n", - domain_name + \r\n" ); // If early data is available with this server, then early_data() @@ -69,7 +68,7 @@ fn start_connection(config: &Arc, domain_name: &str, port: BufReader::new(stream) .read_line(&mut first_response_line) .unwrap(); - println!(" * Server response: {:?}", first_response_line); + println!(" * Server response: {first_response_line:?}"); } fn main() { diff --git a/examples/src/bin/simple_0rtt_server.rs b/examples/src/bin/simple_0rtt_server.rs index fcdf799abb7..047345f3646 100644 --- a/examples/src/bin/simple_0rtt_server.rs +++ b/examples/src/bin/simple_0rtt_server.rs @@ -91,7 +91,7 @@ fn main() -> Result<(), Box> { .unwrap(); if bytes_read != 0 { - println!("Early data from client: {:?}", buf); + println!("Early data from client: {buf:?}"); } } } diff --git a/examples/src/bin/tlsclient-mio.rs b/examples/src/bin/tlsclient-mio.rs index cc8e2de4b79..2aa20752480 100644 --- a/examples/src/bin/tlsclient-mio.rs +++ b/examples/src/bin/tlsclient-mio.rs @@ -93,7 +93,7 @@ impl TlsClient { if error.kind() == io::ErrorKind::WouldBlock { return; } - println!("TLS read error: {:?}", error); + println!("TLS read error: {error:?}"); self.closing = true; return; } @@ -291,7 +291,7 @@ fn lookup_suites(suites: &[String]) -> Vec { let scs = find_suite(csname); match scs { Some(s) => out.push(s), - None => panic!("cannot look up ciphersuite '{}'", csname), + None => panic!("cannot look up ciphersuite '{csname}'"), } } @@ -306,10 +306,7 @@ fn lookup_versions(versions: &[String]) -> Vec<&'static rustls::SupportedProtoco let version = match vname.as_ref() { "1.2" => &rustls::version::TLS12, "1.3" => &rustls::version::TLS13, - _ => panic!( - "cannot look up version '{}', valid are '1.2' and '1.3'", - vname - ), + _ => panic!("cannot look up version '{vname}', valid are '1.2' and '1.3'"), }; out.push(version); } @@ -526,7 +523,7 @@ fn main() { // Polling can be interrupted (e.g. by a debugger) - retry if so. Err(e) if e.kind() == io::ErrorKind::Interrupted => continue, Err(e) => { - panic!("poll failed: {:?}", e) + panic!("poll failed: {e:?}") } } diff --git a/examples/src/bin/tlsserver-mio.rs b/examples/src/bin/tlsserver-mio.rs index 6478b55710c..b156d34a49b 100644 --- a/examples/src/bin/tlsserver-mio.rs +++ b/examples/src/bin/tlsserver-mio.rs @@ -76,7 +76,7 @@ impl TlsServer { loop { match self.server.accept() { Ok((socket, addr)) => { - debug!("Accepting new connection from {:?}", addr); + debug!("Accepting new connection from {addr:?}"); let tls_conn = rustls::ServerConnection::new(Arc::clone(&self.tls_config)).unwrap(); @@ -92,10 +92,7 @@ impl TlsServer { } Err(err) if err.kind() == io::ErrorKind::WouldBlock => return Ok(()), Err(err) => { - println!( - "encountered error while accepting connection; err={:?}", - err - ); + println!("encountered error while accepting connection; err={err:?}"); return Err(err); } } @@ -224,7 +221,7 @@ impl OpenConnection { return; } - error!("read error {:?}", err); + error!("read error {err:?}"); self.closing = true; return; } @@ -238,7 +235,7 @@ impl OpenConnection { // Process newly-received TLS messages. if let Err(err) = self.tls_conn.process_new_packets() { - error!("cannot process packet: {:?}", err); + error!("cannot process packet: {err:?}"); // last gasp write to send any alerts self.do_tls_write_and_handle_error(); @@ -288,7 +285,7 @@ impl OpenConnection { let rc = try_read(back.read(&mut buf)); if rc.is_err() { - error!("backend read failed: {:?}", rc); + error!("backend read failed: {rc:?}"); self.closing = true; return; } @@ -355,7 +352,7 @@ impl OpenConnection { fn do_tls_write_and_handle_error(&mut self) { let rc = self.tls_write(); if rc.is_err() { - error!("write failed {:?}", rc); + error!("write failed {rc:?}"); self.closing = true; } } @@ -494,7 +491,7 @@ fn lookup_suites(suites: &[String]) -> Vec { let scs = find_suite(csname); match scs { Some(s) => out.push(s), - None => panic!("cannot look up ciphersuite '{}'", csname), + None => panic!("cannot look up ciphersuite '{csname}'"), } } @@ -509,10 +506,7 @@ fn lookup_versions(versions: &[String]) -> Vec<&'static rustls::SupportedProtoco let version = match vname.as_ref() { "1.2" => &rustls::version::TLS12, "1.3" => &rustls::version::TLS13, - _ => panic!( - "cannot look up version '{}', valid are '1.2' and '1.3'", - vname - ), + _ => panic!("cannot look up version '{vname}', valid are '1.2' and '1.3'"), }; out.push(version); } @@ -669,7 +663,7 @@ fn main() { // Polling can be interrupted (e.g. by a debugger) - retry if so. Err(e) if e.kind() == io::ErrorKind::Interrupted => continue, Err(e) => { - panic!("poll failed: {:?}", e) + panic!("poll failed: {e:?}") } } diff --git a/rustls/src/bs_debug.rs b/rustls/src/bs_debug.rs index 06c723605dc..eac4149f9e6 100644 --- a/rustls/src/bs_debug.rs +++ b/rustls/src/bs_debug.rs @@ -31,7 +31,7 @@ impl fmt::Debug for BsDebug<'_> { } else if (0x20..0x7f).contains(&c) { write!(fmt, "{}", c as char)?; } else { - write!(fmt, "\\x{:02x}", c)?; + write!(fmt, "\\x{c:02x}")?; } } write!(fmt, "\"")?; diff --git a/rustls/src/builder.rs b/rustls/src/builder.rs index 342e3633600..f8ff61405b1 100644 --- a/rustls/src/builder.rs +++ b/rustls/src/builder.rs @@ -183,7 +183,7 @@ impl fmt::Debug for ConfigBuilder", name,)) + f.debug_struct(&format!("ConfigBuilder<{name}, _>",)) .field("state", &self.state) .finish() } diff --git a/rustls/src/client/common.rs b/rustls/src/client/common.rs index 74803a866e9..214fe07a2ec 100644 --- a/rustls/src/client/common.rs +++ b/rustls/src/client/common.rs @@ -60,7 +60,7 @@ impl ClientHelloDetails { let ext_type = ext.ext_type(); if !self.sent_extensions.contains(&ext_type) && !allowed_unsolicited.contains(&ext_type) { - trace!("Unsolicited extension {:?}", ext_type); + trace!("Unsolicited extension {ext_type:?}"); return true; } } diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index dec0f6ef821..e50e11018fe 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -685,7 +685,7 @@ impl EchState { }; } - trace!("ECH Inner Hello: {:#?}", inner_hello); + 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 diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 5e10682c589..e1ce25454cb 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -85,7 +85,7 @@ fn find_session( } }) .or_else(|| { - debug!("No cached session for {:?}", server_name); + debug!("No cached session for {server_name:?}"); None }); @@ -553,7 +553,7 @@ fn emit_client_hello_for_retry( tls13::emit_fake_ccs(&mut input.sent_tls13_fake_ccs, cx.common); } - trace!("Sending ClientHello {:#?}", ch); + trace!("Sending ClientHello {ch:#?}"); transcript_buffer.add_message(&ch); cx.common.send_msg(ch, false); @@ -752,7 +752,7 @@ impl State for ExpectServerHello { { let server_hello = require_handshake_msg!(m, HandshakeType::ServerHello, HandshakePayload::ServerHello)?; - trace!("We got ServerHello {:#?}", server_hello); + trace!("We got ServerHello {server_hello:#?}"); use crate::ProtocolVersion::{TLSv1_2, TLSv1_3}; let config = &self.input.config; @@ -878,7 +878,7 @@ impl State for ExpectServerHello { }); } _ => { - debug!("Using ciphersuite {:?}", suite); + debug!("Using ciphersuite {suite:?}"); self.suite = Some(suite); cx.common.suite = Some(suite); } @@ -983,7 +983,7 @@ impl ExpectServerHelloOrHelloRetryRequest { HandshakeType::HelloRetryRequest, HandshakePayload::HelloRetryRequest )?; - trace!("Got HRR {:?}", hrr); + trace!("Got HRR {hrr:?}"); cx.common.check_aligned_handshake()?; diff --git a/rustls/src/client/tls12.rs b/rustls/src/client/tls12.rs index 914ad526f92..8c24d9598d7 100644 --- a/rustls/src/client/tls12.rs +++ b/rustls/src/client/tls12.rs @@ -733,7 +733,7 @@ impl State for ExpectCertificateRequest<'_> { HandshakePayload::CertificateRequest )?; self.transcript.add_message(&m); - debug!("Got CertificateRequest {:?}", certreq); + debug!("Got CertificateRequest {certreq:?}"); // The RFC jovially describes the design here as 'somewhat complicated' // and 'somewhat underspecified'. So thanks for that. diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index 11830a7f3ea..90ce762cc93 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -470,7 +470,7 @@ impl State for ExpectEncryptedExtensions { HandshakeType::EncryptedExtensions, HandshakePayload::EncryptedExtensions )?; - debug!("TLS1.3 encrypted extensions: {:?}", exts); + debug!("TLS1.3 encrypted extensions: {exts:?}"); self.transcript.add_message(&m); validate_encrypted_extensions(cx.common, &self.hello, exts)?; @@ -854,7 +854,7 @@ impl State for ExpectCertificateRequest { HandshakePayload::CertificateRequestTls13 )?; self.transcript.add_message(&m); - debug!("Got CertificateRequest {:?}", certreq); + debug!("Got CertificateRequest {certreq:?}"); // Fortunately the problems here in TLS1.2 and prior are corrected in // TLS1.3. diff --git a/rustls/src/common_state.rs b/rustls/src/common_state.rs index 156eb0824cf..171767aff4b 100644 --- a/rustls/src/common_state.rs +++ b/rustls/src/common_state.rs @@ -503,7 +503,7 @@ impl CommonState { } fn send_warning_alert(&mut self, desc: AlertDescription) { - warn!("Sending warning alert {:?}", desc); + warn!("Sending warning alert {desc:?}"); self.send_warning_alert_no_log(desc); } diff --git a/rustls/src/conn/unbuffered.rs b/rustls/src/conn/unbuffered.rs index 59c5a51fb52..84fe3f0941a 100644 --- a/rustls/src/conn/unbuffered.rs +++ b/rustls/src/conn/unbuffered.rs @@ -564,8 +564,7 @@ impl fmt::Display for EncodeError { match self { Self::InsufficientSize(InsufficientSizeError { required_size }) => write!( f, - "cannot encode due to insufficient size, {} bytes are required", - required_size + "cannot encode due to insufficient size, {required_size} bytes are required" ), Self::AlreadyEncoded => "cannot encode, data has already been encoded".fmt(f), } diff --git a/rustls/src/crypto/aws_lc_rs/sign.rs b/rustls/src/crypto/aws_lc_rs/sign.rs index 4139906a226..8f8c5f6127f 100644 --- a/rustls/src/crypto/aws_lc_rs/sign.rs +++ b/rustls/src/crypto/aws_lc_rs/sign.rs @@ -117,7 +117,7 @@ impl RsaSigningKey { } } .map_err(|key_rejected| { - Error::General(format!("failed to parse RSA private key: {}", key_rejected)) + Error::General(format!("failed to parse RSA private key: {key_rejected}")) })?; Ok(Self { @@ -428,7 +428,7 @@ mod tests { )); let k = any_supported_type(&key).unwrap(); - assert_eq!(format!("{:?}", k), "EcdsaSigningKey { algorithm: ECDSA }"); + assert_eq!(format!("{k:?}"), "EcdsaSigningKey { algorithm: ECDSA }"); assert_eq!(k.algorithm(), SignatureAlgorithm::ECDSA); assert!( @@ -443,7 +443,7 @@ mod tests { .choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256]) .unwrap(); assert_eq!( - format!("{:?}", s), + format!("{s:?}"), "EcdsaSigner { scheme: ECDSA_NISTP256_SHA256 }" ); assert_eq!(s.scheme(), SignatureScheme::ECDSA_NISTP256_SHA256); @@ -481,7 +481,7 @@ mod tests { )); let k = any_supported_type(&key).unwrap(); - assert_eq!(format!("{:?}", k), "EcdsaSigningKey { algorithm: ECDSA }"); + assert_eq!(format!("{k:?}"), "EcdsaSigningKey { algorithm: ECDSA }"); assert_eq!(k.algorithm(), SignatureAlgorithm::ECDSA); assert!( @@ -496,7 +496,7 @@ mod tests { .choose_scheme(&[SignatureScheme::ECDSA_NISTP384_SHA384]) .unwrap(); assert_eq!( - format!("{:?}", s), + format!("{s:?}"), "EcdsaSigner { scheme: ECDSA_NISTP384_SHA384 }" ); assert_eq!(s.scheme(), SignatureScheme::ECDSA_NISTP384_SHA384); @@ -534,7 +534,7 @@ mod tests { )); let k = any_supported_type(&key).unwrap(); - assert_eq!(format!("{:?}", k), "EcdsaSigningKey { algorithm: ECDSA }"); + assert_eq!(format!("{k:?}"), "EcdsaSigningKey { algorithm: ECDSA }"); assert_eq!(k.algorithm(), SignatureAlgorithm::ECDSA); assert!( @@ -553,7 +553,7 @@ mod tests { .choose_scheme(&[SignatureScheme::ECDSA_NISTP521_SHA512]) .unwrap(); assert_eq!( - format!("{:?}", s), + format!("{s:?}"), "EcdsaSigner { scheme: ECDSA_NISTP521_SHA512 }" ); assert_eq!(s.scheme(), SignatureScheme::ECDSA_NISTP521_SHA512); @@ -579,10 +579,7 @@ mod tests { 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!(format!("{k:?}"), "Ed25519SigningKey { algorithm: ED25519 }"); assert_eq!(k.algorithm(), SignatureAlgorithm::ED25519); assert!( @@ -596,7 +593,7 @@ mod tests { let s = k .choose_scheme(&[SignatureScheme::ED25519]) .unwrap(); - assert_eq!(format!("{:?}", s), "Ed25519Signer { scheme: ED25519 }"); + assert_eq!(format!("{s:?}"), "Ed25519Signer { scheme: ED25519 }"); assert_eq!(s.scheme(), SignatureScheme::ED25519); assert_eq!(s.sign(b"hello").unwrap().len(), 64); } @@ -627,7 +624,7 @@ mod tests { )); let k = any_supported_type(&key).unwrap(); - assert_eq!(format!("{:?}", k), "RsaSigningKey { algorithm: RSA }"); + assert_eq!(format!("{k:?}"), "RsaSigningKey { algorithm: RSA }"); assert_eq!(k.algorithm(), SignatureAlgorithm::RSA); assert!( @@ -642,7 +639,7 @@ mod tests { let s = k .choose_scheme(&[SignatureScheme::RSA_PSS_SHA256]) .unwrap(); - assert_eq!(format!("{:?}", s), "RsaSigner { scheme: RSA_PSS_SHA256 }"); + 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); diff --git a/rustls/src/crypto/aws_lc_rs/ticketer.rs b/rustls/src/crypto/aws_lc_rs/ticketer.rs index 31d94bf38bf..b1b245495a2 100644 --- a/rustls/src/crypto/aws_lc_rs/ticketer.rs +++ b/rustls/src/crypto/aws_lc_rs/ticketer.rs @@ -404,7 +404,7 @@ mod tests { let t = make_ticket_generator().unwrap(); - assert_eq!(format!("{:?}", t), "Rfc5077Ticketer { lifetime: 43200 }"); + assert_eq!(format!("{t:?}"), "Rfc5077Ticketer { lifetime: 43200 }"); assert!(t.enabled()); assert_eq!(t.lifetime(), 43200); } diff --git a/rustls/src/crypto/ring/sign.rs b/rustls/src/crypto/ring/sign.rs index 91b753a1cae..426d03eeea1 100644 --- a/rustls/src/crypto/ring/sign.rs +++ b/rustls/src/crypto/ring/sign.rs @@ -110,7 +110,7 @@ impl RsaSigningKey { } } .map_err(|key_rejected| { - Error::General(format!("failed to parse RSA private key: {}", key_rejected)) + Error::General(format!("failed to parse RSA private key: {key_rejected}")) })?; Ok(Self { @@ -461,7 +461,7 @@ mod tests { )); let k = any_supported_type(&key).unwrap(); - assert_eq!(format!("{:?}", k), "EcdsaSigningKey { algorithm: ECDSA }"); + assert_eq!(format!("{k:?}"), "EcdsaSigningKey { algorithm: ECDSA }"); assert_eq!(k.algorithm(), SignatureAlgorithm::ECDSA); assert!( @@ -476,7 +476,7 @@ mod tests { .choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256]) .unwrap(); assert_eq!( - format!("{:?}", s), + format!("{s:?}"), "EcdsaSigner { scheme: ECDSA_NISTP256_SHA256 }" ); assert_eq!(s.scheme(), SignatureScheme::ECDSA_NISTP256_SHA256); @@ -514,7 +514,7 @@ mod tests { )); let k = any_supported_type(&key).unwrap(); - assert_eq!(format!("{:?}", k), "EcdsaSigningKey { algorithm: ECDSA }"); + assert_eq!(format!("{k:?}"), "EcdsaSigningKey { algorithm: ECDSA }"); assert_eq!(k.algorithm(), SignatureAlgorithm::ECDSA); assert!( @@ -529,7 +529,7 @@ mod tests { .choose_scheme(&[SignatureScheme::ECDSA_NISTP384_SHA384]) .unwrap(); assert_eq!( - format!("{:?}", s), + format!("{s:?}"), "EcdsaSigner { scheme: ECDSA_NISTP384_SHA384 }" ); assert_eq!(s.scheme(), SignatureScheme::ECDSA_NISTP384_SHA384); @@ -555,10 +555,7 @@ mod tests { 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!(format!("{k:?}"), "Ed25519SigningKey { algorithm: ED25519 }"); assert_eq!(k.algorithm(), SignatureAlgorithm::ED25519); assert!( @@ -572,7 +569,7 @@ mod tests { let s = k .choose_scheme(&[SignatureScheme::ED25519]) .unwrap(); - assert_eq!(format!("{:?}", s), "Ed25519Signer { scheme: ED25519 }"); + assert_eq!(format!("{s:?}"), "Ed25519Signer { scheme: ED25519 }"); assert_eq!(s.scheme(), SignatureScheme::ED25519); assert_eq!(s.sign(b"hello").unwrap().len(), 64); } @@ -603,7 +600,7 @@ mod tests { )); let k = any_supported_type(&key).unwrap(); - assert_eq!(format!("{:?}", k), "RsaSigningKey { algorithm: RSA }"); + assert_eq!(format!("{k:?}"), "RsaSigningKey { algorithm: RSA }"); assert_eq!(k.algorithm(), SignatureAlgorithm::RSA); assert!( @@ -618,7 +615,7 @@ mod tests { let s = k .choose_scheme(&[SignatureScheme::RSA_PSS_SHA256]) .unwrap(); - assert_eq!(format!("{:?}", s), "RsaSigner { scheme: RSA_PSS_SHA256 }"); + 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); diff --git a/rustls/src/crypto/ring/ticketer.rs b/rustls/src/crypto/ring/ticketer.rs index 95793f6223d..45fe5db8a53 100644 --- a/rustls/src/crypto/ring/ticketer.rs +++ b/rustls/src/crypto/ring/ticketer.rs @@ -370,7 +370,7 @@ mod tests { let t = make_ticket_generator().unwrap(); let expect = format!("AeadTicketer {{ alg: {TICKETER_AEAD:?}, lifetime: 43200 }}"); - assert_eq!(format!("{:?}", t), expect); + assert_eq!(format!("{t:?}"), expect); assert!(t.enabled()); assert_eq!(t.lifetime(), 43200); } diff --git a/rustls/src/error.rs b/rustls/src/error.rs index 09a4244ed4a..76569c1d4f8 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -591,7 +591,7 @@ impl fmt::Display for CertificateError { f, "is not valid for any names (according to its subjectAltName extension)" ), - [one] => write!(f, "is only valid for {}", one), + [one] => write!(f, "is only valid for {one}"), many => { write!(f, "is only valid for ")?; @@ -600,12 +600,12 @@ impl fmt::Display for CertificateError { let last = &many[n - 1]; for (i, name) in all_but_last.iter().enumerate() { - write!(f, "{}", name)?; + write!(f, "{name}")?; if i < n - 2 { write!(f, ", ")?; } } - write!(f, " or {}", last) + write!(f, " or {last}") } } } @@ -662,7 +662,7 @@ impl fmt::Display for CertificateError { Ok(()) } - other => write!(f, "{:?}", other), + other => write!(f, "{other:?}"), } } } @@ -812,7 +812,7 @@ impl From for Error { fn join(items: &[T]) -> String { items .iter() - .map(|x| format!("{:?}", x)) + .map(|x| format!("{x:?}")) .collect::>() .join(" or ") } @@ -839,22 +839,22 @@ impl fmt::Display for Error { join::(expect_types) ), Self::InvalidMessage(typ) => { - write!(f, "received corrupt message of type {:?}", 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::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) + write!(f, "invalid peer certificate: {err}") } Self::InvalidCertRevocationList(err) => { - write!(f, "invalid certificate revocation list: {:?}", 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) + write!(f, "encrypted client hello failure: {err:?}") } Self::EncryptError => write!(f, "cannot encrypt message"), Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"), @@ -866,10 +866,10 @@ impl fmt::Display for Error { write!(f, "the supplied max_fragment_size was too small or large") } Self::InconsistentKeys(why) => { - write!(f, "keys may not be consistent: {:?}", 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), + Self::General(err) => write!(f, "unexpected error: {err}"), + Self::Other(err) => write!(f, "other error: {err}"), } } } @@ -1174,8 +1174,8 @@ mod tests { ]; for err in all { - println!("{:?}:", err); - println!(" fmt '{}'", err); + println!("{err:?}:"); + println!(" fmt '{err}'"); } } diff --git a/rustls/src/key_log_file.rs b/rustls/src/key_log_file.rs index c79771a62a8..e12b596565e 100644 --- a/rustls/src/key_log_file.rs +++ b/rustls/src/key_log_file.rs @@ -33,7 +33,7 @@ impl KeyLogFileInner { { Ok(f) => Some(f), Err(e) => { - warn!("unable to create key log file {:?}: {}", path, e); + warn!("unable to create key log file {path:?}: {e}"); None } }; @@ -53,13 +53,13 @@ impl KeyLogFileInner { }; self.buf.truncate(0); - write!(self.buf, "{} ", label)?; + write!(self.buf, "{label} ")?; for b in client_random.iter() { - write!(self.buf, "{:02x}", b)?; + write!(self.buf, "{b:02x}")?; } write!(self.buf, " ")?; for b in secret.iter() { - write!(self.buf, "{:02x}", b)?; + write!(self.buf, "{b:02x}")?; } writeln!(self.buf)?; file.write_all(&self.buf) @@ -105,7 +105,7 @@ impl KeyLog for KeyLogFile { { Ok(()) => {} Err(e) => { - warn!("error writing to key log file: {}", e); + warn!("error writing to key log file: {e}"); } } } @@ -114,7 +114,7 @@ impl KeyLog for KeyLogFile { 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), + Ok(key_log_file) => write!(f, "{key_log_file:?}"), Err(_) => write!(f, "KeyLogFile {{ }}"), } } diff --git a/rustls/src/msgs/base.rs b/rustls/src/msgs/base.rs index 3a1b43f4981..38eb3ede32e 100644 --- a/rustls/src/msgs/base.rs +++ b/rustls/src/msgs/base.rs @@ -232,7 +232,7 @@ pub(super) fn hex<'a>( payload: impl IntoIterator, ) -> fmt::Result { for b in payload { - write!(f, "{:02x}", b)?; + write!(f, "{b:02x}")?; } Ok(()) } diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 6c3cb4027f5..2926c85807b 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -310,8 +310,7 @@ impl<'a> Codec<'a> for ServerNamePayload<'a> { HostNamePayload::IpAddress(_invalid) => { warn!( - "Illegal SNI extension: ignoring IP address presented as hostname ({:?})", - _invalid + "Illegal SNI extension: ignoring IP address presented as hostname ({_invalid:?})" ); Some(Self::IpAddress) } diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index 30b07dd0c3f..f5cb1ae6332 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -41,7 +41,7 @@ fn reads_random() { let bytes = [0x01; 32]; let mut rd = Reader::init(&bytes); let rnd = Random::read(&mut rd).unwrap(); - println!("{:?}", rnd); + println!("{rnd:?}"); assert!(!rd.any_left()); } @@ -80,7 +80,7 @@ fn accepts_short_session_id() { let bytes = [1; 2]; let mut rd = Reader::init(&bytes); let sess = SessionId::read(&mut rd).unwrap(); - println!("{:?}", sess); + println!("{sess:?}"); #[cfg(feature = "tls12")] assert!(!sess.is_empty()); @@ -93,7 +93,7 @@ fn accepts_empty_session_id() { let bytes = [0; 1]; let mut rd = Reader::init(&bytes); let sess = SessionId::read(&mut rd).unwrap(); - println!("{:?}", sess); + println!("{sess:?}"); #[cfg(feature = "tls12")] assert!(sess.is_empty()); @@ -111,7 +111,7 @@ fn debug_session_id() { let sess = SessionId::read(&mut rd).unwrap(); assert_eq!( "0101010101010101010101010101010101010101010101010101010101010101", - format!("{:?}", sess) + format!("{sess:?}") ); } @@ -121,7 +121,7 @@ fn can_round_trip_unknown_client_ext() { let mut rd = Reader::init(&bytes); let ext = ClientExtension::read(&mut rd).unwrap(); - println!("{:?}", ext); + println!("{ext:?}"); assert_eq!(ext.ext_type(), ExtensionType::Unknown(0x1234)); assert_eq!(bytes.to_vec(), ext.get_encoding()); } @@ -173,7 +173,7 @@ fn can_round_trip_single_sni() { let bytes = [0, 0, 0, 7, 0, 5, 0, 0, 2, 0x6c, 0x6f]; let mut rd = Reader::init(&bytes); let ext = ClientExtension::read(&mut rd).unwrap(); - println!("{:?}", ext); + println!("{ext:?}"); assert_eq!(ext.ext_type(), ExtensionType::ServerName); assert_eq!(bytes.to_vec(), ext.get_encoding()); @@ -184,7 +184,7 @@ fn can_round_trip_mixed_case_sni() { let bytes = [0, 0, 0, 7, 0, 5, 0, 0, 2, 0x4c, 0x6f]; let mut rd = Reader::init(&bytes); let ext = ClientExtension::read(&mut rd).unwrap(); - println!("{:?}", ext); + println!("{ext:?}"); assert_eq!(ext.ext_type(), ExtensionType::ServerName); assert_eq!(bytes.to_vec(), ext.get_encoding()); @@ -195,7 +195,7 @@ fn single_hostname_returns_none_for_other_sni_name_types() { let bytes = [0, 0, 0, 7, 0, 5, 1, 0, 2, 0x6c, 0x6f]; let mut rd = Reader::init(&bytes); let ext = ClientExtension::read(&mut rd).unwrap(); - println!("{:?}", ext); + println!("{ext:?}"); assert_eq!(ext.ext_type(), ExtensionType::ServerName); assert!(matches!( @@ -232,13 +232,13 @@ fn rejects_truncated_sni() { 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); + 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); + 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()); @@ -250,7 +250,7 @@ fn can_round_trip_psk_offer() { 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); + println!("{psko:?}"); assert_eq!(psko.identities.len(), 1); assert_eq!(psko.identities[0].identity.0, vec![0x99]); @@ -263,7 +263,7 @@ fn can_round_trip_psk_offer() { #[test] fn can_round_trip_cert_status_req_for_ocsp() { let ext = ClientExtension::CertificateStatusRequest(CertificateStatusRequest::build_ocsp()); - println!("{:?}", ext); + println!("{ext:?}"); let bytes = [ 0, 5, // CertificateStatusRequest @@ -272,7 +272,7 @@ fn can_round_trip_cert_status_req_for_ocsp() { ]; let csr = ClientExtension::read(&mut Reader::init(&bytes)).unwrap(); - println!("{:?}", csr); + println!("{csr:?}"); assert_eq!(csr.get_encoding(), bytes.to_vec()); } @@ -285,7 +285,7 @@ fn can_round_trip_cert_status_req_for_other() { ]; let csr = ClientExtension::read(&mut Reader::init(&bytes)).unwrap(); - println!("{:?}", csr); + println!("{csr:?}"); assert_eq!(csr.get_encoding(), bytes.to_vec()); } @@ -294,7 +294,7 @@ fn can_round_trip_multi_proto() { let bytes = [0, 16, 0, 8, 0, 6, 2, 0x68, 0x69, 2, 0x6c, 0x6f]; let mut rd = Reader::init(&bytes); let ext = ClientExtension::read(&mut rd).unwrap(); - println!("{:?}", ext); + println!("{ext:?}"); assert_eq!(ext.ext_type(), ExtensionType::ALProtocolNegotiation); assert_eq!(ext.get_encoding(), bytes.to_vec()); @@ -317,7 +317,7 @@ fn can_round_trip_single_proto() { let bytes = [0, 16, 0, 5, 0, 3, 2, 0x68, 0x69]; let mut rd = Reader::init(&bytes); let ext = ClientExtension::read(&mut rd).unwrap(); - println!("{:?}", ext); + println!("{ext:?}"); assert_eq!(ext.ext_type(), ExtensionType::ALProtocolNegotiation); assert_eq!(bytes.to_vec(), ext.get_encoding()); @@ -367,7 +367,7 @@ fn test_truncated_psk_offer() { }); let mut enc = ext.get_encoding(); - println!("testing {:?} enc {:?}", ext, enc); + println!("testing {ext:?} enc {enc:?}"); for l in 0..enc.len() { if l == 9 { continue; @@ -382,7 +382,7 @@ fn test_truncated_psk_offer() { fn test_truncated_client_hello_is_detected() { let ch = sample_client_hello_payload(); let enc = ch.get_encoding(); - println!("testing {:?} enc {:?}", ch, enc); + println!("testing {ch:?} enc {enc:?}"); for l in 0..enc.len() { println!("len {:?} enc {:?}", l, &enc[..l]); @@ -399,7 +399,7 @@ fn test_truncated_client_extension_is_detected() { for ext in &chp.extensions { let mut enc = ext.get_encoding(); - println!("testing {:?} enc {:?}", ext, enc); + println!("testing {ext:?} enc {enc:?}"); // "outer" truncation, i.e., where the extension-level length is longer than // the input @@ -419,7 +419,7 @@ fn test_truncated_client_extension_is_detected() { // 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 {:?} len {:?}", enc, l); + println!(" encoding {enc:?} len {l:?}"); assert!(ClientExtension::read_bytes(&enc).is_err()); } } @@ -533,7 +533,7 @@ fn test_truncated_hello_retry_extension_is_detected() { for ext in &hrr.extensions { let mut enc = ext.get_encoding(); - println!("testing {:?} enc {:?}", ext, enc); + println!("testing {ext:?} enc {enc:?}"); // "outer" truncation, i.e., where the extension-level length is longer than // the input @@ -550,7 +550,7 @@ fn test_truncated_hello_retry_extension_is_detected() { // 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 {:?} len {:?}", enc, l); + println!(" encoding {enc:?} len {l:?}"); assert!(HelloRetryExtension::read_bytes(&enc).is_err()); } } @@ -599,7 +599,7 @@ fn test_truncated_server_extension_is_detected() { for ext in &shp.extensions { let mut enc = ext.get_encoding(); - println!("testing {:?} enc {:?}", ext, enc); + println!("testing {ext:?} enc {enc:?}"); // "outer" truncation, i.e., where the extension-level length is longer than // the input @@ -619,7 +619,7 @@ fn test_truncated_server_extension_is_detected() { // 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 {:?} len {:?}", enc, l); + println!(" encoding {enc:?} len {l:?}"); assert!(ServerExtension::read_bytes(&enc).is_err()); } } @@ -728,8 +728,8 @@ fn can_round_trip_all_tls12_handshake_payloads() { assert!(!rd.any_left()); assert_eq!(hm.get_encoding(), other.get_encoding()); - println!("{:?}", hm); - println!("{:?}", other); + println!("{hm:?}"); + println!("{other:?}"); } } @@ -748,7 +748,7 @@ fn can_into_owned_all_tls12_handshake_payloads() { 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 {:?} enc {:?}", hm, enc); + println!("test {hm:?} enc {enc:?}"); // outer truncation for l in 0..enc.len() { @@ -758,7 +758,7 @@ fn can_detect_truncation_of_all_tls12_handshake_payloads() { // inner truncation for l in 0..enc.len() - 4 { put_u24(l as u32, &mut enc[1..]); - println!(" check len {:?} enc {:?}", l, enc); + println!(" check len {l:?} enc {enc:?}"); match (hm.typ, l) { (HandshakeType::ClientHello, 41) @@ -794,8 +794,8 @@ fn can_round_trip_all_tls13_handshake_payloads() { assert!(!rd.any_left()); assert_eq!(hm.get_encoding(), other.get_encoding()); - println!("{:?}", hm); - println!("{:?}", other); + println!("{hm:?}"); + println!("{other:?}"); } } @@ -814,7 +814,7 @@ fn can_into_owned_all_tls13_handshake_payloads() { 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 {:?} enc {:?}", hm, enc); + println!("test {hm:?} enc {enc:?}"); // outer truncation for l in 0..enc.len() { @@ -824,7 +824,7 @@ fn can_detect_truncation_of_all_tls13_handshake_payloads() { // inner truncation for l in 0..enc.len() - 4 { put_u24(l as u32, &mut enc[1..]); - println!(" check len {:?} enc {:?}", l, enc); + println!(" check len {l:?} enc {enc:?}"); match (hm.typ, l) { (HandshakeType::ClientHello, 41) @@ -859,7 +859,7 @@ fn cannot_read_message_hash_from_network() { typ: HandshakeType::MessageHash, payload: HandshakePayload::MessageHash(Payload::new(vec![1, 2, 3])), }; - println!("mh {:?}", mh); + println!("mh {mh:?}"); let enc = mh.get_encoding(); assert!(HandshakeMessagePayload::read_bytes(&enc).is_err()); } @@ -898,7 +898,7 @@ 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); + println!("msg: {hm:?}"); } #[test] diff --git a/rustls/src/msgs/message/outbound.rs b/rustls/src/msgs/message/outbound.rs index 7345e54b37e..810c066cb5c 100644 --- a/rustls/src/msgs/message/outbound.rs +++ b/rustls/src/msgs/message/outbound.rs @@ -318,7 +318,7 @@ mod tests { let borrowed_payload = OutboundChunks::Single(owner); let (before, after) = borrowed_payload.split_at(6); - println!("before:{:?}\nafter:{:?}", before, after); + println!("before:{before:?}\nafter:{after:?}"); assert_eq!(before.to_vec(), &[0, 1, 2, 3, 4, 5]); assert_eq!(after.to_vec(), &[6, 7]); } @@ -329,17 +329,17 @@ mod tests { let borrowed_payload = OutboundChunks::new(&owner); let (before, after) = borrowed_payload.split_at(3); - println!("before:{:?}\nafter:{:?}", before, after); + 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:{:?}\nafter:{:?}", before, after); + 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:{:?}\nafter:{:?}", before, after); + 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]); } @@ -350,19 +350,19 @@ mod tests { let single_payload = OutboundChunks::Single(owner[0]); let (before, after) = single_payload.split_at(17); - println!("before:{:?}\nafter:{:?}", before, after); + 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:{:?}\nafter:{:?}", before, after); + 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:{:?}\nafter:{:?}", before, after); + println!("before:{before:?}\nafter:{after:?}"); assert!(before.is_empty()); assert!(after.is_empty()); } @@ -393,7 +393,7 @@ mod tests { let payload = OutboundChunks::new(&slices); assert_eq!(payload.to_vec(), owner); - println!("{:#?}", payload); + println!("{payload:#?}"); for start in 0..128 { for end in start..128 { diff --git a/rustls/src/msgs/message_test.rs b/rustls/src/msgs/message_test.rs index c52fde58575..013f41eb565 100644 --- a/rustls/src/msgs/message_test.rs +++ b/rustls/src/msgs/message_test.rs @@ -32,7 +32,7 @@ fn test_read_fuzz_corpus() { let msg = OutboundOpaqueMessage::read(&mut rd) .unwrap() .into_plain_message(); - println!("{:?}", msg); + println!("{msg:?}"); let Ok(msg) = Message::try_from(msg) else { continue; @@ -70,7 +70,7 @@ fn can_read_safari_client_hello_with_ip_address_in_sni_extension() { \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); + println!("m = {m:?}"); Message::try_from(m.into_plain_message()).unwrap(); } @@ -91,9 +91,9 @@ fn construct_all_types() { ]; for &bytes in samples.iter() { let m = OutboundOpaqueMessage::read(&mut Reader::init(bytes)).unwrap(); - println!("m = {:?}", m); + println!("m = {m:?}"); let m = Message::try_from(m.into_plain_message()); - println!("m' = {:?}", m); + println!("m' = {m:?}"); } } diff --git a/rustls/src/msgs/persist.rs b/rustls/src/msgs/persist.rs index 9179eedfd52..8ddec1699c9 100644 --- a/rustls/src/msgs/persist.rs +++ b/rustls/src/msgs/persist.rs @@ -435,11 +435,7 @@ impl ServerSessionValue { .saturating_sub(self.creation_time_sec) as u32) .saturating_mul(1000); - let age_difference = if client_age_ms < server_age_ms { - server_age_ms - client_age_ms - } else { - client_age_ms - server_age_ms - }; + let age_difference = server_age_ms.abs_diff(client_age_ms); self.freshness = Some(age_difference <= MAX_FRESHNESS_SKEW_MS); self @@ -469,7 +465,7 @@ mod tests { UnixTime::now(), 0x12345678, ); - println!("{:?}", ssv); + println!("{ssv:?}"); } #[test] diff --git a/rustls/src/server/hs.rs b/rustls/src/server/hs.rs index f426cff870c..b3c0e9a1b27 100644 --- a/rustls/src/server/hs.rs +++ b/rustls/src/server/hs.rs @@ -91,7 +91,7 @@ impl ExtensionProcessing { }) .cloned(); if let Some(selected_protocol) = &cx.common.alpn_protocol { - debug!("Chosen ALPN protocol {:?}", selected_protocol); + debug!("Chosen ALPN protocol {selected_protocol:?}"); self.exts .push(ServerExtension::Protocols(SingleProtocolName::new( selected_protocol.clone(), @@ -449,7 +449,7 @@ impl ExpectClientHello { .send_fatal_alert(AlertDescription::HandshakeFailure, incompat) })?; - debug!("decided upon suite {:?}", suite); + debug!("decided upon suite {suite:?}"); cx.common.suite = Some(suite); cx.common.kx_state = KxState::Start(skxg); @@ -672,7 +672,7 @@ pub(super) fn process_client_hello<'m>( ) -> Result<(&'m ClientHelloPayload, Vec), Error> { let client_hello = require_handshake_msg!(m, HandshakeType::ClientHello, HandshakePayload::ClientHello)?; - trace!("we got a clienthello {:?}", client_hello); + trace!("we got a clienthello {client_hello:?}"); if !client_hello .compression_methods diff --git a/rustls/src/server/tls12.rs b/rustls/src/server/tls12.rs index 8fc46de7382..c0c403c6eea 100644 --- a/rustls/src/server/tls12.rs +++ b/rustls/src/server/tls12.rs @@ -91,7 +91,7 @@ mod client_hello { .ecpoints_extension() .unwrap_or(&[ECPointFormat::Uncompressed]); - trace!("ecpoints {:?}", ecpoints_ext); + trace!("ecpoints {ecpoints_ext:?}"); if !ecpoints_ext.contains(&ECPointFormat::Uncompressed) { return Err(cx.common.send_fatal_alert( @@ -358,7 +358,7 @@ mod client_hello { extensions: ep.exts, }), }; - trace!("sending server hello {:?}", sh); + trace!("sending server hello {sh:?}"); flight.add(sh); Ok(ep.send_ticket) @@ -445,7 +445,7 @@ mod client_hello { payload: HandshakePayload::CertificateRequest(cr), }; - trace!("Sending CertificateRequest {:?}", creq); + trace!("Sending CertificateRequest {creq:?}"); flight.add(creq); Ok(true) } @@ -492,7 +492,7 @@ impl State for ExpectCertificate { .verifier .client_auth_mandatory(); - trace!("certs {:?}", cert_chain); + trace!("certs {cert_chain:?}"); let client_cert = match cert_chain.split_first() { None if mandatory => { diff --git a/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index 4af77ddb611..5e55dff9e09 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -532,7 +532,7 @@ mod client_hello { let client_hello_hash = transcript.hash_given(&[]); - trace!("sending server hello {:?}", sh); + trace!("sending server hello {sh:?}"); transcript.add_message(&sh); cx.common.send_msg(sh, false); @@ -605,7 +605,7 @@ mod client_hello { }), }; - trace!("Requesting retry {:?}", m); + trace!("Requesting retry {m:?}"); transcript.rollup_for_hrr(); transcript.add_message(&m); common.send_msg(m, false); @@ -691,7 +691,7 @@ mod client_hello { payload: HandshakePayload::EncryptedExtensions(ep.exts), }; - trace!("sending encrypted extensions {:?}", ee); + trace!("sending encrypted extensions {ee:?}"); flight.add(ee); Ok(early_data) } @@ -737,7 +737,7 @@ mod client_hello { payload: HandshakePayload::CertificateRequestTls13(cr), }; - trace!("Sending CertificateRequest {:?}", creq); + trace!("Sending CertificateRequest {creq:?}"); flight.add(creq); Ok(true) } @@ -755,7 +755,7 @@ mod client_hello { )), }; - trace!("sending certificate {:?}", cert); + trace!("sending certificate {cert:?}"); flight.add(cert); } @@ -780,7 +780,7 @@ mod client_hello { payload: HandshakePayload::CompressedCertificate(entry.compressed_cert_payload()), }; - trace!("sending compressed certificate {:?}", c); + trace!("sending compressed certificate {c:?}"); flight.add(c); } @@ -811,7 +811,7 @@ mod client_hello { payload: HandshakePayload::CertificateVerify(cv), }; - trace!("sending certificate-verify {:?}", cv); + trace!("sending certificate-verify {cv:?}"); flight.add(cv); Ok(()) } @@ -832,7 +832,7 @@ mod client_hello { payload: HandshakePayload::Finished(verify_data_payload), }; - trace!("sending finished {:?}", fin); + trace!("sending finished {fin:?}"); flight.add(fin); let hash_at_server_fin = flight.transcript.current_hash(); flight.finish(cx.common); @@ -1344,7 +1344,7 @@ impl ExpectFinished { typ: HandshakeType::NewSessionTicket, payload: HandshakePayload::NewSessionTicketTls13(payload), }; - trace!("sending new ticket {:?} (stateless: {})", t, stateless); + trace!("sending new ticket {t:?} (stateless: {stateless})"); flight.add(t); Ok(()) diff --git a/rustls/src/webpki/anchors.rs b/rustls/src/webpki/anchors.rs index e4558db889b..b526ed252ab 100644 --- a/rustls/src/webpki/anchors.rs +++ b/rustls/src/webpki/anchors.rs @@ -45,15 +45,14 @@ impl RootCertStore { } Err(err) => { trace!("invalid cert der {:?}", der_cert.as_ref()); - debug!("certificate parsing failed: {:?}", err); + debug!("certificate parsing failed: {err:?}"); invalid_count += 1; } }; } debug!( - "add_parsable_certificates processed {} valid and {} invalid certs", - valid_count, invalid_count + "add_parsable_certificates processed {valid_count} valid and {invalid_count} invalid certs" ); (valid_count, invalid_count) @@ -138,7 +137,7 @@ fn root_cert_store_debug() { let store = RootCertStore::from_iter(iter::repeat(ta).take(138)); assert_eq!( - format!("{:?}", store), + format!("{store:?}"), "RootCertStore { roots: \"(138 roots)\" }" ); } diff --git a/rustls/src/webpki/client_verifier.rs b/rustls/src/webpki/client_verifier.rs index a69264bcb0c..78bb7720ed0 100644 --- a/rustls/src/webpki/client_verifier.rs +++ b/rustls/src/webpki/client_verifier.rs @@ -488,7 +488,7 @@ mod tests { provider::default_provider().into(), ); // The builder should be Debug. - println!("{:?}", builder); + println!("{builder:?}"); builder.build().unwrap(); } @@ -502,7 +502,7 @@ mod tests { ) .allow_unauthenticated(); // The builder should be Debug. - println!("{:?}", builder); + println!("{builder:?}"); builder.build().unwrap(); } @@ -516,7 +516,7 @@ mod tests { provider::default_provider().into(), ); // The builder should be Debug. - println!("{:?}", builder); + println!("{builder:?}"); builder.build().unwrap(); } @@ -530,7 +530,7 @@ mod tests { ) .allow_unauthenticated(); // The builder should be Debug. - println!("{:?}", builder); + println!("{builder:?}"); builder.build().unwrap(); } @@ -564,7 +564,7 @@ mod tests { // 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); + println!("{builder:?}"); builder.build().unwrap(); } @@ -578,7 +578,7 @@ mod tests { ) .with_crls(test_crls()); // The builder should be Debug. - println!("{:?}", builder); + println!("{builder:?}"); builder.build().unwrap(); } @@ -593,7 +593,7 @@ mod tests { .with_crls(test_crls()) .allow_unauthenticated(); // The builder should be Debug. - println!("{:?}", builder); + println!("{builder:?}"); builder.build().unwrap(); } @@ -607,7 +607,7 @@ mod tests { .with_crls(test_crls()) .only_check_end_entity_revocation(); // The builder should be Debug. - println!("{:?}", builder); + println!("{builder:?}"); builder.build().unwrap(); } @@ -621,7 +621,7 @@ mod tests { .with_crls(test_crls()) .allow_unknown_revocation_status(); // The builder should be Debug. - println!("{:?}", builder); + println!("{builder:?}"); builder.build().unwrap(); } @@ -635,7 +635,7 @@ mod tests { .with_crls(test_crls()) .enforce_revocation_expiration(); // The builder should be Debug. - println!("{:?}", builder); + println!("{builder:?}"); builder.build().unwrap(); } @@ -658,8 +658,8 @@ mod tests { ]; for err in all { - let _ = format!("{:?}", err); - let _ = format!("{}", err); + let _ = format!("{err:?}"); + let _ = format!("{err}"); } } } diff --git a/rustls/src/webpki/mod.rs b/rustls/src/webpki/mod.rs index c6c40916a7a..2c7e5a17171 100644 --- a/rustls/src/webpki/mod.rs +++ b/rustls/src/webpki/mod.rs @@ -48,7 +48,7 @@ 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), + Self::InvalidCrl(e) => write!(f, "provided CRL could not be parsed: {e:?}"), } } } diff --git a/rustls/src/webpki/server_verifier.rs b/rustls/src/webpki/server_verifier.rs index 5c54e7fe660..9405c123a23 100644 --- a/rustls/src/webpki/server_verifier.rs +++ b/rustls/src/webpki/server_verifier.rs @@ -375,7 +375,7 @@ mod tests { // 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); + println!("{builder:?}"); builder.build().unwrap(); } @@ -399,7 +399,7 @@ mod tests { ) .only_check_end_entity_revocation(); // The builder should be Debug. - println!("{:?}", builder); + println!("{builder:?}"); builder.build().unwrap(); } @@ -413,7 +413,7 @@ mod tests { ) .allow_unknown_revocation_status(); // The builder should be Debug. - println!("{:?}", builder); + println!("{builder:?}"); builder.build().unwrap(); } @@ -428,7 +428,7 @@ mod tests { .allow_unknown_revocation_status() .only_check_end_entity_revocation(); // The builder should be Debug. - println!("{:?}", builder); + println!("{builder:?}"); builder.build().unwrap(); } @@ -442,7 +442,7 @@ mod tests { ) .enforce_revocation_expiration(); // The builder should be Debug. - println!("{:?}", builder); + println!("{builder:?}"); builder.build().unwrap(); } } diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 95bc0cbf642..e26a98edc46 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -561,10 +561,7 @@ fn version_test( let client_config = make_client_config_with_versions(KeyType::Rsa2048, client_versions); let server_config = make_server_config_with_versions(KeyType::Rsa2048, server_versions); - println!( - "version {:?} {:?} -> {:?}", - client_versions, server_versions, result - ); + println!("version {client_versions:?} {server_versions:?} -> {result:?}"); let (mut client, mut server) = make_pair_for_configs(client_config, server_config); @@ -1090,11 +1087,11 @@ fn test_config_builders_debug() { } .into(), ); - let _ = format!("{:?}", b); + let _ = format!("{b:?}"); let b = server_config_builder_with_versions(&[&rustls::version::TLS13]); - let _ = format!("{:?}", b); + let _ = format!("{b:?}"); let b = b.with_no_client_auth(); - let _ = format!("{:?}", b); + let _ = format!("{b:?}"); let b = ClientConfig::builder_with_provider( CryptoProvider { @@ -1104,9 +1101,9 @@ fn test_config_builders_debug() { } .into(), ); - let _ = format!("{:?}", b); + let _ = format!("{b:?}"); let b = client_config_builder_with_versions(&[&rustls::version::TLS13]); - let _ = format!("{:?}", b); + let _ = format!("{b:?}"); } /// Test that the server handles combination of `offer_client_auth()` returning true @@ -2762,7 +2759,7 @@ fn client_fill_buf_returns_wouldblock_when_no_data() { fn new_server_returns_initial_io_state() { let (_, mut server) = make_pair(KeyType::Rsa2048); let io_state = server.process_new_packets().unwrap(); - println!("IoState is Debug {:?}", io_state); + println!("IoState is Debug {io_state:?}"); assert_eq!(io_state.plaintext_bytes_to_read(), 0); assert!(!io_state.peer_has_closed()); assert_eq!(io_state.tls_bytes_to_write(), 0); @@ -2772,7 +2769,7 @@ fn new_server_returns_initial_io_state() { fn new_client_returns_initial_io_state() { let (mut client, _) = make_pair(KeyType::Rsa2048); let io_state = client.process_new_packets().unwrap(); - println!("IoState is Debug {:?}", io_state); + println!("IoState is Debug {io_state:?}"); assert_eq!(io_state.plaintext_bytes_to_read(), 0); assert!(!io_state.peer_has_closed()); assert!(io_state.tls_bytes_to_write() > 200); @@ -3259,7 +3256,7 @@ fn stream_write_swallows_underlying_io_error_after_plaintext_processed() { .unwrap(); let mut client_stream = Stream::new(&mut client, &mut pipe); let rc = client_stream.write(b"world"); - assert_eq!(format!("{:?}", rc), "Ok(5)"); + assert_eq!(format!("{rc:?}"), "Ok(5)"); } fn make_disjoint_suite_configs() -> (ClientConfig, ServerConfig) { @@ -3300,13 +3297,13 @@ fn client_stream_handshake_error() { let rc = client_stream.write(b"hello"); assert!(rc.is_err()); assert_eq!( - format!("{:?}", rc), + format!("{rc:?}"), "Err(Custom { kind: InvalidData, error: AlertReceived(HandshakeFailure) })" ); let rc = client_stream.write(b"hello"); assert!(rc.is_err()); assert_eq!( - format!("{:?}", rc), + format!("{rc:?}"), "Err(Custom { kind: InvalidData, error: AlertReceived(HandshakeFailure) })" ); } @@ -3322,13 +3319,13 @@ fn client_streamowned_handshake_error() { let rc = client_stream.write(b"hello"); assert!(rc.is_err()); assert_eq!( - format!("{:?}", rc), + format!("{rc:?}"), "Err(Custom { kind: InvalidData, error: AlertReceived(HandshakeFailure) })" ); let rc = client_stream.write(b"hello"); assert!(rc.is_err()); assert_eq!( - format!("{:?}", rc), + format!("{rc:?}"), "Err(Custom { kind: InvalidData, error: AlertReceived(HandshakeFailure) })" ); @@ -3352,7 +3349,7 @@ fn server_stream_handshake_error() { let rc = server_stream.read(&mut bytes); assert!(rc.is_err()); assert_eq!( - format!("{:?}", rc), + format!("{rc:?}"), "Err(Custom { kind: InvalidData, error: PeerIncompatible(NoCipherSuitesInCommon) })" ); } @@ -3374,7 +3371,7 @@ fn server_streamowned_handshake_error() { let rc = server_stream.read(&mut bytes); assert!(rc.is_err()); assert_eq!( - format!("{:?}", rc), + format!("{rc:?}"), "Err(Custom { kind: InvalidData, error: PeerIncompatible(NoCipherSuitesInCommon) })" ); } @@ -3392,13 +3389,13 @@ fn client_config_is_clone() { #[test] fn client_connection_is_debug() { let (client, _) = make_pair(KeyType::Rsa2048); - println!("{:?}", client); + println!("{client:?}"); } #[test] fn server_connection_is_debug() { let (_, server) = make_pair(KeyType::Rsa2048); - println!("{:?}", server); + println!("{server:?}"); } #[test] @@ -5350,7 +5347,7 @@ mod test_quic { ]; for &(size, ok) in cases.iter() { - println!("early data size case: {:?}", size); + println!("early data size case: {size:?}"); if let Some(new) = size { server_config.max_early_data_size = new; } @@ -5929,7 +5926,7 @@ fn test_client_attempts_to_use_unsupported_kx_group() { do_handshake_until_error(&mut client_1, &mut server).unwrap(); let ops = shared_storage.ops(); - println!("storage {:#?}", ops); + println!("storage {ops:#?}"); assert_eq!(ops.len(), 7); assert!(matches!( ops[3], @@ -5985,7 +5982,7 @@ fn test_client_sends_share_for_less_preferred_group() { do_handshake_until_error(&mut client_1, &mut server).unwrap(); let ops = shared_storage.ops(); - println!("storage {:#?}", ops); + println!("storage {ops:#?}"); assert_eq!(ops.len(), 7); assert!(matches!( ops[3], @@ -6003,9 +6000,9 @@ fn test_client_sends_share_for_less_preferred_group() { assert_eq!(keyshares.len(), 1); assert_eq!(keyshares[0].group(), rustls::NamedGroup::secp384r1); } - _ => panic!("unexpected handshake message {:?}", parsed), + _ => panic!("unexpected handshake message {parsed:?}"), }, - _ => panic!("unexpected non-handshake message {:?}", msg), + _ => panic!("unexpected non-handshake message {msg:?}"), }; Altered::InPlace }; @@ -6017,10 +6014,10 @@ fn test_client_sends_share_for_less_preferred_group() { let group = hrr.requested_key_share_group(); assert_eq!(group, Some(rustls::NamedGroup::X25519)); } - _ => panic!("unexpected handshake message {:?}", parsed), + _ => panic!("unexpected handshake message {parsed:?}"), }, MessagePayload::ChangeCipherSpec(_) => (), - _ => panic!("unexpected non-handshake message {:?}", msg), + _ => panic!("unexpected non-handshake message {msg:?}"), }; Altered::InPlace }; @@ -6059,7 +6056,7 @@ fn test_tls13_client_resumption_does_not_reuse_tickets() { do_handshake_until_error(&mut client, &mut server).unwrap(); let ops = shared_storage.ops_and_reset(); - println!("storage {:#?}", ops); + println!("storage {ops:#?}"); assert_eq!(ops.len(), 10); assert!(matches!(ops[5], ClientStorageOp::InsertTls13Ticket(_))); assert!(matches!(ops[6], ClientStorageOp::InsertTls13Ticket(_))); @@ -6090,7 +6087,7 @@ fn test_tls13_client_resumption_does_not_reuse_tickets() { server.process_new_packets().unwrap(); let ops = shared_storage.ops_and_reset(); - println!("last {:?}", ops); + println!("last {ops:?}"); assert!(matches!(ops[0], ClientStorageOp::TakeTls13Ticket(_, false))); } @@ -6134,7 +6131,7 @@ fn test_client_mtu_reduction() { let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); let writes = collect_write_lengths(&mut client); - println!("writes at mtu=64: {:?}", writes); + println!("writes at mtu=64: {writes:?}"); assert!(writes.iter().all(|x| *x <= 64)); assert!(writes.len() > 1); } @@ -6250,7 +6247,7 @@ fn handshakes_complete_and_data_flows_with_gratuitious_max_fragment_sizes() { fn assert_lt(left: usize, right: usize) { if left >= right { - panic!("expected {} < {}", left, right); + panic!("expected {left} < {right}"); } } @@ -6395,7 +6392,7 @@ fn test_server_rejects_clients_without_any_kx_group_overlap() { fn test_client_rejects_illegal_tls13_ccs() { fn corrupt_ccs(msg: &mut Message) -> Altered { if let MessagePayload::ChangeCipherSpec(_) = &mut msg.payload { - println!("seen CCS {:?}", msg); + println!("seen CCS {msg:?}"); return Altered::Raw(encoding::message_framing( ContentType::ChangeCipherSpec, ProtocolVersion::TLSv1_2, diff --git a/rustls/tests/common/mod.rs b/rustls/tests/common/mod.rs index 41fdc01e337..34169c32bc4 100644 --- a/rustls/tests/common/mod.rs +++ b/rustls/tests/common/mod.rs @@ -1084,8 +1084,7 @@ impl ServerCertVerifier for MockServerVerifier { now: UnixTime, ) -> Result { println!( - "verify_server_cert({:?}, {:?}, {:?}, {:?}, {:?})", - end_entity, intermediates, server_name, ocsp_response, now + "verify_server_cert({end_entity:?}, {intermediates:?}, {server_name:?}, {ocsp_response:?}, {now:?})" ); if let Some(expected_ocsp) = &self.expected_ocsp_response { assert_eq!(expected_ocsp, ocsp_response); @@ -1102,10 +1101,7 @@ impl ServerCertVerifier for MockServerVerifier { cert: &CertificateDer<'_>, dss: &DigitallySignedStruct, ) -> Result { - println!( - "verify_tls12_signature({:?}, {:?}, {:?})", - message, cert, dss - ); + println!("verify_tls12_signature({message:?}, {cert:?}, {dss:?})"); match &self.tls12_signature_error { Some(error) => Err(error.clone()), _ => Ok(HandshakeSignatureValid::assertion()), @@ -1118,10 +1114,7 @@ impl ServerCertVerifier for MockServerVerifier { cert: &CertificateDer<'_>, dss: &DigitallySignedStruct, ) -> Result { - println!( - "verify_tls13_signature({:?}, {:?}, {:?})", - message, cert, dss - ); + println!("verify_tls13_signature({message:?}, {cert:?}, {dss:?})"); match &self.tls13_signature_error { Some(error) => Err(error.clone()), _ if self.requires_raw_public_keys => verify_tls13_signature_with_raw_key( diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index bb5292ae71b..706f7e16e98 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -1107,7 +1107,7 @@ fn advance_client( let UnbufferedStatus { discard, state } = conn.process_tls_records(buffers.incoming.filled()); let state = state.unwrap(); - transcript.push(format!("{:?}", state)); + transcript.push(format!("{state:?}")); let state = match state { ConnectionState::TransmitTlsData(mut state) => { @@ -1152,7 +1152,7 @@ fn advance_server( let UnbufferedStatus { discard, state } = conn.process_tls_records(buffers.incoming.filled()); let state = state.unwrap(); - transcript.push(format!("{:?}", state)); + transcript.push(format!("{state:?}")); let state = match state { ConnectionState::ReadEarlyData(mut state) => { @@ -1424,7 +1424,7 @@ fn server_receives_handshake_byte_by_byte() { _ => panic!("unexpected first client event"), }; - println!("client hello: {:?}", client_hello_buffer); + println!("client hello: {client_hello_buffer:?}"); for prefix in 0..client_hello_buffer.len() - 1 { let UnbufferedStatus { discard, state } = From f331d5e9c09b65a1390e68d5e914c437aeeb9b25 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 15 May 2025 20:52:35 +0200 Subject: [PATCH 197/403] Move .clippy.toml to cover just core crate --- .clippy.toml => rustls/.clippy.toml | 1 - 1 file changed, 1 deletion(-) rename .clippy.toml => rustls/.clippy.toml (75%) diff --git a/.clippy.toml b/rustls/.clippy.toml similarity index 75% rename from .clippy.toml rename to rustls/.clippy.toml index 6b6a85a00c8..8b79eddd64c 100644 --- a/.clippy.toml +++ b/rustls/.clippy.toml @@ -1,6 +1,5 @@ upper-case-acronyms-aggressive = true -# only intended to affect main rustls crate - need to allow disallowed-types in all other crates in Clippy CI job disallowed-types = [ { path = "std::sync::Arc", reason = "must use Arc from sync module to support downstream forks targeting architectures without atomic ptrs" }, { path = "std::sync::Weak", reason = "must use Weak from sync module to support downstream forks targeting architectures without atomic ptrs" }, From 795ae1f5d0435dbc80dac04ec147e85d4970563c Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 15 May 2025 20:55:23 +0200 Subject: [PATCH 198/403] build.yml: simplify clippy use --- .github/workflows/build.yml | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bd21e1f8a60..27f732cd614 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -476,12 +476,7 @@ jobs: uses: dtolnay/rust-toolchain@stable with: components: clippy - # We want to be free of any warnings, so deny them. - # - Allow `clippy::disallowed_types` as a workaround since `disallowed_types` configured in `.clippy.toml` - # is only intended for the main `rustls` crate. - - run: ./admin/clippy -- --deny warnings --allow clippy::disallowed_types - # - Keep the main crate free of all warnings. - - run: cargo clippy -p rustls -- --deny warnings + - run: ./admin/clippy -- --deny warnings clippy-nightly: name: Clippy (Nightly) @@ -501,11 +496,7 @@ jobs: with: components: clippy # Do not deny warnings, as nightly clippy sometimes has false negatives. - # - Ignore `clippy::disallowed_types` as a workaround since `disallowed_types` configured in `.clippy.toml` - # is only intended for main `rustls` crate. - - run: ./admin/clippy -- --allow clippy::disallowed_types - # Check the main crate for any Clippy nightly warnings, but do not deny them. - - run: cargo clippy -p rustls + - run: ./admin/clippy check-external-types: name: Validate external types appearing in public API From 5f8926a860e6b26c997761db7c87e29a14a2ae99 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 15:16:49 +0100 Subject: [PATCH 199/403] Allow `clippy::if_same_then_else` for logging-only branch --- rustls/src/server/tls12.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/rustls/src/server/tls12.rs b/rustls/src/server/tls12.rs index c0c403c6eea..48935600d9d 100644 --- a/rustls/src/server/tls12.rs +++ b/rustls/src/server/tls12.rs @@ -911,6 +911,7 @@ impl State for ExpectFinished { .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 { From f9b859ac070e7425ae3e95c89f858fcba96df341 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 15:18:59 +0100 Subject: [PATCH 200/403] Correct `clippy::unused_enumerate_index` allowance --- rustls/src/client/ech.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index e50e11018fe..80acff93941 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -107,7 +107,7 @@ impl EchConfig { // Note: we name the index var _i because if the log feature is disabled // it is unused. - #[cfg_attr(not(feature = "std"), allow(clippy::unused_enumerate_index))] + #[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, From 2c2dfe615186a6a0becc72c416756b219899f568 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 15:20:24 +0100 Subject: [PATCH 201/403] Address `clippy::manual_let_else` lint --- rustls/src/key_log_file.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/rustls/src/key_log_file.rs b/rustls/src/key_log_file.rs index e12b596565e..45f29da552c 100644 --- a/rustls/src/key_log_file.rs +++ b/rustls/src/key_log_file.rs @@ -45,11 +45,8 @@ impl KeyLogFileInner { } fn try_write(&mut self, label: &str, client_random: &[u8], secret: &[u8]) -> io::Result<()> { - let file = match &mut self.file { - None => { - return Ok(()); - } - Some(f) => f, + let Some(file) = &mut self.file else { + return Ok(()); }; self.buf.truncate(0); From 24a6231c5638c15cd751f9016beb776d2d9f70cc Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 15:33:50 +0100 Subject: [PATCH 202/403] rustls-bench: address `clippy::uninlined_format_args` --- rustls-bench/src/main.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/rustls-bench/src/main.rs b/rustls-bench/src/main.rs index 8bbc155c0e2..73385f74f7f 100644 --- a/rustls-bench/src/main.rs +++ b/rustls-bench/src/main.rs @@ -483,7 +483,7 @@ fn report_timings( for t in thread_timings.iter() { let rate = work_per_thread / which(t); total_rate += rate; - print!("{:.2}\t", rate); + print!("{rate:.2}\t"); } println!( @@ -681,7 +681,7 @@ fn lookup_matching_benches( .collect(); if r.is_empty() { - panic!("unknown suite {:?}", ciphersuite_name); + panic!("unknown suite {ciphersuite_name:?}"); } r @@ -1047,10 +1047,10 @@ enum KeyType { impl KeyType { fn path_for(&self, part: &str) -> String { match self { - Self::Rsa2048 => format!("test-ca/rsa-2048/{}", part), - Self::EcdsaP256 => format!("test-ca/ecdsa-p256/{}", part), - Self::EcdsaP384 => format!("test-ca/ecdsa-p384/{}", part), - Self::Ed25519 => format!("test-ca/eddsa/{}", part), + Self::Rsa2048 => format!("test-ca/rsa-2048/{part}"), + Self::EcdsaP256 => format!("test-ca/ecdsa-p256/{part}"), + Self::EcdsaP384 => format!("test-ca/ecdsa-p384/{part}"), + Self::Ed25519 => format!("test-ca/eddsa/{part}"), } } @@ -1389,7 +1389,7 @@ where offs += read; } Err(err) => { - panic!("error on transfer {}..{}: {}", offs, sz, err); + panic!("error on transfer {offs}..{sz}: {err}"); } } @@ -1398,7 +1398,7 @@ where let sz = match right.reader().read(&mut [0u8; 16_384]) { Ok(sz) => sz, Err(err) if err.kind() == io::ErrorKind::WouldBlock => break, - Err(err) => panic!("failed to read data: {}", err), + Err(err) => panic!("failed to read data: {err}"), }; *left -= sz; From e2a6fc78b8217aab97159151ae73e2389c753ad6 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 15:35:12 +0100 Subject: [PATCH 203/403] openssl-tests: address `clippy::uninlined_format_args` --- openssl-tests/src/raw_key_openssl_interop.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openssl-tests/src/raw_key_openssl_interop.rs b/openssl-tests/src/raw_key_openssl_interop.rs index 589e4a08bb6..c6857330d69 100644 --- a/openssl-tests/src/raw_key_openssl_interop.rs +++ b/openssl-tests/src/raw_key_openssl_interop.rs @@ -64,7 +64,7 @@ mod client { pub(super) fn run_client(config: ClientConfig, port: u16) -> Result { let server_name = "0.0.0.0".try_into().unwrap(); let mut conn = ClientConnection::new(Arc::new(config), server_name).unwrap(); - let mut sock = TcpStream::connect(format!("[::]:{}", port)).unwrap(); + let mut sock = TcpStream::connect(format!("[::]:{port}")).unwrap(); let mut tls = Stream::new(&mut conn, &mut sock); let mut buf = vec![0; 128]; @@ -368,7 +368,7 @@ mod tests { assert_eq!(server_message, "Hello from the server"); } Err(e) => { - panic!("Client failed to communicate with the server: {:?}", e); + panic!("Client failed to communicate with the server: {e:?}"); } } @@ -383,7 +383,7 @@ mod tests { assert_eq!(client_message, "Hello from the client"); } Err(e) => { - panic!("Server failed to communicate with the client: {:?}", e); + panic!("Server failed to communicate with the client: {e:?}"); } } } @@ -415,7 +415,7 @@ mod tests { let mut openssl_client = Command::new("openssl") .arg("s_client") .arg("-connect") - .arg(format!("[::]:{:?}", port)) + .arg(format!("[::]:{port:?}")) .arg("-enable_client_rpk") .arg("-key") .arg(CLIENT_PRIV_KEY_FILE) @@ -457,7 +457,7 @@ mod tests { let mut openssl_client = Command::new("openssl") .arg("s_client") .arg("-connect") - .arg(format!("[::]:{:?}", port)) + .arg(format!("[::]:{port:?}")) .arg("-enable_server_rpk") .arg("-enable_client_rpk") .arg("-key") @@ -552,7 +552,7 @@ mod tests { } } Err(e) => { - panic!("Error reading from OpenSSL stdout: {:?}", e); + panic!("Error reading from OpenSSL stdout: {e:?}"); } } } From 1ddc74b0f71684bdb1de242eea09eb99963f9638 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 15:35:56 +0100 Subject: [PATCH 204/403] connect-tests: address `clippy::uninlined_format_args` --- connect-tests/tests/common/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/connect-tests/tests/common/mod.rs b/connect-tests/tests/common/mod.rs index 145e7e9219f..148482f784e 100644 --- a/connect-tests/tests/common/mod.rs +++ b/connect-tests/tests/common/mod.rs @@ -153,7 +153,7 @@ impl TlsClient { .args(&args) .env("SSLKEYLOGFILE", "./sslkeylogfile.txt") .output() - .unwrap_or_else(|e| panic!("failed to execute: {}", e)); + .unwrap_or_else(|e| panic!("failed to execute: {e}")); let stdout_str = String::from_utf8_lossy(&output.stdout); let stderr_str = String::from_utf8_lossy(&output.stderr); @@ -161,8 +161,8 @@ impl TlsClient { for expect in &self.expect_output { let re = Regex::new(expect).unwrap(); if re.find(&stdout_str).is_none() { - println!("We expected to find '{}' in the following output:", expect); - println!("{:?}", output); + println!("We expected to find '{expect}' in the following output:"); + println!("{output:?}"); panic!("Test failed"); } } @@ -170,8 +170,8 @@ impl TlsClient { for expect in &self.expect_log { let re = Regex::new(expect).unwrap(); if re.find(&stderr_str).is_none() { - println!("We expected to find '{}' in the following output:", expect); - println!("{:?}", output); + println!("We expected to find '{expect}' in the following output:"); + println!("{output:?}"); panic!("Test failed"); } } From 98a4848491b01d85818e54c24d753a024fca58dd Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 15:36:23 +0100 Subject: [PATCH 205/403] ci-bench: address `clippy::uninlined_format_args` --- ci-bench/src/util.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ci-bench/src/util.rs b/ci-bench/src/util.rs index f45759ac310..f883ff294ba 100644 --- a/ci-bench/src/util.rs +++ b/ci-bench/src/util.rs @@ -11,9 +11,9 @@ pub enum KeyType { impl KeyType { pub(crate) fn path_for(&self, part: &str) -> String { match self { - Self::Rsa2048 => format!("../test-ca/rsa-2048/{}", part), - Self::EcdsaP256 => format!("../test-ca/ecdsa-p256/{}", part), - Self::EcdsaP384 => format!("../test-ca/ecdsa-p384/{}", part), + Self::Rsa2048 => format!("../test-ca/rsa-2048/{part}"), + Self::EcdsaP256 => format!("../test-ca/ecdsa-p256/{part}"), + Self::EcdsaP384 => format!("../test-ca/ecdsa-p384/{part}"), } } From 8374213cf8d95a2700fdef05c74d8b350b57c14b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 15:37:03 +0100 Subject: [PATCH 206/403] bogo: address `clippy::uninlined_format_args` --- bogo/src/main.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/bogo/src/main.rs b/bogo/src/main.rs index 59429a4cf14..065912c7788 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -316,7 +316,7 @@ fn decode_hex(hex: &str) -> Vec { (0..hex.len()) .step_by(2) .map(|i| u8::from_str_radix(&hex[i..i + 2], 16).unwrap()) - .inspect(|x| println!("item {:?}", x)) + .inspect(|x| println!("item {x:?}")) .collect() } @@ -865,7 +865,7 @@ fn quit_err(why: &str) -> ! { } fn handle_err(opts: &Options, err: Error) -> ! { - println!("TLS error: {:?}", err); + println!("TLS error: {err:?}"); thread::sleep(time::Duration::from_millis(100)); match err { @@ -990,7 +990,7 @@ fn handle_err(opts: &Options, err: Error) -> ! { quit(":CANNOT_PARSE_LEAF_CERT:") } Error::InvalidCertificate(CertificateError::BadSignature) => quit(":BAD_SIGNATURE:"), - Error::InvalidCertificate(e) => quit(&format!(":BAD_CERT: ({:?})", e)), + Error::InvalidCertificate(e) => quit(&format!(":BAD_CERT: ({e:?})")), Error::PeerSentOversizedRecord => quit(":DATA_LENGTH_TOO_LONG:"), _ => { println_err!("unhandled error: {:?}", err); @@ -1002,7 +1002,7 @@ fn handle_err(opts: &Options, err: Error) -> ! { fn flush(sess: &mut Connection, conn: &mut net::TcpStream) { while sess.wants_write() { if let Err(err) = sess.write_tls(conn) { - println!("IO error: {:?}", err); + println!("IO error: {err:?}"); process::exit(0); } } @@ -1033,12 +1033,12 @@ fn read_n_bytes(opts: &Options, sess: &mut Connection, conn: &mut net::TcpStream let mut bytes = [0u8; MAX_MESSAGE_SIZE]; match conn.read(&mut bytes[..n]) { Ok(count) => { - println!("read {:?} bytes", count); + println!("read {count:?} bytes"); sess.read_tls(&mut io::Cursor::new(&mut bytes[..count])) .expect("read_tls not expected to fail reading from buffer"); } Err(err) if err.kind() == io::ErrorKind::ConnectionReset => {} - Err(err) => panic!("invalid read: {}", err), + Err(err) => panic!("invalid read: {err}"), }; after_read(opts, sess, conn); @@ -1048,7 +1048,7 @@ fn read_all_bytes(opts: &Options, sess: &mut Connection, conn: &mut net::TcpStre match sess.read_tls(conn) { Ok(_) => {} Err(err) if err.kind() == io::ErrorKind::ConnectionReset => {} - Err(err) => panic!("invalid read: {}", err), + Err(err) => panic!("invalid read: {err}"), }; after_read(opts, sess, conn); @@ -1269,7 +1269,7 @@ fn exec(opts: &Options, mut sess: Connection, count: usize) { println!("EOF (tcp)"); return; } - Err(err) => panic!("unhandled read error {:?}", err), + Err(err) => panic!("unhandled read error {err:?}"), }; if opts.shut_down_after_handshake && !sent_shutdown && !sess.is_handshaking() { @@ -1278,7 +1278,7 @@ fn exec(opts: &Options, mut sess: Connection, count: usize) { } if quench_writes && len > 0 { - println!("unquenching writes after {:?}", len); + println!("unquenching writes after {len:?}"); quench_writes = false; } @@ -1302,7 +1302,7 @@ pub fn main() { println!("No"); process::exit(0); } - println!("options: {:?}", args); + println!("options: {args:?}"); let mut opts = Options::new(); @@ -1355,7 +1355,7 @@ pub fn main() { "-tls13-variant" => { let variant = args.remove(0).parse::().unwrap(); if variant != 1 { - println!("NYI TLS1.3 variant selection: {:?} {:?}", arg, variant); + println!("NYI TLS1.3 variant selection: {arg:?} {variant:?}"); process::exit(BOGO_NACK); } } @@ -1426,7 +1426,7 @@ pub fn main() { "-expect-tls13-downgrade" | "-enable-signed-cert-timestamps" | "-expect-session-id" => { - println!("not checking {}; NYI", arg); + println!("not checking {arg}; NYI"); } "-key-update" => { @@ -1541,7 +1541,7 @@ pub fn main() { opts.expect_reject_early_data = true; } _ => { - println!("NYI early data reason: {}", reason); + println!("NYI early data reason: {reason}"); process::exit(1); } } @@ -1706,7 +1706,7 @@ pub fn main() { "-expect-resumable-across-names" | "-expect-not-resumable-across-names" | "-use-custom-verify-callback" => { - println!("NYI option {:?}", arg); + println!("NYI option {arg:?}"); process::exit(BOGO_NACK); } @@ -1718,13 +1718,13 @@ pub fn main() { } _ => { - println!("unhandled option {:?}", arg); + println!("unhandled option {arg:?}"); process::exit(1); } } } - println!("opts {:?}", opts); + println!("opts {opts:?}"); #[cfg(unix)] if opts.wait_for_debugger { From 0004af074d3b358e65bb330c7029bec2e27fc3d4 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 20 May 2025 17:16:34 +0200 Subject: [PATCH 207/403] rustls-post-quantum: upgrade to webpki-roots 1 --- Cargo.lock | 2 +- rustls-post-quantum/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4f136c86274..9a9a4237903 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2714,7 +2714,7 @@ dependencies = [ "criterion", "env_logger", "rustls 0.23.27", - "webpki-roots 0.26.11", + "webpki-roots 1.0.0", ] [[package]] diff --git a/rustls-post-quantum/Cargo.toml b/rustls-post-quantum/Cargo.toml index 54d0798272e..b0547af7c9e 100644 --- a/rustls-post-quantum/Cargo.toml +++ b/rustls-post-quantum/Cargo.toml @@ -17,7 +17,7 @@ rustls = { version = "0.23.22", features = ["aws_lc_rs", "prefer-post-quantum"], [dev-dependencies] criterion = "0.5" env_logger = "0.11" -webpki-roots = "0.26" +webpki-roots = "1" [[bench]] name = "benchmarks" From bf30549350a62c6d815bcb849fc936b7c7cf9e20 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 20 May 2025 17:17:45 +0200 Subject: [PATCH 208/403] rustls-post-quantum: use workspace dependencies --- Cargo.toml | 1 + rustls-post-quantum/Cargo.toml | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 73f1089a63d..24fde84a774 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,6 +51,7 @@ byteorder = "1.4.3" chacha20poly1305 = { version = "0.10", default-features = false, features = ["alloc"] } clap = { version = "4.3.21", features = ["derive", "env"] } crabgrind = "=0.1.9" # compatible with valgrind package on GHA ubuntu-latest +criterion = "0.5" der = "0.7" ecdsa = "0.16.8" env_logger = "0.11" diff --git a/rustls-post-quantum/Cargo.toml b/rustls-post-quantum/Cargo.toml index b0547af7c9e..4c17db70ba4 100644 --- a/rustls-post-quantum/Cargo.toml +++ b/rustls-post-quantum/Cargo.toml @@ -15,9 +15,9 @@ autobenches = false rustls = { version = "0.23.22", features = ["aws_lc_rs", "prefer-post-quantum"], path = "../rustls" } [dev-dependencies] -criterion = "0.5" -env_logger = "0.11" -webpki-roots = "1" +criterion = { workspace = true } +env_logger = { workspace = true } +webpki-roots = { workspace = true } [[bench]] name = "benchmarks" From e9335c8b95dee6a3a0bc2722a5f69e6a94011649 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 20 May 2025 17:20:21 +0200 Subject: [PATCH 209/403] Upgrade to criterion 0.6 --- Cargo.lock | 37 ++++++++--------------- Cargo.toml | 2 +- rustls-post-quantum/benches/benchmarks.rs | 3 +- 3 files changed, 16 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9a9a4237903..0b6edc41410 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -725,25 +725,22 @@ dependencies = [ [[package]] name = "criterion" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +checksum = "3bf7af66b0989381bd0be551bd7cc91912a655a58c6918420c9527b1fd8b4679" dependencies = [ "anes", "cast", "ciborium", "clap", "criterion-plot", - "is-terminal", - "itertools 0.10.5", + "itertools 0.13.0", "num-traits", - "once_cell", "oorandom", "plotters", "rayon", "regex", "serde", - "serde_derive", "serde_json", "tinytemplate", "walkdir", @@ -1322,12 +1319,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" -[[package]] -name = "hermit-abi" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" - [[package]] name = "hex" version = "0.4.3" @@ -1641,17 +1632,6 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" -[[package]] -name = "is-terminal" -version = "0.4.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" -dependencies = [ - "hermit-abi 0.5.1", - "libc", - "windows-sys 0.59.0", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -1676,6 +1656,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.14.0" @@ -2240,7 +2229,7 @@ checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi 0.4.0", + "hermit-abi", "pin-project-lite", "rustix", "tracing", diff --git a/Cargo.toml b/Cargo.toml index 24fde84a774..d560df2d56e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,7 +51,7 @@ byteorder = "1.4.3" chacha20poly1305 = { version = "0.10", default-features = false, features = ["alloc"] } clap = { version = "4.3.21", features = ["derive", "env"] } crabgrind = "=0.1.9" # compatible with valgrind package on GHA ubuntu-latest -criterion = "0.5" +criterion = "0.6" der = "0.7" ecdsa = "0.16.8" env_logger = "0.11" diff --git a/rustls-post-quantum/benches/benchmarks.rs b/rustls-post-quantum/benches/benchmarks.rs index fe6023cafd2..8d486b7e462 100644 --- a/rustls-post-quantum/benches/benchmarks.rs +++ b/rustls-post-quantum/benches/benchmarks.rs @@ -1,6 +1,7 @@ +use std::hint::black_box; use std::sync::Arc; -use criterion::{Criterion, Throughput, black_box, criterion_group, criterion_main}; +use criterion::{Criterion, Throughput, criterion_group, criterion_main}; use rustls::crypto::aws_lc_rs::kx_group::X25519; use rustls::crypto::{ ActiveKeyExchange, CryptoProvider, SharedSecret, SupportedKxGroup, aws_lc_rs, From 902cc50529f88b5e1401461d88e74933e0506957 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 08:48:07 +0100 Subject: [PATCH 210/403] Introduce server::test for low-level protocol tests --- rustls/src/lib.rs | 2 ++ rustls/src/server/test.rs | 54 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 rustls/src/server/test.rs diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 51fa5741f3e..cf428cef27f 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -629,6 +629,8 @@ pub mod server { pub(crate) mod handy; mod hs; mod server_conn; + #[cfg(test)] + mod test; #[cfg(feature = "tls12")] mod tls12; mod tls13; diff --git a/rustls/src/server/test.rs b/rustls/src/server/test.rs new file mode 100644 index 00000000000..6f1b5980656 --- /dev/null +++ b/rustls/src/server/test.rs @@ -0,0 +1,54 @@ +use std::prelude::v1::*; +use std::vec; + +use super::ServerConnectionData; +use crate::common_state::Context; +use crate::msgs::enums::Compression; +use crate::msgs::handshake::{ + ClientExtension, ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, Random, + SessionId, +}; +use crate::msgs::message::{Message, MessagePayload}; +use crate::{CommonState, Error, HandshakeType, PeerIncompatible, ProtocolVersion, Side}; + +#[test] +fn null_compression_required() { + assert_eq!( + test_process_client_hello(ClientHelloPayload { + compression_methods: vec![], + ..minimal_client_hello() + }), + Err(PeerIncompatible::NullCompressionRequired.into()), + ); +} + +fn test_process_client_hello(hello: ClientHelloPayload) -> Result<(), Error> { + let m = Message { + version: ProtocolVersion::TLSv1_2, + payload: MessagePayload::handshake(HandshakeMessagePayload { + typ: HandshakeType::ClientHello, + payload: 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(|_| ()) +} + +fn minimal_client_hello() -> ClientHelloPayload { + ClientHelloPayload { + client_version: ProtocolVersion::TLSv1_3, + random: Random::from([0u8; 32]), + session_id: SessionId::empty(), + cipher_suites: vec![], + compression_methods: vec![Compression::Null], + extensions: vec![ClientExtension::SignatureAlgorithms(vec![])], + } +} From 70ea0e48625d5b17e610e3410939d14ab940d486 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 09:03:05 +0100 Subject: [PATCH 211/403] server::test: port `server_ignores_sni_with_ip_address` --- rustls/src/server/test.rs | 28 +++++++++++++++++++++++++++- rustls/tests/api.rs | 8 -------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/rustls/src/server/test.rs b/rustls/src/server/test.rs index 6f1b5980656..09e91d08dcf 100644 --- a/rustls/src/server/test.rs +++ b/rustls/src/server/test.rs @@ -3,7 +3,8 @@ use std::vec; use super::ServerConnectionData; use crate::common_state::Context; -use crate::msgs::enums::Compression; +use crate::msgs::codec::{Codec, LengthPrefixedBuffer, ListLength}; +use crate::msgs::enums::{Compression, ExtensionType}; use crate::msgs::handshake::{ ClientExtension, ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, Random, SessionId, @@ -22,6 +23,15 @@ fn null_compression_required() { ); } +#[test] +fn server_ignores_sni_with_ip_address() { + let mut ch = minimal_client_hello(); + ch.extensions + .push(ClientExtension::read_bytes(&sni_extension(&[b"1.1.1.1"])).unwrap()); + std::println!("{:?}", ch.extensions); + assert_eq!(test_process_client_hello(ch), Ok(())); +} + fn test_process_client_hello(hello: ClientHelloPayload) -> Result<(), Error> { let m = Message { version: ProtocolVersion::TLSv1_2, @@ -52,3 +62,19 @@ fn minimal_client_hello() -> ClientHelloPayload { extensions: vec![ClientExtension::SignatureAlgorithms(vec![])], } } + +fn sni_extension(names: &[&[u8]]) -> Vec { + let mut r = Vec::new(); + ExtensionType::ServerName.encode(&mut r); + let outer = LengthPrefixedBuffer::new(ListLength::U16, &mut r); + let name_items = LengthPrefixedBuffer::new(ListLength::U16, outer.buf); + for name in names { + name_items.buf.push(0); + let host_name = LengthPrefixedBuffer::new(ListLength::U16, name_items.buf); + host_name.buf.extend_from_slice(name); + drop(host_name); + } + drop(name_items); + drop(outer); + r +} diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index e26a98edc46..495b0449c42 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -1542,14 +1542,6 @@ fn client_trims_terminating_dot() { } } -#[test] -fn server_ignores_sni_with_ip_address() { - check_sni_error( - encoding::Extension::new_sni(b"1.1.1.1"), - Error::General("no server certificate chain resolved".to_string()), - ); -} - #[test] fn server_rejects_sni_with_illegal_dns_name() { check_sni_error( From a81e4d106ab0fb0b5365e0d8ba813b385f63f441 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 09:12:28 +0100 Subject: [PATCH 212/403] server::test: port `server_rejects_sni_with_illegal_dns_name` --- rustls/src/server/test.rs | 16 +++++++++++++++- rustls/tests/api.rs | 8 -------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/rustls/src/server/test.rs b/rustls/src/server/test.rs index 09e91d08dcf..52ea61316e2 100644 --- a/rustls/src/server/test.rs +++ b/rustls/src/server/test.rs @@ -10,7 +10,9 @@ use crate::msgs::handshake::{ SessionId, }; use crate::msgs::message::{Message, MessagePayload}; -use crate::{CommonState, Error, HandshakeType, PeerIncompatible, ProtocolVersion, Side}; +use crate::{ + CommonState, Error, HandshakeType, PeerIncompatible, PeerMisbehaved, ProtocolVersion, Side, +}; #[test] fn null_compression_required() { @@ -32,6 +34,18 @@ fn server_ignores_sni_with_ip_address() { 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 + .push(ClientExtension::read_bytes(&sni_extension(&[b"ab@cd.com"])).unwrap()); + 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, diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 495b0449c42..234205f8d46 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -1542,14 +1542,6 @@ fn client_trims_terminating_dot() { } } -#[test] -fn server_rejects_sni_with_illegal_dns_name() { - check_sni_error( - encoding::Extension::new_sni(b"ab@cd.com"), - Error::PeerMisbehaved(PeerMisbehaved::ServerNameMustContainOneHostName), - ); -} - fn check_sni_error(sni_extension: encoding::Extension, expected_error: Error) { for kt in ALL_KEY_TYPES { let mut server_config = make_server_config(*kt); From c332c50f4316ebe2a39723540fe7ca940622463c Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 09:30:40 +0100 Subject: [PATCH 213/403] Lower `test_server_rejects_empty_sni_extension` This moves from an integration test to a unit test of `ClientExtension`. --- rustls/src/msgs/handshake_test.rs | 8 ++++++++ rustls/tests/api.rs | 11 ----------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index f5cb1ae6332..23416865698 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -228,6 +228,14 @@ fn rejects_truncated_sni() { assert!(ClientExtension::read(&mut Reader::init(&bytes)).is_err()); } +#[test] +fn rejects_empty_sni_extension() { + assert_eq!( + ClientExtension::read_bytes(&[0, 0, 0, 2, 0, 0]).unwrap_err(), + InvalidMessage::IllegalEmptyList("ServerNames") + ); +} + #[test] fn can_round_trip_psk_identity() { let bytes = [0, 1, 0x99, 0x11, 0x22, 0x33, 0x44]; diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 234205f8d46..80d969d70e0 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -6263,17 +6263,6 @@ fn test_server_rejects_duplicate_sni_names() { ); } -#[test] -fn test_server_rejects_empty_sni_extension() { - check_sni_error( - encoding::Extension { - typ: ExtensionType::ServerName, - body: encoding::len_u16(vec![]), - }, - Error::InvalidMessage(InvalidMessage::IllegalEmptyList("ServerNames")), - ); -} - #[test] fn test_server_rejects_clients_without_any_kx_groups() { let (_, mut server) = make_pair(KeyType::Rsa2048); From 8639c870eb25ec0f1793259201afa782b0ccce43 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 09:39:48 +0100 Subject: [PATCH 214/403] Lower `test_server_rejects_duplicate_sni_names` This becomes a unit test on `ClientExtension` decoding. --- rustls/src/msgs/handshake_test.rs | 9 ++++++++ rustls/tests/api.rs | 35 ------------------------------- rustls/tests/common/mod.rs | 17 --------------- 3 files changed, 9 insertions(+), 52 deletions(-) diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index 23416865698..e90546bde27 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -236,6 +236,15 @@ fn rejects_empty_sni_extension() { ); } +#[test] +fn rejects_duplicate_names_in_sni_extension() { + assert_eq!( + ClientExtension::read_bytes(&[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]; diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 80d969d70e0..767c94696d9 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -1542,28 +1542,6 @@ fn client_trims_terminating_dot() { } } -fn check_sni_error(sni_extension: encoding::Extension, expected_error: Error) { - for kt in ALL_KEY_TYPES { - let mut server_config = make_server_config(*kt); - server_config.cert_resolver = Arc::new(ServerCheckNoSni {}); - - let mut server = ServerConnection::new(Arc::new(server_config)).unwrap(); - server - .read_tls( - &mut encoding::message_framing( - ContentType::Handshake, - ProtocolVersion::TLSv1_2, - encoding::basic_client_hello(vec![sni_extension.clone()]), - ) - .as_slice(), - ) - .unwrap(); - - assert_eq!(server.process_new_packets(), Err(expected_error.clone()),); - assert_eq!(None, server.server_name()); - } -} - #[cfg(feature = "tls12")] fn check_sigalgs_reduced_by_ciphersuite( kt: KeyType, @@ -6250,19 +6228,6 @@ fn connection_types_are_not_huge() { ); } -#[test] -fn test_server_rejects_duplicate_sni_names() { - let mut body = encoding::Extension::sni_dns_hostname(b"example.com"); - body.extend_from_slice(&encoding::Extension::sni_dns_hostname(b"example.com")); - check_sni_error( - encoding::Extension { - typ: ExtensionType::ServerName, - body: encoding::len_u16(body), - }, - Error::InvalidMessage(InvalidMessage::InvalidServerName), - ); -} - #[test] fn test_server_rejects_clients_without_any_kx_groups() { let (_, mut server) = make_pair(KeyType::Rsa2048); diff --git a/rustls/tests/common/mod.rs b/rustls/tests/common/mod.rs index 34169c32bc4..31c7b2b1fb3 100644 --- a/rustls/tests/common/mod.rs +++ b/rustls/tests/common/mod.rs @@ -1642,23 +1642,6 @@ pub mod encoding { } impl Extension { - pub fn new_sni(name: &[u8]) -> Self { - let body = Self::sni_dns_hostname(name); - let body = len_u16(body); - Self { - typ: ExtensionType::ServerName, - body, - } - } - - pub fn sni_dns_hostname(name: &[u8]) -> Vec { - const SNI_HOSTNAME_TYPE: u8 = 0; - - let mut out = len_u16(name.to_vec()); - out.insert(0, SNI_HOSTNAME_TYPE); - out - } - pub fn new_sig_algs() -> Extension { Extension { typ: ExtensionType::SignatureAlgorithms, From 33187f8a5ff8ab516b14dbe506c3c0f24364a1c2 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 10:52:06 +0100 Subject: [PATCH 215/403] Move `test_no_session_ticket_request_on_tls_1_3` into crate --- rustls/src/client/test.rs | 68 +++++++++++++++++++++++++++++++++++++++ rustls/src/lib.rs | 2 ++ rustls/tests/api.rs | 34 -------------------- 3 files changed, 70 insertions(+), 34 deletions(-) create mode 100644 rustls/src/client/test.rs diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs new file mode 100644 index 00000000000..dbe68d26c8b --- /dev/null +++ b/rustls/src/client/test.rs @@ -0,0 +1,68 @@ +#![cfg(any(feature = "ring", feature = "aws_lc_rs"))] +use std::prelude::v1::*; + +use pki_types::{CertificateDer, ServerName}; + +use crate::client::{ClientConfig, ClientConnection, Resumption, Tls12Resumption}; +use crate::msgs::codec::Reader; +use crate::msgs::handshake::{ClientHelloPayload, HandshakeMessagePayload, HandshakePayload}; +use crate::msgs::message::{Message, MessagePayload, OutboundOpaqueMessage}; +use crate::{Error, RootCertStore}; + +#[macro_rules_attribute::apply(test_for_each_provider)] +mod tests { + use super::super::*; + use crate::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.ticket_extension().is_none()); + } +} + +fn client_hello_sent_for_config(config: ClientConfig) -> Result { + 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 { + payload: 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/rustls/src/lib.rs b/rustls/src/lib.rs index cf428cef27f..1898ba2f40d 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -588,6 +588,8 @@ pub mod client { mod ech; pub(super) mod handy; mod hs; + #[cfg(test)] + mod test; #[cfg(feature = "tls12")] mod tls12; mod tls13; diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 767c94696d9..11ee94666b7 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -6259,40 +6259,6 @@ fn test_server_rejects_clients_without_any_kx_groups() { ); } -/// 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() { - /// Panics if TLS 1.2 session_ticket(35) extension is detected. - /// - /// Does not actually alter the payload. - fn panic_on_session_ticket(msg: &mut Message) -> Altered { - let MessagePayload::Handshake { parsed, encoded: _ } = &msg.payload else { - return Altered::InPlace; - }; - - let HandshakePayload::ClientHello(ch) = &parsed.payload else { - return Altered::InPlace; - }; - - for ext in &ch.extensions { - if matches!(ext, ClientExtension::SessionTicket(_)) { - panic!("TLS 1.2 session_ticket extension in TLS 1.3 handshake detected."); - } - } - - Altered::InPlace - } - - let client_config = - make_client_config_with_versions(KeyType::Rsa2048, &[&rustls::version::TLS13]); - let server_config = make_server_config(KeyType::Rsa2048); - - let (client, server) = make_pair_for_configs(client_config, server_config); - let (mut client, mut server) = (client.into(), server.into()); - transfer_altered(&mut client, panic_on_session_ticket, &mut server); -} - #[test] fn test_server_rejects_clients_without_any_kx_group_overlap() { for version in rustls::ALL_VERSIONS { From c628fae92721bbf0ee078cae67b728b77ef45c2b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 12:05:02 +0100 Subject: [PATCH 216/403] Make provider explicit in RPK test functions --- rustls/tests/api.rs | 28 ++++++---- rustls/tests/client_cert_verifier.rs | 12 +++-- rustls/tests/common/mod.rs | 76 ++++++++++++++++++++-------- rustls/tests/server_cert_verifier.rs | 2 +- 4 files changed, 81 insertions(+), 37 deletions(-) diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 11ee94666b7..3230274e245 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -60,9 +60,10 @@ mod test_raw_keys { #[test] fn successful_raw_key_connection_and_correct_peer_certificates() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let client_config = make_client_config_with_raw_key_support(*kt); - let server_config = make_server_config_with_raw_key_support(*kt); + let client_config = make_client_config_with_raw_key_support(*kt, &provider); + let server_config = make_server_config_with_raw_key_support(*kt, &provider); let (mut client, mut server) = make_pair_for_configs(client_config, server_config); do_handshake(&mut client, &mut server); @@ -95,9 +96,10 @@ mod test_raw_keys { #[test] fn correct_certificate_type_extensions_from_client_hello() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let client_config = make_client_config_with_raw_key_support(*kt); - let mut server_config = make_server_config_with_raw_key_support(*kt); + let client_config = make_client_config_with_raw_key_support(*kt, &provider); + let mut server_config = make_server_config_with_raw_key_support(*kt, &provider); server_config.cert_resolver = Arc::new(ServerCheckCertResolve { expected_client_cert_types: Some(vec![CertificateType::RawPublicKey]), @@ -113,8 +115,9 @@ mod test_raw_keys { #[test] fn only_client_supports_raw_keys() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let client_config_rpk = make_client_config_with_raw_key_support(*kt); + let client_config_rpk = make_client_config_with_raw_key_support(*kt, &provider); let server_config = make_server_config(*kt); let (mut client_rpk, mut server) = @@ -139,9 +142,10 @@ mod test_raw_keys { #[test] fn only_server_supports_raw_keys() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { let client_config = make_client_config_with_versions(*kt, &[&rustls::version::TLS13]); - let server_config_rpk = make_server_config_with_raw_key_support(*kt); + let server_config_rpk = make_server_config_with_raw_key_support(*kt, &provider); let (mut client, mut server_rpk) = make_pair_for_configs(client_config, server_config_rpk); @@ -188,10 +192,11 @@ mod test_raw_keys { client_cert_types: Option<&Vec>, expected_result: Result<(), ErrorFromPeer>, ) { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { let client_config = Arc::new(make_client_config(*kt)); let server_config_rpk = match server_requires_raw_keys { - true => Arc::new(make_server_config_with_raw_key_support(*kt)), + true => Arc::new(make_server_config_with_raw_key_support(*kt, &provider)), false => Arc::new(make_server_config(*kt)), }; @@ -211,12 +216,13 @@ mod test_raw_keys { #[test] fn incorrectly_alter_server_hello() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { let supported_suite = cipher_suite::TLS13_AES_256_GCM_SHA384; // Alter Server Hello server certificate extension and expect IncorrectCertificateTypeExtension error - let client_config_rpk = make_client_config_with_raw_key_support(*kt); - let server_config_rpk = make_server_config_with_raw_key_support(*kt); + let client_config_rpk = make_client_config_with_raw_key_support(*kt, &provider); + let server_config_rpk = make_server_config_with_raw_key_support(*kt, &provider); add_keylog_and_do_altered_handshake( client_config_rpk, server_config_rpk, @@ -227,8 +233,8 @@ mod test_raw_keys { ); // Alter Server Hello client certificate extension and expect IncorrectCertificateTypeExtension error - let client_config_rpk = make_client_config_with_raw_key_support(*kt); - let server_config_rpk = make_server_config_with_raw_key_support(*kt); + let client_config_rpk = make_client_config_with_raw_key_support(*kt, &provider); + let server_config_rpk = make_server_config_with_raw_key_support(*kt, &provider); add_keylog_and_do_altered_handshake( client_config_rpk, server_config_rpk, diff --git a/rustls/tests/client_cert_verifier.rs b/rustls/tests/client_cert_verifier.rs index a0915d9d316..ea9ef1a121e 100644 --- a/rustls/tests/client_cert_verifier.rs +++ b/rustls/tests/client_cert_verifier.rs @@ -46,8 +46,9 @@ fn server_config_with_verifier( #[test] // Happy path, we resolve to a root, it is verified OK, should be able to connect fn client_verifier_works() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES.iter() { - let client_verifier = MockClientVerifier::new(ver_ok, *kt); + let client_verifier = MockClientVerifier::new(ver_ok, *kt, &provider); let server_config = server_config_with_verifier(*kt, client_verifier); let server_config = Arc::new(server_config); @@ -64,8 +65,9 @@ fn client_verifier_works() { // Server offers no verification schemes #[test] fn client_verifier_no_schemes() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES.iter() { - let mut client_verifier = MockClientVerifier::new(ver_ok, *kt); + let mut client_verifier = MockClientVerifier::new(ver_ok, *kt, &provider); client_verifier.offered_schemes = Some(vec![]); let server_config = server_config_with_verifier(*kt, client_verifier); let server_config = Arc::new(server_config); @@ -88,8 +90,9 @@ fn client_verifier_no_schemes() { // If we do have a root, we must do auth #[test] fn client_verifier_no_auth_yes_root() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES.iter() { - let client_verifier = MockClientVerifier::new(ver_unreachable, *kt); + let client_verifier = MockClientVerifier::new(ver_unreachable, *kt, &provider); let server_config = server_config_with_verifier(*kt, client_verifier); let server_config = Arc::new(server_config); @@ -115,8 +118,9 @@ fn client_verifier_no_auth_yes_root() { #[test] // Triple checks we propagate the rustls::Error through fn client_verifier_fails_properly() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES.iter() { - let client_verifier = MockClientVerifier::new(ver_err, *kt); + let client_verifier = MockClientVerifier::new(ver_err, *kt, &provider); let server_config = server_config_with_verifier(*kt, client_verifier); let server_config = Arc::new(server_config); diff --git a/rustls/tests/common/mod.rs b/rustls/tests/common/mod.rs index 31c7b2b1fb3..aa40837c8b9 100644 --- a/rustls/tests/common/mod.rs +++ b/rustls/tests/common/mod.rs @@ -17,7 +17,9 @@ use rustls::client::{ WebPkiServerVerifier, }; use rustls::crypto::cipher::{InboundOpaqueMessage, MessageDecrypter, MessageEncrypter}; -use rustls::crypto::{CryptoProvider, verify_tls13_signature_with_raw_key}; +use rustls::crypto::{ + CryptoProvider, WebPkiSupportedAlgorithms, verify_tls13_signature_with_raw_key, +}; use rustls::internal::msgs::codec::{Codec, Reader}; use rustls::internal::msgs::message::{Message, OutboundOpaqueMessage, PlainMessage}; use rustls::server::danger::{ClientCertVerified, ClientCertVerifier}; @@ -388,8 +390,11 @@ impl KeyType { SubjectPublicKeyInfoDer::from_pem_slice(self.bytes_for("client.spki.pem")).unwrap() } - pub fn get_certified_client_key(&self) -> Result, Error> { - let private_key = provider::default_provider() + pub fn get_certified_client_key( + &self, + provider: &CryptoProvider, + ) -> Result, Error> { + let private_key = provider .key_provider .load_private_key(self.get_client_key())?; let public_key = private_key @@ -402,8 +407,11 @@ impl KeyType { ))) } - pub fn certified_key_with_raw_pub_key(&self) -> Result, Error> { - let private_key = provider::default_provider() + pub fn certified_key_with_raw_pub_key( + &self, + provider: &CryptoProvider, + ) -> Result, Error> { + let private_key = provider .key_provider .load_private_key(self.get_key())?; let public_key = private_key @@ -416,8 +424,11 @@ impl KeyType { ))) } - pub fn certified_key_with_cert_chain(&self) -> Result, Error> { - let private_key = provider::default_provider() + pub fn certified_key_with_cert_chain( + &self, + provider: &CryptoProvider, + ) -> Result, Error> { + let private_key = provider .key_provider .load_private_key(self.get_key())?; Ok(Arc::new(CertifiedKey::new(self.get_chain(), private_key))) @@ -584,10 +595,14 @@ pub fn make_server_config_with_client_verifier( .unwrap() } -pub fn make_server_config_with_raw_key_support(kt: KeyType) -> ServerConfig { - let mut client_verifier = MockClientVerifier::new(|| Ok(ClientCertVerified::assertion()), kt); +pub fn make_server_config_with_raw_key_support( + kt: KeyType, + provider: &CryptoProvider, +) -> ServerConfig { + let mut client_verifier = + MockClientVerifier::new(|| Ok(ClientCertVerified::assertion()), kt, provider); let server_cert_resolver = Arc::new(AlwaysResolvesServerRawPublicKeys::new( - kt.certified_key_with_raw_pub_key() + kt.certified_key_with_raw_pub_key(provider) .unwrap(), )); client_verifier.expect_raw_public_keys = true; @@ -597,10 +612,14 @@ pub fn make_server_config_with_raw_key_support(kt: KeyType) -> ServerConfig { .with_cert_resolver(server_cert_resolver) } -pub fn make_client_config_with_raw_key_support(kt: KeyType) -> ClientConfig { - let server_verifier = Arc::new(MockServerVerifier::expects_raw_public_keys()); +pub fn make_client_config_with_raw_key_support( + kt: KeyType, + provider: &CryptoProvider, +) -> ClientConfig { + let server_verifier = Arc::new(MockServerVerifier::expects_raw_public_keys(provider)); let client_cert_resolver = Arc::new(AlwaysResolvesClientRawPublicKeys::new( - kt.get_certified_client_key().unwrap(), + kt.get_certified_client_key(provider) + .unwrap(), )); // We don't support tls1.2 for Raw Public Keys, hence the version is hard-coded. client_config_builder_with_versions(&[&rustls::version::TLS13]) @@ -612,15 +631,17 @@ pub fn make_client_config_with_raw_key_support(kt: KeyType) -> ClientConfig { pub fn make_client_config_with_cipher_suite_and_raw_key_support( kt: KeyType, cipher_suite: SupportedCipherSuite, + provider: &CryptoProvider, ) -> ClientConfig { - let server_verifier = Arc::new(MockServerVerifier::expects_raw_public_keys()); + let server_verifier = Arc::new(MockServerVerifier::expects_raw_public_keys(provider)); let client_cert_resolver = Arc::new(AlwaysResolvesClientRawPublicKeys::new( - kt.get_certified_client_key().unwrap(), + kt.get_certified_client_key(provider) + .unwrap(), )); ClientConfig::builder_with_provider( CryptoProvider { cipher_suites: vec![cipher_suite], - ..provider::default_provider() + ..provider.clone() } .into(), ) @@ -1072,6 +1093,7 @@ pub struct MockServerVerifier { signature_schemes: Vec, expected_ocsp_response: Option>, requires_raw_public_keys: bool, + raw_public_key_algorithms: Option, } impl ServerCertVerifier for MockServerVerifier { @@ -1121,7 +1143,9 @@ impl ServerCertVerifier for MockServerVerifier { message, &SubjectPublicKeyInfoDer::from(cert.as_ref()), dss, - &provider::default_provider().signature_verification_algorithms, + self.raw_public_key_algorithms + .as_ref() + .unwrap(), ), _ => Ok(HandshakeSignatureValid::assertion()), } @@ -1179,9 +1203,10 @@ impl MockServerVerifier { } } - pub fn expects_raw_public_keys() -> Self { + pub fn expects_raw_public_keys(provider: &CryptoProvider) -> Self { MockServerVerifier { requires_raw_public_keys: true, + raw_public_key_algorithms: Some(provider.signature_verification_algorithms), ..Default::default() } } @@ -1203,6 +1228,7 @@ impl Default for MockServerVerifier { ], expected_ocsp_response: None, requires_raw_public_keys: false, + raw_public_key_algorithms: None, } } } @@ -1213,12 +1239,17 @@ pub struct MockClientVerifier { pub subjects: Vec, pub mandatory: bool, pub offered_schemes: Option>, - pub expect_raw_public_keys: bool, + expect_raw_public_keys: bool, + raw_public_key_algorithms: Option, parent: Arc, } impl MockClientVerifier { - pub fn new(verified: fn() -> Result, kt: KeyType) -> Self { + pub fn new( + verified: fn() -> Result, + kt: KeyType, + provider: &CryptoProvider, + ) -> Self { Self { parent: webpki_client_verifier_builder(get_client_root_store(kt)) .build() @@ -1228,6 +1259,7 @@ impl MockClientVerifier { mandatory: true, offered_schemes: None, expect_raw_public_keys: false, + raw_public_key_algorithms: Some(provider.signature_verification_algorithms), } } } @@ -1275,7 +1307,9 @@ impl ClientCertVerifier for MockClientVerifier { message, &SubjectPublicKeyInfoDer::from(cert.as_ref()), dss, - &provider::default_provider().signature_verification_algorithms, + self.raw_public_key_algorithms + .as_ref() + .unwrap(), ) } else { self.parent diff --git a/rustls/tests/server_cert_verifier.rs b/rustls/tests/server_cert_verifier.rs index 1f0a6bb7d29..d0eadac3863 100644 --- a/rustls/tests/server_cert_verifier.rs +++ b/rustls/tests/server_cert_verifier.rs @@ -238,7 +238,7 @@ fn client_can_request_certain_trusted_cas() { kt.ca_distinguished_name() .to_vec() .into(), - kt.certified_key_with_cert_chain() + kt.certified_key_with_cert_chain(&provider::default_provider()) .unwrap(), ) }) From fa52d0c185a80b525abbada5f2bb6fef8aaa50bd Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 12:22:37 +0100 Subject: [PATCH 217/403] Make provider explicit in general testing helpers --- rustls/benches/benchmarks.rs | 2 +- rustls/tests/api.rs | 938 +++++++++++++++++---------- rustls/tests/client_cert_verifier.rs | 13 +- rustls/tests/common/mod.rs | 94 ++- rustls/tests/key_log_file_env.rs | 12 +- rustls/tests/server_cert_verifier.rs | 48 +- rustls/tests/unbuffered.rs | 86 ++- 7 files changed, 766 insertions(+), 427 deletions(-) diff --git a/rustls/benches/benchmarks.rs b/rustls/benches/benchmarks.rs index 28d596ff3c5..85c2013ff90 100644 --- a/rustls/benches/benchmarks.rs +++ b/rustls/benches/benchmarks.rs @@ -13,7 +13,7 @@ use rustls::ServerConnection; use test_utils::*; fn bench_ewouldblock(c: &mut Bencher) { - let server_config = make_server_config(KeyType::Rsa2048); + 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)); diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 3230274e245..923c380c2ba 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -118,7 +118,7 @@ mod test_raw_keys { let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { let client_config_rpk = make_client_config_with_raw_key_support(*kt, &provider); - let server_config = make_server_config(*kt); + let server_config = make_server_config(*kt, &provider); let (mut client_rpk, mut server) = make_pair_for_configs(client_config_rpk, server_config); @@ -144,7 +144,8 @@ mod test_raw_keys { fn only_server_supports_raw_keys() { let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let client_config = make_client_config_with_versions(*kt, &[&rustls::version::TLS13]); + let client_config = + make_client_config_with_versions(*kt, &[&rustls::version::TLS13], &provider); let server_config_rpk = make_server_config_with_raw_key_support(*kt, &provider); let (mut client, mut server_rpk) = @@ -194,10 +195,10 @@ mod test_raw_keys { ) { let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let client_config = Arc::new(make_client_config(*kt)); + let client_config = Arc::new(make_client_config(*kt, &provider)); let server_config_rpk = match server_requires_raw_keys { true => Arc::new(make_server_config_with_raw_key_support(*kt, &provider)), - false => Arc::new(make_server_config(*kt)), + false => Arc::new(make_server_config(*kt, &provider)), }; // Alter Client Hello client certificate extension @@ -245,8 +246,8 @@ mod test_raw_keys { ); // Alter Server Hello server certificate extension and expect UnexpectedCertificateTypeExtension error - let client_config = make_client_config(*kt); - let server_config_rpk = make_server_config(*kt); + let client_config = make_client_config(*kt, &provider); + let server_config_rpk = make_server_config(*kt, &provider); add_keylog_and_do_altered_handshake( client_config, server_config_rpk, @@ -257,8 +258,8 @@ mod test_raw_keys { ); // Alter Server Hello client certificate extension and expect UnexpectedCertificateTypeExtension error - let client_config = make_client_config(*kt); - let server_config_rpk = make_server_config(*kt); + let client_config = make_client_config(*kt, &provider); + let server_config_rpk = make_server_config(*kt, &provider); add_keylog_and_do_altered_handshake( client_config, server_config_rpk, @@ -456,13 +457,15 @@ fn alpn_test_error( agreed: Option<&[u8]>, expected_error: Option, ) { - let mut server_config = make_server_config(KeyType::Rsa2048); + let provider = provider::default_provider(); + let mut server_config = make_server_config(KeyType::Rsa2048, &provider); server_config.alpn_protocols = server_protos; let server_config = Arc::new(server_config); for version in rustls::ALL_VERSIONS { - let mut client_config = make_client_config_with_versions(KeyType::Rsa2048, &[version]); + let mut client_config = + make_client_config_with_versions(KeyType::Rsa2048, &[version], &provider); client_config .alpn_protocols .clone_from(&client_protos); @@ -520,12 +523,13 @@ fn alpn() { #[test] fn connection_level_alpn_protocols() { - let mut server_config = make_server_config(KeyType::Rsa2048); + let provider = provider::default_provider(); + let mut server_config = make_server_config(KeyType::Rsa2048, &provider); server_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()]; let server_config = Arc::new(server_config); // Config specifies `h2` - let mut client_config = make_client_config(KeyType::Rsa2048); + let mut client_config = make_client_config(KeyType::Rsa2048, &provider); client_config.alpn_protocols = vec![b"h2".to_vec()]; let client_config = Arc::new(client_config); @@ -553,6 +557,7 @@ fn version_test( server_versions: &[&'static rustls::SupportedProtocolVersion], result: Option, ) { + let provider = provider::default_provider(); let client_versions = if client_versions.is_empty() { rustls::ALL_VERSIONS } else { @@ -564,8 +569,10 @@ fn version_test( server_versions }; - let client_config = make_client_config_with_versions(KeyType::Rsa2048, client_versions); - let server_config = make_server_config_with_versions(KeyType::Rsa2048, server_versions); + let client_config = + make_client_config_with_versions(KeyType::Rsa2048, client_versions, &provider); + let server_config = + make_server_config_with_versions(KeyType::Rsa2048, server_versions, &provider); println!("version {client_versions:?} {server_versions:?} -> {result:?}"); @@ -797,10 +804,12 @@ fn config_builder_for_server_with_time() { #[test] fn buffered_client_data_sent() { - let server_config = Arc::new(make_server_config(KeyType::Rsa2048)); + let provider = provider::default_provider(); + let server_config = Arc::new(make_server_config(KeyType::Rsa2048, &provider)); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions(KeyType::Rsa2048, &[version]); + let client_config = + make_client_config_with_versions(KeyType::Rsa2048, &[version], &provider); let (mut client, mut server) = make_pair_for_arc_configs(&Arc::new(client_config), &server_config); @@ -816,10 +825,12 @@ fn buffered_client_data_sent() { #[test] fn buffered_server_data_sent() { - let server_config = Arc::new(make_server_config(KeyType::Rsa2048)); + let provider = provider::default_provider(); + let server_config = Arc::new(make_server_config(KeyType::Rsa2048, &provider)); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions(KeyType::Rsa2048, &[version]); + let client_config = + make_client_config_with_versions(KeyType::Rsa2048, &[version], &provider); let (mut client, mut server) = make_pair_for_arc_configs(&Arc::new(client_config), &server_config); @@ -835,10 +846,12 @@ fn buffered_server_data_sent() { #[test] fn buffered_both_data_sent() { - let server_config = Arc::new(make_server_config(KeyType::Rsa2048)); + let provider = provider::default_provider(); + let server_config = Arc::new(make_server_config(KeyType::Rsa2048, &provider)); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions(KeyType::Rsa2048, &[version]); + let client_config = + make_client_config_with_versions(KeyType::Rsa2048, &[version], &provider); let (mut client, mut server) = make_pair_for_arc_configs(&Arc::new(client_config), &server_config); @@ -871,11 +884,12 @@ fn buffered_both_data_sent() { #[test] fn client_can_get_server_cert() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions(*kt, &[version]); + let client_config = make_client_config_with_versions(*kt, &[version], &provider); let (mut client, mut server) = - make_pair_for_configs(client_config, make_server_config(*kt)); + make_pair_for_configs(client_config, make_server_config(*kt, &provider)); do_handshake(&mut client, &mut server); let certs = client.peer_certificates(); @@ -886,10 +900,11 @@ fn client_can_get_server_cert() { #[test] fn client_can_get_server_cert_after_resumption() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let server_config = make_server_config(*kt); + let server_config = make_server_config(*kt, &provider); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions(*kt, &[version]); + let client_config = make_client_config_with_versions(*kt, &[version], &provider); let (mut client, mut server) = make_pair_for_configs(client_config.clone(), server_config.clone()); do_handshake(&mut client, &mut server); @@ -911,13 +926,14 @@ fn client_can_get_server_cert_after_resumption() { #[test] fn client_only_attempts_resumption_with_compatible_security() { + let provider = provider::default_provider(); let kt = KeyType::Rsa2048; CountingLogger::install(); CountingLogger::reset(); - let server_config = make_server_config(kt); + let server_config = make_server_config(kt, &provider); for version in rustls::ALL_VERSIONS { - let base_client_config = make_client_config_with_versions(kt, &[version]); + let base_client_config = make_client_config_with_versions(kt, &[version], &provider); let (mut client, mut server) = make_pair_for_configs(base_client_config.clone(), server_config.clone()); do_handshake(&mut client, &mut server); @@ -939,7 +955,8 @@ fn client_only_attempts_resumption_with_compatible_security() { // disallowed case: unmatching `client_auth_cert_resolver` let mut client_config = ClientConfig::clone(&base_client_config); client_config.client_auth_cert_resolver = - make_client_config_with_versions_with_auth(kt, &[version]).client_auth_cert_resolver; + make_client_config_with_versions_with_auth(kt, &[version], &provider) + .client_auth_cert_resolver; CountingLogger::reset(); let (mut client, mut server) = @@ -954,7 +971,8 @@ fn client_only_attempts_resumption_with_compatible_security() { })); // disallowed case: unmatching `verifier` - let mut client_config = make_client_config_with_versions_with_auth(kt, &[version]); + let mut client_config = + make_client_config_with_versions_with_auth(kt, &[version], &provider); client_config.resumption = base_client_config.resumption.clone(); client_config.client_auth_cert_resolver = Arc::clone(&base_client_config.client_auth_cert_resolver); @@ -976,11 +994,15 @@ fn client_only_attempts_resumption_with_compatible_security() { #[test] fn server_can_get_client_cert() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let server_config = Arc::new(make_server_config_with_mandatory_client_auth(*kt)); + let server_config = Arc::new(make_server_config_with_mandatory_client_auth( + *kt, &provider, + )); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions_with_auth(*kt, &[version]); + let client_config = + make_client_config_with_versions_with_auth(*kt, &[version], &provider); let (mut client, mut server) = make_pair_for_arc_configs(&Arc::new(client_config), &server_config); do_handshake(&mut client, &mut server); @@ -993,11 +1015,15 @@ fn server_can_get_client_cert() { #[test] fn server_can_get_client_cert_after_resumption() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let server_config = Arc::new(make_server_config_with_mandatory_client_auth(*kt)); + let server_config = Arc::new(make_server_config_with_mandatory_client_auth( + *kt, &provider, + )); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions_with_auth(*kt, &[version]); + let client_config = + make_client_config_with_versions_with_auth(*kt, &[version], &provider); let client_config = Arc::new(client_config); let (mut client, mut server) = make_pair_for_arc_configs(&client_config, &server_config); @@ -1015,10 +1041,11 @@ fn server_can_get_client_cert_after_resumption() { #[test] fn resumption_combinations() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let server_config = make_server_config(*kt); + let server_config = make_server_config(*kt, &provider); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions(*kt, &[version]); + let client_config = make_client_config_with_versions(*kt, &[version], &provider); let (mut client, mut server) = make_pair_for_configs(client_config.clone(), server_config.clone()); do_handshake(&mut client, &mut server); @@ -1094,7 +1121,10 @@ fn test_config_builders_debug() { .into(), ); let _ = format!("{b:?}"); - let b = server_config_builder_with_versions(&[&rustls::version::TLS13]); + let b = server_config_builder_with_versions( + &[&rustls::version::TLS13], + &provider::default_provider(), + ); let _ = format!("{b:?}"); let b = b.with_no_client_auth(); let _ = format!("{b:?}"); @@ -1108,7 +1138,10 @@ fn test_config_builders_debug() { .into(), ); let _ = format!("{b:?}"); - let b = client_config_builder_with_versions(&[&rustls::version::TLS13]); + let b = client_config_builder_with_versions( + &[&rustls::version::TLS13], + &provider::default_provider(), + ); let _ = format!("{b:?}"); } @@ -1118,15 +1151,16 @@ fn test_config_builders_debug() { /// certificate and not being given one. #[test] fn server_allow_any_anonymous_or_authenticated_client() { + let provider = provider::default_provider(); let kt = KeyType::Rsa2048; for client_cert_chain in [None, Some(kt.get_client_chain())] { let client_auth_roots = get_client_root_store(kt); - let client_auth = webpki_client_verifier_builder(client_auth_roots.clone()) + let client_auth = webpki_client_verifier_builder(client_auth_roots.clone(), &provider) .allow_unauthenticated() .build() .unwrap(); - let server_config = server_config_builder() + let server_config = server_config_builder(&provider) .with_client_cert_verifier(client_auth) .with_single_cert(kt.get_chain(), kt.get_key()) .unwrap(); @@ -1134,9 +1168,9 @@ fn server_allow_any_anonymous_or_authenticated_client() { for version in rustls::ALL_VERSIONS { let client_config = if client_cert_chain.is_some() { - make_client_config_with_versions_with_auth(kt, &[version]) + make_client_config_with_versions_with_auth(kt, &[version], &provider) } else { - make_client_config_with_versions(kt, &[version]) + make_client_config_with_versions(kt, &[version], &provider) }; let (mut client, mut server) = make_pair_for_arc_configs(&Arc::new(client_config), &server_config); @@ -1155,11 +1189,12 @@ fn check_read_and_close(reader: &mut dyn io::Read, expect: &[u8]) { #[test] fn server_close_notify() { + let provider = provider::default_provider(); let kt = KeyType::Rsa2048; - let server_config = Arc::new(make_server_config_with_mandatory_client_auth(kt)); + let server_config = Arc::new(make_server_config_with_mandatory_client_auth(kt, &provider)); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions_with_auth(kt, &[version]); + let client_config = make_client_config_with_versions_with_auth(kt, &[version], &provider); let (mut client, mut server) = make_pair_for_arc_configs(&Arc::new(client_config), &server_config); do_handshake(&mut client, &mut server); @@ -1194,11 +1229,12 @@ fn server_close_notify() { #[test] fn client_close_notify() { + let provider = provider::default_provider(); let kt = KeyType::Rsa2048; - let server_config = Arc::new(make_server_config_with_mandatory_client_auth(kt)); + let server_config = Arc::new(make_server_config_with_mandatory_client_auth(kt, &provider)); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions_with_auth(kt, &[version]); + let client_config = make_client_config_with_versions_with_auth(kt, &[version], &provider); let (mut client, mut server) = make_pair_for_arc_configs(&Arc::new(client_config), &server_config); do_handshake(&mut client, &mut server); @@ -1233,11 +1269,12 @@ fn client_close_notify() { #[test] fn server_closes_uncleanly() { + let provider = provider::default_provider(); let kt = KeyType::Rsa2048; - let server_config = Arc::new(make_server_config(kt)); + let server_config = Arc::new(make_server_config(kt, &provider)); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions(kt, &[version]); + let client_config = make_client_config_with_versions(kt, &[version], &provider); let (mut client, mut server) = make_pair_for_arc_configs(&Arc::new(client_config), &server_config); do_handshake(&mut client, &mut server); @@ -1278,11 +1315,12 @@ fn server_closes_uncleanly() { #[test] fn client_closes_uncleanly() { + let provider = provider::default_provider(); let kt = KeyType::Rsa2048; - let server_config = Arc::new(make_server_config(kt)); + let server_config = Arc::new(make_server_config(kt, &provider)); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions(kt, &[version]); + let client_config = make_client_config_with_versions(kt, &[version], &provider); let (mut client, mut server) = make_pair_for_arc_configs(&Arc::new(client_config), &server_config); do_handshake(&mut client, &mut server); @@ -1323,7 +1361,7 @@ fn client_closes_uncleanly() { #[test] fn test_tls13_valid_early_plaintext_alert() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); // Perform the start of a TLS 1.3 handshake, sending a client hello to the server. // The client will not have written a CCS or any encrypted messages to the server yet. @@ -1352,7 +1390,7 @@ fn test_tls13_valid_early_plaintext_alert() { #[test] fn test_tls13_too_short_early_plaintext_alert() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); // Perform the start of a TLS 1.3 handshake, sending a client hello to the server. // The client will not have written a CCS or any encrypted messages to the server yet. @@ -1375,7 +1413,7 @@ fn test_tls13_too_short_early_plaintext_alert() { #[test] fn test_tls13_late_plaintext_alert() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); // Complete a bi-directional TLS1.3 handshake. After this point no plaintext messages // should occur. @@ -1488,9 +1526,10 @@ impl ResolvesServerCert for ServerCheckCertResolve { #[test] fn server_cert_resolve_with_sni() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let client_config = make_client_config(*kt); - let mut server_config = make_server_config(*kt); + let client_config = make_client_config(*kt, &provider); + let mut server_config = make_server_config(*kt, &provider); server_config.cert_resolver = Arc::new(ServerCheckCertResolve { expected_sni: Some("the-value-from-sni".into()), @@ -1509,11 +1548,12 @@ fn server_cert_resolve_with_sni() { #[test] fn server_cert_resolve_with_alpn() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let mut client_config = make_client_config(*kt); + let mut client_config = make_client_config(*kt, &provider); client_config.alpn_protocols = vec!["foo".into(), "bar".into()]; - let mut server_config = make_server_config(*kt); + let mut server_config = make_server_config(*kt, &provider); server_config.cert_resolver = Arc::new(ServerCheckCertResolve { expected_alpn: Some(vec![b"foo".to_vec(), b"bar".to_vec()]), ..Default::default() @@ -1530,9 +1570,10 @@ fn server_cert_resolve_with_alpn() { #[test] fn client_trims_terminating_dot() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let client_config = make_client_config(*kt); - let mut server_config = make_server_config(*kt); + let client_config = make_client_config(*kt, &provider); + let mut server_config = make_server_config(*kt, &provider); server_config.cert_resolver = Arc::new(ServerCheckCertResolve { expected_sni: Some("some-host.com".into()), @@ -1567,7 +1608,7 @@ fn check_sigalgs_reduced_by_ciphersuite( .unwrap(), ); - let mut server_config = make_server_config(kt); + let mut server_config = make_server_config(kt, &provider::default_provider()); server_config.cert_resolver = Arc::new(ServerCheckCertResolve { expected_sigalgs: Some(expected_sigalgs), @@ -1636,13 +1677,14 @@ impl ResolvesServerCert for ServerCheckNoSni { #[test] fn client_with_sni_disabled_does_not_send_sni() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let mut server_config = make_server_config(*kt); + let mut server_config = make_server_config(*kt, &provider); server_config.cert_resolver = Arc::new(ServerCheckNoSni {}); let server_config = Arc::new(server_config); for version in rustls::ALL_VERSIONS { - let mut client_config = make_client_config_with_versions(*kt, &[version]); + let mut client_config = make_client_config_with_versions(*kt, &[version], &provider); client_config.enable_sni = false; let mut client = @@ -1658,11 +1700,12 @@ fn client_with_sni_disabled_does_not_send_sni() { #[test] fn client_checks_server_certificate_with_given_name() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let server_config = Arc::new(make_server_config(*kt)); + let server_config = Arc::new(make_server_config(*kt, &provider)); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions(*kt, &[version]); + let client_config = make_client_config_with_versions(*kt, &[version], &provider); let mut client = ClientConnection::new( Arc::new(client_config), server_name("not-the-right-hostname.com"), @@ -1693,11 +1736,13 @@ fn client_checks_server_certificate_with_given_ip_address() { do_handshake_until_error(&mut client, &mut server) } + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let server_config = Arc::new(make_server_config(*kt)); + let server_config = Arc::new(make_server_config(*kt, &provider)); for version in rustls::ALL_VERSIONS { - let client_config = Arc::new(make_client_config_with_versions(*kt, &[version])); + let client_config = + Arc::new(make_client_config_with_versions(*kt, &[version], &provider)); // positive ipv4 case assert_eq!( @@ -1732,17 +1777,19 @@ fn client_checks_server_certificate_with_given_ip_address() { #[test] fn client_check_server_certificate_ee_revoked() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let server_config = Arc::new(make_server_config(*kt)); + let server_config = Arc::new(make_server_config(*kt, &provider)); // Setup a server verifier that will check the EE certificate's revocation status. let crls = vec![kt.end_entity_crl()]; - let builder = webpki_server_verifier_builder(get_client_root_store(*kt)) + let builder = webpki_server_verifier_builder(get_client_root_store(*kt), &provider) .with_crls(crls) .only_check_end_entity_revocation(); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_verifier(&[version], builder.clone()); + let client_config = + make_client_config_with_verifier(&[version], builder.clone(), &provider); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); @@ -1761,26 +1808,32 @@ fn client_check_server_certificate_ee_revoked() { #[test] fn client_check_server_certificate_ee_unknown_revocation() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let server_config = Arc::new(make_server_config(*kt)); + let server_config = Arc::new(make_server_config(*kt, &provider)); // Setup a server verifier builder that will check the EE certificate's revocation status, but not // allow unknown revocation status (the default). We'll provide CRLs that are not relevant // to the EE cert to ensure its status is unknown. let unrelated_crls = vec![kt.intermediate_crl()]; - let forbid_unknown_verifier = webpki_server_verifier_builder(get_client_root_store(*kt)) - .with_crls(unrelated_crls.clone()) - .only_check_end_entity_revocation(); + let forbid_unknown_verifier = + webpki_server_verifier_builder(get_client_root_store(*kt), &provider) + .with_crls(unrelated_crls.clone()) + .only_check_end_entity_revocation(); // Also set up a verifier builder that will allow unknown revocation status. - let allow_unknown_verifier = webpki_server_verifier_builder(get_client_root_store(*kt)) - .with_crls(unrelated_crls) - .only_check_end_entity_revocation() - .allow_unknown_revocation_status(); + let allow_unknown_verifier = + webpki_server_verifier_builder(get_client_root_store(*kt), &provider) + .with_crls(unrelated_crls) + .only_check_end_entity_revocation() + .allow_unknown_revocation_status(); for version in rustls::ALL_VERSIONS { - let client_config = - make_client_config_with_verifier(&[version], forbid_unknown_verifier.clone()); + let client_config = make_client_config_with_verifier( + &[version], + forbid_unknown_verifier.clone(), + &provider, + ); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); @@ -1796,8 +1849,11 @@ fn client_check_server_certificate_ee_unknown_revocation() { ); // We expect if we use the allow_unknown_verifier that the handshake will not fail. - let client_config = - make_client_config_with_verifier(&[version], allow_unknown_verifier.clone()); + let client_config = make_client_config_with_verifier( + &[version], + allow_unknown_verifier.clone(), + &provider, + ); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); @@ -1809,28 +1865,33 @@ fn client_check_server_certificate_ee_unknown_revocation() { #[test] fn client_check_server_certificate_intermediate_revoked() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let server_config = Arc::new(make_server_config(*kt)); + let server_config = Arc::new(make_server_config(*kt, &provider)); // Setup a server verifier builder that will check the full chain revocation status against a CRL // that marks the intermediate certificate as revoked. We allow unknown revocation status // so the EE cert's unknown status doesn't cause an error. let crls = vec![kt.intermediate_crl()]; let full_chain_verifier_builder = - webpki_server_verifier_builder(get_client_root_store(*kt)) + webpki_server_verifier_builder(get_client_root_store(*kt), &provider) .with_crls(crls.clone()) .allow_unknown_revocation_status(); // Also set up a verifier builder that will use the same CRL, but only check the EE certificate // revocation status. - let ee_verifier_builder = webpki_server_verifier_builder(get_client_root_store(*kt)) - .with_crls(crls.clone()) - .only_check_end_entity_revocation() - .allow_unknown_revocation_status(); + let ee_verifier_builder = + webpki_server_verifier_builder(get_client_root_store(*kt), &provider) + .with_crls(crls.clone()) + .only_check_end_entity_revocation() + .allow_unknown_revocation_status(); for version in rustls::ALL_VERSIONS { - let client_config = - make_client_config_with_verifier(&[version], full_chain_verifier_builder.clone()); + let client_config = make_client_config_with_verifier( + &[version], + full_chain_verifier_builder.clone(), + &provider, + ); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); @@ -1845,8 +1906,11 @@ fn client_check_server_certificate_intermediate_revoked() { ))) ); - let client_config = - make_client_config_with_verifier(&[version], ee_verifier_builder.clone()); + let client_config = make_client_config_with_verifier( + &[version], + ee_verifier_builder.clone(), + &provider, + ); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); @@ -1860,25 +1924,31 @@ fn client_check_server_certificate_intermediate_revoked() { #[test] fn client_check_server_certificate_ee_crl_expired() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let server_config = Arc::new(make_server_config(*kt)); + let server_config = Arc::new(make_server_config(*kt, &provider)); // Setup a server verifier that will check the EE certificate's revocation status, with CRL expiration enforced. let crls = vec![kt.end_entity_crl_expired()]; - let enforce_expiration_builder = webpki_server_verifier_builder(get_client_root_store(*kt)) - .with_crls(crls) - .only_check_end_entity_revocation() - .enforce_revocation_expiration(); + let enforce_expiration_builder = + webpki_server_verifier_builder(get_client_root_store(*kt), &provider) + .with_crls(crls) + .only_check_end_entity_revocation() + .enforce_revocation_expiration(); // Also setup a server verifier without CRL expiration enforced. let crls = vec![kt.end_entity_crl_expired()]; - let ignore_expiration_builder = webpki_server_verifier_builder(get_client_root_store(*kt)) - .with_crls(crls) - .only_check_end_entity_revocation(); + let ignore_expiration_builder = + webpki_server_verifier_builder(get_client_root_store(*kt), &provider) + .with_crls(crls) + .only_check_end_entity_revocation(); for version in rustls::ALL_VERSIONS { - let client_config = - make_client_config_with_verifier(&[version], enforce_expiration_builder.clone()); + let client_config = make_client_config_with_verifier( + &[version], + enforce_expiration_builder.clone(), + &provider, + ); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); @@ -1892,8 +1962,11 @@ fn client_check_server_certificate_ee_crl_expired() { ))) )); - let client_config = - make_client_config_with_verifier(&[version], ignore_expiration_builder.clone()); + let client_config = make_client_config_with_verifier( + &[version], + ignore_expiration_builder.clone(), + &provider, + ); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); @@ -2039,10 +2112,11 @@ fn test_client_cert_resolve( server_config: Arc, expected_root_hint_subjects: Vec>, ) { + let provider = provider::default_provider(); for version in rustls::ALL_VERSIONS { println!("{:?} {:?}:", version.version, key_type); - let mut client_config = make_client_config_with_versions(key_type, &[version]); + let mut client_config = make_client_config_with_versions(key_type, &[version], &provider); client_config.client_auth_cert_resolver = Arc::new(ClientCheckCertResolve::new( 1, expected_root_hint_subjects.clone(), @@ -2090,8 +2164,11 @@ fn default_signature_schemes(version: ProtocolVersion) -> Vec { fn client_cert_resolve_default() { // Test that in the default configuration that a client cert resolver gets the expected // CA subject hints, and supported signature algorithms. + let provider = provider::default_provider(); for key_type in ALL_KEY_TYPES { - let server_config = Arc::new(make_server_config_with_mandatory_client_auth(*key_type)); + let server_config = Arc::new(make_server_config_with_mandatory_client_auth( + *key_type, &provider, + )); // In a default configuration we expect that the verifier's trust anchors are used // for the hint subjects. @@ -2109,11 +2186,12 @@ fn client_cert_resolve_default() { fn client_cert_resolve_server_no_hints() { // Test that a server can provide no hints and the client cert resolver gets the expected // arguments. + let provider = provider::default_provider(); for key_type in ALL_KEY_TYPES { // Build a verifier with no hint subjects. - let verifier = webpki_client_verifier_builder(get_client_root_store(*key_type)) + let verifier = webpki_client_verifier_builder(get_client_root_store(*key_type), &provider) .clear_root_hint_subjects(); - let server_config = make_server_config_with_client_verifier(*key_type, verifier); + let server_config = make_server_config_with_client_verifier(*key_type, verifier, &provider); let expected_root_hint_subjects = Vec::default(); // no hints expected. test_client_cert_resolve(*key_type, server_config.into(), expected_root_hint_subjects); } @@ -2123,6 +2201,7 @@ fn client_cert_resolve_server_no_hints() { fn client_cert_resolve_server_added_hint() { // Test that a server can add an extra subject above/beyond those found in its trust store // and the client cert resolver gets the expected arguments. + let provider = provider::default_provider(); let extra_name = b"0\x1a1\x180\x16\x06\x03U\x04\x03\x0c\x0fponyland IDK CA".to_vec(); for key_type in ALL_KEY_TYPES { let expected_hint_subjects = vec![ @@ -2133,20 +2212,24 @@ fn client_cert_resolve_server_added_hint() { ]; // Create a verifier that adds the extra_name as a hint subject in addition to the ones // from the root cert store. - let verifier = webpki_client_verifier_builder(get_client_root_store(*key_type)) + let verifier = webpki_client_verifier_builder(get_client_root_store(*key_type), &provider) .add_root_hint_subjects([DistinguishedName::from(extra_name.clone())].into_iter()); - let server_config = make_server_config_with_client_verifier(*key_type, verifier); + let server_config = make_server_config_with_client_verifier(*key_type, verifier, &provider); test_client_cert_resolve(*key_type, server_config.into(), expected_hint_subjects); } } #[test] fn client_auth_works() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let server_config = Arc::new(make_server_config_with_mandatory_client_auth(*kt)); + let server_config = Arc::new(make_server_config_with_mandatory_client_auth( + *kt, &provider, + )); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions_with_auth(*kt, &[version]); + let client_config = + make_client_config_with_versions_with_auth(*kt, &[version], &provider); let (mut client, mut server) = make_pair_for_arc_configs(&Arc::new(client_config), &server_config); do_handshake(&mut client, &mut server); @@ -2159,43 +2242,52 @@ fn client_mandatory_auth_client_revocation_works() { for kt in ALL_KEY_TYPES { // Create a server configuration that includes a CRL that specifies the client certificate // is revoked. + let provider = provider::default_provider(); let relevant_crls = vec![kt.client_crl()]; // Only check the EE certificate status. See client_mandatory_auth_intermediate_revocation_works // for testing revocation status of the whole chain. - let ee_verifier_builder = webpki_client_verifier_builder(get_client_root_store(*kt)) - .with_crls(relevant_crls) - .only_check_end_entity_revocation(); + let ee_verifier_builder = + webpki_client_verifier_builder(get_client_root_store(*kt), &provider) + .with_crls(relevant_crls) + .only_check_end_entity_revocation(); let revoked_server_config = Arc::new(make_server_config_with_client_verifier( *kt, ee_verifier_builder, + &provider, )); // Create a server configuration that includes a CRL that doesn't cover the client certificate, // and uses the default behaviour of treating unknown revocation status as an error. let unrelated_crls = vec![kt.intermediate_crl()]; - let ee_verifier_builder = webpki_client_verifier_builder(get_client_root_store(*kt)) - .with_crls(unrelated_crls.clone()) - .only_check_end_entity_revocation(); + let ee_verifier_builder = + webpki_client_verifier_builder(get_client_root_store(*kt), &provider) + .with_crls(unrelated_crls.clone()) + .only_check_end_entity_revocation(); let missing_client_crl_server_config = Arc::new(make_server_config_with_client_verifier( *kt, ee_verifier_builder, + &provider, )); // Create a server configuration that includes a CRL that doesn't cover the client certificate, // but change the builder to allow unknown revocation status. - let ee_verifier_builder = webpki_client_verifier_builder(get_client_root_store(*kt)) - .with_crls(unrelated_crls.clone()) - .only_check_end_entity_revocation() - .allow_unknown_revocation_status(); + let ee_verifier_builder = + webpki_client_verifier_builder(get_client_root_store(*kt), &provider) + .with_crls(unrelated_crls.clone()) + .only_check_end_entity_revocation() + .allow_unknown_revocation_status(); let allow_missing_client_crl_server_config = Arc::new( - make_server_config_with_client_verifier(*kt, ee_verifier_builder), + make_server_config_with_client_verifier(*kt, ee_verifier_builder, &provider), ); for version in rustls::ALL_VERSIONS { // Connecting to the server with a CRL that indicates the client certificate is revoked // should fail with the expected error. - let client_config = - Arc::new(make_client_config_with_versions_with_auth(*kt, &[version])); + let client_config = Arc::new(make_client_config_with_versions_with_auth( + *kt, + &[version], + &provider, + )); let (mut client, mut server) = make_pair_for_arc_configs(&client_config, &revoked_server_config); let err = do_handshake_until_error(&mut client, &mut server); @@ -2228,35 +2320,42 @@ fn client_mandatory_auth_client_revocation_works() { #[test] fn client_mandatory_auth_intermediate_revocation_works() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { // Create a server configuration that includes a CRL that specifies the intermediate certificate // is revoked. We check the full chain for revocation status (default), and allow unknown // revocation status so the EE's unknown revocation status isn't an error. let crls = vec![kt.intermediate_crl()]; let full_chain_verifier_builder = - webpki_client_verifier_builder(get_client_root_store(*kt)) + webpki_client_verifier_builder(get_client_root_store(*kt), &provider) .with_crls(crls.clone()) .allow_unknown_revocation_status(); let full_chain_server_config = Arc::new(make_server_config_with_client_verifier( *kt, full_chain_verifier_builder, + &provider, )); // Also create a server configuration that uses the same CRL, but that only checks the EE // cert revocation status. - let ee_only_verifier_builder = webpki_client_verifier_builder(get_client_root_store(*kt)) - .with_crls(crls) - .only_check_end_entity_revocation() - .allow_unknown_revocation_status(); + let ee_only_verifier_builder = + webpki_client_verifier_builder(get_client_root_store(*kt), &provider) + .with_crls(crls) + .only_check_end_entity_revocation() + .allow_unknown_revocation_status(); let ee_server_config = Arc::new(make_server_config_with_client_verifier( *kt, ee_only_verifier_builder, + &provider, )); for version in rustls::ALL_VERSIONS { // When checking the full chain, we expect an error - the intermediate is revoked. - let client_config = - Arc::new(make_client_config_with_versions_with_auth(*kt, &[version])); + let client_config = Arc::new(make_client_config_with_versions_with_auth( + *kt, + &[version], + &provider, + )); let (mut client, mut server) = make_pair_for_arc_configs(&client_config, &full_chain_server_config); let err = do_handshake_until_error(&mut client, &mut server); @@ -2277,14 +2376,18 @@ fn client_mandatory_auth_intermediate_revocation_works() { #[test] fn client_optional_auth_client_revocation_works() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { // Create a server configuration that includes a CRL that specifies the client certificate // is revoked. let crls = vec![kt.client_crl()]; - let server_config = Arc::new(make_server_config_with_optional_client_auth(*kt, crls)); + let server_config = Arc::new(make_server_config_with_optional_client_auth( + *kt, crls, &provider, + )); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions_with_auth(*kt, &[version]); + let client_config = + make_client_config_with_versions_with_auth(*kt, &[version], &provider); let (mut client, mut server) = make_pair_for_arc_configs(&Arc::new(client_config), &server_config); // Because the client certificate is revoked, the handshake should fail. @@ -2301,7 +2404,7 @@ fn client_optional_auth_client_revocation_works() { #[test] fn client_error_is_sticky() { - let (mut client, _) = make_pair(KeyType::Rsa2048); + let (mut client, _) = make_pair(KeyType::Rsa2048, &provider::default_provider()); client .read_tls(&mut b"\x16\x03\x03\x00\x08\x0f\x00\x00\x04junk".as_ref()) .unwrap(); @@ -2313,7 +2416,7 @@ fn client_error_is_sticky() { #[test] fn server_error_is_sticky() { - let (_, mut server) = make_pair(KeyType::Rsa2048); + let (_, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); server .read_tls(&mut b"\x16\x03\x03\x00\x08\x0f\x00\x00\x04junk".as_ref()) .unwrap(); @@ -2325,20 +2428,20 @@ fn server_error_is_sticky() { #[test] fn server_flush_does_nothing() { - let (_, mut server) = make_pair(KeyType::Rsa2048); + let (_, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); assert!(matches!(server.writer().flush(), Ok(()))); } #[test] fn client_flush_does_nothing() { - let (mut client, _) = make_pair(KeyType::Rsa2048); + let (mut client, _) = make_pair(KeyType::Rsa2048, &provider::default_provider()); assert!(matches!(client.writer().flush(), Ok(()))); } #[allow(clippy::no_effect)] #[test] fn server_is_send_and_sync() { - let (_, server) = make_pair(KeyType::Rsa2048); + let (_, server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); &server as &dyn Send; &server as &dyn Sync; } @@ -2346,14 +2449,14 @@ fn server_is_send_and_sync() { #[allow(clippy::no_effect)] #[test] fn client_is_send_and_sync() { - let (client, _) = make_pair(KeyType::Rsa2048); + let (client, _) = make_pair(KeyType::Rsa2048, &provider::default_provider()); &client as &dyn Send; &client as &dyn Sync; } #[test] fn server_respects_buffer_limit_pre_handshake() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); server.set_buffer_limit(Some(32)); @@ -2381,7 +2484,7 @@ fn server_respects_buffer_limit_pre_handshake() { #[test] fn server_respects_buffer_limit_pre_handshake_with_vectored_write() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); server.set_buffer_limit(Some(32)); @@ -2405,7 +2508,7 @@ fn server_respects_buffer_limit_pre_handshake_with_vectored_write() { #[test] fn server_respects_buffer_limit_post_handshake() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); // this test will vary in behaviour depending on the default suites do_handshake(&mut client, &mut server); @@ -2434,7 +2537,7 @@ fn server_respects_buffer_limit_post_handshake() { #[test] fn client_respects_buffer_limit_pre_handshake() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); client.set_buffer_limit(Some(32)); @@ -2462,7 +2565,7 @@ fn client_respects_buffer_limit_pre_handshake() { #[test] fn client_respects_buffer_limit_pre_handshake_with_vectored_write() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); client.set_buffer_limit(Some(32)); @@ -2486,7 +2589,7 @@ fn client_respects_buffer_limit_pre_handshake_with_vectored_write() { #[test] fn client_respects_buffer_limit_post_handshake() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); do_handshake(&mut client, &mut server); client.set_buffer_limit(Some(48)); @@ -2515,7 +2618,7 @@ fn client_respects_buffer_limit_post_handshake() { #[test] fn client_detects_broken_write_vectored_impl() { // see https://github.com/rustls/rustls/issues/2316 - let (mut client, _) = make_pair(KeyType::Rsa2048); + let (mut client, _) = make_pair(KeyType::Rsa2048, &provider::default_provider()); let err = client .write_tls(&mut BrokenWriteVectored) .unwrap_err(); @@ -2543,7 +2646,7 @@ fn client_detects_broken_write_vectored_impl() { #[test] fn buf_read() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); do_handshake(&mut client, &mut server); @@ -2697,35 +2800,35 @@ where #[test] fn server_read_returns_wouldblock_when_no_data() { - let (_, mut server) = make_pair(KeyType::Rsa2048); + let (_, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); assert!(matches!(server.reader().read(&mut [0u8; 1]), Err(err) if err.kind() == io::ErrorKind::WouldBlock)); } #[test] fn client_read_returns_wouldblock_when_no_data() { - let (mut client, _) = make_pair(KeyType::Rsa2048); + let (mut client, _) = make_pair(KeyType::Rsa2048, &provider::default_provider()); assert!(matches!(client.reader().read(&mut [0u8; 1]), Err(err) if err.kind() == io::ErrorKind::WouldBlock)); } #[test] fn server_fill_buf_returns_wouldblock_when_no_data() { - let (_, mut server) = make_pair(KeyType::Rsa2048); + let (_, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); assert!(matches!(server.reader().fill_buf(), Err(err) if err.kind() == io::ErrorKind::WouldBlock)); } #[test] fn client_fill_buf_returns_wouldblock_when_no_data() { - let (mut client, _) = make_pair(KeyType::Rsa2048); + let (mut client, _) = make_pair(KeyType::Rsa2048, &provider::default_provider()); assert!(matches!(client.reader().fill_buf(), Err(err) if err.kind() == io::ErrorKind::WouldBlock)); } #[test] fn new_server_returns_initial_io_state() { - let (_, mut server) = make_pair(KeyType::Rsa2048); + let (_, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); let io_state = server.process_new_packets().unwrap(); println!("IoState is Debug {io_state:?}"); assert_eq!(io_state.plaintext_bytes_to_read(), 0); @@ -2735,7 +2838,7 @@ fn new_server_returns_initial_io_state() { #[test] fn new_client_returns_initial_io_state() { - let (mut client, _) = make_pair(KeyType::Rsa2048); + let (mut client, _) = make_pair(KeyType::Rsa2048, &provider::default_provider()); let io_state = client.process_new_packets().unwrap(); println!("IoState is Debug {io_state:?}"); assert_eq!(io_state.plaintext_bytes_to_read(), 0); @@ -2745,7 +2848,7 @@ fn new_client_returns_initial_io_state() { #[test] fn client_complete_io_for_handshake() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); assert!(client.is_handshaking()); let (rdlen, wrlen) = client @@ -2758,7 +2861,7 @@ fn client_complete_io_for_handshake() { #[test] fn buffered_client_complete_io_for_handshake() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); assert!(client.is_handshaking()); let (rdlen, wrlen) = client @@ -2771,7 +2874,7 @@ fn buffered_client_complete_io_for_handshake() { #[test] fn client_complete_io_for_handshake_eof() { - let (mut client, _) = make_pair(KeyType::Rsa2048); + let (mut client, _) = make_pair(KeyType::Rsa2048, &provider::default_provider()); let mut input = io::Cursor::new(Vec::new()); assert!(client.is_handshaking()); @@ -2783,8 +2886,9 @@ fn client_complete_io_for_handshake_eof() { #[test] fn client_complete_io_for_write() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let (mut client, mut server) = make_pair(*kt); + let (mut client, mut server) = make_pair(*kt, &provider); do_handshake(&mut client, &mut server); @@ -2812,8 +2916,9 @@ fn client_complete_io_for_write() { #[test] fn buffered_client_complete_io_for_write() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let (mut client, mut server) = make_pair(*kt); + let (mut client, mut server) = make_pair(*kt, &provider); do_handshake(&mut client, &mut server); @@ -2841,8 +2946,9 @@ fn buffered_client_complete_io_for_write() { #[test] fn client_complete_io_for_read() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let (mut client, mut server) = make_pair(*kt); + let (mut client, mut server) = make_pair(*kt, &provider); do_handshake(&mut client, &mut server); @@ -2862,8 +2968,9 @@ fn client_complete_io_for_read() { #[test] fn server_complete_io_for_handshake() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let (mut client, mut server) = make_pair(*kt); + let (mut client, mut server) = make_pair(*kt, &provider); assert!(server.is_handshaking()); let (rdlen, wrlen) = server @@ -2877,7 +2984,7 @@ fn server_complete_io_for_handshake() { #[test] fn server_complete_io_for_handshake_eof() { - let (_, mut server) = make_pair(KeyType::Rsa2048); + let (_, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); let mut input = io::Cursor::new(Vec::new()); assert!(server.is_handshaking()); @@ -2889,8 +2996,9 @@ fn server_complete_io_for_handshake_eof() { #[test] fn server_complete_io_for_write() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let (mut client, mut server) = make_pair(*kt); + let (mut client, mut server) = make_pair(*kt, &provider); do_handshake(&mut client, &mut server); @@ -2917,8 +3025,9 @@ fn server_complete_io_for_write() { #[test] fn server_complete_io_for_write_eof() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let (mut client, mut server) = make_pair(*kt); + let (mut client, mut server) = make_pair(*kt, &provider); do_handshake(&mut client, &mut server); @@ -2973,8 +3082,9 @@ impl std::io::Read for EofWriter { #[test] fn server_complete_io_for_read() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let (mut client, mut server) = make_pair(*kt); + let (mut client, mut server) = make_pair(*kt, &provider); do_handshake(&mut client, &mut server); @@ -3011,8 +3121,9 @@ enum StreamKind { } fn test_client_stream_write(stream_kind: StreamKind) { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let (mut client, mut server) = make_pair(*kt); + let (mut client, mut server) = make_pair(*kt, &provider); let data = b"hello"; { let mut pipe = OtherSession::new(&mut server); @@ -3027,8 +3138,9 @@ fn test_client_stream_write(stream_kind: StreamKind) { } fn test_server_stream_write(stream_kind: StreamKind) { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let (mut client, mut server) = make_pair(*kt); + let (mut client, mut server) = make_pair(*kt, &provider); let data = b"hello"; { let mut pipe = OtherSession::new(&mut client); @@ -3095,8 +3207,9 @@ fn test_stream_read(read_kind: ReadKind, mut stream: impl BufRead, data: &[u8]) } fn test_client_stream_read(stream_kind: StreamKind, read_kind: ReadKind) { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let (mut client, mut server) = make_pair(*kt); + let (mut client, mut server) = make_pair(*kt, &provider); let data = b"world"; server.writer().write_all(data).unwrap(); @@ -3115,8 +3228,9 @@ fn test_client_stream_read(stream_kind: StreamKind, read_kind: ReadKind) { } fn test_server_stream_read(stream_kind: StreamKind, read_kind: ReadKind) { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let (mut client, mut server) = make_pair(*kt); + let (mut client, mut server) = make_pair(*kt, &provider); let data = b"world"; client.writer().write_all(data).unwrap(); @@ -3136,7 +3250,7 @@ fn test_server_stream_read(stream_kind: StreamKind, read_kind: ReadKind) { #[test] fn test_client_write_and_vectored_write_equivalence() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); do_handshake(&mut client, &mut server); const N: usize = 1000; @@ -3191,7 +3305,7 @@ impl io::Write for FailsWrites { #[test] fn stream_write_reports_underlying_io_error_before_plaintext_processed() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); do_handshake(&mut client, &mut server); let mut pipe = FailsWrites { @@ -3211,7 +3325,7 @@ fn stream_write_reports_underlying_io_error_before_plaintext_processed() { #[test] fn stream_write_swallows_underlying_io_error_after_plaintext_processed() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); do_handshake(&mut client, &mut server); let mut pipe = FailsWrites { @@ -3346,23 +3460,23 @@ fn server_streamowned_handshake_error() { #[test] fn server_config_is_clone() { - let _ = make_server_config(KeyType::Rsa2048); + let _ = make_server_config(KeyType::Rsa2048, &provider::default_provider()); } #[test] fn client_config_is_clone() { - let _ = make_client_config(KeyType::Rsa2048); + let _ = make_client_config(KeyType::Rsa2048, &provider::default_provider()); } #[test] fn client_connection_is_debug() { - let (client, _) = make_pair(KeyType::Rsa2048); + let (client, _) = make_pair(KeyType::Rsa2048, &provider::default_provider()); println!("{client:?}"); } #[test] fn server_connection_is_debug() { - let (_, server) = make_pair(KeyType::Rsa2048); + let (_, server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); println!("{server:?}"); } @@ -3387,14 +3501,16 @@ fn server_complete_io_for_handshake_ending_with_alert() { #[test] fn server_exposes_offered_sni() { let kt = KeyType::Rsa2048; + let provider = provider::default_provider(); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions(kt, &[version]); + let client_config = make_client_config_with_versions(kt, &[version], &provider); let mut client = ClientConnection::new( Arc::new(client_config), server_name("second.testserver.com"), ) .unwrap(); - let mut server = ServerConnection::new(Arc::new(make_server_config(kt))).unwrap(); + let mut server = + ServerConnection::new(Arc::new(make_server_config(kt, &provider))).unwrap(); assert_eq!(None, server.server_name()); do_handshake(&mut client, &mut server); @@ -3406,14 +3522,16 @@ fn server_exposes_offered_sni() { fn server_exposes_offered_sni_smashed_to_lowercase() { // webpki actually does this for us in its DnsName type let kt = KeyType::Rsa2048; + let provider = provider::default_provider(); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions(kt, &[version]); + let client_config = make_client_config_with_versions(kt, &[version], &provider); let mut client = ClientConnection::new( Arc::new(client_config), server_name("SECOND.TESTServer.com"), ) .unwrap(); - let mut server = ServerConnection::new(Arc::new(make_server_config(kt))).unwrap(); + let mut server = + ServerConnection::new(Arc::new(make_server_config(kt, &provider))).unwrap(); assert_eq!(None, server.server_name()); do_handshake(&mut client, &mut server); @@ -3424,14 +3542,15 @@ fn server_exposes_offered_sni_smashed_to_lowercase() { #[test] fn server_exposes_offered_sni_even_if_resolver_fails() { let kt = KeyType::Rsa2048; + let provider = provider::default_provider(); let resolver = rustls::server::ResolvesServerCertUsingSni::new(); - let mut server_config = make_server_config(kt); + let mut server_config = make_server_config(kt, &provider); server_config.cert_resolver = Arc::new(resolver); let server_config = Arc::new(server_config); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions(kt, &[version]); + let client_config = make_client_config_with_versions(kt, &[version], &provider); let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); let mut client = ClientConnection::new(Arc::new(client_config), server_name("thisdoesNOTexist.com")) @@ -3452,6 +3571,7 @@ fn server_exposes_offered_sni_even_if_resolver_fails() { #[test] fn sni_resolver_works() { let kt = KeyType::Rsa2048; + let provider = provider::default_provider(); let mut resolver = rustls::server::ResolvesServerCertUsingSni::new(); let signing_key = RsaSigningKey::new(&kt.get_key()).unwrap(); let signing_key: Arc = Arc::new(signing_key); @@ -3462,19 +3582,22 @@ fn sni_resolver_works() { ) .unwrap(); - let mut server_config = make_server_config(kt); + let mut server_config = make_server_config(kt, &provider); server_config.cert_resolver = Arc::new(resolver); let server_config = Arc::new(server_config); let mut server1 = ServerConnection::new(Arc::clone(&server_config)).unwrap(); - let mut client1 = - ClientConnection::new(Arc::new(make_client_config(kt)), server_name("localhost")).unwrap(); + let mut client1 = ClientConnection::new( + Arc::new(make_client_config(kt, &provider)), + server_name("localhost"), + ) + .unwrap(); let err = do_handshake_until_error(&mut client1, &mut server1); assert_eq!(err, Ok(())); let mut server2 = ServerConnection::new(Arc::clone(&server_config)).unwrap(); let mut client2 = ClientConnection::new( - Arc::new(make_client_config(kt)), + Arc::new(make_client_config(kt, &provider)), server_name("notlocalhost"), ) .unwrap(); @@ -3538,6 +3661,7 @@ fn certificate_error_expecting_name(expected: &str) -> CertificateError { #[test] fn sni_resolver_lower_cases_configured_names() { let kt = KeyType::Rsa2048; + let provider = provider::default_provider(); let mut resolver = rustls::server::ResolvesServerCertUsingSni::new(); let signing_key = RsaSigningKey::new(&kt.get_key()).unwrap(); let signing_key: Arc = Arc::new(signing_key); @@ -3550,13 +3674,16 @@ fn sni_resolver_lower_cases_configured_names() { ) ); - let mut server_config = make_server_config(kt); + let mut server_config = make_server_config(kt, &provider); server_config.cert_resolver = Arc::new(resolver); let server_config = Arc::new(server_config); let mut server1 = ServerConnection::new(Arc::clone(&server_config)).unwrap(); - let mut client1 = - ClientConnection::new(Arc::new(make_client_config(kt)), server_name("localhost")).unwrap(); + let mut client1 = ClientConnection::new( + Arc::new(make_client_config(kt, &provider)), + server_name("localhost"), + ) + .unwrap(); let err = do_handshake_until_error(&mut client1, &mut server1); assert_eq!(err, Ok(())); } @@ -3565,6 +3692,7 @@ fn sni_resolver_lower_cases_configured_names() { fn sni_resolver_lower_cases_queried_names() { // actually, the handshake parser does this, but the effect is the same. let kt = KeyType::Rsa2048; + let provider = provider::default_provider(); let mut resolver = rustls::server::ResolvesServerCertUsingSni::new(); let signing_key = RsaSigningKey::new(&kt.get_key()).unwrap(); let signing_key: Arc = Arc::new(signing_key); @@ -3577,13 +3705,16 @@ fn sni_resolver_lower_cases_queried_names() { ) ); - let mut server_config = make_server_config(kt); + let mut server_config = make_server_config(kt, &provider); server_config.cert_resolver = Arc::new(resolver); let server_config = Arc::new(server_config); let mut server1 = ServerConnection::new(Arc::clone(&server_config)).unwrap(); - let mut client1 = - ClientConnection::new(Arc::new(make_client_config(kt)), server_name("LOCALHOST")).unwrap(); + let mut client1 = ClientConnection::new( + Arc::new(make_client_config(kt, &provider)), + server_name("LOCALHOST"), + ) + .unwrap(); let err = do_handshake_until_error(&mut client1, &mut server1); assert_eq!(err, Ok(())); } @@ -3737,9 +3868,11 @@ fn do_exporter_test(client_config: ClientConfig, server_config: ServerConfig) { #[cfg(feature = "tls12")] #[test] fn test_tls12_exporter() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let client_config = make_client_config_with_versions(*kt, &[&rustls::version::TLS12]); - let server_config = make_server_config(*kt); + let client_config = + make_client_config_with_versions(*kt, &[&rustls::version::TLS12], &provider); + let server_config = make_server_config(*kt, &provider); do_exporter_test(client_config, server_config); } @@ -3747,9 +3880,11 @@ fn test_tls12_exporter() { #[test] fn test_tls13_exporter() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let client_config = make_client_config_with_versions(*kt, &[&rustls::version::TLS13]); - let server_config = make_server_config(*kt); + let client_config = + make_client_config_with_versions(*kt, &[&rustls::version::TLS13], &provider); + let server_config = make_server_config(*kt, &provider); do_exporter_test(client_config, server_config); } @@ -3757,9 +3892,10 @@ fn test_tls13_exporter() { #[test] fn test_tls13_exporter_maximum_output_length() { + let provider = provider::default_provider(); let client_config = - make_client_config_with_versions(KeyType::EcdsaP256, &[&rustls::version::TLS13]); - let server_config = make_server_config(KeyType::EcdsaP256); + make_client_config_with_versions(KeyType::EcdsaP256, &[&rustls::version::TLS13], &provider); + let server_config = make_server_config(KeyType::EcdsaP256, &provider); let (mut client, mut server) = make_pair_for_configs(client_config, server_config); do_handshake(&mut client, &mut server); @@ -3885,10 +4021,11 @@ fn test_ciphersuites() -> Vec<( #[test] fn negotiated_ciphersuite_default() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { do_suite_and_kx_test( - make_client_config(*kt), - make_server_config(*kt), + make_client_config(*kt, &provider), + make_server_config(*kt, &provider), find_suite(CipherSuite::TLS13_AES_256_GCM_SHA384), expected_kx_for_version(&rustls::version::TLS13), ProtocolVersion::TLSv1_3, @@ -3923,7 +4060,7 @@ fn negotiated_ciphersuite_client() { do_suite_and_kx_test( client_config, - make_server_config(kt), + make_server_config(kt, &provider::default_provider()), scs, expected_kx_for_version(version), version.version, @@ -3949,7 +4086,7 @@ fn negotiated_ciphersuite_server() { ); do_suite_and_kx_test( - make_client_config(kt), + make_client_config(kt, &provider::default_provider()), server_config, scs, expected_kx_for_version(version), @@ -4063,12 +4200,14 @@ fn key_log_for_tls12() { let client_key_log = Arc::new(KeyLogToVec::new("client")); let server_key_log = Arc::new(KeyLogToVec::new("server")); + let provider = provider::default_provider(); let kt = KeyType::Rsa2048; - let mut client_config = make_client_config_with_versions(kt, &[&rustls::version::TLS12]); + let mut client_config = + make_client_config_with_versions(kt, &[&rustls::version::TLS12], &provider); client_config.key_log = client_key_log.clone(); let client_config = Arc::new(client_config); - let mut server_config = make_server_config(kt); + let mut server_config = make_server_config(kt, &provider); server_config.key_log = server_key_log.clone(); let server_config = Arc::new(server_config); @@ -4099,12 +4238,14 @@ fn key_log_for_tls13() { let client_key_log = Arc::new(KeyLogToVec::new("client")); let server_key_log = Arc::new(KeyLogToVec::new("server")); + let provider = provider::default_provider(); let kt = KeyType::Rsa2048; - let mut client_config = make_client_config_with_versions(kt, &[&rustls::version::TLS13]); + let mut client_config = + make_client_config_with_versions(kt, &[&rustls::version::TLS13], &provider); client_config.key_log = client_key_log.clone(); let client_config = Arc::new(client_config); - let mut server_config = make_server_config(kt); + let mut server_config = make_server_config(kt, &provider); server_config.key_log = server_key_log.clone(); let server_config = Arc::new(server_config); @@ -4171,7 +4312,7 @@ fn key_log_for_tls13() { #[test] fn vectored_write_for_server_appdata() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); do_handshake(&mut client, &mut server); server @@ -4196,7 +4337,7 @@ fn vectored_write_for_server_appdata() { #[test] fn vectored_write_for_client_appdata() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); do_handshake(&mut client, &mut server); client @@ -4221,10 +4362,11 @@ fn vectored_write_for_client_appdata() { #[test] fn vectored_write_for_server_handshake_with_half_rtt_data() { - let mut server_config = make_server_config(KeyType::Rsa2048); + let provider = provider::default_provider(); + let mut server_config = make_server_config(KeyType::Rsa2048, &provider); server_config.send_half_rtt_data = true; let (mut client, mut server) = make_pair_for_configs( - make_client_config_with_auth(KeyType::Rsa2048), + make_client_config_with_auth(KeyType::Rsa2048, &provider), server_config, ); @@ -4266,7 +4408,7 @@ fn vectored_write_for_server_handshake_with_half_rtt_data() { fn check_half_rtt_does_not_work(server_config: ServerConfig) { let (mut client, mut server) = make_pair_for_configs( - make_client_config_with_auth(KeyType::Rsa2048), + make_client_config_with_auth(KeyType::Rsa2048, &provider::default_provider()), server_config, ); @@ -4312,21 +4454,24 @@ fn check_half_rtt_does_not_work(server_config: ServerConfig) { #[test] fn vectored_write_for_server_handshake_no_half_rtt_with_client_auth() { - let mut server_config = make_server_config_with_mandatory_client_auth(KeyType::Rsa2048); + let mut server_config = make_server_config_with_mandatory_client_auth( + KeyType::Rsa2048, + &provider::default_provider(), + ); server_config.send_half_rtt_data = true; // ask even though it will be ignored check_half_rtt_does_not_work(server_config); } #[test] fn vectored_write_for_server_handshake_no_half_rtt_by_default() { - let server_config = make_server_config(KeyType::Rsa2048); + let server_config = make_server_config(KeyType::Rsa2048, &provider::default_provider()); assert!(!server_config.send_half_rtt_data); check_half_rtt_does_not_work(server_config); } #[test] fn vectored_write_for_client_handshake() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); client .writer() @@ -4363,7 +4508,7 @@ fn vectored_write_for_client_handshake() { #[test] fn vectored_write_with_slow_client() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); client.set_buffer_limit(Some(32)); @@ -4596,10 +4741,11 @@ impl rustls::client::ClientSessionStore for ClientStorage { #[test] fn tls13_stateful_resumption() { let kt = KeyType::Rsa2048; - let client_config = make_client_config_with_versions(kt, &[&rustls::version::TLS13]); + let provider = provider::default_provider(); + let client_config = make_client_config_with_versions(kt, &[&rustls::version::TLS13], &provider); let client_config = Arc::new(client_config); - let mut server_config = make_server_config(kt); + let mut server_config = make_server_config(kt, &provider); let storage = Arc::new(ServerStorage::new()); server_config.session_storage = storage.clone(); let server_config = Arc::new(server_config); @@ -4657,10 +4803,11 @@ fn tls13_stateful_resumption() { #[test] fn tls13_stateless_resumption() { let kt = KeyType::Rsa2048; - let client_config = make_client_config_with_versions(kt, &[&rustls::version::TLS13]); + let provider = provider::default_provider(); + let client_config = make_client_config_with_versions(kt, &[&rustls::version::TLS13], &provider); let client_config = Arc::new(client_config); - let mut server_config = make_server_config(kt); + let mut server_config = make_server_config(kt, &provider); server_config.ticketer = provider::Ticketer::new().unwrap(); let storage = Arc::new(ServerStorage::new()); server_config.session_storage = storage.clone(); @@ -4718,17 +4865,18 @@ fn tls13_stateless_resumption() { #[test] fn early_data_not_available() { - let (mut client, _) = make_pair(KeyType::Rsa2048); + let (mut client, _) = make_pair(KeyType::Rsa2048, &provider::default_provider()); assert!(client.early_data().is_none()); } fn early_data_configs() -> (Arc, Arc) { let kt = KeyType::Rsa2048; - let mut client_config = make_client_config(kt); + let provider = provider::default_provider(); + let mut client_config = make_client_config(kt, &provider); client_config.enable_early_data = true; client_config.resumption = Resumption::store(Arc::new(ClientStorage::new())); - let mut server_config = make_server_config(kt); + let mut server_config = make_server_config(kt, &provider); server_config.max_early_data_size = 1234; (Arc::new(client_config), Arc::new(server_config)) } @@ -4778,7 +4926,11 @@ fn early_data_is_available_on_resumption() { #[test] fn early_data_not_available_on_server_before_client_hello() { - let mut server = ServerConnection::new(Arc::new(make_server_config(KeyType::Rsa2048))).unwrap(); + let mut server = ServerConnection::new(Arc::new(make_server_config( + KeyType::Rsa2048, + &provider::default_provider(), + ))) + .unwrap(); assert!(server.early_data().is_none()); } @@ -5029,10 +5181,13 @@ mod test_quic { } let kt = KeyType::Rsa2048; - let mut client_config = make_client_config_with_versions(kt, &[&rustls::version::TLS13]); + let provider = provider::default_provider(); + let mut client_config = + make_client_config_with_versions(kt, &[&rustls::version::TLS13], &provider); client_config.enable_early_data = true; let client_config = Arc::new(client_config); - let mut server_config = make_server_config_with_versions(kt, &[&rustls::version::TLS13]); + let mut server_config = + make_server_config_with_versions(kt, &[&rustls::version::TLS13], &provider); server_config.max_early_data_size = 0xffffffff; let server_config = Arc::new(server_config); let client_params = &b"client params"[..]; @@ -5233,13 +5388,15 @@ mod test_quic { fn test_quic_rejects_missing_alpn() { let client_params = &b"client params"[..]; let server_params = &b"server params"[..]; + let provider = provider::default_provider(); for &kt in ALL_KEY_TYPES { - let client_config = make_client_config_with_versions(kt, &[&rustls::version::TLS13]); + let client_config = + make_client_config_with_versions(kt, &[&rustls::version::TLS13], &provider); let client_config = Arc::new(client_config); let mut server_config = - make_server_config_with_versions(kt, &[&rustls::version::TLS13]); + make_server_config_with_versions(kt, &[&rustls::version::TLS13], &provider); server_config.alpn_protocols = vec!["foo".into()]; let server_config = Arc::new(server_config); @@ -5271,8 +5428,12 @@ mod test_quic { #[cfg(feature = "tls12")] #[test] fn test_quic_no_tls13_error() { - let mut client_config = - make_client_config_with_versions(KeyType::Ed25519, &[&rustls::version::TLS12]); + let provider = provider::default_provider(); + let mut client_config = make_client_config_with_versions( + KeyType::Ed25519, + &[&rustls::version::TLS12], + &provider, + ); client_config.alpn_protocols = vec!["foo".into()]; let client_config = Arc::new(client_config); @@ -5286,8 +5447,11 @@ mod test_quic { .is_err() ); - let mut server_config = - make_server_config_with_versions(KeyType::Ed25519, &[&rustls::version::TLS12]); + let mut server_config = make_server_config_with_versions( + KeyType::Ed25519, + &[&rustls::version::TLS12], + &provider, + ); server_config.alpn_protocols = vec!["foo".into()]; let server_config = Arc::new(server_config); @@ -5303,8 +5467,12 @@ mod test_quic { #[test] fn test_quic_invalid_early_data_size() { - let mut server_config = - make_server_config_with_versions(KeyType::Ed25519, &[&rustls::version::TLS13]); + let provider = provider::default_provider(); + let mut server_config = make_server_config_with_versions( + KeyType::Ed25519, + &[&rustls::version::TLS13], + &provider, + ); server_config.alpn_protocols = vec!["foo".into()]; let cases = [ @@ -5331,8 +5499,12 @@ mod test_quic { #[test] fn test_quic_server_no_params_received() { - let server_config = - make_server_config_with_versions(KeyType::Ed25519, &[&rustls::version::TLS13]); + let provider = provider::default_provider(); + let server_config = make_server_config_with_versions( + KeyType::Ed25519, + &[&rustls::version::TLS13], + &provider, + ); let server_config = Arc::new(server_config); let mut server = quic::ServerConnection::new( @@ -5353,8 +5525,12 @@ mod test_quic { #[test] fn test_quic_server_no_tls12() { - let mut server_config = - make_server_config_with_versions(KeyType::Ed25519, &[&rustls::version::TLS13]); + let provider = provider::default_provider(); + let mut server_config = make_server_config_with_versions( + KeyType::Ed25519, + &[&rustls::version::TLS13], + &provider, + ); server_config.alpn_protocols = vec!["foo".into()]; let server_config = Arc::new(server_config); @@ -5577,9 +5753,12 @@ mod test_quic { #[test] fn test_quic_exporter() { + let provider = provider::default_provider(); for &kt in ALL_KEY_TYPES { - let client_config = make_client_config_with_versions(kt, &[&rustls::version::TLS13]); - let server_config = make_server_config_with_versions(kt, &[&rustls::version::TLS13]); + let client_config = + make_client_config_with_versions(kt, &[&rustls::version::TLS13], &provider); + let server_config = + make_server_config_with_versions(kt, &[&rustls::version::TLS13], &provider); do_exporter_test(client_config, server_config); } @@ -5588,8 +5767,11 @@ mod test_quic { #[test] fn test_fragmented_append() { // Create a QUIC client connection. - let client_config = - make_client_config_with_versions(KeyType::Rsa2048, &[&rustls::version::TLS13]); + let client_config = make_client_config_with_versions( + KeyType::Rsa2048, + &[&rustls::version::TLS13], + &provider::default_provider(), + ); let client_config = Arc::new(client_config); let mut client = quic::ClientConnection::new( Arc::clone(&client_config), @@ -5627,10 +5809,12 @@ fn test_client_does_not_offer_sha1() { use rustls::internal::msgs::handshake::HandshakePayload; use rustls::internal::msgs::message::{MessagePayload, OutboundOpaqueMessage}; + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions(*kt, &[version]); - let (mut client, _) = make_pair_for_configs(client_config, make_server_config(*kt)); + let client_config = make_client_config_with_versions(*kt, &[version], &provider); + let (mut client, _) = + make_pair_for_configs(client_config, make_server_config(*kt, &provider)); assert!(client.wants_write()); let mut buf = [0u8; 262144]; @@ -5662,19 +5846,28 @@ fn test_client_does_not_offer_sha1() { #[test] fn test_client_config_keyshare() { + let provider = provider::default_provider(); let kx_groups = vec![provider::kx_group::SECP384R1]; - let client_config = make_client_config_with_kx_groups(KeyType::Rsa2048, kx_groups.clone()); - let server_config = make_server_config_with_kx_groups(KeyType::Rsa2048, kx_groups); + let client_config = + make_client_config_with_kx_groups(KeyType::Rsa2048, kx_groups.clone(), &provider); + let server_config = make_server_config_with_kx_groups(KeyType::Rsa2048, kx_groups, &provider); let (mut client, mut server) = make_pair_for_configs(client_config, server_config); do_handshake_until_error(&mut client, &mut server).unwrap(); } #[test] fn test_client_config_keyshare_mismatch() { - let client_config = - make_client_config_with_kx_groups(KeyType::Rsa2048, vec![provider::kx_group::SECP384R1]); - let server_config = - make_server_config_with_kx_groups(KeyType::Rsa2048, vec![provider::kx_group::X25519]); + let provider = provider::default_provider(); + let client_config = make_client_config_with_kx_groups( + KeyType::Rsa2048, + vec![provider::kx_group::SECP384R1], + &provider, + ); + let server_config = make_server_config_with_kx_groups( + KeyType::Rsa2048, + vec![provider::kx_group::X25519], + &provider, + ); let (mut client, mut server) = make_pair_for_configs(client_config, server_config); assert!(do_handshake_until_error(&mut client, &mut server).is_err()); } @@ -5682,18 +5875,23 @@ fn test_client_config_keyshare_mismatch() { #[cfg(feature = "tls12")] #[test] fn test_client_sends_helloretryrequest() { + let provider = provider::default_provider(); // client sends a secp384r1 key share let mut client_config = make_client_config_with_kx_groups( KeyType::Rsa2048, vec![provider::kx_group::SECP384R1, provider::kx_group::X25519], + &provider, ); let storage = Arc::new(ClientStorage::new()); client_config.resumption = Resumption::store(storage.clone()); // but server only accepts x25519, so a HRR is required - let server_config = - make_server_config_with_kx_groups(KeyType::Rsa2048, vec![provider::kx_group::X25519]); + let server_config = make_server_config_with_kx_groups( + KeyType::Rsa2048, + vec![provider::kx_group::X25519], + &provider, + ); let (mut client, mut server) = make_pair_for_configs(client_config, server_config); @@ -5840,13 +6038,18 @@ fn test_client_rejects_hrr_with_varied_session_id() { }; // client prefers a secp384r1 key share, server only accepts x25519 + let provider = provider::default_provider(); let client_config = make_client_config_with_kx_groups( KeyType::Rsa2048, vec![provider::kx_group::SECP384R1, provider::kx_group::X25519], + &provider, ); - let server_config = - make_server_config_with_kx_groups(KeyType::Rsa2048, vec![provider::kx_group::X25519]); + let server_config = make_server_config_with_kx_groups( + KeyType::Rsa2048, + vec![provider::kx_group::X25519], + &provider, + ); let (client, server) = make_pair_for_configs(client_config, server_config); let (mut client, mut server) = (client.into(), server.into()); @@ -5874,20 +6077,27 @@ fn test_client_rejects_hrr_with_varied_session_id() { fn test_client_attempts_to_use_unsupported_kx_group() { // common to both client configs let shared_storage = Arc::new(ClientStorage::new()); + let provider = provider::default_provider(); // first, client sends a secp-256 share and server agrees. secp-256 is inserted // into kx group cache. - let mut client_config_1 = - make_client_config_with_kx_groups(KeyType::Rsa2048, vec![provider::kx_group::SECP256R1]); + let mut client_config_1 = make_client_config_with_kx_groups( + KeyType::Rsa2048, + vec![provider::kx_group::SECP256R1], + &provider, + ); client_config_1.resumption = Resumption::store(shared_storage.clone()); // second, client only supports secp-384 and so kx group cache // contains an unusable value. - let mut client_config_2 = - make_client_config_with_kx_groups(KeyType::Rsa2048, vec![provider::kx_group::SECP384R1]); + let mut client_config_2 = make_client_config_with_kx_groups( + KeyType::Rsa2048, + vec![provider::kx_group::SECP384R1], + &provider, + ); client_config_2.resumption = Resumption::store(shared_storage.clone()); - let server_config = make_server_config(KeyType::Rsa2048); + let server_config = make_server_config(KeyType::Rsa2048, &provider); // first handshake let (mut client_1, mut server) = make_pair_for_configs(client_config_1, server_config.clone()); @@ -5927,11 +6137,15 @@ fn test_client_sends_share_for_less_preferred_group() { // common to both client configs let shared_storage = Arc::new(ClientStorage::new()); + let provider = provider::default_provider(); // first, client sends a secp384r1 share and server agrees. secp384r1 is inserted // into kx group cache. - let mut client_config_1 = - make_client_config_with_kx_groups(KeyType::Rsa2048, vec![provider::kx_group::SECP384R1]); + let mut client_config_1 = make_client_config_with_kx_groups( + KeyType::Rsa2048, + vec![provider::kx_group::SECP384R1], + &provider, + ); client_config_1.resumption = Resumption::store(shared_storage.clone()); // second, client supports (x25519, secp384r1) and so kx group cache @@ -5939,11 +6153,15 @@ fn test_client_sends_share_for_less_preferred_group() { let mut client_config_2 = make_client_config_with_kx_groups( KeyType::Rsa2048, vec![provider::kx_group::X25519, provider::kx_group::SECP384R1], + &provider, ); client_config_2.resumption = Resumption::store(shared_storage.clone()); - let server_config = - make_server_config_with_kx_groups(KeyType::Rsa2048, provider::ALL_KX_GROUPS.to_vec()); + let server_config = make_server_config_with_kx_groups( + KeyType::Rsa2048, + provider::ALL_KX_GROUPS.to_vec(), + &provider, + ); // first handshake let (mut client_1, mut server) = make_pair_for_configs(client_config_1, server_config.clone()); @@ -6010,12 +6228,13 @@ fn test_client_sends_share_for_less_preferred_group() { #[test] fn test_tls13_client_resumption_does_not_reuse_tickets() { let shared_storage = Arc::new(ClientStorage::new()); + let provider = provider::default_provider(); - let mut client_config = make_client_config(KeyType::Rsa2048); + let mut client_config = make_client_config(KeyType::Rsa2048, &provider); client_config.resumption = Resumption::store(shared_storage.clone()); let client_config = Arc::new(client_config); - let mut server_config = make_server_config(KeyType::Rsa2048); + let mut server_config = make_server_config(KeyType::Rsa2048, &provider); server_config.send_tls13_tickets = 5; let server_config = Arc::new(server_config); @@ -6093,8 +6312,9 @@ fn test_client_mtu_reduction() { collector.writevs[0].clone() } + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { - let mut client_config = make_client_config(*kt); + let mut client_config = make_client_config(*kt, &provider); client_config.max_fragment_size = Some(64); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); @@ -6107,11 +6327,14 @@ fn test_client_mtu_reduction() { #[test] fn test_server_mtu_reduction() { - let mut server_config = make_server_config(KeyType::Rsa2048); + let provider = provider::default_provider(); + let mut server_config = make_server_config(KeyType::Rsa2048, &provider); server_config.max_fragment_size = Some(64); server_config.send_half_rtt_data = true; - let (mut client, mut server) = - make_pair_for_configs(make_client_config(KeyType::Rsa2048), server_config); + let (mut client, mut server) = make_pair_for_configs( + make_client_config(KeyType::Rsa2048, &provider), + server_config, + ); let big_data = [0u8; 2048]; server @@ -6154,7 +6377,8 @@ fn test_server_mtu_reduction() { } fn check_client_max_fragment_size(size: usize) -> Option { - let mut client_config = make_client_config(KeyType::Ed25519); + let provider = provider::default_provider(); + let mut client_config = make_client_config(KeyType::Ed25519, &provider); client_config.max_fragment_size = Some(size); ClientConnection::new(Arc::new(client_config), server_name("localhost")).err() } @@ -6183,14 +6407,16 @@ fn bad_client_max_fragment_sizes() { #[test] fn handshakes_complete_and_data_flows_with_gratuitious_max_fragment_sizes() { // general exercising of msgs::fragmenter and msgs::deframer + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { for version in rustls::ALL_VERSIONS { // no hidden significance to these numbers for frag_size in [37, 61, 101, 257] { println!("test kt={kt:?} version={version:?} frag={frag_size:?}"); - let mut client_config = make_client_config_with_versions(*kt, &[version]); + let mut client_config = + make_client_config_with_versions(*kt, &[version], &provider); client_config.max_fragment_size = Some(frag_size); - let mut server_config = make_server_config(*kt); + let mut server_config = make_server_config(*kt, &provider); server_config.max_fragment_size = Some(frag_size); let (mut client, mut server) = make_pair_for_configs(client_config, server_config); @@ -6236,7 +6462,7 @@ fn connection_types_are_not_huge() { #[test] fn test_server_rejects_clients_without_any_kx_groups() { - let (_, mut server) = make_pair(KeyType::Rsa2048); + let (_, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); server .read_tls( &mut encoding::message_framing( @@ -6269,7 +6495,11 @@ fn test_server_rejects_clients_without_any_kx_groups() { fn test_server_rejects_clients_without_any_kx_group_overlap() { for version in rustls::ALL_VERSIONS { let (mut client, mut server) = make_pair_for_configs( - make_client_config_with_kx_groups(KeyType::Rsa2048, vec![provider::kx_group::X25519]), + make_client_config_with_kx_groups( + KeyType::Rsa2048, + vec![provider::kx_group::X25519], + &provider::default_provider(), + ), finish_server_config( KeyType::Rsa2048, ServerConfig::builder_with_provider( @@ -6312,7 +6542,7 @@ fn test_client_rejects_illegal_tls13_ccs() { Altered::InPlace } - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); transfer(&mut client, &mut server); server.process_new_packets().unwrap(); @@ -6331,7 +6561,8 @@ fn test_client_rejects_illegal_tls13_ccs() { #[test] fn test_client_rejects_no_extended_master_secret_extension_when_require_ems_or_fips() { let key_type = KeyType::Rsa2048; - let mut client_config = make_client_config(key_type); + let provider = provider::default_provider(); + let mut client_config = make_client_config(key_type, &provider); if provider_is_fips() { assert!(client_config.require_ems); } else { @@ -6339,7 +6570,7 @@ fn test_client_rejects_no_extended_master_secret_extension_when_require_ems_or_f } let mut server_config = finish_server_config( key_type, - server_config_builder_with_versions(&[&rustls::version::TLS12]), + server_config_builder_with_versions(&[&rustls::version::TLS12], &provider), ); server_config.require_ems = false; let (client, server) = make_pair_for_configs(client_config, server_config); @@ -6359,10 +6590,11 @@ fn test_client_rejects_no_extended_master_secret_extension_when_require_ems_or_f #[test] fn test_server_rejects_no_extended_master_secret_extension_when_require_ems_or_fips() { let key_type = KeyType::Rsa2048; - let client_config = make_client_config(key_type); + let provider = provider::default_provider(); + let client_config = make_client_config(key_type, &provider); let mut server_config = finish_server_config( key_type, - server_config_builder_with_versions(&[&rustls::version::TLS12]), + server_config_builder_with_versions(&[&rustls::version::TLS12], &provider), ); if provider_is_fips() { assert!(server_config.require_ems); @@ -6398,19 +6630,20 @@ fn remove_ems_request(msg: &mut Message) -> Altered { #[cfg(feature = "tls12")] #[test] fn test_client_tls12_no_resume_after_server_downgrade() { - let mut client_config = common::make_client_config(KeyType::Ed25519); + let provider = provider::default_provider(); + let mut client_config = common::make_client_config(KeyType::Ed25519, &provider); let client_storage = Arc::new(ClientStorage::new()); client_config.resumption = Resumption::store(client_storage.clone()); let client_config = Arc::new(client_config); let server_config_1 = Arc::new(common::finish_server_config( KeyType::Ed25519, - server_config_builder_with_versions(&[&rustls::version::TLS13]), + server_config_builder_with_versions(&[&rustls::version::TLS13], &provider), )); let mut server_config_2 = common::finish_server_config( KeyType::Ed25519, - server_config_builder_with_versions(&[&rustls::version::TLS12]), + server_config_builder_with_versions(&[&rustls::version::TLS12], &provider), ); server_config_2.session_storage = Arc::new(rustls::server::NoServerSessionStorage {}); @@ -6493,7 +6726,11 @@ fn test_client_with_custom_verifier_can_accept_ecdsa_sha1_signatures() { .dangerous() .with_custom_certificate_verifier(Arc::new(MockServerVerifier::accepts_anything())) .with_no_client_auth(); - let server_config = make_server_config_with_kx_groups(KeyType::EcdsaP256, kx_groups.to_vec()); + let server_config = make_server_config_with_kx_groups( + KeyType::EcdsaP256, + kx_groups.to_vec(), + &provider::default_provider(), + ); let (mut client, mut server) = make_pair_for_configs(client_config, server_config); transfer(&mut client, &mut server); server.process_new_packets().unwrap(); @@ -6510,12 +6747,13 @@ fn test_client_with_custom_verifier_can_accept_ecdsa_sha1_signatures() { fn test_acceptor() { use rustls::server::Acceptor; - let client_config = Arc::new(make_client_config(KeyType::Ed25519)); + let provider = provider::default_provider(); + let client_config = Arc::new(make_client_config(KeyType::Ed25519, &provider)); let mut client = ClientConnection::new(client_config, server_name("localhost")).unwrap(); let mut buf = Vec::new(); client.write_tls(&mut buf).unwrap(); - let server_config = Arc::new(make_server_config(KeyType::Ed25519)); + let server_config = Arc::new(make_server_config(KeyType::Ed25519, &provider)); let mut acceptor = Acceptor::default(); acceptor .read_tls(&mut buf.as_slice()) @@ -6648,11 +6886,12 @@ fn test_no_warning_logging_during_successful_sessions() { CountingLogger::install(); CountingLogger::reset(); + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES { for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions(*kt, &[version]); + let client_config = make_client_config_with_versions(*kt, &[version], &provider); let (mut client, mut server) = - make_pair_for_configs(client_config, make_server_config(*kt)); + make_pair_for_configs(client_config, make_server_config(*kt, &provider)); do_handshake(&mut client, &mut server); } } @@ -6691,6 +6930,7 @@ fn test_secret_extraction_enabled() { // We support 3 different AEAD algorithms (AES-128-GCM mode, AES-256-GCM, and // Chacha20Poly1305), so that's 2*3 = 6 combinations to test. let kt = KeyType::Rsa2048; + let provider = provider::default_provider(); for suite in [ cipher_suite::TLS13_AES_128_GCM_SHA256, cipher_suite::TLS13_AES_256_GCM_SHA384, @@ -6708,7 +6948,7 @@ fn test_secret_extraction_enabled() { let mut server_config = ServerConfig::builder_with_provider( CryptoProvider { cipher_suites: vec![suite], - ..provider::default_provider() + ..provider.clone() } .into(), ) @@ -6721,7 +6961,7 @@ fn test_secret_extraction_enabled() { server_config.enable_secret_extraction = true; let server_config = Arc::new(server_config); - let mut client_config = make_client_config(kt); + let mut client_config = make_client_config(kt, &provider); client_config.enable_secret_extraction = true; let (mut client, mut server) = @@ -6854,7 +7094,7 @@ fn test_secret_extraction_disabled_or_too_early() { server_config.enable_secret_extraction = server_enable; let server_config = Arc::new(server_config); - let mut client_config = make_client_config(kt); + let mut client_config = make_client_config(kt, &provider); client_config.enable_secret_extraction = client_enable; let client_config = Arc::new(client_config); @@ -6896,12 +7136,13 @@ fn test_secret_extraction_disabled_or_too_early() { #[test] fn test_received_plaintext_backpressure() { let kt = KeyType::Rsa2048; + let provider = provider::default_provider(); let server_config = Arc::new( ServerConfig::builder_with_provider( CryptoProvider { cipher_suites: vec![cipher_suite::TLS13_AES_128_GCM_SHA256], - ..provider::default_provider() + ..provider.clone() } .into(), ) @@ -6912,7 +7153,7 @@ fn test_received_plaintext_backpressure() { .unwrap(), ); - let client_config = Arc::new(make_client_config(kt)); + let client_config = Arc::new(make_client_config(kt, &provider)); let (mut client, mut server) = make_pair_for_arc_configs(&client_config, &server_config); do_handshake(&mut client, &mut server); @@ -7153,12 +7394,13 @@ fn test_client_removes_tls12_session_if_server_sends_undecryptable_first_message } } + let provider = provider::default_provider(); let mut client_config = - make_client_config_with_versions(KeyType::Rsa2048, &[&rustls::version::TLS12]); + make_client_config_with_versions(KeyType::Rsa2048, &[&rustls::version::TLS12], &provider); let storage = Arc::new(ClientStorage::new()); client_config.resumption = Resumption::store(storage.clone()); let client_config = Arc::new(client_config); - let server_config = Arc::new(make_server_config(KeyType::Rsa2048)); + let server_config = Arc::new(make_server_config(KeyType::Rsa2048, &provider)); // successful handshake to allow resumption let (mut client, mut server) = make_pair_for_arc_configs(&client_config, &server_config); @@ -7194,7 +7436,7 @@ fn test_client_removes_tls12_session_if_server_sends_undecryptable_first_message #[test] fn test_client_fips_service_indicator() { assert_eq!( - make_client_config(KeyType::Rsa2048).fips(), + make_client_config(KeyType::Rsa2048, &provider::default_provider()).fips(), provider_is_fips() ); } @@ -7202,15 +7444,16 @@ fn test_client_fips_service_indicator() { #[test] fn test_server_fips_service_indicator() { assert_eq!( - make_server_config(KeyType::Rsa2048).fips(), + make_server_config(KeyType::Rsa2048, &provider::default_provider()).fips(), provider_is_fips() ); } #[test] fn test_connection_fips_service_indicator() { - let client_config = Arc::new(make_client_config(KeyType::Rsa2048)); - let server_config = Arc::new(make_server_config(KeyType::Rsa2048)); + let provider = provider::default_provider(); + let client_config = Arc::new(make_client_config(KeyType::Rsa2048, &provider)); + let server_config = Arc::new(make_server_config(KeyType::Rsa2048, &provider)); let conn_pair = make_pair_for_arc_configs(&client_config, &server_config); // Each connection's FIPS status should reflect the FIPS status of the config it was created // from. @@ -7224,7 +7467,7 @@ fn test_client_fips_service_indicator_includes_require_ems() { return; } - let mut client_config = make_client_config(KeyType::Rsa2048); + let mut client_config = make_client_config(KeyType::Rsa2048, &provider::default_provider()); assert!(client_config.fips()); client_config.require_ems = false; assert!(!client_config.fips()); @@ -7236,7 +7479,7 @@ fn test_server_fips_service_indicator_includes_require_ems() { return; } - let mut server_config = make_server_config(KeyType::Rsa2048); + let mut server_config = make_server_config(KeyType::Rsa2048, &provider::default_provider()); assert!(server_config.fips()); server_config.require_ems = false; assert!(!server_config.fips()); @@ -7300,7 +7543,11 @@ fn test_client_fips_service_indicator_includes_ech_hpke_suite() { #[test] fn test_complete_io_errors_if_close_notify_received_too_early() { - let mut server = ServerConnection::new(Arc::new(make_server_config(KeyType::Rsa2048))).unwrap(); + let mut server = ServerConnection::new(Arc::new(make_server_config( + KeyType::Rsa2048, + &provider::default_provider(), + ))) + .unwrap(); let client_hello_followed_by_close_notify_alert = b"\ \x16\x03\x01\x00\xc8\x01\x00\x00\xc4\x03\x03\xec\x12\xdd\x17\x64\ \xa4\x39\xfd\x7e\x8c\x85\x46\xb8\x4d\x1e\xa0\x6e\xb3\xd7\xa0\x51\ @@ -7329,7 +7576,7 @@ fn test_complete_io_errors_if_close_notify_received_too_early() { #[test] fn test_complete_io_with_no_io_needed() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); do_handshake(&mut client, &mut server); client .writer() @@ -7367,7 +7614,7 @@ fn test_complete_io_with_no_io_needed() { #[test] fn test_junk_after_close_notify_received() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); do_handshake(&mut client, &mut server); client .writer() @@ -7410,7 +7657,7 @@ fn test_junk_after_close_notify_received() { #[test] fn test_data_after_close_notify_is_ignored() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); do_handshake(&mut client, &mut server); client @@ -7442,7 +7689,7 @@ fn test_data_after_close_notify_is_ignored() { #[test] fn test_close_notify_sent_prior_to_handshake_complete() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); client.send_close_notify(); assert_eq!( do_handshake_until_error(&mut client, &mut server), @@ -7454,7 +7701,7 @@ fn test_close_notify_sent_prior_to_handshake_complete() { #[test] fn test_subsequent_close_notify_ignored() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); client.send_close_notify(); assert!(transfer(&mut client, &mut server) > 0); @@ -7465,7 +7712,7 @@ fn test_subsequent_close_notify_ignored() { #[test] fn test_second_close_notify_after_handshake() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); do_handshake(&mut client, &mut server); client.send_close_notify(); assert!(transfer(&mut client, &mut server) > 0); @@ -7478,7 +7725,7 @@ fn test_second_close_notify_after_handshake() { #[test] fn test_read_tls_artificial_eof_after_close_notify() { - let (mut client, mut server) = make_pair(KeyType::Rsa2048); + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); do_handshake(&mut client, &mut server); client.send_close_notify(); assert!(transfer(&mut client, &mut server) > 0); @@ -7497,14 +7744,15 @@ fn test_read_tls_artificial_eof_after_close_notify() { fn test_pinned_ocsp_response_given_to_custom_server_cert_verifier() { let ocsp_response = b"hello-ocsp-world!"; let kt = KeyType::EcdsaP256; + let provider = provider::default_provider(); for version in rustls::ALL_VERSIONS { - let server_config = server_config_builder() + let server_config = server_config_builder(&provider) .with_no_client_auth() .with_single_cert_with_ocsp(kt.get_chain(), kt.get_key(), ocsp_response.to_vec()) .unwrap(); - let client_config = client_config_builder_with_versions(&[version]) + let client_config = client_config_builder_with_versions(&[version], &provider) .dangerous() .with_custom_certificate_verifier(Arc::new(MockServerVerifier::expects_ocsp_response( ocsp_response, @@ -7521,9 +7769,10 @@ fn test_pinned_ocsp_response_given_to_custom_server_cert_verifier() { fn test_server_uses_cached_compressed_certificates() { static COMPRESS_COUNT: AtomicUsize = AtomicUsize::new(0); - let mut server_config = make_server_config(KeyType::Rsa2048); + let provider = provider::default_provider(); + let mut server_config = make_server_config(KeyType::Rsa2048, &provider); server_config.cert_compressors = vec![&CountingCompressor]; - let mut client_config = make_client_config(KeyType::Rsa2048); + let mut client_config = make_client_config(KeyType::Rsa2048, &provider); client_config.resumption = Resumption::disabled(); let server_config = Arc::new(server_config); @@ -7559,9 +7808,10 @@ fn test_server_uses_cached_compressed_certificates() { #[test] fn test_server_uses_uncompressed_certificate_if_compression_fails() { - let mut server_config = make_server_config(KeyType::Rsa2048); + let provider = provider::default_provider(); + let mut server_config = make_server_config(KeyType::Rsa2048, &provider); server_config.cert_compressors = vec![&FailingCompressor]; - let mut client_config = make_client_config(KeyType::Rsa2048); + let mut client_config = make_client_config(KeyType::Rsa2048, &provider); client_config.cert_decompressors = vec![&NeverDecompressor]; let (mut client, mut server) = make_pair_for_configs(client_config, server_config); @@ -7570,9 +7820,11 @@ fn test_server_uses_uncompressed_certificate_if_compression_fails() { #[test] fn test_client_uses_uncompressed_certificate_if_compression_fails() { - let mut server_config = make_server_config_with_mandatory_client_auth(KeyType::Rsa2048); + let provider = provider::default_provider(); + let mut server_config = + make_server_config_with_mandatory_client_auth(KeyType::Rsa2048, &provider); server_config.cert_decompressors = vec![&NeverDecompressor]; - let mut client_config = make_client_config_with_auth(KeyType::Rsa2048); + let mut client_config = make_client_config_with_auth(KeyType::Rsa2048, &provider); client_config.cert_compressors = vec![&FailingCompressor]; let (mut client, mut server) = make_pair_for_configs(client_config, server_config); @@ -7619,10 +7871,11 @@ impl rustls::compress::CertDecompressor for NeverDecompressor { fn test_server_can_opt_out_of_compression_cache() { static COMPRESS_COUNT: AtomicUsize = AtomicUsize::new(0); - let mut server_config = make_server_config(KeyType::Rsa2048); + let provider = provider::default_provider(); + let mut server_config = make_server_config(KeyType::Rsa2048, &provider); server_config.cert_compressors = vec![&AlwaysInteractiveCompressor]; server_config.cert_compression_cache = Arc::new(rustls::compress::CompressionCache::Disabled); - let mut client_config = make_client_config(KeyType::Rsa2048); + let mut client_config = make_client_config(KeyType::Rsa2048, &provider); client_config.resumption = Resumption::disabled(); let server_config = Arc::new(server_config); @@ -7659,9 +7912,10 @@ fn test_server_can_opt_out_of_compression_cache() { #[test] fn test_cert_decompression_by_client_produces_invalid_cert_payload() { - let mut server_config = make_server_config(KeyType::Rsa2048); + let provider = provider::default_provider(); + let mut server_config = make_server_config(KeyType::Rsa2048, &provider); server_config.cert_compressors = vec![&IdentityCompressor]; - let mut client_config = make_client_config(KeyType::Rsa2048); + let mut client_config = make_client_config(KeyType::Rsa2048, &provider); client_config.cert_decompressors = vec![&GarbageDecompressor]; let (mut client, mut server) = make_pair_for_configs(client_config, server_config); @@ -7680,9 +7934,11 @@ fn test_cert_decompression_by_client_produces_invalid_cert_payload() { #[test] fn test_cert_decompression_by_server_produces_invalid_cert_payload() { - let mut server_config = make_server_config_with_mandatory_client_auth(KeyType::Rsa2048); + let provider = provider::default_provider(); + let mut server_config = + make_server_config_with_mandatory_client_auth(KeyType::Rsa2048, &provider); server_config.cert_decompressors = vec![&GarbageDecompressor]; - let mut client_config = make_client_config_with_auth(KeyType::Rsa2048); + let mut client_config = make_client_config_with_auth(KeyType::Rsa2048, &provider); client_config.cert_compressors = vec![&IdentityCompressor]; let (mut client, mut server) = make_pair_for_configs(client_config, server_config); @@ -7701,9 +7957,11 @@ fn test_cert_decompression_by_server_produces_invalid_cert_payload() { #[test] fn test_cert_decompression_by_server_fails() { - let mut server_config = make_server_config_with_mandatory_client_auth(KeyType::Rsa2048); + let provider = provider::default_provider(); + let mut server_config = + make_server_config_with_mandatory_client_auth(KeyType::Rsa2048, &provider); server_config.cert_decompressors = vec![&FailingDecompressor]; - let mut client_config = make_client_config_with_auth(KeyType::Rsa2048); + let mut client_config = make_client_config_with_auth(KeyType::Rsa2048, &provider); client_config.cert_compressors = vec![&IdentityCompressor]; let (mut client, mut server) = make_pair_for_configs(client_config, server_config); @@ -7723,8 +7981,9 @@ fn test_cert_decompression_by_server_fails() { #[cfg(feature = "zlib")] #[test] fn test_cert_decompression_by_server_would_result_in_excessively_large_cert() { - let server_config = make_server_config_with_mandatory_client_auth(KeyType::Rsa2048); - let mut client_config = make_client_config_with_auth(KeyType::Rsa2048); + let provider = provider::default_provider(); + let server_config = make_server_config_with_mandatory_client_auth(KeyType::Rsa2048, &provider); + let mut client_config = make_client_config_with_auth(KeyType::Rsa2048, &provider); let big_cert = CertificateDer::from(vec![0u8; 0xffff]); let key = provider::default_provider() @@ -7825,9 +8084,10 @@ impl io::Write for FakeStream<'_> { #[test] fn test_illegal_server_renegotiation_attempt_after_tls13_handshake() { + let provider = provider::default_provider(); let client_config = - make_client_config_with_versions(KeyType::Rsa2048, &[&rustls::version::TLS13]); - let mut server_config = make_server_config(KeyType::Rsa2048); + make_client_config_with_versions(KeyType::Rsa2048, &[&rustls::version::TLS13], &provider); + let mut server_config = make_server_config(KeyType::Rsa2048, &provider); server_config.enable_secret_extraction = true; let (mut client, mut server) = make_pair_for_configs(client_config, server_config); @@ -7859,9 +8119,10 @@ fn test_illegal_server_renegotiation_attempt_after_tls13_handshake() { #[cfg(feature = "tls12")] #[test] fn test_illegal_server_renegotiation_attempt_after_tls12_handshake() { + let provider = provider::default_provider(); let client_config = - make_client_config_with_versions(KeyType::Rsa2048, &[&rustls::version::TLS12]); - let mut server_config = make_server_config(KeyType::Rsa2048); + make_client_config_with_versions(KeyType::Rsa2048, &[&rustls::version::TLS12], &provider); + let mut server_config = make_server_config(KeyType::Rsa2048, &provider); server_config.enable_secret_extraction = true; let (mut client, mut server) = make_pair_for_configs(client_config, server_config); @@ -7898,10 +8159,11 @@ fn test_illegal_server_renegotiation_attempt_after_tls12_handshake() { #[test] fn test_illegal_client_renegotiation_attempt_after_tls13_handshake() { + let provider = provider::default_provider(); let mut client_config = - make_client_config_with_versions(KeyType::Rsa2048, &[&rustls::version::TLS13]); + make_client_config_with_versions(KeyType::Rsa2048, &[&rustls::version::TLS13], &provider); client_config.enable_secret_extraction = true; - let server_config = make_server_config(KeyType::Rsa2048); + let server_config = make_server_config(KeyType::Rsa2048, &provider); let (mut client, mut server) = make_pair_for_configs(client_config, server_config); do_handshake(&mut client, &mut server); @@ -7926,9 +8188,10 @@ fn test_illegal_client_renegotiation_attempt_after_tls13_handshake() { #[cfg(feature = "tls12")] #[test] fn test_illegal_client_renegotiation_attempt_during_tls12_handshake() { - let server_config = make_server_config(KeyType::Rsa2048); + let provider = provider::default_provider(); + let server_config = make_server_config(KeyType::Rsa2048, &provider); let client_config = - make_client_config_with_versions(KeyType::Rsa2048, &[&rustls::version::TLS12]); + make_client_config_with_versions(KeyType::Rsa2048, &[&rustls::version::TLS12], &provider); let (mut client, mut server) = make_pair_for_configs(client_config, server_config); let mut client_hello = vec![]; @@ -7955,7 +8218,7 @@ fn test_illegal_client_renegotiation_attempt_during_tls12_handshake() { #[test] fn test_refresh_traffic_keys_during_handshake() { - let (mut client, mut server) = make_pair(KeyType::Ed25519); + let (mut client, mut server) = make_pair(KeyType::Ed25519, &provider::default_provider()); assert_eq!( client .refresh_traffic_keys() @@ -7972,7 +8235,7 @@ fn test_refresh_traffic_keys_during_handshake() { #[test] fn test_refresh_traffic_keys() { - let (mut client, mut server) = make_pair(KeyType::Ed25519); + let (mut client, mut server) = make_pair(KeyType::Ed25519, &provider::default_provider()); do_handshake(&mut client, &mut server); fn check_both_directions(client: &mut ClientConnection, server: &mut ServerConnection) { @@ -8181,7 +8444,7 @@ fn tls13_packed_handshake() { #[test] fn large_client_hello() { - let (_, mut server) = make_pair(KeyType::Rsa2048); + let (_, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); let hello = include_bytes!("data/bug2227-clienthello.bin"); let mut cursor = io::Cursor::new(hello); loop { @@ -8222,7 +8485,7 @@ fn hybrid_kx_component_share_offered_if_supported_seperately() { .with_safe_default_protocol_versions() .unwrap(), ); - let server_config = make_server_config(kt); + let server_config = make_server_config(kt, &provider::default_provider()); let (client, server) = make_pair_for_configs(client_config, server_config); let (mut client, mut server) = (client.into(), server.into()); @@ -8248,7 +8511,7 @@ fn hybrid_kx_component_share_not_offered_unless_supported_seperately() { .with_safe_default_protocol_versions() .unwrap(), ); - let server_config = make_server_config(kt); + let server_config = make_server_config(kt, &provider::default_provider()); let (client, server) = make_pair_for_configs(client_config, server_config); let (mut client, mut server) = (client.into(), server.into()); @@ -8274,10 +8537,11 @@ fn hybrid_kx_component_share_offered_but_server_chooses_something_else() { .with_safe_default_protocol_versions() .unwrap(), ); - let server_config = make_server_config(kt); + let provider = provider::default_provider(); + let server_config = make_server_config(kt, &provider); let (mut client_1, mut server) = make_pair_for_configs(client_config, server_config); - let (mut client_2, _) = make_pair(kt); + let (mut client_2, _) = make_pair(kt, &provider); // client_2 supplies the ClientHello, client_1 receives the ServerHello transfer(&mut client_2, &mut server); diff --git a/rustls/tests/client_cert_verifier.rs b/rustls/tests/client_cert_verifier.rs index ea9ef1a121e..381c16d430b 100644 --- a/rustls/tests/client_cert_verifier.rs +++ b/rustls/tests/client_cert_verifier.rs @@ -37,7 +37,7 @@ fn server_config_with_verifier( kt: KeyType, client_cert_verifier: MockClientVerifier, ) -> ServerConfig { - server_config_builder() + server_config_builder(&provider::default_provider()) .with_client_cert_verifier(Arc::new(client_cert_verifier)) .with_single_cert(kt.get_chain(), kt.get_key()) .unwrap() @@ -53,7 +53,8 @@ fn client_verifier_works() { let server_config = Arc::new(server_config); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions_with_auth(*kt, &[version]); + let client_config = + make_client_config_with_versions_with_auth(*kt, &[version], &provider); let (mut client, mut server) = make_pair_for_arc_configs(&Arc::new(client_config.clone()), &server_config); let err = do_handshake_until_error(&mut client, &mut server); @@ -73,7 +74,8 @@ fn client_verifier_no_schemes() { let server_config = Arc::new(server_config); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions_with_auth(*kt, &[version]); + let client_config = + make_client_config_with_versions_with_auth(*kt, &[version], &provider); let (mut client, mut server) = make_pair_for_arc_configs(&Arc::new(client_config.clone()), &server_config); let err = do_handshake_until_error(&mut client, &mut server); @@ -97,7 +99,7 @@ fn client_verifier_no_auth_yes_root() { let server_config = Arc::new(server_config); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions(*kt, &[version]); + let client_config = make_client_config_with_versions(*kt, &[version], &provider); let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); @@ -125,7 +127,8 @@ fn client_verifier_fails_properly() { let server_config = Arc::new(server_config); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions_with_auth(*kt, &[version]); + let client_config = + make_client_config_with_versions_with_auth(*kt, &[version], &provider); let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); diff --git a/rustls/tests/common/mod.rs b/rustls/tests/common/mod.rs index aa40837c8b9..f377605ee6c 100644 --- a/rustls/tests/common/mod.rs +++ b/rustls/tests/common/mod.rs @@ -454,13 +454,15 @@ impl KeyType { } } -pub fn server_config_builder() -> rustls::ConfigBuilder { +pub fn server_config_builder( + provider: &CryptoProvider, +) -> rustls::ConfigBuilder { // ensure `ServerConfig::builder()` is covered, even though it is // equivalent to `builder_with_provider(provider::provider().into())`. if exactly_one_provider() { rustls::ServerConfig::builder() } else { - rustls::ServerConfig::builder_with_provider(provider::default_provider().into()) + rustls::ServerConfig::builder_with_provider(provider.clone().into()) .with_safe_default_protocol_versions() .unwrap() } @@ -468,23 +470,26 @@ pub fn server_config_builder() -> rustls::ConfigBuilder rustls::ConfigBuilder { if exactly_one_provider() { rustls::ServerConfig::builder_with_protocol_versions(versions) } else { - rustls::ServerConfig::builder_with_provider(provider::default_provider().into()) + rustls::ServerConfig::builder_with_provider(provider.clone().into()) .with_protocol_versions(versions) .unwrap() } } -pub fn client_config_builder() -> rustls::ConfigBuilder { +pub fn client_config_builder( + provider: &CryptoProvider, +) -> rustls::ConfigBuilder { // ensure `ClientConfig::builder()` is covered, even though it is // equivalent to `builder_with_provider(provider::provider().into())`. if exactly_one_provider() { rustls::ClientConfig::builder() } else { - rustls::ClientConfig::builder_with_provider(provider::default_provider().into()) + rustls::ClientConfig::builder_with_provider(provider.clone().into()) .with_safe_default_protocol_versions() .unwrap() } @@ -492,11 +497,12 @@ pub fn client_config_builder() -> rustls::ConfigBuilder rustls::ConfigBuilder { if exactly_one_provider() { rustls::ClientConfig::builder_with_protocol_versions(versions) } else { - rustls::ClientConfig::builder_with_provider(provider::default_provider().into()) + rustls::ClientConfig::builder_with_provider(provider.clone().into()) .with_protocol_versions(versions) .unwrap() } @@ -511,27 +517,29 @@ pub fn finish_server_config( .unwrap() } -pub fn make_server_config(kt: KeyType) -> ServerConfig { - finish_server_config(kt, server_config_builder()) +pub fn make_server_config(kt: KeyType, provider: &CryptoProvider) -> ServerConfig { + finish_server_config(kt, server_config_builder(provider)) } pub fn make_server_config_with_versions( kt: KeyType, versions: &[&'static rustls::SupportedProtocolVersion], + provider: &CryptoProvider, ) -> ServerConfig { - finish_server_config(kt, server_config_builder_with_versions(versions)) + finish_server_config(kt, server_config_builder_with_versions(versions, provider)) } pub fn make_server_config_with_kx_groups( kt: KeyType, kx_groups: Vec<&'static dyn rustls::crypto::SupportedKxGroup>, + provider: &CryptoProvider, ) -> ServerConfig { finish_server_config( kt, ServerConfig::builder_with_provider( CryptoProvider { kx_groups, - ..provider::default_provider() + ..provider.clone() } .into(), ) @@ -558,38 +566,47 @@ pub fn get_client_root_store(kt: KeyType) -> Arc { pub fn make_server_config_with_mandatory_client_auth_crls( kt: KeyType, crls: Vec>, + provider: &CryptoProvider, ) -> ServerConfig { make_server_config_with_client_verifier( kt, - webpki_client_verifier_builder(get_client_root_store(kt)).with_crls(crls), + webpki_client_verifier_builder(get_client_root_store(kt), provider).with_crls(crls), + provider, ) } -pub fn make_server_config_with_mandatory_client_auth(kt: KeyType) -> ServerConfig { +pub fn make_server_config_with_mandatory_client_auth( + kt: KeyType, + provider: &CryptoProvider, +) -> ServerConfig { make_server_config_with_client_verifier( kt, - webpki_client_verifier_builder(get_client_root_store(kt)), + webpki_client_verifier_builder(get_client_root_store(kt), provider), + provider, ) } pub fn make_server_config_with_optional_client_auth( kt: KeyType, crls: Vec>, + provider: &CryptoProvider, ) -> ServerConfig { make_server_config_with_client_verifier( kt, - webpki_client_verifier_builder(get_client_root_store(kt)) + webpki_client_verifier_builder(get_client_root_store(kt), provider) .with_crls(crls) .allow_unknown_revocation_status() .allow_unauthenticated(), + provider, ) } pub fn make_server_config_with_client_verifier( kt: KeyType, verifier_builder: ClientCertVerifierBuilder, + provider: &CryptoProvider, ) -> ServerConfig { - server_config_builder() + server_config_builder(provider) .with_client_cert_verifier(verifier_builder.build().unwrap()) .with_single_cert(kt.get_chain(), kt.get_key()) .unwrap() @@ -607,7 +624,7 @@ pub fn make_server_config_with_raw_key_support( )); client_verifier.expect_raw_public_keys = true; // We don't support tls1.2 for Raw Public Keys, hence the version is hard-coded. - server_config_builder_with_versions(&[&rustls::version::TLS13]) + server_config_builder_with_versions(&[&rustls::version::TLS13], provider) .with_client_cert_verifier(Arc::new(client_verifier)) .with_cert_resolver(server_cert_resolver) } @@ -622,7 +639,7 @@ pub fn make_client_config_with_raw_key_support( .unwrap(), )); // We don't support tls1.2 for Raw Public Keys, hence the version is hard-coded. - client_config_builder_with_versions(&[&rustls::version::TLS13]) + client_config_builder_with_versions(&[&rustls::version::TLS13], provider) .dangerous() .with_custom_certificate_verifier(server_verifier) .with_client_cert_resolver(client_cert_resolver) @@ -681,18 +698,19 @@ pub fn finish_client_config_with_creds( .unwrap() } -pub fn make_client_config(kt: KeyType) -> ClientConfig { - finish_client_config(kt, client_config_builder()) +pub fn make_client_config(kt: KeyType, provider: &CryptoProvider) -> ClientConfig { + finish_client_config(kt, client_config_builder(provider)) } pub fn make_client_config_with_kx_groups( kt: KeyType, kx_groups: Vec<&'static dyn rustls::crypto::SupportedKxGroup>, + provider: &CryptoProvider, ) -> ClientConfig { let builder = ClientConfig::builder_with_provider( CryptoProvider { kx_groups, - ..provider::default_provider() + ..provider.clone() } .into(), ) @@ -704,49 +722,61 @@ pub fn make_client_config_with_kx_groups( pub fn make_client_config_with_versions( kt: KeyType, versions: &[&'static rustls::SupportedProtocolVersion], + provider: &CryptoProvider, ) -> ClientConfig { - finish_client_config(kt, client_config_builder_with_versions(versions)) + finish_client_config(kt, client_config_builder_with_versions(versions, provider)) } -pub fn make_client_config_with_auth(kt: KeyType) -> ClientConfig { - finish_client_config_with_creds(kt, client_config_builder()) +pub fn make_client_config_with_auth(kt: KeyType, provider: &CryptoProvider) -> ClientConfig { + finish_client_config_with_creds(kt, client_config_builder(provider)) } pub fn make_client_config_with_versions_with_auth( kt: KeyType, versions: &[&'static rustls::SupportedProtocolVersion], + provider: &CryptoProvider, ) -> ClientConfig { - finish_client_config_with_creds(kt, client_config_builder_with_versions(versions)) + finish_client_config_with_creds(kt, client_config_builder_with_versions(versions, provider)) } pub fn make_client_config_with_verifier( versions: &[&'static rustls::SupportedProtocolVersion], verifier_builder: ServerCertVerifierBuilder, + provider: &CryptoProvider, ) -> ClientConfig { - client_config_builder_with_versions(versions) + client_config_builder_with_versions(versions, provider) .dangerous() .with_custom_certificate_verifier(verifier_builder.build().unwrap()) .with_no_client_auth() } -pub fn webpki_client_verifier_builder(roots: Arc) -> ClientCertVerifierBuilder { +pub fn webpki_client_verifier_builder( + roots: Arc, + provider: &CryptoProvider, +) -> ClientCertVerifierBuilder { if exactly_one_provider() { WebPkiClientVerifier::builder(roots) } else { - WebPkiClientVerifier::builder_with_provider(roots, provider::default_provider().into()) + WebPkiClientVerifier::builder_with_provider(roots, provider.clone().into()) } } -pub fn webpki_server_verifier_builder(roots: Arc) -> ServerCertVerifierBuilder { +pub fn webpki_server_verifier_builder( + roots: Arc, + provider: &CryptoProvider, +) -> ServerCertVerifierBuilder { if exactly_one_provider() { WebPkiServerVerifier::builder(roots) } else { - WebPkiServerVerifier::builder_with_provider(roots, provider::default_provider().into()) + WebPkiServerVerifier::builder_with_provider(roots, provider.clone().into()) } } -pub fn make_pair(kt: KeyType) -> (ClientConnection, ServerConnection) { - make_pair_for_configs(make_client_config(kt), make_server_config(kt)) +pub fn make_pair(kt: KeyType, provider: &CryptoProvider) -> (ClientConnection, ServerConnection) { + make_pair_for_configs( + make_client_config(kt, provider), + make_server_config(kt, provider), + ) } pub fn make_pair_for_configs( @@ -1251,7 +1281,7 @@ impl MockClientVerifier { provider: &CryptoProvider, ) -> Self { Self { - parent: webpki_client_verifier_builder(get_client_root_store(kt)) + parent: webpki_client_verifier_builder(get_client_root_store(kt), provider) .build() .unwrap(), verified, diff --git a/rustls/tests/key_log_file_env.rs b/rustls/tests/key_log_file_env.rs index 0f2c889549b..8f18c1a141b 100644 --- a/rustls/tests/key_log_file_env.rs +++ b/rustls/tests/key_log_file_env.rs @@ -37,11 +37,13 @@ use common::{ #[test] fn exercise_key_log_file_for_client() { serialized(|| { - let server_config = Arc::new(make_server_config(KeyType::Rsa2048)); + let provider = provider::default_provider(); + let server_config = Arc::new(make_server_config(KeyType::Rsa2048, &provider)); unsafe { env::set_var("SSLKEYLOGFILE", "./sslkeylogfile.txt") }; for version in rustls::ALL_VERSIONS { - let mut client_config = make_client_config_with_versions(KeyType::Rsa2048, &[version]); + let mut client_config = + make_client_config_with_versions(KeyType::Rsa2048, &[version], &provider); client_config.key_log = Arc::new(rustls::KeyLogFile::new()); let (mut client, mut server) = @@ -59,7 +61,8 @@ fn exercise_key_log_file_for_client() { #[test] fn exercise_key_log_file_for_server() { serialized(|| { - let mut server_config = make_server_config(KeyType::Rsa2048); + let provider = provider::default_provider(); + let mut server_config = make_server_config(KeyType::Rsa2048, &provider); unsafe { env::set_var("SSLKEYLOGFILE", "./sslkeylogfile.txt") }; server_config.key_log = Arc::new(rustls::KeyLogFile::new()); @@ -67,7 +70,8 @@ fn exercise_key_log_file_for_server() { let server_config = Arc::new(server_config); for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions(KeyType::Rsa2048, &[version]); + let client_config = + make_client_config_with_versions(KeyType::Rsa2048, &[version], &provider); let (mut client, mut server) = make_pair_for_arc_configs(&Arc::new(client_config), &server_config); diff --git a/rustls/tests/server_cert_verifier.rs b/rustls/tests/server_cert_verifier.rs index d0eadac3863..b0d2508b65d 100644 --- a/rustls/tests/server_cert_verifier.rs +++ b/rustls/tests/server_cert_verifier.rs @@ -32,13 +32,14 @@ use x509_parser::x509::X509Name; #[test] fn client_can_override_certificate_verification() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES.iter() { let verifier = Arc::new(MockServerVerifier::accepts_anything()); - let server_config = Arc::new(make_server_config(*kt)); + let server_config = Arc::new(make_server_config(*kt, &provider)); for version in rustls::ALL_VERSIONS { - let mut client_config = make_client_config_with_versions(*kt, &[version]); + let mut client_config = make_client_config_with_versions(*kt, &[version], &provider); client_config .dangerous() .set_certificate_verifier(verifier.clone()); @@ -52,15 +53,16 @@ fn client_can_override_certificate_verification() { #[test] fn client_can_override_certificate_verification_and_reject_certificate() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES.iter() { let verifier = Arc::new(MockServerVerifier::rejects_certificate( Error::InvalidMessage(InvalidMessage::HandshakePayloadTooLarge), )); - let server_config = Arc::new(make_server_config(*kt)); + let server_config = Arc::new(make_server_config(*kt, &provider)); for version in rustls::ALL_VERSIONS { - let mut client_config = make_client_config_with_versions(*kt, &[version]); + let mut client_config = make_client_config_with_versions(*kt, &[version], &provider); client_config .dangerous() .set_certificate_verifier(verifier.clone()); @@ -84,8 +86,10 @@ fn client_can_override_certificate_verification_and_reject_certificate() { #[cfg(feature = "tls12")] #[test] fn client_can_override_certificate_verification_and_reject_tls12_signatures() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES.iter() { - let mut client_config = make_client_config_with_versions(*kt, &[&rustls::version::TLS12]); + let mut client_config = + make_client_config_with_versions(*kt, &[&rustls::version::TLS12], &provider); let verifier = Arc::new(MockServerVerifier::rejects_tls12_signatures( Error::InvalidMessage(InvalidMessage::HandshakePayloadTooLarge), )); @@ -94,7 +98,7 @@ fn client_can_override_certificate_verification_and_reject_tls12_signatures() { .dangerous() .set_certificate_verifier(verifier); - let server_config = Arc::new(make_server_config(*kt)); + let server_config = Arc::new(make_server_config(*kt, &provider)); let (mut client, mut server) = make_pair_for_arc_configs(&Arc::new(client_config), &server_config); @@ -113,8 +117,13 @@ fn client_can_override_certificate_verification_and_reject_tls12_signatures() { #[test] fn client_can_override_certificate_verification_and_reject_tls13_signatures() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES.iter() { - let mut client_config = make_client_config_with_versions(*kt, &[&rustls::version::TLS13]); + let mut client_config = make_client_config_with_versions( + *kt, + &[&rustls::version::TLS13], + &provider::default_provider(), + ); let verifier = Arc::new(MockServerVerifier::rejects_tls13_signatures( Error::InvalidMessage(InvalidMessage::HandshakePayloadTooLarge), )); @@ -123,7 +132,7 @@ fn client_can_override_certificate_verification_and_reject_tls13_signatures() { .dangerous() .set_certificate_verifier(verifier); - let server_config = Arc::new(make_server_config(*kt)); + let server_config = Arc::new(make_server_config(*kt, &provider)); let (mut client, mut server) = make_pair_for_arc_configs(&Arc::new(client_config), &server_config); @@ -142,13 +151,14 @@ fn client_can_override_certificate_verification_and_reject_tls13_signatures() { #[test] fn client_can_override_certificate_verification_and_offer_no_signature_schemes() { + let provider = provider::default_provider(); for kt in ALL_KEY_TYPES.iter() { let verifier = Arc::new(MockServerVerifier::offers_no_signature_schemes()); - let server_config = Arc::new(make_server_config(*kt)); + let server_config = Arc::new(make_server_config(*kt, &provider)); for version in rustls::ALL_VERSIONS { - let mut client_config = make_client_config_with_versions(*kt, &[version]); + let mut client_config = make_client_config_with_versions(*kt, &[version], &provider); client_config .dangerous() .set_certificate_verifier(verifier.clone()); @@ -171,7 +181,8 @@ fn client_can_override_certificate_verification_and_offer_no_signature_schemes() #[test] fn cas_extension_in_client_hello_if_server_verifier_requests_it() { - let server_config = Arc::new(make_server_config(KeyType::Rsa2048)); + let provider = provider::default_provider(); + let server_config = Arc::new(make_server_config(KeyType::Rsa2048, &provider)); let mut root_cert_store = RootCertStore::empty(); root_cert_store @@ -180,7 +191,7 @@ fn cas_extension_in_client_hello_if_server_verifier_requests_it() { let server_verifier = WebPkiServerVerifier::builder_with_provider( Arc::new(root_cert_store), - Arc::new(provider::default_provider()), + Arc::new(provider.clone()), ) .build() .unwrap(); @@ -196,7 +207,7 @@ fn cas_extension_in_client_hello_if_server_verifier_requests_it() { for (protocol_version, cas_extension_expected) in [(&TLS12, false), (&TLS13, true)] { let client_config = Arc::new( - client_config_builder_with_versions(&[protocol_version]) + client_config_builder_with_versions(&[protocol_version], &provider) .dangerous() .with_custom_certificate_verifier(cas_sending_server_verifier.clone()) .with_no_client_auth(), @@ -227,6 +238,7 @@ fn cas_extension_in_client_hello_if_server_verifier_requests_it() { #[test] fn client_can_request_certain_trusted_cas() { + let provider = provider::default_provider(); // These keys have CAs with different names, which our test needs. // They also share the same sigalgs, so the server won't pick one over the other based on sigalgs. let key_types = [KeyType::Rsa2048, KeyType::Rsa3072, KeyType::Rsa4096]; @@ -238,7 +250,7 @@ fn client_can_request_certain_trusted_cas() { kt.ca_distinguished_name() .to_vec() .into(), - kt.certified_key_with_cert_chain(&provider::default_provider()) + kt.certified_key_with_cert_chain(&provider) .unwrap(), ) }) @@ -246,7 +258,7 @@ fn client_can_request_certain_trusted_cas() { ); let server_config = Arc::new( - server_config_builder() + server_config_builder(&provider) .with_no_client_auth() .with_cert_resolver(Arc::new(cert_resolver.clone())), ); @@ -260,7 +272,7 @@ fn client_can_request_certain_trusted_cas() { .unwrap(); let server_verifier = WebPkiServerVerifier::builder_with_provider( Arc::new(root_store), - Arc::new(provider::default_provider()), + Arc::new(provider.clone()), ) .build() .unwrap(); @@ -274,7 +286,7 @@ fn client_can_request_certain_trusted_cas() { )], }); - let cas_sending_client_config = client_config_builder() + let cas_sending_client_config = client_config_builder(&provider) .dangerous() .with_custom_certificate_verifier(cas_sending_server_verifier) .with_no_client_auth(); @@ -283,7 +295,7 @@ fn client_can_request_certain_trusted_cas() { make_pair_for_arc_configs(&Arc::new(cas_sending_client_config), &server_config); do_handshake(&mut client, &mut server); - let cas_unaware_client_config = client_config_builder() + let cas_unaware_client_config = client_config_builder(&provider) .dangerous() .with_custom_certificate_verifier(server_verifier) .with_no_client_auth(); diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index 706f7e16e98..f38d16a2843 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -115,8 +115,10 @@ fn handshake_config( version: &'static rustls::SupportedProtocolVersion, editor: impl Fn(&mut ClientConfig, &mut ServerConfig), ) -> Outcome { - let mut server_config = make_server_config_with_versions(KeyType::Rsa2048, &[version]); - let mut client_config = make_client_config(KeyType::Rsa2048); + let provider = provider::default_provider(); + let mut server_config = + make_server_config_with_versions(KeyType::Rsa2048, &[version], &provider); + let mut client_config = make_client_config(KeyType::Rsa2048, &provider); editor(&mut client_config, &mut server_config); run( @@ -129,11 +131,13 @@ fn handshake_config( #[test] fn app_data_client_to_server() { + let provider = provider::default_provider(); let expected: &[_] = b"hello"; for version in rustls::ALL_VERSIONS { eprintln!("{version:?}"); - let server_config = make_server_config_with_versions(KeyType::Rsa2048, &[version]); - let client_config = make_client_config(KeyType::Rsa2048); + let server_config = + make_server_config_with_versions(KeyType::Rsa2048, &[version], &provider); + let client_config = make_client_config(KeyType::Rsa2048, &provider); let mut client_actions = Actions { app_data_to_send: Some(expected), @@ -163,11 +167,13 @@ fn app_data_client_to_server() { #[test] fn app_data_server_to_client() { + let provider = provider::default_provider(); let expected: &[_] = b"hello"; for version in rustls::ALL_VERSIONS { eprintln!("{version:?}"); - let server_config = make_server_config_with_versions(KeyType::Rsa2048, &[version]); - let client_config = make_client_config(KeyType::Rsa2048); + let server_config = + make_server_config_with_versions(KeyType::Rsa2048, &[version], &provider); + let client_config = make_client_config(KeyType::Rsa2048, &provider); let mut server_actions = Actions { app_data_to_send: Some(expected), @@ -197,13 +203,15 @@ fn app_data_server_to_client() { #[test] fn early_data() { + let provider = provider::default_provider(); let expected: &[_] = b"hello"; - let mut server_config = make_server_config(KeyType::Rsa2048); + let mut server_config = make_server_config(KeyType::Rsa2048, &provider); server_config.max_early_data_size = 128; let server_config = Arc::new(server_config); - let mut client_config = make_client_config_with_versions(KeyType::Rsa2048, &[&TLS13]); + let mut client_config = + make_client_config_with_versions(KeyType::Rsa2048, &[&TLS13], &provider); client_config.enable_early_data = true; let client_config = Arc::new(client_config); @@ -426,10 +434,12 @@ fn run( #[test] fn close_notify_client_to_server() { + let provider = provider::default_provider(); for version in rustls::ALL_VERSIONS { eprintln!("{version:?}"); - let server_config = make_server_config_with_versions(KeyType::Rsa2048, &[version]); - let client_config = make_client_config(KeyType::Rsa2048); + let server_config = + make_server_config_with_versions(KeyType::Rsa2048, &[version], &provider); + let client_config = make_client_config(KeyType::Rsa2048, &provider); let mut client_actions = Actions { send_close_notify: true, @@ -450,10 +460,12 @@ fn close_notify_client_to_server() { #[test] fn close_notify_server_to_client() { + let provider = provider::default_provider(); for version in rustls::ALL_VERSIONS { eprintln!("{version:?}"); - let server_config = make_server_config_with_versions(KeyType::Rsa2048, &[version]); - let client_config = make_client_config(KeyType::Rsa2048); + let server_config = + make_server_config_with_versions(KeyType::Rsa2048, &[version], &provider); + let client_config = make_client_config(KeyType::Rsa2048, &provider); let mut server_actions = Actions { send_close_notify: true, @@ -725,7 +737,7 @@ fn refresh_traffic_keys_automatically() { .unwrap(), ); - let server_config = make_server_config(KeyType::Rsa2048); + let server_config = make_server_config(KeyType::Rsa2048, &provider::default_provider()); let mut outcome = run( Arc::new(client_config), &mut NO_ACTIONS.clone(), @@ -794,7 +806,7 @@ fn tls12_connection_fails_after_key_reaches_confidentiality_limit() { .unwrap(), ); - let server_config = make_server_config(KeyType::Ed25519); + let server_config = make_server_config(KeyType::Ed25519, &provider::default_provider()); let mut outcome = run( Arc::new(client_config), &mut NO_ACTIONS.clone(), @@ -891,8 +903,11 @@ fn tls13_packed_handshake() { #[test] fn rejects_junk() { - let mut server = - UnbufferedServerConnection::new(Arc::new(make_server_config(KeyType::Rsa2048))).unwrap(); + let mut server = UnbufferedServerConnection::new(Arc::new(make_server_config( + KeyType::Rsa2048, + &provider::default_provider(), + ))) + .unwrap(); let mut buf = [0xff; 5]; let UnbufferedStatus { discard, state } = server.process_tls_records(&mut buf); @@ -1397,8 +1412,9 @@ impl Buffer { fn make_connection_pair( version: &'static rustls::SupportedProtocolVersion, ) -> (UnbufferedClientConnection, UnbufferedServerConnection) { - let server_config = make_server_config(KeyType::Rsa2048); - let client_config = make_client_config_with_versions(KeyType::Rsa2048, &[version]); + let provider = provider::default_provider(); + let server_config = make_server_config(KeyType::Rsa2048, &provider); + let client_config = make_client_config_with_versions(KeyType::Rsa2048, &[version], &provider); let client = UnbufferedClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); @@ -1481,6 +1497,7 @@ fn test_secret_extraction_enabled() { // We support 3 different AEAD algorithms (AES-128-GCM mode, AES-256-GCM, and // Chacha20Poly1305), so that's 2*3 = 6 combinations to test. let kt = KeyType::Rsa2048; + let provider = provider::default_provider(); for suite in [ cipher_suite::TLS13_AES_128_GCM_SHA256, cipher_suite::TLS13_AES_256_GCM_SHA384, @@ -1498,7 +1515,7 @@ fn test_secret_extraction_enabled() { let mut server_config = ServerConfig::builder_with_provider( CryptoProvider { cipher_suites: vec![suite], - ..provider::default_provider() + ..provider.clone() } .into(), ) @@ -1511,7 +1528,7 @@ fn test_secret_extraction_enabled() { server_config.enable_secret_extraction = true; let server_config = Arc::new(server_config); - let mut client_config = make_client_config(kt); + let mut client_config = make_client_config(kt, &provider); client_config.enable_secret_extraction = true; let mut outcome = run( @@ -1570,10 +1587,11 @@ fn test_secret_extraction_enabled() { #[test] fn kernel_err_on_secret_extraction_not_enabled() { - let server_config = make_server_config(KeyType::Rsa2048); + let provider = provider::default_provider(); + let server_config = make_server_config(KeyType::Rsa2048, &provider); let server_config = Arc::new(server_config); - let client_config = make_client_config(KeyType::Rsa2048); + let client_config = make_client_config(KeyType::Rsa2048, &provider); let client_config = Arc::new(client_config); let mut server = UnbufferedServerConnection::new(server_config).unwrap(); @@ -1596,11 +1614,12 @@ fn kernel_err_on_secret_extraction_not_enabled() { #[test] fn kernel_err_on_handshake_not_complete() { - let mut server_config = make_server_config(KeyType::Rsa2048); + let provider = provider::default_provider(); + let mut server_config = make_server_config(KeyType::Rsa2048, &provider); server_config.enable_secret_extraction = true; let server_config = Arc::new(server_config); - let mut client_config = make_client_config(KeyType::Rsa2048); + let mut client_config = make_client_config(KeyType::Rsa2048, &provider); client_config.enable_secret_extraction = true; let client_config = Arc::new(client_config); @@ -1620,11 +1639,12 @@ fn kernel_err_on_handshake_not_complete() { #[test] fn kernel_initial_traffic_secrets_match() { - let mut server_config = make_server_config(KeyType::Rsa2048); + let provider = provider::default_provider(); + let mut server_config = make_server_config(KeyType::Rsa2048, &provider); server_config.enable_secret_extraction = true; let server_config = Arc::new(server_config); - let mut client_config = make_client_config(KeyType::Rsa2048); + let mut client_config = make_client_config(KeyType::Rsa2048, &provider); client_config.enable_secret_extraction = true; let client_config = Arc::new(client_config); @@ -1647,11 +1667,14 @@ fn kernel_initial_traffic_secrets_match() { #[test] fn kernel_key_updates_tls13() { - let mut server_config = make_server_config_with_versions(KeyType::Rsa2048, &[&TLS13]); + let provider = provider::default_provider(); + let mut server_config = + make_server_config_with_versions(KeyType::Rsa2048, &[&TLS13], &provider); server_config.enable_secret_extraction = true; let server_config = Arc::new(server_config); - let mut client_config = make_client_config_with_versions(KeyType::Rsa2048, &[&TLS13]); + let mut client_config = + make_client_config_with_versions(KeyType::Rsa2048, &[&TLS13], &provider); client_config.enable_secret_extraction = true; let client_config = Arc::new(client_config); @@ -1685,11 +1708,14 @@ fn kernel_key_updates_tls12() { let _ = env_logger::try_init(); - let mut server_config = make_server_config_with_versions(KeyType::Rsa2048, &[&TLS12]); + let provider = provider::default_provider(); + let mut server_config = + make_server_config_with_versions(KeyType::Rsa2048, &[&TLS12], &provider); server_config.enable_secret_extraction = true; let server_config = Arc::new(server_config); - let mut client_config = make_client_config_with_versions(KeyType::Rsa2048, &[&TLS12]); + let mut client_config = + make_client_config_with_versions(KeyType::Rsa2048, &[&TLS12], &provider); client_config.enable_secret_extraction = true; let client_config = Arc::new(client_config); From c387ec591d8263754854b2f3f3bb5a98f1f8d4e8 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 13:50:45 +0100 Subject: [PATCH 218/403] Make provider explicit in AEAD limit tests --- rustls/tests/api.rs | 4 ++-- rustls/tests/common/mod.rs | 21 +++++++++++++++------ rustls/tests/unbuffered.rs | 16 ++++++++++------ 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 923c380c2ba..b652290d5e2 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -8278,7 +8278,7 @@ fn test_automatic_refresh_traffic_keys() { } const KEY_UPDATE_SIZE: usize = encrypted_size(5); - let provider = aes_128_gcm_with_1024_confidentiality_limit(); + let provider = aes_128_gcm_with_1024_confidentiality_limit(provider::default_provider()); let client_config = finish_client_config( KeyType::Ed25519, @@ -8343,7 +8343,7 @@ fn test_automatic_refresh_traffic_keys() { #[cfg(feature = "tls12")] #[test] fn tls12_connection_fails_after_key_reaches_confidentiality_limit() { - let provider = aes_128_gcm_with_1024_confidentiality_limit(); + let provider = aes_128_gcm_with_1024_confidentiality_limit(provider::default_provider()); let client_config = finish_client_config( KeyType::Ed25519, diff --git a/rustls/tests/common/mod.rs b/rustls/tests/common/mod.rs index f377605ee6c..797908be7af 100644 --- a/rustls/tests/common/mod.rs +++ b/rustls/tests/common/mod.rs @@ -32,7 +32,7 @@ use rustls::unbuffered::{ ConnectionState, EncodeError, UnbufferedConnectionCommon, UnbufferedStatus, }; use rustls::{ - ClientConfig, ClientConnection, Connection, ConnectionCommon, ContentType, + CipherSuite, ClientConfig, ClientConnection, Connection, ConnectionCommon, ContentType, DigitallySignedStruct, DistinguishedName, Error, InconsistentKeys, NamedGroup, ProtocolVersion, RootCertStore, ServerConfig, ServerConnection, SideData, SignatureScheme, SupportedCipherSuite, }; @@ -1483,7 +1483,9 @@ impl RawTls { } } -pub fn aes_128_gcm_with_1024_confidentiality_limit() -> Arc { +pub fn aes_128_gcm_with_1024_confidentiality_limit( + provider: CryptoProvider, +) -> Arc { const CONFIDENTIALITY_LIMIT: u64 = 1024; // needed to extend lifetime of Tls13CipherSuite to 'static @@ -1491,7 +1493,11 @@ pub fn aes_128_gcm_with_1024_confidentiality_limit() -> Arc { static TLS12_LIMITED_SUITE: OnceLock = OnceLock::new(); let tls13_limited = TLS13_LIMITED_SUITE.get_or_init(|| { - let tls13 = provider::cipher_suite::TLS13_AES_128_GCM_SHA256 + let tls13 = provider + .cipher_suites + .iter() + .find(|cs| cs.suite() == CipherSuite::TLS13_AES_128_GCM_SHA256) + .unwrap() .tls13() .unwrap(); @@ -1505,8 +1511,11 @@ pub fn aes_128_gcm_with_1024_confidentiality_limit() -> Arc { }); let tls12_limited = TLS12_LIMITED_SUITE.get_or_init(|| { - let SupportedCipherSuite::Tls12(tls12) = - provider::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + let SupportedCipherSuite::Tls12(tls12) = *provider + .cipher_suites + .iter() + .find(|cs| cs.suite() == CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) + .unwrap() else { unreachable!(); }; @@ -1525,7 +1534,7 @@ pub fn aes_128_gcm_with_1024_confidentiality_limit() -> Arc { SupportedCipherSuite::Tls13(tls13_limited), SupportedCipherSuite::Tls12(tls12_limited), ], - ..provider::default_provider() + ..provider } .into() } diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index f38d16a2843..53c280e6b1a 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -732,9 +732,11 @@ fn refresh_traffic_keys_automatically() { let client_config = finish_client_config( KeyType::Rsa2048, - ClientConfig::builder_with_provider(aes_128_gcm_with_1024_confidentiality_limit()) - .with_safe_default_protocol_versions() - .unwrap(), + ClientConfig::builder_with_provider(aes_128_gcm_with_1024_confidentiality_limit( + provider::default_provider(), + )) + .with_safe_default_protocol_versions() + .unwrap(), ); let server_config = make_server_config(KeyType::Rsa2048, &provider::default_provider()); @@ -801,9 +803,11 @@ fn tls12_connection_fails_after_key_reaches_confidentiality_limit() { let client_config = finish_client_config( KeyType::Ed25519, - ClientConfig::builder_with_provider(aes_128_gcm_with_1024_confidentiality_limit()) - .with_protocol_versions(&[&rustls::version::TLS12]) - .unwrap(), + ClientConfig::builder_with_provider(aes_128_gcm_with_1024_confidentiality_limit( + provider::default_provider(), + )) + .with_protocol_versions(&[&rustls::version::TLS12]) + .unwrap(), ); let server_config = make_server_config(KeyType::Ed25519, &provider::default_provider()); From 3f79b1792303993914dcdee97024ba182980270b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 13:53:43 +0100 Subject: [PATCH 219/403] Make provider explicit in tests using plaintext suite --- rustls/tests/api.rs | 18 ++++++++++-------- rustls/tests/common/mod.rs | 12 +++++++----- rustls/tests/unbuffered.rs | 18 ++++++++++-------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index b652290d5e2..0851c9f95d6 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -8407,14 +8407,16 @@ fn tls13_packed_handshake() { // regression test for https://github.com/rustls/rustls/issues/2040 // (did not affect the buffered api) - let client_config = ClientConfig::builder_with_provider(unsafe_plaintext_crypto_provider()) - .with_safe_default_protocol_versions() - .unwrap() - .dangerous() - .with_custom_certificate_verifier(Arc::new(MockServerVerifier::rejects_certificate( - CertificateError::UnknownIssuer.into(), - ))) - .with_no_client_auth(); + let client_config = ClientConfig::builder_with_provider(unsafe_plaintext_crypto_provider( + provider::default_provider(), + )) + .with_safe_default_protocol_versions() + .unwrap() + .dangerous() + .with_custom_certificate_verifier(Arc::new(MockServerVerifier::rejects_certificate( + CertificateError::UnknownIssuer.into(), + ))) + .with_no_client_auth(); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); diff --git a/rustls/tests/common/mod.rs b/rustls/tests/common/mod.rs index 797908be7af..26f1c7f8290 100644 --- a/rustls/tests/common/mod.rs +++ b/rustls/tests/common/mod.rs @@ -39,8 +39,6 @@ use rustls::{ use webpki::anchor_from_trusted_cert; -use super::provider; - // Import `Arc` here for tests - can be overwritten to test with another `Arc` such as `portable_atomic_util::Arc` pub use std::sync::Arc; @@ -1539,11 +1537,15 @@ pub fn aes_128_gcm_with_1024_confidentiality_limit( .into() } -pub fn unsafe_plaintext_crypto_provider() -> Arc { +pub fn unsafe_plaintext_crypto_provider(provider: CryptoProvider) -> Arc { static TLS13_PLAIN_SUITE: OnceLock = OnceLock::new(); let tls13 = TLS13_PLAIN_SUITE.get_or_init(|| { - let tls13 = provider::cipher_suite::TLS13_AES_256_GCM_SHA384 + let tls13 = provider + .cipher_suites + .iter() + .find(|cs| cs.suite() == CipherSuite::TLS13_AES_256_GCM_SHA384) + .unwrap() .tls13() .unwrap(); @@ -1556,7 +1558,7 @@ pub fn unsafe_plaintext_crypto_provider() -> Arc { CryptoProvider { cipher_suites: vec![SupportedCipherSuite::Tls13(tls13)], - ..provider::default_provider() + ..provider } .into() } diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index 53c280e6b1a..e32b051371f 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -878,14 +878,16 @@ fn tls13_packed_handshake() { } // regression test for https://github.com/rustls/rustls/issues/2040 - let client_config = ClientConfig::builder_with_provider(unsafe_plaintext_crypto_provider()) - .with_safe_default_protocol_versions() - .unwrap() - .dangerous() - .with_custom_certificate_verifier(Arc::new(MockServerVerifier::rejects_certificate( - CertificateError::UnknownIssuer.into(), - ))) - .with_no_client_auth(); + let client_config = ClientConfig::builder_with_provider(unsafe_plaintext_crypto_provider( + provider::default_provider(), + )) + .with_safe_default_protocol_versions() + .unwrap() + .dangerous() + .with_custom_certificate_verifier(Arc::new(MockServerVerifier::rejects_certificate( + CertificateError::UnknownIssuer.into(), + ))) + .with_no_client_auth(); let mut client = UnbufferedClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); From c3496caa4341a196d75b293b7bd87ad6a32813d0 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 14:32:25 +0100 Subject: [PATCH 220/403] Eliminate final use of webpki crate in rustls tests --- rustls/tests/common/mod.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/rustls/tests/common/mod.rs b/rustls/tests/common/mod.rs index 26f1c7f8290..9186a451e27 100644 --- a/rustls/tests/common/mod.rs +++ b/rustls/tests/common/mod.rs @@ -37,8 +37,6 @@ use rustls::{ RootCertStore, ServerConfig, ServerConnection, SideData, SignatureScheme, SupportedCipherSuite, }; -use webpki::anchor_from_trusted_cert; - // Import `Arc` here for tests - can be overwritten to test with another `Arc` such as `portable_atomic_util::Arc` pub use std::sync::Arc; @@ -550,15 +548,11 @@ pub fn get_client_root_store(kt: KeyType) -> Arc { // The key type's chain file contains the DER encoding of the EE cert, the intermediate cert, // and the root trust anchor. We want only the trust anchor to build the root cert store. let chain = kt.get_chain(); - let trust_anchor = chain.last().unwrap(); - RootCertStore { - roots: vec![ - anchor_from_trusted_cert(trust_anchor) - .unwrap() - .to_owned(), - ], - } - .into() + let mut roots = RootCertStore::empty(); + roots + .add(chain.last().unwrap().clone()) + .unwrap(); + roots.into() } pub fn make_server_config_with_mandatory_client_auth_crls( From 708a91731c5a246d2abcf3da374d54d73dfb0b05 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 11:58:06 +0100 Subject: [PATCH 221/403] Move tests/common/mod.rs to rustls-test crate Everything moves, with the exception of parts that depend on the cargo features of the rustls crate. --- Cargo.lock | 9 + Cargo.toml | 3 + admin/coverage | 2 +- ci-bench/Cargo.toml | 1 + ci-bench/src/benchmark.rs | 2 +- ci-bench/src/main.rs | 12 +- ci-bench/src/util.rs | 31 - rustls-test/Cargo.toml | 8 + rustls-test/src/lib.rs | 1748 ++++++++++++++++++++++++++++++++++ rustls/Cargo.toml | 1 + rustls/benches/benchmarks.rs | 4 +- rustls/tests/common/mod.rs | 1706 +-------------------------------- 12 files changed, 1782 insertions(+), 1745 deletions(-) create mode 100644 rustls-test/Cargo.toml create mode 100644 rustls-test/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 0b6edc41410..4b545ee4bc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2589,6 +2589,7 @@ dependencies = [ "rcgen", "ring", "rustls-pki-types", + "rustls-test", "rustls-webpki", "rustversion", "serde", @@ -2639,6 +2640,7 @@ dependencies = [ "itertools 0.14.0", "rayon", "rustls 0.23.27", + "rustls-test", "tikv-jemallocator", ] @@ -2741,6 +2743,13 @@ dependencies = [ "serde_json", ] +[[package]] +name = "rustls-test" +version = "0.1.0" +dependencies = [ + "rustls 0.23.27", +] + [[package]] name = "rustls-webpki" version = "0.103.2" diff --git a/Cargo.toml b/Cargo.toml index d560df2d56e..0e3fb6a9a6c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,8 @@ members = [ "provider-example", # the main library and tests "rustls", + # common code for testing the core crate + "rustls-test", # benchmarking tool "rustls-bench", # experimental post-quantum algorithm support @@ -79,6 +81,7 @@ rcgen = { version = "0.13", features = ["pem", "aws_lc_rs"], default-features = regex = "1" ring = "0.17" rsa = { version = "0.9", features = ["sha2"], default-features = false } +rustls-test = { path = "rustls-test/" } serde = { version = "1", features = ["derive"] } serde_json = "1" sha2 = { version = "0.10", default-features = false } diff --git a/admin/coverage b/admin/coverage index b23c0ef2a63..3ede3b233a1 100755 --- a/admin/coverage +++ b/admin/coverage @@ -17,4 +17,4 @@ cargo test --locked $(admin/all-features-except brotli rustls) ## bogo cargo test --locked --test bogo -- --ignored --test-threads 1 -cargo llvm-cov report --ignore-filename-regex bogo/ "$@" +cargo llvm-cov report --ignore-filename-regex "(bogo|rustls-test)/" "$@" diff --git a/ci-bench/Cargo.toml b/ci-bench/Cargo.toml index 6fde65b814e..ff92bfb507d 100644 --- a/ci-bench/Cargo.toml +++ b/ci-bench/Cargo.toml @@ -15,6 +15,7 @@ fxhash = { workspace = true } itertools = { workspace = true } rayon = { workspace = true } rustls = { path = "../rustls", features = ["ring", "aws_lc_rs"] } +rustls-test = { workspace = true } [target.'cfg(not(target_env = "msvc"))'.dependencies] tikv-jemallocator = { workspace = true } diff --git a/ci-bench/src/benchmark.rs b/ci-bench/src/benchmark.rs index 1e38cc5401e..325de04b796 100644 --- a/ci-bench/src/benchmark.rs +++ b/ci-bench/src/benchmark.rs @@ -5,7 +5,7 @@ use itertools::Itertools; use crate::Side; use crate::callgrind::InstructionCounts; -use crate::util::KeyType; +use rustls_test::KeyType; /// Validates a benchmark collection, returning an error if the provided benchmarks are invalid /// diff --git a/ci-bench/src/main.rs b/ci-bench/src/main.rs index 2b768bab87a..3d2d3595960 100644 --- a/ci-bench/src/main.rs +++ b/ci-bench/src/main.rs @@ -17,20 +17,18 @@ use rayon::iter::Either; use rayon::prelude::*; use rustls::client::Resumption; use rustls::crypto::{CryptoProvider, GetRandomFailed, SecureRandom, aws_lc_rs, ring}; -use rustls::pki_types::CertificateDer; -use rustls::pki_types::pem::PemObject; use rustls::server::{NoServerSessionStorage, ServerSessionMemoryCache, WebPkiClientVerifier}; use rustls::{ CipherSuite, ClientConfig, ClientConnection, HandshakeKind, ProtocolVersion, RootCertStore, ServerConfig, ServerConnection, }; +use rustls_test::KeyType; use crate::benchmark::{ Benchmark, BenchmarkKind, BenchmarkParams, ResumptionKind, get_reported_instr_count, validate_benchmarks, }; use crate::callgrind::{CallgrindRunner, CountInstructions}; -use crate::util::KeyType; use crate::util::async_io::{self, AsyncRead, AsyncWrite}; use crate::util::transport::{ read_handshake_message, read_plaintext_to_end_bounded, send_handshake_message, @@ -504,11 +502,9 @@ impl ClientSideStepper<'_> { fn make_config(params: &BenchmarkParams, resume: ResumptionKind) -> Arc { assert_eq!(params.ciphersuite.version(), params.version); let mut root_store = RootCertStore::empty(); - root_store.add_parsable_certificates( - CertificateDer::pem_file_iter(params.key_type.path_for("ca.cert")) - .unwrap() - .map(|result| result.unwrap()), - ); + root_store + .add(params.key_type.ca_cert()) + .unwrap(); let mut cfg = ClientConfig::builder_with_provider( CryptoProvider { diff --git a/ci-bench/src/util.rs b/ci-bench/src/util.rs index f883ff294ba..f924d0d641f 100644 --- a/ci-bench/src/util.rs +++ b/ci-bench/src/util.rs @@ -1,34 +1,3 @@ -use rustls::pki_types::pem::PemObject; -use rustls::pki_types::{CertificateDer, PrivateKeyDer}; - -#[derive(PartialEq, Clone, Copy, Debug)] -pub enum KeyType { - Rsa2048, - EcdsaP256, - EcdsaP384, -} - -impl KeyType { - pub(crate) fn path_for(&self, part: &str) -> String { - match self { - Self::Rsa2048 => format!("../test-ca/rsa-2048/{part}"), - Self::EcdsaP256 => format!("../test-ca/ecdsa-p256/{part}"), - Self::EcdsaP384 => format!("../test-ca/ecdsa-p384/{part}"), - } - } - - pub(crate) fn get_chain(&self) -> Vec> { - CertificateDer::pem_file_iter(self.path_for("end.fullchain")) - .unwrap() - .map(|result| result.unwrap()) - .collect() - } - - pub(crate) fn get_key(&self) -> PrivateKeyDer<'static> { - PrivateKeyDer::from_pem_file(self.path_for("end.key")).unwrap() - } -} - pub mod async_io { //! Async IO building blocks required for sharing code between the instruction count and //! wall-time benchmarks diff --git a/rustls-test/Cargo.toml b/rustls-test/Cargo.toml new file mode 100644 index 00000000000..877ec34833e --- /dev/null +++ b/rustls-test/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "rustls-test" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +rustls = { path = "../rustls", default-features = false, features = ["std", "tls12"] } diff --git a/rustls-test/src/lib.rs b/rustls-test/src/lib.rs new file mode 100644 index 00000000000..64e922bad15 --- /dev/null +++ b/rustls-test/src/lib.rs @@ -0,0 +1,1748 @@ +use std::io; +use std::ops::DerefMut; +use std::sync::Arc; +use std::sync::OnceLock; + +use rustls::pki_types::pem::PemObject; +use rustls::pki_types::{ + CertificateDer, CertificateRevocationListDer, PrivateKeyDer, PrivatePkcs8KeyDer, ServerName, + SubjectPublicKeyInfoDer, UnixTime, +}; + +use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; +use rustls::client::{ + AlwaysResolvesClientRawPublicKeys, ServerCertVerifierBuilder, UnbufferedClientConnection, + WebPkiServerVerifier, +}; +use rustls::crypto::cipher::{InboundOpaqueMessage, MessageDecrypter, MessageEncrypter}; +use rustls::crypto::{ + CryptoProvider, WebPkiSupportedAlgorithms, verify_tls13_signature_with_raw_key, +}; +use rustls::internal::msgs::codec::{Codec, Reader}; +use rustls::internal::msgs::message::{Message, OutboundOpaqueMessage, PlainMessage}; +use rustls::server::danger::{ClientCertVerified, ClientCertVerifier}; +use rustls::server::{ + AlwaysResolvesServerRawPublicKeys, ClientCertVerifierBuilder, UnbufferedServerConnection, + WebPkiClientVerifier, +}; +use rustls::sign::CertifiedKey; +use rustls::unbuffered::{ + ConnectionState, EncodeError, UnbufferedConnectionCommon, UnbufferedStatus, +}; +use rustls::{ + CipherSuite, ClientConfig, ClientConnection, Connection, ConnectionCommon, ContentType, + DigitallySignedStruct, DistinguishedName, Error, InconsistentKeys, NamedGroup, ProtocolVersion, + RootCertStore, ServerConfig, ServerConnection, SideData, SignatureScheme, SupportedCipherSuite, +}; + +macro_rules! embed_files { + ( + $( + ($name:ident, $keytype:expr, $path:expr); + )+ + ) => { + $( + const $name: &'static [u8] = include_bytes!( + concat!("../../test-ca/", $keytype, "/", $path)); + )+ + + pub fn bytes_for(keytype: &str, path: &str) -> &'static [u8] { + match (keytype, path) { + $( + ($keytype, $path) => $name, + )+ + _ => panic!("unknown keytype {} with path {}", keytype, path), + } + } + } +} + +embed_files! { + (ECDSA_P256_END_PEM_SPKI, "ecdsa-p256", "end.spki.pem"); + (ECDSA_P256_CLIENT_PEM_SPKI, "ecdsa-p256", "client.spki.pem"); + (ECDSA_P256_CA_CERT, "ecdsa-p256", "ca.cert"); + (ECDSA_P256_CA_DER, "ecdsa-p256", "ca.der"); + (ECDSA_P256_CA_KEY, "ecdsa-p256", "ca.key"); + (ECDSA_P256_CLIENT_CERT, "ecdsa-p256", "client.cert"); + (ECDSA_P256_CLIENT_CHAIN, "ecdsa-p256", "client.chain"); + (ECDSA_P256_CLIENT_FULLCHAIN, "ecdsa-p256", "client.fullchain"); + (ECDSA_P256_CLIENT_KEY, "ecdsa-p256", "client.key"); + (ECDSA_P256_END_CRL_PEM, "ecdsa-p256", "end.revoked.crl.pem"); + (ECDSA_P256_CLIENT_CRL_PEM, "ecdsa-p256", "client.revoked.crl.pem"); + (ECDSA_P256_INTERMEDIATE_CRL_PEM, "ecdsa-p256", "inter.revoked.crl.pem"); + (ECDSA_P256_EXPIRED_CRL_PEM, "ecdsa-p256", "end.expired.crl.pem"); + (ECDSA_P256_END_CERT, "ecdsa-p256", "end.cert"); + (ECDSA_P256_END_CHAIN, "ecdsa-p256", "end.chain"); + (ECDSA_P256_END_FULLCHAIN, "ecdsa-p256", "end.fullchain"); + (ECDSA_P256_END_KEY, "ecdsa-p256", "end.key"); + (ECDSA_P256_INTER_CERT, "ecdsa-p256", "inter.cert"); + (ECDSA_P256_INTER_KEY, "ecdsa-p256", "inter.key"); + + (ECDSA_P384_END_PEM_SPKI, "ecdsa-p384", "end.spki.pem"); + (ECDSA_P384_CLIENT_PEM_SPKI, "ecdsa-p384", "client.spki.pem"); + (ECDSA_P384_CA_CERT, "ecdsa-p384", "ca.cert"); + (ECDSA_P384_CA_DER, "ecdsa-p384", "ca.der"); + (ECDSA_P384_CA_KEY, "ecdsa-p384", "ca.key"); + (ECDSA_P384_CLIENT_CERT, "ecdsa-p384", "client.cert"); + (ECDSA_P384_CLIENT_CHAIN, "ecdsa-p384", "client.chain"); + (ECDSA_P384_CLIENT_FULLCHAIN, "ecdsa-p384", "client.fullchain"); + (ECDSA_P384_CLIENT_KEY, "ecdsa-p384", "client.key"); + (ECDSA_P384_END_CRL_PEM, "ecdsa-p384", "end.revoked.crl.pem"); + (ECDSA_P384_CLIENT_CRL_PEM, "ecdsa-p384", "client.revoked.crl.pem"); + (ECDSA_P384_INTERMEDIATE_CRL_PEM, "ecdsa-p384", "inter.revoked.crl.pem"); + (ECDSA_P384_EXPIRED_CRL_PEM, "ecdsa-p384", "end.expired.crl.pem"); + (ECDSA_P384_END_CERT, "ecdsa-p384", "end.cert"); + (ECDSA_P384_END_CHAIN, "ecdsa-p384", "end.chain"); + (ECDSA_P384_END_FULLCHAIN, "ecdsa-p384", "end.fullchain"); + (ECDSA_P384_END_KEY, "ecdsa-p384", "end.key"); + (ECDSA_P384_INTER_CERT, "ecdsa-p384", "inter.cert"); + (ECDSA_P384_INTER_KEY, "ecdsa-p384", "inter.key"); + + (ECDSA_P521_END_PEM_SPKI, "ecdsa-p521", "end.spki.pem"); + (ECDSA_P521_CLIENT_PEM_SPKI, "ecdsa-p521", "client.spki.pem"); + (ECDSA_P521_CA_CERT, "ecdsa-p521", "ca.cert"); + (ECDSA_P521_CA_DER, "ecdsa-p521", "ca.der"); + (ECDSA_P521_CA_KEY, "ecdsa-p521", "ca.key"); + (ECDSA_P521_CLIENT_CERT, "ecdsa-p521", "client.cert"); + (ECDSA_P521_CLIENT_CHAIN, "ecdsa-p521", "client.chain"); + (ECDSA_P521_CLIENT_FULLCHAIN, "ecdsa-p521", "client.fullchain"); + (ECDSA_P521_CLIENT_KEY, "ecdsa-p521", "client.key"); + (ECDSA_P521_END_CRL_PEM, "ecdsa-p521", "end.revoked.crl.pem"); + (ECDSA_P521_CLIENT_CRL_PEM, "ecdsa-p521", "client.revoked.crl.pem"); + (ECDSA_P521_INTERMEDIATE_CRL_PEM, "ecdsa-p521", "inter.revoked.crl.pem"); + (ECDSA_P521_EXPIRED_CRL_PEM, "ecdsa-p521", "end.expired.crl.pem"); + (ECDSA_P521_END_CERT, "ecdsa-p521", "end.cert"); + (ECDSA_P521_END_CHAIN, "ecdsa-p521", "end.chain"); + (ECDSA_P521_END_FULLCHAIN, "ecdsa-p521", "end.fullchain"); + (ECDSA_P521_END_KEY, "ecdsa-p521", "end.key"); + (ECDSA_P521_INTER_CERT, "ecdsa-p521", "inter.cert"); + (ECDSA_P521_INTER_KEY, "ecdsa-p521", "inter.key"); + + (EDDSA_END_PEM_SPKI, "eddsa", "end.spki.pem"); + (EDDSA_CLIENT_PEM_SPKI, "eddsa", "client.spki.pem"); + (EDDSA_CA_CERT, "eddsa", "ca.cert"); + (EDDSA_CA_DER, "eddsa", "ca.der"); + (EDDSA_CA_KEY, "eddsa", "ca.key"); + (EDDSA_CLIENT_CERT, "eddsa", "client.cert"); + (EDDSA_CLIENT_CHAIN, "eddsa", "client.chain"); + (EDDSA_CLIENT_FULLCHAIN, "eddsa", "client.fullchain"); + (EDDSA_CLIENT_KEY, "eddsa", "client.key"); + (EDDSA_END_CRL_PEM, "eddsa", "end.revoked.crl.pem"); + (EDDSA_CLIENT_CRL_PEM, "eddsa", "client.revoked.crl.pem"); + (EDDSA_INTERMEDIATE_CRL_PEM, "eddsa", "inter.revoked.crl.pem"); + (EDDSA_EXPIRED_CRL_PEM, "eddsa", "end.expired.crl.pem"); + (EDDSA_END_CERT, "eddsa", "end.cert"); + (EDDSA_END_CHAIN, "eddsa", "end.chain"); + (EDDSA_END_FULLCHAIN, "eddsa", "end.fullchain"); + (EDDSA_END_KEY, "eddsa", "end.key"); + (EDDSA_INTER_CERT, "eddsa", "inter.cert"); + (EDDSA_INTER_KEY, "eddsa", "inter.key"); + + (RSA_2048_END_PEM_SPKI, "rsa-2048", "end.spki.pem"); + (RSA_2048_CLIENT_PEM_SPKI, "rsa-2048", "client.spki.pem"); + (RSA_2048_CA_CERT, "rsa-2048", "ca.cert"); + (RSA_2048_CA_DER, "rsa-2048", "ca.der"); + (RSA_2048_CA_KEY, "rsa-2048", "ca.key"); + (RSA_2048_CLIENT_CERT, "rsa-2048", "client.cert"); + (RSA_2048_CLIENT_CHAIN, "rsa-2048", "client.chain"); + (RSA_2048_CLIENT_FULLCHAIN, "rsa-2048", "client.fullchain"); + (RSA_2048_CLIENT_KEY, "rsa-2048", "client.key"); + (RSA_2048_END_CRL_PEM, "rsa-2048", "end.revoked.crl.pem"); + (RSA_2048_CLIENT_CRL_PEM, "rsa-2048", "client.revoked.crl.pem"); + (RSA_2048_INTERMEDIATE_CRL_PEM, "rsa-2048", "inter.revoked.crl.pem"); + (RSA_2048_EXPIRED_CRL_PEM, "rsa-2048", "end.expired.crl.pem"); + (RSA_2048_END_CERT, "rsa-2048", "end.cert"); + (RSA_2048_END_CHAIN, "rsa-2048", "end.chain"); + (RSA_2048_END_FULLCHAIN, "rsa-2048", "end.fullchain"); + (RSA_2048_END_KEY, "rsa-2048", "end.key"); + (RSA_2048_INTER_CERT, "rsa-2048", "inter.cert"); + (RSA_2048_INTER_KEY, "rsa-2048", "inter.key"); + + (RSA_3072_END_PEM_SPKI, "rsa-3072", "end.spki.pem"); + (RSA_3072_CLIENT_PEM_SPKI, "rsa-3072", "client.spki.pem"); + (RSA_3072_CA_CERT, "rsa-3072", "ca.cert"); + (RSA_3072_CA_DER, "rsa-3072", "ca.der"); + (RSA_3072_CA_KEY, "rsa-3072", "ca.key"); + (RSA_3072_CLIENT_CERT, "rsa-3072", "client.cert"); + (RSA_3072_CLIENT_CHAIN, "rsa-3072", "client.chain"); + (RSA_3072_CLIENT_FULLCHAIN, "rsa-3072", "client.fullchain"); + (RSA_3072_CLIENT_KEY, "rsa-3072", "client.key"); + (RSA_3072_END_CRL_PEM, "rsa-3072", "end.revoked.crl.pem"); + (RSA_3072_CLIENT_CRL_PEM, "rsa-3072", "client.revoked.crl.pem"); + (RSA_3072_INTERMEDIATE_CRL_PEM, "rsa-3072", "inter.revoked.crl.pem"); + (RSA_3072_EXPIRED_CRL_PEM, "rsa-3072", "end.expired.crl.pem"); + (RSA_3072_END_CERT, "rsa-3072", "end.cert"); + (RSA_3072_END_CHAIN, "rsa-3072", "end.chain"); + (RSA_3072_END_FULLCHAIN, "rsa-3072", "end.fullchain"); + (RSA_3072_END_KEY, "rsa-3072", "end.key"); + (RSA_3072_INTER_CERT, "rsa-3072", "inter.cert"); + (RSA_3072_INTER_KEY, "rsa-3072", "inter.key"); + + (RSA_4096_END_PEM_SPKI, "rsa-4096", "end.spki.pem"); + (RSA_4096_CLIENT_PEM_SPKI, "rsa-4096", "client.spki.pem"); + (RSA_4096_CA_CERT, "rsa-4096", "ca.cert"); + (RSA_4096_CA_DER, "rsa-4096", "ca.der"); + (RSA_4096_CA_KEY, "rsa-4096", "ca.key"); + (RSA_4096_CLIENT_CERT, "rsa-4096", "client.cert"); + (RSA_4096_CLIENT_CHAIN, "rsa-4096", "client.chain"); + (RSA_4096_CLIENT_FULLCHAIN, "rsa-4096", "client.fullchain"); + (RSA_4096_CLIENT_KEY, "rsa-4096", "client.key"); + (RSA_4096_END_CRL_PEM, "rsa-4096", "end.revoked.crl.pem"); + (RSA_4096_CLIENT_CRL_PEM, "rsa-4096", "client.revoked.crl.pem"); + (RSA_4096_INTERMEDIATE_CRL_PEM, "rsa-4096", "inter.revoked.crl.pem"); + (RSA_4096_EXPIRED_CRL_PEM, "rsa-4096", "end.expired.crl.pem"); + (RSA_4096_END_CERT, "rsa-4096", "end.cert"); + (RSA_4096_END_CHAIN, "rsa-4096", "end.chain"); + (RSA_4096_END_FULLCHAIN, "rsa-4096", "end.fullchain"); + (RSA_4096_END_KEY, "rsa-4096", "end.key"); + (RSA_4096_INTER_CERT, "rsa-4096", "inter.cert"); + (RSA_4096_INTER_KEY, "rsa-4096", "inter.key"); +} + +pub fn transfer( + left: &mut impl DerefMut>, + right: &mut impl DerefMut>, +) -> usize { + let mut buf = [0u8; 262144]; + let mut total = 0; + + while left.wants_write() { + let sz = { + let into_buf: &mut dyn io::Write = &mut &mut buf[..]; + left.write_tls(into_buf).unwrap() + }; + total += sz; + if sz == 0 { + return total; + } + + let mut offs = 0; + loop { + let from_buf: &mut dyn io::Read = &mut &buf[offs..sz]; + offs += right.read_tls(from_buf).unwrap(); + if sz == offs { + break; + } + } + } + + total +} + +pub fn transfer_eof(conn: &mut impl DerefMut>) { + let empty_buf = [0u8; 0]; + let empty_cursor: &mut dyn io::Read = &mut &empty_buf[..]; + let sz = conn.read_tls(empty_cursor).unwrap(); + assert_eq!(sz, 0); +} + +pub enum Altered { + /// message has been edited in-place (or is unchanged) + InPlace, + /// send these raw bytes instead of the message. + Raw(Vec), +} + +pub fn transfer_altered(left: &mut Connection, filter: F, right: &mut Connection) -> usize +where + F: Fn(&mut Message) -> Altered, +{ + let mut buf = [0u8; 262144]; + let mut total = 0; + + while left.wants_write() { + let sz = { + let into_buf: &mut dyn io::Write = &mut &mut buf[..]; + left.write_tls(into_buf).unwrap() + }; + total += sz; + if sz == 0 { + return total; + } + + let mut reader = Reader::init(&buf[..sz]); + while reader.any_left() { + let message = OutboundOpaqueMessage::read(&mut reader).unwrap(); + + // this is a bit of a falsehood: we don't know whether message + // is encrypted. it is quite unlikely that a genuine encrypted + // message can be decoded by `Message::try_from`. + let plain = message.into_plain_message(); + + let message_enc = match Message::try_from(plain.clone()) { + Ok(mut message) => match filter(&mut message) { + Altered::InPlace => PlainMessage::from(message) + .into_unencrypted_opaque() + .encode(), + Altered::Raw(data) => data, + }, + // pass through encrypted/undecodable messages + Err(_) => plain.into_unencrypted_opaque().encode(), + }; + + let message_enc_reader: &mut dyn io::Read = &mut &message_enc[..]; + let len = right + .read_tls(message_enc_reader) + .unwrap(); + assert_eq!(len, message_enc.len()); + } + } + + total +} + +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum KeyType { + Rsa2048, + Rsa3072, + Rsa4096, + EcdsaP256, + EcdsaP384, + EcdsaP521, + Ed25519, +} + +pub static ALL_KEY_TYPES: &[KeyType] = &[ + KeyType::Rsa2048, + KeyType::Rsa3072, + KeyType::Rsa4096, + KeyType::EcdsaP256, + KeyType::EcdsaP384, + KeyType::EcdsaP521, + KeyType::Ed25519, +]; + +impl KeyType { + fn bytes_for(&self, part: &str) -> &'static [u8] { + match self { + Self::Rsa2048 => bytes_for("rsa-2048", part), + Self::Rsa3072 => bytes_for("rsa-3072", part), + Self::Rsa4096 => bytes_for("rsa-4096", part), + Self::EcdsaP256 => bytes_for("ecdsa-p256", part), + Self::EcdsaP384 => bytes_for("ecdsa-p384", part), + Self::EcdsaP521 => bytes_for("ecdsa-p521", part), + Self::Ed25519 => bytes_for("eddsa", part), + } + } + + pub fn ca_cert(&self) -> CertificateDer<'_> { + self.get_chain() + .into_iter() + .next_back() + .expect("cert chain cannot be empty") + } + + pub fn get_chain(&self) -> Vec> { + CertificateDer::pem_slice_iter(self.bytes_for("end.fullchain")) + .map(|result| result.unwrap()) + .collect() + } + + pub fn get_spki(&self) -> SubjectPublicKeyInfoDer<'static> { + SubjectPublicKeyInfoDer::from_pem_slice(self.bytes_for("end.spki.pem")).unwrap() + } + + pub fn get_key(&self) -> PrivateKeyDer<'static> { + PrivatePkcs8KeyDer::from_pem_slice(self.bytes_for("end.key")) + .unwrap() + .into() + } + + pub fn get_client_chain(&self) -> Vec> { + CertificateDer::pem_slice_iter(self.bytes_for("client.fullchain")) + .map(|result| result.unwrap()) + .collect() + } + + pub fn end_entity_crl(&self) -> CertificateRevocationListDer<'static> { + self.get_crl("end", "revoked") + } + + pub fn client_crl(&self) -> CertificateRevocationListDer<'static> { + self.get_crl("client", "revoked") + } + + pub fn intermediate_crl(&self) -> CertificateRevocationListDer<'static> { + self.get_crl("inter", "revoked") + } + + pub fn end_entity_crl_expired(&self) -> CertificateRevocationListDer<'static> { + self.get_crl("end", "expired") + } + + pub fn get_client_key(&self) -> PrivateKeyDer<'static> { + PrivatePkcs8KeyDer::from_pem_slice(self.bytes_for("client.key")) + .unwrap() + .into() + } + + pub fn get_client_spki(&self) -> SubjectPublicKeyInfoDer<'static> { + SubjectPublicKeyInfoDer::from_pem_slice(self.bytes_for("client.spki.pem")).unwrap() + } + + pub fn get_certified_client_key( + &self, + provider: &CryptoProvider, + ) -> Result, Error> { + let private_key = provider + .key_provider + .load_private_key(self.get_client_key())?; + let public_key = private_key + .public_key() + .ok_or(Error::InconsistentKeys(InconsistentKeys::Unknown))?; + let public_key_as_cert = CertificateDer::from(public_key.to_vec()); + Ok(Arc::new(CertifiedKey::new( + vec![public_key_as_cert], + private_key, + ))) + } + + pub fn certified_key_with_raw_pub_key( + &self, + provider: &CryptoProvider, + ) -> Result, Error> { + let private_key = provider + .key_provider + .load_private_key(self.get_key())?; + let public_key = private_key + .public_key() + .ok_or(Error::InconsistentKeys(InconsistentKeys::Unknown))?; + let public_key_as_cert = CertificateDer::from(public_key.to_vec()); + Ok(Arc::new(CertifiedKey::new( + vec![public_key_as_cert], + private_key, + ))) + } + + pub fn certified_key_with_cert_chain( + &self, + provider: &CryptoProvider, + ) -> Result, Error> { + let private_key = provider + .key_provider + .load_private_key(self.get_key())?; + Ok(Arc::new(CertifiedKey::new(self.get_chain(), private_key))) + } + + fn get_crl(&self, role: &str, r#type: &str) -> CertificateRevocationListDer<'static> { + CertificateRevocationListDer::from_pem_slice( + self.bytes_for(&format!("{role}.{type}.crl.pem")), + ) + .unwrap() + } + + pub fn ca_distinguished_name(&self) -> &'static [u8] { + match self { + KeyType::Rsa2048 => b"0\x1f1\x1d0\x1b\x06\x03U\x04\x03\x0c\x14ponytown RSA 2048 CA", + KeyType::Rsa3072 => b"0\x1f1\x1d0\x1b\x06\x03U\x04\x03\x0c\x14ponytown RSA 3072 CA", + KeyType::Rsa4096 => b"0\x1f1\x1d0\x1b\x06\x03U\x04\x03\x0c\x14ponytown RSA 4096 CA", + KeyType::EcdsaP256 => b"0\x211\x1f0\x1d\x06\x03U\x04\x03\x0c\x16ponytown ECDSA p256 CA", + KeyType::EcdsaP384 => b"0\x211\x1f0\x1d\x06\x03U\x04\x03\x0c\x16ponytown ECDSA p384 CA", + KeyType::EcdsaP521 => b"0\x211\x1f0\x1d\x06\x03U\x04\x03\x0c\x16ponytown ECDSA p521 CA", + KeyType::Ed25519 => b"0\x1c1\x1a0\x18\x06\x03U\x04\x03\x0c\x11ponytown EdDSA CA", + } + } +} + +pub fn server_config_builder( + provider: &CryptoProvider, +) -> rustls::ConfigBuilder { + rustls::ServerConfig::builder_with_provider(provider.clone().into()) + .with_safe_default_protocol_versions() + .unwrap() +} + +pub fn server_config_builder_with_versions( + versions: &[&'static rustls::SupportedProtocolVersion], + provider: &CryptoProvider, +) -> rustls::ConfigBuilder { + rustls::ServerConfig::builder_with_provider(provider.clone().into()) + .with_protocol_versions(versions) + .unwrap() +} + +pub fn client_config_builder( + provider: &CryptoProvider, +) -> rustls::ConfigBuilder { + rustls::ClientConfig::builder_with_provider(provider.clone().into()) + .with_safe_default_protocol_versions() + .unwrap() +} + +pub fn client_config_builder_with_versions( + versions: &[&'static rustls::SupportedProtocolVersion], + provider: &CryptoProvider, +) -> rustls::ConfigBuilder { + rustls::ClientConfig::builder_with_provider(provider.clone().into()) + .with_protocol_versions(versions) + .unwrap() +} + +pub fn finish_server_config( + kt: KeyType, + conf: rustls::ConfigBuilder, +) -> ServerConfig { + conf.with_no_client_auth() + .with_single_cert(kt.get_chain(), kt.get_key()) + .unwrap() +} + +pub fn make_server_config(kt: KeyType, provider: &CryptoProvider) -> ServerConfig { + finish_server_config(kt, server_config_builder(provider)) +} + +pub fn make_server_config_with_versions( + kt: KeyType, + versions: &[&'static rustls::SupportedProtocolVersion], + provider: &CryptoProvider, +) -> ServerConfig { + finish_server_config(kt, server_config_builder_with_versions(versions, provider)) +} + +pub fn make_server_config_with_kx_groups( + kt: KeyType, + kx_groups: Vec<&'static dyn rustls::crypto::SupportedKxGroup>, + provider: &CryptoProvider, +) -> ServerConfig { + finish_server_config( + kt, + ServerConfig::builder_with_provider( + CryptoProvider { + kx_groups, + ..provider.clone() + } + .into(), + ) + .with_safe_default_protocol_versions() + .unwrap(), + ) +} + +pub fn get_client_root_store(kt: KeyType) -> Arc { + // The key type's chain file contains the DER encoding of the EE cert, the intermediate cert, + // and the root trust anchor. We want only the trust anchor to build the root cert store. + let chain = kt.get_chain(); + let mut roots = RootCertStore::empty(); + roots + .add(chain.last().unwrap().clone()) + .unwrap(); + roots.into() +} + +pub fn make_server_config_with_mandatory_client_auth_crls( + kt: KeyType, + crls: Vec>, + provider: &CryptoProvider, +) -> ServerConfig { + make_server_config_with_client_verifier( + kt, + webpki_client_verifier_builder(get_client_root_store(kt), provider).with_crls(crls), + provider, + ) +} + +pub fn make_server_config_with_mandatory_client_auth( + kt: KeyType, + provider: &CryptoProvider, +) -> ServerConfig { + make_server_config_with_client_verifier( + kt, + webpki_client_verifier_builder(get_client_root_store(kt), provider), + provider, + ) +} + +pub fn make_server_config_with_optional_client_auth( + kt: KeyType, + crls: Vec>, + provider: &CryptoProvider, +) -> ServerConfig { + make_server_config_with_client_verifier( + kt, + webpki_client_verifier_builder(get_client_root_store(kt), provider) + .with_crls(crls) + .allow_unknown_revocation_status() + .allow_unauthenticated(), + provider, + ) +} + +pub fn make_server_config_with_client_verifier( + kt: KeyType, + verifier_builder: ClientCertVerifierBuilder, + provider: &CryptoProvider, +) -> ServerConfig { + server_config_builder(provider) + .with_client_cert_verifier(verifier_builder.build().unwrap()) + .with_single_cert(kt.get_chain(), kt.get_key()) + .unwrap() +} + +pub fn make_server_config_with_raw_key_support( + kt: KeyType, + provider: &CryptoProvider, +) -> ServerConfig { + let mut client_verifier = + MockClientVerifier::new(|| Ok(ClientCertVerified::assertion()), kt, provider); + let server_cert_resolver = Arc::new(AlwaysResolvesServerRawPublicKeys::new( + kt.certified_key_with_raw_pub_key(provider) + .unwrap(), + )); + client_verifier.expect_raw_public_keys = true; + // We don't support tls1.2 for Raw Public Keys, hence the version is hard-coded. + server_config_builder_with_versions(&[&rustls::version::TLS13], provider) + .with_client_cert_verifier(Arc::new(client_verifier)) + .with_cert_resolver(server_cert_resolver) +} + +pub fn make_client_config_with_raw_key_support( + kt: KeyType, + provider: &CryptoProvider, +) -> ClientConfig { + let server_verifier = Arc::new(MockServerVerifier::expects_raw_public_keys(provider)); + let client_cert_resolver = Arc::new(AlwaysResolvesClientRawPublicKeys::new( + kt.get_certified_client_key(provider) + .unwrap(), + )); + // We don't support tls1.2 for Raw Public Keys, hence the version is hard-coded. + client_config_builder_with_versions(&[&rustls::version::TLS13], provider) + .dangerous() + .with_custom_certificate_verifier(server_verifier) + .with_client_cert_resolver(client_cert_resolver) +} + +pub fn make_client_config_with_cipher_suite_and_raw_key_support( + kt: KeyType, + cipher_suite: SupportedCipherSuite, + provider: &CryptoProvider, +) -> ClientConfig { + let server_verifier = Arc::new(MockServerVerifier::expects_raw_public_keys(provider)); + let client_cert_resolver = Arc::new(AlwaysResolvesClientRawPublicKeys::new( + kt.get_certified_client_key(provider) + .unwrap(), + )); + ClientConfig::builder_with_provider( + CryptoProvider { + cipher_suites: vec![cipher_suite], + ..provider.clone() + } + .into(), + ) + .with_protocol_versions(&[&rustls::version::TLS13]) + .unwrap() + .dangerous() + .with_custom_certificate_verifier(server_verifier) + .with_client_cert_resolver(client_cert_resolver) +} + +pub fn finish_client_config( + kt: KeyType, + config: rustls::ConfigBuilder, +) -> ClientConfig { + let mut root_store = RootCertStore::empty(); + root_store.add_parsable_certificates( + CertificateDer::pem_slice_iter(kt.bytes_for("ca.cert")).map(|result| result.unwrap()), + ); + + config + .with_root_certificates(root_store) + .with_no_client_auth() +} + +pub fn finish_client_config_with_creds( + kt: KeyType, + config: rustls::ConfigBuilder, +) -> ClientConfig { + let mut root_store = RootCertStore::empty(); + root_store.add_parsable_certificates( + CertificateDer::pem_slice_iter(kt.bytes_for("ca.cert")).map(|result| result.unwrap()), + ); + + config + .with_root_certificates(root_store) + .with_client_auth_cert(kt.get_client_chain(), kt.get_client_key()) + .unwrap() +} + +pub fn make_client_config(kt: KeyType, provider: &CryptoProvider) -> ClientConfig { + finish_client_config(kt, client_config_builder(provider)) +} + +pub fn make_client_config_with_kx_groups( + kt: KeyType, + kx_groups: Vec<&'static dyn rustls::crypto::SupportedKxGroup>, + provider: &CryptoProvider, +) -> ClientConfig { + let builder = ClientConfig::builder_with_provider( + CryptoProvider { + kx_groups, + ..provider.clone() + } + .into(), + ) + .with_safe_default_protocol_versions() + .unwrap(); + finish_client_config(kt, builder) +} + +pub fn make_client_config_with_versions( + kt: KeyType, + versions: &[&'static rustls::SupportedProtocolVersion], + provider: &CryptoProvider, +) -> ClientConfig { + finish_client_config(kt, client_config_builder_with_versions(versions, provider)) +} + +pub fn make_client_config_with_auth(kt: KeyType, provider: &CryptoProvider) -> ClientConfig { + finish_client_config_with_creds(kt, client_config_builder(provider)) +} + +pub fn make_client_config_with_versions_with_auth( + kt: KeyType, + versions: &[&'static rustls::SupportedProtocolVersion], + provider: &CryptoProvider, +) -> ClientConfig { + finish_client_config_with_creds(kt, client_config_builder_with_versions(versions, provider)) +} + +pub fn make_client_config_with_verifier( + versions: &[&'static rustls::SupportedProtocolVersion], + verifier_builder: ServerCertVerifierBuilder, + provider: &CryptoProvider, +) -> ClientConfig { + client_config_builder_with_versions(versions, provider) + .dangerous() + .with_custom_certificate_verifier(verifier_builder.build().unwrap()) + .with_no_client_auth() +} + +pub fn webpki_client_verifier_builder( + roots: Arc, + provider: &CryptoProvider, +) -> ClientCertVerifierBuilder { + WebPkiClientVerifier::builder_with_provider(roots, provider.clone().into()) +} + +pub fn webpki_server_verifier_builder( + roots: Arc, + provider: &CryptoProvider, +) -> ServerCertVerifierBuilder { + WebPkiServerVerifier::builder_with_provider(roots, provider.clone().into()) +} + +pub fn make_pair(kt: KeyType, provider: &CryptoProvider) -> (ClientConnection, ServerConnection) { + make_pair_for_configs( + make_client_config(kt, provider), + make_server_config(kt, provider), + ) +} + +pub fn make_pair_for_configs( + client_config: ClientConfig, + server_config: ServerConfig, +) -> (ClientConnection, ServerConnection) { + make_pair_for_arc_configs(&Arc::new(client_config), &Arc::new(server_config)) +} + +pub fn make_pair_for_arc_configs( + client_config: &Arc, + server_config: &Arc, +) -> (ClientConnection, ServerConnection) { + ( + ClientConnection::new(Arc::clone(client_config), server_name("localhost")).unwrap(), + ServerConnection::new(Arc::clone(server_config)).unwrap(), + ) +} + +pub fn do_handshake( + client: &mut impl DerefMut>, + server: &mut impl DerefMut>, +) -> (usize, usize) { + let (mut to_client, mut to_server) = (0, 0); + while server.is_handshaking() || client.is_handshaking() { + to_server += transfer(client, server); + server.process_new_packets().unwrap(); + to_client += transfer(server, client); + client.process_new_packets().unwrap(); + } + (to_server, to_client) +} + +// Drive a handshake using unbuffered connections. +// +// Note that this drives the connection beyond the handshake until both +// connections are idle and there is no pending data waiting to be processed +// by either. In practice this just means that session tickets are processed +// by the client. +pub fn do_unbuffered_handshake( + client: &mut UnbufferedClientConnection, + server: &mut UnbufferedServerConnection, +) { + fn is_idle(conn: &UnbufferedConnectionCommon, data: &[u8]) -> bool { + !conn.is_handshaking() && !conn.wants_write() && data.is_empty() + } + + let mut client_data = Vec::with_capacity(1024); + let mut server_data = Vec::with_capacity(1024); + + while !is_idle(client, &client_data) || !is_idle(server, &server_data) { + loop { + let UnbufferedStatus { discard, state } = client.process_tls_records(&mut client_data); + let state = state.unwrap(); + + match state { + ConnectionState::BlockedHandshake | ConnectionState::WriteTraffic(_) => { + client_data.drain(..discard); + break; + } + ConnectionState::Closed | ConnectionState::PeerClosed => unreachable!(), + ConnectionState::ReadEarlyData(_) => (), + ConnectionState::EncodeTlsData(mut data) => { + let required = match data.encode(&mut []) { + Err(EncodeError::InsufficientSize(err)) => err.required_size, + _ => unreachable!(), + }; + + let old_len = server_data.len(); + server_data.resize(old_len + required, 0); + data.encode(&mut server_data[old_len..]) + .unwrap(); + } + ConnectionState::TransmitTlsData(data) => data.done(), + st => unreachable!("unexpected connection state: {st:?}"), + } + + client_data.drain(..discard); + } + + loop { + let UnbufferedStatus { discard, state } = server.process_tls_records(&mut server_data); + let state = state.unwrap(); + + match state { + ConnectionState::BlockedHandshake | ConnectionState::WriteTraffic(_) => { + server_data.drain(..discard); + break; + } + ConnectionState::Closed | ConnectionState::PeerClosed => unreachable!(), + ConnectionState::ReadEarlyData(_) => unreachable!(), + ConnectionState::EncodeTlsData(mut data) => { + let required = match data.encode(&mut []) { + Err(EncodeError::InsufficientSize(err)) => err.required_size, + _ => unreachable!(), + }; + + let old_len = client_data.len(); + client_data.resize(old_len + required, 0); + data.encode(&mut client_data[old_len..]) + .unwrap(); + } + ConnectionState::TransmitTlsData(data) => data.done(), + _ => unreachable!(), + } + + server_data.drain(..discard); + } + } + + assert!(server_data.is_empty()); + assert!(client_data.is_empty()); +} + +#[derive(PartialEq, Debug)] +pub enum ErrorFromPeer { + Client(Error), + Server(Error), +} + +pub fn do_handshake_until_error( + client: &mut ClientConnection, + server: &mut ServerConnection, +) -> Result<(), ErrorFromPeer> { + while server.is_handshaking() || client.is_handshaking() { + transfer(client, server); + server + .process_new_packets() + .map_err(ErrorFromPeer::Server)?; + transfer(server, client); + client + .process_new_packets() + .map_err(ErrorFromPeer::Client)?; + } + + Ok(()) +} + +pub fn do_handshake_altered( + client: ClientConnection, + alter_server_message: impl Fn(&mut Message) -> Altered, + alter_client_message: impl Fn(&mut Message) -> Altered, + server: ServerConnection, +) -> Result<(), ErrorFromPeer> { + let mut client: Connection = Connection::Client(client); + let mut server: Connection = Connection::Server(server); + + while server.is_handshaking() || client.is_handshaking() { + transfer_altered(&mut client, &alter_client_message, &mut server); + + server + .process_new_packets() + .map_err(ErrorFromPeer::Server)?; + + transfer_altered(&mut server, &alter_server_message, &mut client); + + client + .process_new_packets() + .map_err(ErrorFromPeer::Client)?; + } + + Ok(()) +} + +pub fn do_handshake_until_both_error( + client: &mut ClientConnection, + server: &mut ServerConnection, +) -> Result<(), Vec> { + match do_handshake_until_error(client, server) { + Err(server_err @ ErrorFromPeer::Server(_)) => { + let mut errors = vec![server_err]; + transfer(server, client); + let client_err = client + .process_new_packets() + .map_err(ErrorFromPeer::Client) + .expect_err("client didn't produce error after server error"); + errors.push(client_err); + Err(errors) + } + + Err(client_err @ ErrorFromPeer::Client(_)) => { + let mut errors = vec![client_err]; + transfer(client, server); + let server_err = server + .process_new_packets() + .map_err(ErrorFromPeer::Server) + .expect_err("server didn't produce error after client error"); + errors.push(server_err); + Err(errors) + } + + Ok(()) => Ok(()), + } +} + +pub fn server_name(name: &'static str) -> ServerName<'static> { + name.try_into().unwrap() +} + +pub struct FailsReads { + errkind: io::ErrorKind, +} + +impl FailsReads { + pub fn new(errkind: io::ErrorKind) -> Self { + Self { errkind } + } +} + +impl io::Read for FailsReads { + fn read(&mut self, _b: &mut [u8]) -> io::Result { + Err(io::Error::from(self.errkind)) + } +} + +pub fn do_suite_and_kx_test( + client_config: ClientConfig, + server_config: ServerConfig, + expect_suite: SupportedCipherSuite, + expect_kx: NamedGroup, + expect_version: ProtocolVersion, +) { + println!( + "do_suite_test {:?} {:?}", + expect_version, + expect_suite.suite() + ); + let (mut client, mut server) = make_pair_for_configs(client_config, server_config); + + assert_eq!(None, client.negotiated_cipher_suite()); + assert_eq!(None, server.negotiated_cipher_suite()); + assert!( + client + .negotiated_key_exchange_group() + .is_none() + ); + assert!( + server + .negotiated_key_exchange_group() + .is_none() + ); + assert_eq!(None, client.protocol_version()); + assert_eq!(None, server.protocol_version()); + assert!(client.is_handshaking()); + assert!(server.is_handshaking()); + + transfer(&mut client, &mut server); + server.process_new_packets().unwrap(); + + assert!(client.is_handshaking()); + assert!(server.is_handshaking()); + assert_eq!(None, client.protocol_version()); + assert_eq!(Some(expect_version), server.protocol_version()); + assert_eq!(None, client.negotiated_cipher_suite()); + assert_eq!(Some(expect_suite), server.negotiated_cipher_suite()); + assert!( + client + .negotiated_key_exchange_group() + .is_none() + ); + if matches!(expect_version, ProtocolVersion::TLSv1_2) { + assert!( + server + .negotiated_key_exchange_group() + .is_none() + ); + } else { + assert_eq!( + expect_kx, + server + .negotiated_key_exchange_group() + .unwrap() + .name() + ); + } + + transfer(&mut server, &mut client); + client.process_new_packets().unwrap(); + + assert_eq!(Some(expect_suite), client.negotiated_cipher_suite()); + assert_eq!(Some(expect_suite), server.negotiated_cipher_suite()); + assert_eq!( + expect_kx, + client + .negotiated_key_exchange_group() + .unwrap() + .name() + ); + if matches!(expect_version, ProtocolVersion::TLSv1_2) { + assert!( + server + .negotiated_key_exchange_group() + .is_none() + ); + } else { + assert_eq!( + expect_kx, + server + .negotiated_key_exchange_group() + .unwrap() + .name() + ); + } + + transfer(&mut client, &mut server); + server.process_new_packets().unwrap(); + transfer(&mut server, &mut client); + client.process_new_packets().unwrap(); + + assert!(!client.is_handshaking()); + assert!(!server.is_handshaking()); + assert_eq!(Some(expect_version), client.protocol_version()); + assert_eq!(Some(expect_version), server.protocol_version()); + assert_eq!(Some(expect_suite), client.negotiated_cipher_suite()); + assert_eq!(Some(expect_suite), server.negotiated_cipher_suite()); + assert_eq!( + expect_kx, + client + .negotiated_key_exchange_group() + .unwrap() + .name() + ); + assert_eq!( + expect_kx, + server + .negotiated_key_exchange_group() + .unwrap() + .name() + ); +} + +#[derive(Debug)] +pub struct MockServerVerifier { + cert_rejection_error: Option, + tls12_signature_error: Option, + tls13_signature_error: Option, + signature_schemes: Vec, + expected_ocsp_response: Option>, + requires_raw_public_keys: bool, + raw_public_key_algorithms: Option, +} + +impl ServerCertVerifier for MockServerVerifier { + fn verify_server_cert( + &self, + end_entity: &CertificateDer<'_>, + intermediates: &[CertificateDer<'_>], + server_name: &ServerName<'_>, + ocsp_response: &[u8], + now: UnixTime, + ) -> Result { + println!( + "verify_server_cert({end_entity:?}, {intermediates:?}, {server_name:?}, {ocsp_response:?}, {now:?})" + ); + if let Some(expected_ocsp) = &self.expected_ocsp_response { + assert_eq!(expected_ocsp, ocsp_response); + } + match &self.cert_rejection_error { + Some(error) => Err(error.clone()), + _ => Ok(ServerCertVerified::assertion()), + } + } + + fn verify_tls12_signature( + &self, + message: &[u8], + cert: &CertificateDer<'_>, + dss: &DigitallySignedStruct, + ) -> Result { + println!("verify_tls12_signature({message:?}, {cert:?}, {dss:?})"); + match &self.tls12_signature_error { + Some(error) => Err(error.clone()), + _ => Ok(HandshakeSignatureValid::assertion()), + } + } + + fn verify_tls13_signature( + &self, + message: &[u8], + cert: &CertificateDer<'_>, + dss: &DigitallySignedStruct, + ) -> Result { + println!("verify_tls13_signature({message:?}, {cert:?}, {dss:?})"); + match &self.tls13_signature_error { + Some(error) => Err(error.clone()), + _ if self.requires_raw_public_keys => verify_tls13_signature_with_raw_key( + message, + &SubjectPublicKeyInfoDer::from(cert.as_ref()), + dss, + self.raw_public_key_algorithms + .as_ref() + .unwrap(), + ), + _ => Ok(HandshakeSignatureValid::assertion()), + } + } + + fn supported_verify_schemes(&self) -> Vec { + self.signature_schemes.clone() + } + + fn requires_raw_public_keys(&self) -> bool { + self.requires_raw_public_keys + } +} + +impl MockServerVerifier { + pub fn accepts_anything() -> Self { + MockServerVerifier { + cert_rejection_error: None, + ..Default::default() + } + } + + pub fn expects_ocsp_response(response: &[u8]) -> Self { + MockServerVerifier { + expected_ocsp_response: Some(response.to_vec()), + ..Default::default() + } + } + + pub fn rejects_certificate(err: Error) -> Self { + MockServerVerifier { + cert_rejection_error: Some(err), + ..Default::default() + } + } + + pub fn rejects_tls12_signatures(err: Error) -> Self { + MockServerVerifier { + tls12_signature_error: Some(err), + ..Default::default() + } + } + + pub fn rejects_tls13_signatures(err: Error) -> Self { + MockServerVerifier { + tls13_signature_error: Some(err), + ..Default::default() + } + } + + pub fn offers_no_signature_schemes() -> Self { + MockServerVerifier { + signature_schemes: vec![], + ..Default::default() + } + } + + pub fn expects_raw_public_keys(provider: &CryptoProvider) -> Self { + MockServerVerifier { + requires_raw_public_keys: true, + raw_public_key_algorithms: Some(provider.signature_verification_algorithms), + ..Default::default() + } + } +} + +impl Default for MockServerVerifier { + fn default() -> Self { + MockServerVerifier { + cert_rejection_error: None, + tls12_signature_error: None, + tls13_signature_error: None, + signature_schemes: vec![ + SignatureScheme::RSA_PSS_SHA256, + SignatureScheme::RSA_PKCS1_SHA256, + SignatureScheme::ED25519, + SignatureScheme::ECDSA_NISTP256_SHA256, + SignatureScheme::ECDSA_NISTP384_SHA384, + SignatureScheme::ECDSA_NISTP521_SHA512, + ], + expected_ocsp_response: None, + requires_raw_public_keys: false, + raw_public_key_algorithms: None, + } + } +} + +#[derive(Debug)] +pub struct MockClientVerifier { + pub verified: fn() -> Result, + pub subjects: Vec, + pub mandatory: bool, + pub offered_schemes: Option>, + expect_raw_public_keys: bool, + raw_public_key_algorithms: Option, + parent: Arc, +} + +impl MockClientVerifier { + pub fn new( + verified: fn() -> Result, + kt: KeyType, + provider: &CryptoProvider, + ) -> Self { + Self { + parent: webpki_client_verifier_builder(get_client_root_store(kt), provider) + .build() + .unwrap(), + verified, + subjects: get_client_root_store(kt).subjects(), + mandatory: true, + offered_schemes: None, + expect_raw_public_keys: false, + raw_public_key_algorithms: Some(provider.signature_verification_algorithms), + } + } +} + +impl ClientCertVerifier for MockClientVerifier { + fn client_auth_mandatory(&self) -> bool { + self.mandatory + } + + fn root_hint_subjects(&self) -> &[DistinguishedName] { + &self.subjects + } + + fn verify_client_cert( + &self, + _end_entity: &CertificateDer<'_>, + _intermediates: &[CertificateDer<'_>], + _now: UnixTime, + ) -> Result { + (self.verified)() + } + + fn verify_tls12_signature( + &self, + message: &[u8], + cert: &CertificateDer<'_>, + dss: &DigitallySignedStruct, + ) -> Result { + if self.expect_raw_public_keys { + Ok(HandshakeSignatureValid::assertion()) + } else { + self.parent + .verify_tls12_signature(message, cert, dss) + } + } + + fn verify_tls13_signature( + &self, + message: &[u8], + cert: &CertificateDer<'_>, + dss: &DigitallySignedStruct, + ) -> Result { + if self.expect_raw_public_keys { + verify_tls13_signature_with_raw_key( + message, + &SubjectPublicKeyInfoDer::from(cert.as_ref()), + dss, + self.raw_public_key_algorithms + .as_ref() + .unwrap(), + ) + } else { + self.parent + .verify_tls13_signature(message, cert, dss) + } + } + + fn supported_verify_schemes(&self) -> Vec { + if let Some(schemes) = &self.offered_schemes { + schemes.clone() + } else { + self.parent.supported_verify_schemes() + } + } + + fn requires_raw_public_keys(&self) -> bool { + self.expect_raw_public_keys + } +} + +/// This allows injection/receipt of raw messages into a post-handshake connection. +/// +/// It consumes one of the peers, extracts its secrets, and then reconstitutes the +/// message encrypter/decrypter. It does not do fragmentation/joining. +pub struct RawTls { + encrypter: Box, + enc_seq: u64, + decrypter: Box, + dec_seq: u64, +} + +impl RawTls { + /// conn must be post-handshake, and must have been created with `enable_secret_extraction` + pub fn new_client(conn: ClientConnection) -> Self { + let suite = conn.negotiated_cipher_suite().unwrap(); + Self::new( + suite, + conn.dangerous_extract_secrets() + .unwrap(), + ) + } + + /// conn must be post-handshake, and must have been created with `enable_secret_extraction` + pub fn new_server(conn: ServerConnection) -> Self { + let suite = conn.negotiated_cipher_suite().unwrap(); + Self::new( + suite, + conn.dangerous_extract_secrets() + .unwrap(), + ) + } + + fn new(suite: SupportedCipherSuite, secrets: rustls::ExtractedSecrets) -> Self { + let rustls::ExtractedSecrets { + tx: (tx_seq, tx_keys), + rx: (rx_seq, rx_keys), + } = secrets; + + let encrypter = match (tx_keys, suite) { + ( + rustls::ConnectionTrafficSecrets::Aes256Gcm { key, iv }, + SupportedCipherSuite::Tls13(tls13), + ) => tls13.aead_alg.encrypter(key, iv), + + ( + rustls::ConnectionTrafficSecrets::Aes256Gcm { key, iv }, + SupportedCipherSuite::Tls12(tls12), + ) => tls12 + .aead_alg + .encrypter(key, &iv.as_ref()[..4], &iv.as_ref()[4..]), + + _ => todo!(), + }; + + let decrypter = match (rx_keys, suite) { + ( + rustls::ConnectionTrafficSecrets::Aes256Gcm { key, iv }, + SupportedCipherSuite::Tls13(tls13), + ) => tls13.aead_alg.decrypter(key, iv), + + ( + rustls::ConnectionTrafficSecrets::Aes256Gcm { key, iv }, + SupportedCipherSuite::Tls12(tls12), + ) => tls12 + .aead_alg + .decrypter(key, &iv.as_ref()[..4]), + + _ => todo!(), + }; + + Self { + encrypter, + enc_seq: tx_seq, + decrypter, + dec_seq: rx_seq, + } + } + + pub fn encrypt_and_send( + &mut self, + msg: &PlainMessage, + peer: &mut impl DerefMut>, + ) { + let data = self + .encrypter + .encrypt(msg.borrow_outbound(), self.enc_seq) + .unwrap() + .encode(); + self.enc_seq += 1; + peer.read_tls(&mut io::Cursor::new(data)) + .unwrap(); + } + + pub fn receive_and_decrypt( + &mut self, + peer: &mut impl DerefMut>, + f: impl Fn(Message), + ) { + let mut data = vec![]; + peer.write_tls(&mut io::Cursor::new(&mut data)) + .unwrap(); + + let mut reader = Reader::init(&data); + let content_type = ContentType::read(&mut reader).unwrap(); + let version = ProtocolVersion::read(&mut reader).unwrap(); + let len = u16::read(&mut reader).unwrap(); + let left = &mut data[5..]; + assert_eq!(len as usize, left.len()); + + let inbound = InboundOpaqueMessage::new(content_type, version, left); + let plain = self + .decrypter + .decrypt(inbound, self.dec_seq) + .unwrap(); + self.dec_seq += 1; + + let msg = Message::try_from(plain).unwrap(); + println!("receive_and_decrypt: {msg:?}"); + + f(msg); + } +} + +pub fn aes_128_gcm_with_1024_confidentiality_limit( + provider: CryptoProvider, +) -> Arc { + const CONFIDENTIALITY_LIMIT: u64 = 1024; + + // needed to extend lifetime of Tls13CipherSuite to 'static + static TLS13_LIMITED_SUITE: OnceLock = OnceLock::new(); + static TLS12_LIMITED_SUITE: OnceLock = OnceLock::new(); + + let tls13_limited = TLS13_LIMITED_SUITE.get_or_init(|| { + let tls13 = provider + .cipher_suites + .iter() + .find(|cs| cs.suite() == CipherSuite::TLS13_AES_128_GCM_SHA256) + .unwrap() + .tls13() + .unwrap(); + + rustls::Tls13CipherSuite { + common: rustls::crypto::CipherSuiteCommon { + confidentiality_limit: CONFIDENTIALITY_LIMIT, + ..tls13.common + }, + ..*tls13 + } + }); + + let tls12_limited = TLS12_LIMITED_SUITE.get_or_init(|| { + let SupportedCipherSuite::Tls12(tls12) = *provider + .cipher_suites + .iter() + .find(|cs| cs.suite() == CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) + .unwrap() + else { + unreachable!(); + }; + + rustls::Tls12CipherSuite { + common: rustls::crypto::CipherSuiteCommon { + confidentiality_limit: CONFIDENTIALITY_LIMIT, + ..tls12.common + }, + ..*tls12 + } + }); + + CryptoProvider { + cipher_suites: vec![ + SupportedCipherSuite::Tls13(tls13_limited), + SupportedCipherSuite::Tls12(tls12_limited), + ], + ..provider + } + .into() +} + +pub fn unsafe_plaintext_crypto_provider(provider: CryptoProvider) -> Arc { + static TLS13_PLAIN_SUITE: OnceLock = OnceLock::new(); + + let tls13 = TLS13_PLAIN_SUITE.get_or_init(|| { + let tls13 = provider + .cipher_suites + .iter() + .find(|cs| cs.suite() == CipherSuite::TLS13_AES_256_GCM_SHA384) + .unwrap() + .tls13() + .unwrap(); + + rustls::Tls13CipherSuite { + aead_alg: &plaintext::Aead, + common: rustls::crypto::CipherSuiteCommon { ..tls13.common }, + ..*tls13 + } + }); + + CryptoProvider { + cipher_suites: vec![SupportedCipherSuite::Tls13(tls13)], + ..provider + } + .into() +} + +mod plaintext { + use rustls::ConnectionTrafficSecrets; + use rustls::crypto::cipher::{ + AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, MessageDecrypter, MessageEncrypter, + OutboundPlainMessage, PrefixedPayload, Tls13AeadAlgorithm, UnsupportedOperationError, + }; + + use super::*; + + pub(super) struct Aead; + + impl Tls13AeadAlgorithm for Aead { + fn encrypter(&self, _key: AeadKey, _iv: Iv) -> Box { + Box::new(Encrypter) + } + + fn decrypter(&self, _key: AeadKey, _iv: Iv) -> Box { + Box::new(Decrypter) + } + + fn key_len(&self) -> usize { + 32 + } + + fn extract_keys( + &self, + _key: AeadKey, + _iv: Iv, + ) -> Result { + Err(UnsupportedOperationError) + } + } + + struct Encrypter; + + impl MessageEncrypter for Encrypter { + fn encrypt( + &mut self, + msg: OutboundPlainMessage<'_>, + _seq: u64, + ) -> Result { + let mut payload = PrefixedPayload::with_capacity(msg.payload.len()); + payload.extend_from_chunks(&msg.payload); + + Ok(OutboundOpaqueMessage::new( + ContentType::ApplicationData, + ProtocolVersion::TLSv1_2, + payload, + )) + } + + fn encrypted_payload_len(&self, payload_len: usize) -> usize { + payload_len + } + } + + struct Decrypter; + + impl MessageDecrypter for Decrypter { + fn decrypt<'a>( + &mut self, + msg: InboundOpaqueMessage<'a>, + _seq: u64, + ) -> Result, Error> { + Ok(msg.into_plain_message()) + } + } +} + +/// Deeply inefficient, test-only TLS encoding helpers +pub mod encoding { + use rustls::internal::msgs::codec::Codec; + use rustls::internal::msgs::enums::ExtensionType; + use rustls::{ + CipherSuite, ContentType, HandshakeType, NamedGroup, ProtocolVersion, SignatureScheme, + }; + + /// Return a client hello with mandatory extensions added to `extensions` + /// + /// The returned bytes are handshake-framed, but not message-framed. + pub fn basic_client_hello(mut extensions: Vec) -> Vec { + extensions.push(Extension::new_kx_groups()); + extensions.push(Extension::new_sig_algs()); + extensions.push(Extension::new_versions()); + extensions.push(Extension::new_dummy_key_share()); + client_hello_with_extensions(extensions) + } + + /// Return a client hello with exactly `extensions` + /// + /// The returned bytes are handshake-framed, but not message-framed. + pub fn client_hello_with_extensions(extensions: Vec) -> Vec { + client_hello( + ProtocolVersion::TLSv1_2, + &[0u8; 32], + &[0], + vec![ + CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + CipherSuite::TLS13_AES_128_GCM_SHA256, + ], + extensions, + ) + } + + pub fn client_hello( + legacy_version: ProtocolVersion, + random: &[u8; 32], + session_id: &[u8], + cipher_suites: Vec, + extensions: Vec, + ) -> Vec { + let mut out = vec![]; + + legacy_version.encode(&mut out); + out.extend_from_slice(random); + out.extend_from_slice(session_id); + cipher_suites.to_vec().encode(&mut out); + out.extend_from_slice(&[0x01, 0x00]); // only null compression + + let mut exts = vec![]; + for e in extensions { + e.typ.encode(&mut exts); + exts.extend_from_slice(&(e.body.len() as u16).to_be_bytes()); + exts.extend_from_slice(&e.body); + } + + out.extend(len_u16(exts)); + handshake_framing(HandshakeType::ClientHello, out) + } + + /// Apply handshake framing to `body`. + /// + /// This does not do fragmentation. + pub fn handshake_framing(ty: HandshakeType, body: Vec) -> Vec { + let mut body = len_u24(body); + body.splice(0..0, ty.to_array()); + body + } + + /// Apply message framing to `body`. + pub fn message_framing(ty: ContentType, vers: ProtocolVersion, body: Vec) -> Vec { + let mut body = len_u16(body); + body.splice(0..0, vers.to_array()); + body.splice(0..0, ty.to_array()); + body + } + + #[derive(Clone)] + pub struct Extension { + pub typ: ExtensionType, + pub body: Vec, + } + + impl Extension { + pub fn new_sig_algs() -> Extension { + Extension { + typ: ExtensionType::SignatureAlgorithms, + body: len_u16( + SignatureScheme::RSA_PKCS1_SHA256 + .to_array() + .to_vec(), + ), + } + } + + pub fn new_kx_groups() -> Extension { + Extension { + typ: ExtensionType::EllipticCurves, + body: len_u16(vector_of([NamedGroup::secp256r1].into_iter())), + } + } + + pub fn new_versions() -> Extension { + Extension { + typ: ExtensionType::SupportedVersions, + body: len_u8(vector_of( + [ProtocolVersion::TLSv1_3, ProtocolVersion::TLSv1_2].into_iter(), + )), + } + } + + pub fn new_dummy_key_share() -> Extension { + const SOME_POINT_ON_P256: &[u8] = &[ + 4, 41, 39, 177, 5, 18, 186, 227, 237, 220, 254, 70, 120, 40, 18, 139, 173, 41, 3, + 38, 153, 25, 247, 8, 96, 105, 200, 196, 223, 108, 115, 40, 56, 199, 120, 121, 100, + 234, 172, 0, 229, 146, 31, 177, 73, 138, 96, 244, 96, 103, 102, 179, 217, 104, 80, + 1, 85, 141, 26, 151, 78, 115, 65, 81, 62, + ]; + + let mut share = len_u16(SOME_POINT_ON_P256.to_vec()); + share.splice(0..0, NamedGroup::secp256r1.to_array()); + + Extension { + typ: ExtensionType::KeyShare, + body: len_u16(share), + } + } + } + + /// Prefix with u8 length + pub fn len_u8(mut body: Vec) -> Vec { + body.splice(0..0, [body.len() as u8]); + body + } + + /// Prefix with u16 length + pub fn len_u16(mut body: Vec) -> Vec { + body.splice(0..0, (body.len() as u16).to_be_bytes()); + body + } + + /// Prefix with u24 length + pub fn len_u24(mut body: Vec) -> Vec { + let len = (body.len() as u32).to_be_bytes(); + body.insert(0, len[1]); + body.insert(1, len[2]); + body.insert(2, len[3]); + body + } + + /// Encode each of `items` + pub fn vector_of<'a, T: Codec<'a>>(items: impl Iterator) -> Vec { + let mut body = Vec::new(); + + for i in items { + i.encode(&mut body); + } + body + } +} diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 7d93128a7e2..b0ab257849a 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -57,6 +57,7 @@ log = { workspace = true } macro_rules_attribute = { workspace = true } num-bigint = { workspace = true } rcgen = { workspace = true } +rustls-test = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } time = { workspace = true } diff --git a/rustls/benches/benchmarks.rs b/rustls/benches/benchmarks.rs index 85c2013ff90..070e6cf8e5d 100644 --- a/rustls/benches/benchmarks.rs +++ b/rustls/benches/benchmarks.rs @@ -4,13 +4,11 @@ use bencher::{Bencher, benchmark_group, benchmark_main}; use rustls::crypto::ring as provider; -#[path = "../tests/common/mod.rs"] -mod test_utils; use std::io; use std::sync::Arc; use rustls::ServerConnection; -use test_utils::*; +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()); diff --git a/rustls/tests/common/mod.rs b/rustls/tests/common/mod.rs index 9186a451e27..02541e91829 100644 --- a/rustls/tests/common/mod.rs +++ b/rustls/tests/common/mod.rs @@ -1,454 +1,13 @@ #![allow(dead_code)] #![allow(clippy::disallowed_types, clippy::duplicate_mod)] -use std::io; -use std::ops::DerefMut; -use std::sync::OnceLock; - -use pki_types::pem::PemObject; -use pki_types::{ - CertificateDer, CertificateRevocationListDer, PrivateKeyDer, PrivatePkcs8KeyDer, ServerName, - SubjectPublicKeyInfoDer, UnixTime, -}; - -use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; -use rustls::client::{ - AlwaysResolvesClientRawPublicKeys, ServerCertVerifierBuilder, UnbufferedClientConnection, - WebPkiServerVerifier, -}; -use rustls::crypto::cipher::{InboundOpaqueMessage, MessageDecrypter, MessageEncrypter}; -use rustls::crypto::{ - CryptoProvider, WebPkiSupportedAlgorithms, verify_tls13_signature_with_raw_key, -}; -use rustls::internal::msgs::codec::{Codec, Reader}; -use rustls::internal::msgs::message::{Message, OutboundOpaqueMessage, PlainMessage}; -use rustls::server::danger::{ClientCertVerified, ClientCertVerifier}; -use rustls::server::{ - AlwaysResolvesServerRawPublicKeys, ClientCertVerifierBuilder, UnbufferedServerConnection, - WebPkiClientVerifier, -}; -use rustls::sign::CertifiedKey; -use rustls::unbuffered::{ - ConnectionState, EncodeError, UnbufferedConnectionCommon, UnbufferedStatus, -}; -use rustls::{ - CipherSuite, ClientConfig, ClientConnection, Connection, ConnectionCommon, ContentType, - DigitallySignedStruct, DistinguishedName, Error, InconsistentKeys, NamedGroup, ProtocolVersion, - RootCertStore, ServerConfig, ServerConnection, SideData, SignatureScheme, SupportedCipherSuite, -}; - -// Import `Arc` here for tests - can be overwritten to test with another `Arc` such as `portable_atomic_util::Arc` pub use std::sync::Arc; -macro_rules! embed_files { - ( - $( - ($name:ident, $keytype:expr, $path:expr); - )+ - ) => { - $( - const $name: &'static [u8] = include_bytes!( - concat!("../../../test-ca/", $keytype, "/", $path)); - )+ - - pub fn bytes_for(keytype: &str, path: &str) -> &'static [u8] { - match (keytype, path) { - $( - ($keytype, $path) => $name, - )+ - _ => panic!("unknown keytype {} with path {}", keytype, path), - } - } - } -} - -embed_files! { - (ECDSA_P256_END_PEM_SPKI, "ecdsa-p256", "end.spki.pem"); - (ECDSA_P256_CLIENT_PEM_SPKI, "ecdsa-p256", "client.spki.pem"); - (ECDSA_P256_CA_CERT, "ecdsa-p256", "ca.cert"); - (ECDSA_P256_CA_DER, "ecdsa-p256", "ca.der"); - (ECDSA_P256_CA_KEY, "ecdsa-p256", "ca.key"); - (ECDSA_P256_CLIENT_CERT, "ecdsa-p256", "client.cert"); - (ECDSA_P256_CLIENT_CHAIN, "ecdsa-p256", "client.chain"); - (ECDSA_P256_CLIENT_FULLCHAIN, "ecdsa-p256", "client.fullchain"); - (ECDSA_P256_CLIENT_KEY, "ecdsa-p256", "client.key"); - (ECDSA_P256_END_CRL_PEM, "ecdsa-p256", "end.revoked.crl.pem"); - (ECDSA_P256_CLIENT_CRL_PEM, "ecdsa-p256", "client.revoked.crl.pem"); - (ECDSA_P256_INTERMEDIATE_CRL_PEM, "ecdsa-p256", "inter.revoked.crl.pem"); - (ECDSA_P256_EXPIRED_CRL_PEM, "ecdsa-p256", "end.expired.crl.pem"); - (ECDSA_P256_END_CERT, "ecdsa-p256", "end.cert"); - (ECDSA_P256_END_CHAIN, "ecdsa-p256", "end.chain"); - (ECDSA_P256_END_FULLCHAIN, "ecdsa-p256", "end.fullchain"); - (ECDSA_P256_END_KEY, "ecdsa-p256", "end.key"); - (ECDSA_P256_INTER_CERT, "ecdsa-p256", "inter.cert"); - (ECDSA_P256_INTER_KEY, "ecdsa-p256", "inter.key"); - - (ECDSA_P384_END_PEM_SPKI, "ecdsa-p384", "end.spki.pem"); - (ECDSA_P384_CLIENT_PEM_SPKI, "ecdsa-p384", "client.spki.pem"); - (ECDSA_P384_CA_CERT, "ecdsa-p384", "ca.cert"); - (ECDSA_P384_CA_DER, "ecdsa-p384", "ca.der"); - (ECDSA_P384_CA_KEY, "ecdsa-p384", "ca.key"); - (ECDSA_P384_CLIENT_CERT, "ecdsa-p384", "client.cert"); - (ECDSA_P384_CLIENT_CHAIN, "ecdsa-p384", "client.chain"); - (ECDSA_P384_CLIENT_FULLCHAIN, "ecdsa-p384", "client.fullchain"); - (ECDSA_P384_CLIENT_KEY, "ecdsa-p384", "client.key"); - (ECDSA_P384_END_CRL_PEM, "ecdsa-p384", "end.revoked.crl.pem"); - (ECDSA_P384_CLIENT_CRL_PEM, "ecdsa-p384", "client.revoked.crl.pem"); - (ECDSA_P384_INTERMEDIATE_CRL_PEM, "ecdsa-p384", "inter.revoked.crl.pem"); - (ECDSA_P384_EXPIRED_CRL_PEM, "ecdsa-p384", "end.expired.crl.pem"); - (ECDSA_P384_END_CERT, "ecdsa-p384", "end.cert"); - (ECDSA_P384_END_CHAIN, "ecdsa-p384", "end.chain"); - (ECDSA_P384_END_FULLCHAIN, "ecdsa-p384", "end.fullchain"); - (ECDSA_P384_END_KEY, "ecdsa-p384", "end.key"); - (ECDSA_P384_INTER_CERT, "ecdsa-p384", "inter.cert"); - (ECDSA_P384_INTER_KEY, "ecdsa-p384", "inter.key"); - - (ECDSA_P521_END_PEM_SPKI, "ecdsa-p521", "end.spki.pem"); - (ECDSA_P521_CLIENT_PEM_SPKI, "ecdsa-p521", "client.spki.pem"); - (ECDSA_P521_CA_CERT, "ecdsa-p521", "ca.cert"); - (ECDSA_P521_CA_DER, "ecdsa-p521", "ca.der"); - (ECDSA_P521_CA_KEY, "ecdsa-p521", "ca.key"); - (ECDSA_P521_CLIENT_CERT, "ecdsa-p521", "client.cert"); - (ECDSA_P521_CLIENT_CHAIN, "ecdsa-p521", "client.chain"); - (ECDSA_P521_CLIENT_FULLCHAIN, "ecdsa-p521", "client.fullchain"); - (ECDSA_P521_CLIENT_KEY, "ecdsa-p521", "client.key"); - (ECDSA_P521_END_CRL_PEM, "ecdsa-p521", "end.revoked.crl.pem"); - (ECDSA_P521_CLIENT_CRL_PEM, "ecdsa-p521", "client.revoked.crl.pem"); - (ECDSA_P521_INTERMEDIATE_CRL_PEM, "ecdsa-p521", "inter.revoked.crl.pem"); - (ECDSA_P521_EXPIRED_CRL_PEM, "ecdsa-p521", "end.expired.crl.pem"); - (ECDSA_P521_END_CERT, "ecdsa-p521", "end.cert"); - (ECDSA_P521_END_CHAIN, "ecdsa-p521", "end.chain"); - (ECDSA_P521_END_FULLCHAIN, "ecdsa-p521", "end.fullchain"); - (ECDSA_P521_END_KEY, "ecdsa-p521", "end.key"); - (ECDSA_P521_INTER_CERT, "ecdsa-p521", "inter.cert"); - (ECDSA_P521_INTER_KEY, "ecdsa-p521", "inter.key"); - - (EDDSA_END_PEM_SPKI, "eddsa", "end.spki.pem"); - (EDDSA_CLIENT_PEM_SPKI, "eddsa", "client.spki.pem"); - (EDDSA_CA_CERT, "eddsa", "ca.cert"); - (EDDSA_CA_DER, "eddsa", "ca.der"); - (EDDSA_CA_KEY, "eddsa", "ca.key"); - (EDDSA_CLIENT_CERT, "eddsa", "client.cert"); - (EDDSA_CLIENT_CHAIN, "eddsa", "client.chain"); - (EDDSA_CLIENT_FULLCHAIN, "eddsa", "client.fullchain"); - (EDDSA_CLIENT_KEY, "eddsa", "client.key"); - (EDDSA_END_CRL_PEM, "eddsa", "end.revoked.crl.pem"); - (EDDSA_CLIENT_CRL_PEM, "eddsa", "client.revoked.crl.pem"); - (EDDSA_INTERMEDIATE_CRL_PEM, "eddsa", "inter.revoked.crl.pem"); - (EDDSA_EXPIRED_CRL_PEM, "eddsa", "end.expired.crl.pem"); - (EDDSA_END_CERT, "eddsa", "end.cert"); - (EDDSA_END_CHAIN, "eddsa", "end.chain"); - (EDDSA_END_FULLCHAIN, "eddsa", "end.fullchain"); - (EDDSA_END_KEY, "eddsa", "end.key"); - (EDDSA_INTER_CERT, "eddsa", "inter.cert"); - (EDDSA_INTER_KEY, "eddsa", "inter.key"); - - (RSA_2048_END_PEM_SPKI, "rsa-2048", "end.spki.pem"); - (RSA_2048_CLIENT_PEM_SPKI, "rsa-2048", "client.spki.pem"); - (RSA_2048_CA_CERT, "rsa-2048", "ca.cert"); - (RSA_2048_CA_DER, "rsa-2048", "ca.der"); - (RSA_2048_CA_KEY, "rsa-2048", "ca.key"); - (RSA_2048_CLIENT_CERT, "rsa-2048", "client.cert"); - (RSA_2048_CLIENT_CHAIN, "rsa-2048", "client.chain"); - (RSA_2048_CLIENT_FULLCHAIN, "rsa-2048", "client.fullchain"); - (RSA_2048_CLIENT_KEY, "rsa-2048", "client.key"); - (RSA_2048_END_CRL_PEM, "rsa-2048", "end.revoked.crl.pem"); - (RSA_2048_CLIENT_CRL_PEM, "rsa-2048", "client.revoked.crl.pem"); - (RSA_2048_INTERMEDIATE_CRL_PEM, "rsa-2048", "inter.revoked.crl.pem"); - (RSA_2048_EXPIRED_CRL_PEM, "rsa-2048", "end.expired.crl.pem"); - (RSA_2048_END_CERT, "rsa-2048", "end.cert"); - (RSA_2048_END_CHAIN, "rsa-2048", "end.chain"); - (RSA_2048_END_FULLCHAIN, "rsa-2048", "end.fullchain"); - (RSA_2048_END_KEY, "rsa-2048", "end.key"); - (RSA_2048_INTER_CERT, "rsa-2048", "inter.cert"); - (RSA_2048_INTER_KEY, "rsa-2048", "inter.key"); - - (RSA_3072_END_PEM_SPKI, "rsa-3072", "end.spki.pem"); - (RSA_3072_CLIENT_PEM_SPKI, "rsa-3072", "client.spki.pem"); - (RSA_3072_CA_CERT, "rsa-3072", "ca.cert"); - (RSA_3072_CA_DER, "rsa-3072", "ca.der"); - (RSA_3072_CA_KEY, "rsa-3072", "ca.key"); - (RSA_3072_CLIENT_CERT, "rsa-3072", "client.cert"); - (RSA_3072_CLIENT_CHAIN, "rsa-3072", "client.chain"); - (RSA_3072_CLIENT_FULLCHAIN, "rsa-3072", "client.fullchain"); - (RSA_3072_CLIENT_KEY, "rsa-3072", "client.key"); - (RSA_3072_END_CRL_PEM, "rsa-3072", "end.revoked.crl.pem"); - (RSA_3072_CLIENT_CRL_PEM, "rsa-3072", "client.revoked.crl.pem"); - (RSA_3072_INTERMEDIATE_CRL_PEM, "rsa-3072", "inter.revoked.crl.pem"); - (RSA_3072_EXPIRED_CRL_PEM, "rsa-3072", "end.expired.crl.pem"); - (RSA_3072_END_CERT, "rsa-3072", "end.cert"); - (RSA_3072_END_CHAIN, "rsa-3072", "end.chain"); - (RSA_3072_END_FULLCHAIN, "rsa-3072", "end.fullchain"); - (RSA_3072_END_KEY, "rsa-3072", "end.key"); - (RSA_3072_INTER_CERT, "rsa-3072", "inter.cert"); - (RSA_3072_INTER_KEY, "rsa-3072", "inter.key"); - - (RSA_4096_END_PEM_SPKI, "rsa-4096", "end.spki.pem"); - (RSA_4096_CLIENT_PEM_SPKI, "rsa-4096", "client.spki.pem"); - (RSA_4096_CA_CERT, "rsa-4096", "ca.cert"); - (RSA_4096_CA_DER, "rsa-4096", "ca.der"); - (RSA_4096_CA_KEY, "rsa-4096", "ca.key"); - (RSA_4096_CLIENT_CERT, "rsa-4096", "client.cert"); - (RSA_4096_CLIENT_CHAIN, "rsa-4096", "client.chain"); - (RSA_4096_CLIENT_FULLCHAIN, "rsa-4096", "client.fullchain"); - (RSA_4096_CLIENT_KEY, "rsa-4096", "client.key"); - (RSA_4096_END_CRL_PEM, "rsa-4096", "end.revoked.crl.pem"); - (RSA_4096_CLIENT_CRL_PEM, "rsa-4096", "client.revoked.crl.pem"); - (RSA_4096_INTERMEDIATE_CRL_PEM, "rsa-4096", "inter.revoked.crl.pem"); - (RSA_4096_EXPIRED_CRL_PEM, "rsa-4096", "end.expired.crl.pem"); - (RSA_4096_END_CERT, "rsa-4096", "end.cert"); - (RSA_4096_END_CHAIN, "rsa-4096", "end.chain"); - (RSA_4096_END_FULLCHAIN, "rsa-4096", "end.fullchain"); - (RSA_4096_END_KEY, "rsa-4096", "end.key"); - (RSA_4096_INTER_CERT, "rsa-4096", "inter.cert"); - (RSA_4096_INTER_KEY, "rsa-4096", "inter.key"); -} - -pub fn transfer( - left: &mut impl DerefMut>, - right: &mut impl DerefMut>, -) -> usize { - let mut buf = [0u8; 262144]; - let mut total = 0; - - while left.wants_write() { - let sz = { - let into_buf: &mut dyn io::Write = &mut &mut buf[..]; - left.write_tls(into_buf).unwrap() - }; - total += sz; - if sz == 0 { - return total; - } - - let mut offs = 0; - loop { - let from_buf: &mut dyn io::Read = &mut &buf[offs..sz]; - offs += right.read_tls(from_buf).unwrap(); - if sz == offs { - break; - } - } - } - - total -} - -pub fn transfer_eof(conn: &mut impl DerefMut>) { - let empty_buf = [0u8; 0]; - let empty_cursor: &mut dyn io::Read = &mut &empty_buf[..]; - let sz = conn.read_tls(empty_cursor).unwrap(); - assert_eq!(sz, 0); -} - -pub enum Altered { - /// message has been edited in-place (or is unchanged) - InPlace, - /// send these raw bytes instead of the message. - Raw(Vec), -} - -pub fn transfer_altered(left: &mut Connection, filter: F, right: &mut Connection) -> usize -where - F: Fn(&mut Message) -> Altered, -{ - let mut buf = [0u8; 262144]; - let mut total = 0; - - while left.wants_write() { - let sz = { - let into_buf: &mut dyn io::Write = &mut &mut buf[..]; - left.write_tls(into_buf).unwrap() - }; - total += sz; - if sz == 0 { - return total; - } - - let mut reader = Reader::init(&buf[..sz]); - while reader.any_left() { - let message = OutboundOpaqueMessage::read(&mut reader).unwrap(); - - // this is a bit of a falsehood: we don't know whether message - // is encrypted. it is quite unlikely that a genuine encrypted - // message can be decoded by `Message::try_from`. - let plain = message.into_plain_message(); - - let message_enc = match Message::try_from(plain.clone()) { - Ok(mut message) => match filter(&mut message) { - Altered::InPlace => PlainMessage::from(message) - .into_unencrypted_opaque() - .encode(), - Altered::Raw(data) => data, - }, - // pass through encrypted/undecodable messages - Err(_) => plain.into_unencrypted_opaque().encode(), - }; - - let message_enc_reader: &mut dyn io::Read = &mut &message_enc[..]; - let len = right - .read_tls(message_enc_reader) - .unwrap(); - assert_eq!(len, message_enc.len()); - } - } - - total -} - -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum KeyType { - Rsa2048, - Rsa3072, - Rsa4096, - EcdsaP256, - EcdsaP384, - EcdsaP521, - Ed25519, -} - -pub static ALL_KEY_TYPES: &[KeyType] = &[ - KeyType::Rsa2048, - KeyType::Rsa3072, - KeyType::Rsa4096, - KeyType::EcdsaP256, - KeyType::EcdsaP384, - #[cfg(all(not(feature = "ring"), feature = "aws_lc_rs"))] - KeyType::EcdsaP521, - KeyType::Ed25519, -]; - -impl KeyType { - fn bytes_for(&self, part: &str) -> &'static [u8] { - match self { - Self::Rsa2048 => bytes_for("rsa-2048", part), - Self::Rsa3072 => bytes_for("rsa-3072", part), - Self::Rsa4096 => bytes_for("rsa-4096", part), - Self::EcdsaP256 => bytes_for("ecdsa-p256", part), - Self::EcdsaP384 => bytes_for("ecdsa-p384", part), - Self::EcdsaP521 => bytes_for("ecdsa-p521", part), - Self::Ed25519 => bytes_for("eddsa", part), - } - } - - pub fn ca_cert(&self) -> CertificateDer<'_> { - self.get_chain() - .into_iter() - .next_back() - .expect("cert chain cannot be empty") - } - - pub fn get_chain(&self) -> Vec> { - CertificateDer::pem_slice_iter(self.bytes_for("end.fullchain")) - .map(|result| result.unwrap()) - .collect() - } - - pub fn get_spki(&self) -> SubjectPublicKeyInfoDer<'static> { - SubjectPublicKeyInfoDer::from_pem_slice(self.bytes_for("end.spki.pem")).unwrap() - } - - pub fn get_key(&self) -> PrivateKeyDer<'static> { - PrivatePkcs8KeyDer::from_pem_slice(self.bytes_for("end.key")) - .unwrap() - .into() - } - - pub fn get_client_chain(&self) -> Vec> { - CertificateDer::pem_slice_iter(self.bytes_for("client.fullchain")) - .map(|result| result.unwrap()) - .collect() - } - - pub fn end_entity_crl(&self) -> CertificateRevocationListDer<'static> { - self.get_crl("end", "revoked") - } - - pub fn client_crl(&self) -> CertificateRevocationListDer<'static> { - self.get_crl("client", "revoked") - } - - pub fn intermediate_crl(&self) -> CertificateRevocationListDer<'static> { - self.get_crl("inter", "revoked") - } - - pub fn end_entity_crl_expired(&self) -> CertificateRevocationListDer<'static> { - self.get_crl("end", "expired") - } - - pub fn get_client_key(&self) -> PrivateKeyDer<'static> { - PrivatePkcs8KeyDer::from_pem_slice(self.bytes_for("client.key")) - .unwrap() - .into() - } - - pub fn get_client_spki(&self) -> SubjectPublicKeyInfoDer<'static> { - SubjectPublicKeyInfoDer::from_pem_slice(self.bytes_for("client.spki.pem")).unwrap() - } - - pub fn get_certified_client_key( - &self, - provider: &CryptoProvider, - ) -> Result, Error> { - let private_key = provider - .key_provider - .load_private_key(self.get_client_key())?; - let public_key = private_key - .public_key() - .ok_or(Error::InconsistentKeys(InconsistentKeys::Unknown))?; - let public_key_as_cert = CertificateDer::from(public_key.to_vec()); - Ok(Arc::new(CertifiedKey::new( - vec![public_key_as_cert], - private_key, - ))) - } - - pub fn certified_key_with_raw_pub_key( - &self, - provider: &CryptoProvider, - ) -> Result, Error> { - let private_key = provider - .key_provider - .load_private_key(self.get_key())?; - let public_key = private_key - .public_key() - .ok_or(Error::InconsistentKeys(InconsistentKeys::Unknown))?; - let public_key_as_cert = CertificateDer::from(public_key.to_vec()); - Ok(Arc::new(CertifiedKey::new( - vec![public_key_as_cert], - private_key, - ))) - } - - pub fn certified_key_with_cert_chain( - &self, - provider: &CryptoProvider, - ) -> Result, Error> { - let private_key = provider - .key_provider - .load_private_key(self.get_key())?; - Ok(Arc::new(CertifiedKey::new(self.get_chain(), private_key))) - } - - fn get_crl(&self, role: &str, r#type: &str) -> CertificateRevocationListDer<'static> { - CertificateRevocationListDer::from_pem_slice( - self.bytes_for(&format!("{role}.{type}.crl.pem")), - ) - .unwrap() - } - - pub fn ca_distinguished_name(&self) -> &'static [u8] { - match self { - KeyType::Rsa2048 => b"0\x1f1\x1d0\x1b\x06\x03U\x04\x03\x0c\x14ponytown RSA 2048 CA", - KeyType::Rsa3072 => b"0\x1f1\x1d0\x1b\x06\x03U\x04\x03\x0c\x14ponytown RSA 3072 CA", - KeyType::Rsa4096 => b"0\x1f1\x1d0\x1b\x06\x03U\x04\x03\x0c\x14ponytown RSA 4096 CA", - KeyType::EcdsaP256 => b"0\x211\x1f0\x1d\x06\x03U\x04\x03\x0c\x16ponytown ECDSA p256 CA", - KeyType::EcdsaP384 => b"0\x211\x1f0\x1d\x06\x03U\x04\x03\x0c\x16ponytown ECDSA p384 CA", - KeyType::EcdsaP521 => b"0\x211\x1f0\x1d\x06\x03U\x04\x03\x0c\x16ponytown ECDSA p521 CA", - KeyType::Ed25519 => b"0\x1c1\x1a0\x18\x06\x03U\x04\x03\x0c\x11ponytown EdDSA CA", - } - } -} +use rustls::RootCertStore; +use rustls::client::{ClientConfig, ServerCertVerifierBuilder, WebPkiServerVerifier}; +use rustls::crypto::CryptoProvider; +use rustls::server::{ClientCertVerifierBuilder, ServerConfig, WebPkiClientVerifier}; +pub use rustls_test::*; pub fn server_config_builder( provider: &CryptoProvider, @@ -504,244 +63,6 @@ pub fn client_config_builder_with_versions( } } -pub fn finish_server_config( - kt: KeyType, - conf: rustls::ConfigBuilder, -) -> ServerConfig { - conf.with_no_client_auth() - .with_single_cert(kt.get_chain(), kt.get_key()) - .unwrap() -} - -pub fn make_server_config(kt: KeyType, provider: &CryptoProvider) -> ServerConfig { - finish_server_config(kt, server_config_builder(provider)) -} - -pub fn make_server_config_with_versions( - kt: KeyType, - versions: &[&'static rustls::SupportedProtocolVersion], - provider: &CryptoProvider, -) -> ServerConfig { - finish_server_config(kt, server_config_builder_with_versions(versions, provider)) -} - -pub fn make_server_config_with_kx_groups( - kt: KeyType, - kx_groups: Vec<&'static dyn rustls::crypto::SupportedKxGroup>, - provider: &CryptoProvider, -) -> ServerConfig { - finish_server_config( - kt, - ServerConfig::builder_with_provider( - CryptoProvider { - kx_groups, - ..provider.clone() - } - .into(), - ) - .with_safe_default_protocol_versions() - .unwrap(), - ) -} - -pub fn get_client_root_store(kt: KeyType) -> Arc { - // The key type's chain file contains the DER encoding of the EE cert, the intermediate cert, - // and the root trust anchor. We want only the trust anchor to build the root cert store. - let chain = kt.get_chain(); - let mut roots = RootCertStore::empty(); - roots - .add(chain.last().unwrap().clone()) - .unwrap(); - roots.into() -} - -pub fn make_server_config_with_mandatory_client_auth_crls( - kt: KeyType, - crls: Vec>, - provider: &CryptoProvider, -) -> ServerConfig { - make_server_config_with_client_verifier( - kt, - webpki_client_verifier_builder(get_client_root_store(kt), provider).with_crls(crls), - provider, - ) -} - -pub fn make_server_config_with_mandatory_client_auth( - kt: KeyType, - provider: &CryptoProvider, -) -> ServerConfig { - make_server_config_with_client_verifier( - kt, - webpki_client_verifier_builder(get_client_root_store(kt), provider), - provider, - ) -} - -pub fn make_server_config_with_optional_client_auth( - kt: KeyType, - crls: Vec>, - provider: &CryptoProvider, -) -> ServerConfig { - make_server_config_with_client_verifier( - kt, - webpki_client_verifier_builder(get_client_root_store(kt), provider) - .with_crls(crls) - .allow_unknown_revocation_status() - .allow_unauthenticated(), - provider, - ) -} - -pub fn make_server_config_with_client_verifier( - kt: KeyType, - verifier_builder: ClientCertVerifierBuilder, - provider: &CryptoProvider, -) -> ServerConfig { - server_config_builder(provider) - .with_client_cert_verifier(verifier_builder.build().unwrap()) - .with_single_cert(kt.get_chain(), kt.get_key()) - .unwrap() -} - -pub fn make_server_config_with_raw_key_support( - kt: KeyType, - provider: &CryptoProvider, -) -> ServerConfig { - let mut client_verifier = - MockClientVerifier::new(|| Ok(ClientCertVerified::assertion()), kt, provider); - let server_cert_resolver = Arc::new(AlwaysResolvesServerRawPublicKeys::new( - kt.certified_key_with_raw_pub_key(provider) - .unwrap(), - )); - client_verifier.expect_raw_public_keys = true; - // We don't support tls1.2 for Raw Public Keys, hence the version is hard-coded. - server_config_builder_with_versions(&[&rustls::version::TLS13], provider) - .with_client_cert_verifier(Arc::new(client_verifier)) - .with_cert_resolver(server_cert_resolver) -} - -pub fn make_client_config_with_raw_key_support( - kt: KeyType, - provider: &CryptoProvider, -) -> ClientConfig { - let server_verifier = Arc::new(MockServerVerifier::expects_raw_public_keys(provider)); - let client_cert_resolver = Arc::new(AlwaysResolvesClientRawPublicKeys::new( - kt.get_certified_client_key(provider) - .unwrap(), - )); - // We don't support tls1.2 for Raw Public Keys, hence the version is hard-coded. - client_config_builder_with_versions(&[&rustls::version::TLS13], provider) - .dangerous() - .with_custom_certificate_verifier(server_verifier) - .with_client_cert_resolver(client_cert_resolver) -} - -pub fn make_client_config_with_cipher_suite_and_raw_key_support( - kt: KeyType, - cipher_suite: SupportedCipherSuite, - provider: &CryptoProvider, -) -> ClientConfig { - let server_verifier = Arc::new(MockServerVerifier::expects_raw_public_keys(provider)); - let client_cert_resolver = Arc::new(AlwaysResolvesClientRawPublicKeys::new( - kt.get_certified_client_key(provider) - .unwrap(), - )); - ClientConfig::builder_with_provider( - CryptoProvider { - cipher_suites: vec![cipher_suite], - ..provider.clone() - } - .into(), - ) - .with_protocol_versions(&[&rustls::version::TLS13]) - .unwrap() - .dangerous() - .with_custom_certificate_verifier(server_verifier) - .with_client_cert_resolver(client_cert_resolver) -} - -pub fn finish_client_config( - kt: KeyType, - config: rustls::ConfigBuilder, -) -> ClientConfig { - let mut root_store = RootCertStore::empty(); - root_store.add_parsable_certificates( - CertificateDer::pem_slice_iter(kt.bytes_for("ca.cert")).map(|result| result.unwrap()), - ); - - config - .with_root_certificates(root_store) - .with_no_client_auth() -} - -pub fn finish_client_config_with_creds( - kt: KeyType, - config: rustls::ConfigBuilder, -) -> ClientConfig { - let mut root_store = RootCertStore::empty(); - root_store.add_parsable_certificates( - CertificateDer::pem_slice_iter(kt.bytes_for("ca.cert")).map(|result| result.unwrap()), - ); - - config - .with_root_certificates(root_store) - .with_client_auth_cert(kt.get_client_chain(), kt.get_client_key()) - .unwrap() -} - -pub fn make_client_config(kt: KeyType, provider: &CryptoProvider) -> ClientConfig { - finish_client_config(kt, client_config_builder(provider)) -} - -pub fn make_client_config_with_kx_groups( - kt: KeyType, - kx_groups: Vec<&'static dyn rustls::crypto::SupportedKxGroup>, - provider: &CryptoProvider, -) -> ClientConfig { - let builder = ClientConfig::builder_with_provider( - CryptoProvider { - kx_groups, - ..provider.clone() - } - .into(), - ) - .with_safe_default_protocol_versions() - .unwrap(); - finish_client_config(kt, builder) -} - -pub fn make_client_config_with_versions( - kt: KeyType, - versions: &[&'static rustls::SupportedProtocolVersion], - provider: &CryptoProvider, -) -> ClientConfig { - finish_client_config(kt, client_config_builder_with_versions(versions, provider)) -} - -pub fn make_client_config_with_auth(kt: KeyType, provider: &CryptoProvider) -> ClientConfig { - finish_client_config_with_creds(kt, client_config_builder(provider)) -} - -pub fn make_client_config_with_versions_with_auth( - kt: KeyType, - versions: &[&'static rustls::SupportedProtocolVersion], - provider: &CryptoProvider, -) -> ClientConfig { - finish_client_config_with_creds(kt, client_config_builder_with_versions(versions, provider)) -} - -pub fn make_client_config_with_verifier( - versions: &[&'static rustls::SupportedProtocolVersion], - verifier_builder: ServerCertVerifierBuilder, - provider: &CryptoProvider, -) -> ClientConfig { - client_config_builder_with_versions(versions, provider) - .dangerous() - .with_custom_certificate_verifier(verifier_builder.build().unwrap()) - .with_no_client_auth() -} - pub fn webpki_client_verifier_builder( roots: Arc, provider: &CryptoProvider, @@ -764,1026 +85,9 @@ pub fn webpki_server_verifier_builder( } } -pub fn make_pair(kt: KeyType, provider: &CryptoProvider) -> (ClientConnection, ServerConnection) { - make_pair_for_configs( - make_client_config(kt, provider), - make_server_config(kt, provider), - ) -} - -pub fn make_pair_for_configs( - client_config: ClientConfig, - server_config: ServerConfig, -) -> (ClientConnection, ServerConnection) { - make_pair_for_arc_configs(&Arc::new(client_config), &Arc::new(server_config)) -} - -pub fn make_pair_for_arc_configs( - client_config: &Arc, - server_config: &Arc, -) -> (ClientConnection, ServerConnection) { - ( - ClientConnection::new(Arc::clone(client_config), server_name("localhost")).unwrap(), - ServerConnection::new(Arc::clone(server_config)).unwrap(), - ) -} - -pub fn do_handshake( - client: &mut impl DerefMut>, - server: &mut impl DerefMut>, -) -> (usize, usize) { - let (mut to_client, mut to_server) = (0, 0); - while server.is_handshaking() || client.is_handshaking() { - to_server += transfer(client, server); - server.process_new_packets().unwrap(); - to_client += transfer(server, client); - client.process_new_packets().unwrap(); - } - (to_server, to_client) -} - -// Drive a handshake using unbuffered connections. -// -// Note that this drives the connection beyond the handshake until both -// connections are idle and there is no pending data waiting to be processed -// by either. In practice this just means that session tickets are processed -// by the client. -pub fn do_unbuffered_handshake( - client: &mut UnbufferedClientConnection, - server: &mut UnbufferedServerConnection, -) { - fn is_idle(conn: &UnbufferedConnectionCommon, data: &[u8]) -> bool { - !conn.is_handshaking() && !conn.wants_write() && data.is_empty() - } - - let mut client_data = Vec::with_capacity(1024); - let mut server_data = Vec::with_capacity(1024); - - while !is_idle(client, &client_data) || !is_idle(server, &server_data) { - loop { - let UnbufferedStatus { discard, state } = client.process_tls_records(&mut client_data); - let state = state.unwrap(); - - match state { - ConnectionState::BlockedHandshake | ConnectionState::WriteTraffic(_) => { - client_data.drain(..discard); - break; - } - ConnectionState::Closed | ConnectionState::PeerClosed => unreachable!(), - ConnectionState::ReadEarlyData(_) => (), - ConnectionState::EncodeTlsData(mut data) => { - let required = match data.encode(&mut []) { - Err(EncodeError::InsufficientSize(err)) => err.required_size, - _ => unreachable!(), - }; - - let old_len = server_data.len(); - server_data.resize(old_len + required, 0); - data.encode(&mut server_data[old_len..]) - .unwrap(); - } - ConnectionState::TransmitTlsData(data) => data.done(), - st => unreachable!("unexpected connection state: {st:?}"), - } - - client_data.drain(..discard); - } - - loop { - let UnbufferedStatus { discard, state } = server.process_tls_records(&mut server_data); - let state = state.unwrap(); - - match state { - ConnectionState::BlockedHandshake | ConnectionState::WriteTraffic(_) => { - server_data.drain(..discard); - break; - } - ConnectionState::Closed | ConnectionState::PeerClosed => unreachable!(), - ConnectionState::ReadEarlyData(_) => unreachable!(), - ConnectionState::EncodeTlsData(mut data) => { - let required = match data.encode(&mut []) { - Err(EncodeError::InsufficientSize(err)) => err.required_size, - _ => unreachable!(), - }; - - let old_len = client_data.len(); - client_data.resize(old_len + required, 0); - data.encode(&mut client_data[old_len..]) - .unwrap(); - } - ConnectionState::TransmitTlsData(data) => data.done(), - _ => unreachable!(), - } - - server_data.drain(..discard); - } - } - - assert!(server_data.is_empty()); - assert!(client_data.is_empty()); -} - -#[derive(PartialEq, Debug)] -pub enum ErrorFromPeer { - Client(Error), - Server(Error), -} - -pub fn do_handshake_until_error( - client: &mut ClientConnection, - server: &mut ServerConnection, -) -> Result<(), ErrorFromPeer> { - while server.is_handshaking() || client.is_handshaking() { - transfer(client, server); - server - .process_new_packets() - .map_err(ErrorFromPeer::Server)?; - transfer(server, client); - client - .process_new_packets() - .map_err(ErrorFromPeer::Client)?; - } - - Ok(()) -} - -pub fn do_handshake_altered( - client: ClientConnection, - alter_server_message: impl Fn(&mut Message) -> Altered, - alter_client_message: impl Fn(&mut Message) -> Altered, - server: ServerConnection, -) -> Result<(), ErrorFromPeer> { - let mut client: Connection = Connection::Client(client); - let mut server: Connection = Connection::Server(server); - - while server.is_handshaking() || client.is_handshaking() { - transfer_altered(&mut client, &alter_client_message, &mut server); - - server - .process_new_packets() - .map_err(ErrorFromPeer::Server)?; - - transfer_altered(&mut server, &alter_server_message, &mut client); - - client - .process_new_packets() - .map_err(ErrorFromPeer::Client)?; - } - - Ok(()) -} - -pub fn do_handshake_until_both_error( - client: &mut ClientConnection, - server: &mut ServerConnection, -) -> Result<(), Vec> { - match do_handshake_until_error(client, server) { - Err(server_err @ ErrorFromPeer::Server(_)) => { - let mut errors = vec![server_err]; - transfer(server, client); - let client_err = client - .process_new_packets() - .map_err(ErrorFromPeer::Client) - .expect_err("client didn't produce error after server error"); - errors.push(client_err); - Err(errors) - } - - Err(client_err @ ErrorFromPeer::Client(_)) => { - let mut errors = vec![client_err]; - transfer(client, server); - let server_err = server - .process_new_packets() - .map_err(ErrorFromPeer::Server) - .expect_err("server didn't produce error after client error"); - errors.push(server_err); - Err(errors) - } - - Ok(()) => Ok(()), - } -} - -pub fn server_name(name: &'static str) -> ServerName<'static> { - name.try_into().unwrap() -} - -pub struct FailsReads { - errkind: io::ErrorKind, -} - -impl FailsReads { - pub fn new(errkind: io::ErrorKind) -> Self { - Self { errkind } - } -} - -impl io::Read for FailsReads { - fn read(&mut self, _b: &mut [u8]) -> io::Result { - Err(io::Error::from(self.errkind)) - } -} - -pub fn do_suite_and_kx_test( - client_config: ClientConfig, - server_config: ServerConfig, - expect_suite: SupportedCipherSuite, - expect_kx: NamedGroup, - expect_version: ProtocolVersion, -) { - println!( - "do_suite_test {:?} {:?}", - expect_version, - expect_suite.suite() - ); - let (mut client, mut server) = make_pair_for_configs(client_config, server_config); - - assert_eq!(None, client.negotiated_cipher_suite()); - assert_eq!(None, server.negotiated_cipher_suite()); - assert!( - client - .negotiated_key_exchange_group() - .is_none() - ); - assert!( - server - .negotiated_key_exchange_group() - .is_none() - ); - assert_eq!(None, client.protocol_version()); - assert_eq!(None, server.protocol_version()); - assert!(client.is_handshaking()); - assert!(server.is_handshaking()); - - transfer(&mut client, &mut server); - server.process_new_packets().unwrap(); - - assert!(client.is_handshaking()); - assert!(server.is_handshaking()); - assert_eq!(None, client.protocol_version()); - assert_eq!(Some(expect_version), server.protocol_version()); - assert_eq!(None, client.negotiated_cipher_suite()); - assert_eq!(Some(expect_suite), server.negotiated_cipher_suite()); - assert!( - client - .negotiated_key_exchange_group() - .is_none() - ); - if matches!(expect_version, ProtocolVersion::TLSv1_2) { - assert!( - server - .negotiated_key_exchange_group() - .is_none() - ); - } else { - assert_eq!( - expect_kx, - server - .negotiated_key_exchange_group() - .unwrap() - .name() - ); - } - - transfer(&mut server, &mut client); - client.process_new_packets().unwrap(); - - assert_eq!(Some(expect_suite), client.negotiated_cipher_suite()); - assert_eq!(Some(expect_suite), server.negotiated_cipher_suite()); - assert_eq!( - expect_kx, - client - .negotiated_key_exchange_group() - .unwrap() - .name() - ); - if matches!(expect_version, ProtocolVersion::TLSv1_2) { - assert!( - server - .negotiated_key_exchange_group() - .is_none() - ); - } else { - assert_eq!( - expect_kx, - server - .negotiated_key_exchange_group() - .unwrap() - .name() - ); - } - - transfer(&mut client, &mut server); - server.process_new_packets().unwrap(); - transfer(&mut server, &mut client); - client.process_new_packets().unwrap(); - - assert!(!client.is_handshaking()); - assert!(!server.is_handshaking()); - assert_eq!(Some(expect_version), client.protocol_version()); - assert_eq!(Some(expect_version), server.protocol_version()); - assert_eq!(Some(expect_suite), client.negotiated_cipher_suite()); - assert_eq!(Some(expect_suite), server.negotiated_cipher_suite()); - assert_eq!( - expect_kx, - client - .negotiated_key_exchange_group() - .unwrap() - .name() - ); - assert_eq!( - expect_kx, - server - .negotiated_key_exchange_group() - .unwrap() - .name() - ); -} - fn exactly_one_provider() -> bool { cfg!(any( all(feature = "ring", not(feature = "aws_lc_rs")), all(feature = "aws_lc_rs", not(feature = "ring")) )) } - -#[derive(Debug)] -pub struct MockServerVerifier { - cert_rejection_error: Option, - tls12_signature_error: Option, - tls13_signature_error: Option, - signature_schemes: Vec, - expected_ocsp_response: Option>, - requires_raw_public_keys: bool, - raw_public_key_algorithms: Option, -} - -impl ServerCertVerifier for MockServerVerifier { - fn verify_server_cert( - &self, - end_entity: &CertificateDer<'_>, - intermediates: &[CertificateDer<'_>], - server_name: &ServerName<'_>, - ocsp_response: &[u8], - now: UnixTime, - ) -> Result { - println!( - "verify_server_cert({end_entity:?}, {intermediates:?}, {server_name:?}, {ocsp_response:?}, {now:?})" - ); - if let Some(expected_ocsp) = &self.expected_ocsp_response { - assert_eq!(expected_ocsp, ocsp_response); - } - match &self.cert_rejection_error { - Some(error) => Err(error.clone()), - _ => Ok(ServerCertVerified::assertion()), - } - } - - fn verify_tls12_signature( - &self, - message: &[u8], - cert: &CertificateDer<'_>, - dss: &DigitallySignedStruct, - ) -> Result { - println!("verify_tls12_signature({message:?}, {cert:?}, {dss:?})"); - match &self.tls12_signature_error { - Some(error) => Err(error.clone()), - _ => Ok(HandshakeSignatureValid::assertion()), - } - } - - fn verify_tls13_signature( - &self, - message: &[u8], - cert: &CertificateDer<'_>, - dss: &DigitallySignedStruct, - ) -> Result { - println!("verify_tls13_signature({message:?}, {cert:?}, {dss:?})"); - match &self.tls13_signature_error { - Some(error) => Err(error.clone()), - _ if self.requires_raw_public_keys => verify_tls13_signature_with_raw_key( - message, - &SubjectPublicKeyInfoDer::from(cert.as_ref()), - dss, - self.raw_public_key_algorithms - .as_ref() - .unwrap(), - ), - _ => Ok(HandshakeSignatureValid::assertion()), - } - } - - fn supported_verify_schemes(&self) -> Vec { - self.signature_schemes.clone() - } - - fn requires_raw_public_keys(&self) -> bool { - self.requires_raw_public_keys - } -} - -impl MockServerVerifier { - pub fn accepts_anything() -> Self { - MockServerVerifier { - cert_rejection_error: None, - ..Default::default() - } - } - - pub fn expects_ocsp_response(response: &[u8]) -> Self { - MockServerVerifier { - expected_ocsp_response: Some(response.to_vec()), - ..Default::default() - } - } - - pub fn rejects_certificate(err: Error) -> Self { - MockServerVerifier { - cert_rejection_error: Some(err), - ..Default::default() - } - } - - pub fn rejects_tls12_signatures(err: Error) -> Self { - MockServerVerifier { - tls12_signature_error: Some(err), - ..Default::default() - } - } - - pub fn rejects_tls13_signatures(err: Error) -> Self { - MockServerVerifier { - tls13_signature_error: Some(err), - ..Default::default() - } - } - - pub fn offers_no_signature_schemes() -> Self { - MockServerVerifier { - signature_schemes: vec![], - ..Default::default() - } - } - - pub fn expects_raw_public_keys(provider: &CryptoProvider) -> Self { - MockServerVerifier { - requires_raw_public_keys: true, - raw_public_key_algorithms: Some(provider.signature_verification_algorithms), - ..Default::default() - } - } -} - -impl Default for MockServerVerifier { - fn default() -> Self { - MockServerVerifier { - cert_rejection_error: None, - tls12_signature_error: None, - tls13_signature_error: None, - signature_schemes: vec![ - SignatureScheme::RSA_PSS_SHA256, - SignatureScheme::RSA_PKCS1_SHA256, - SignatureScheme::ED25519, - SignatureScheme::ECDSA_NISTP256_SHA256, - SignatureScheme::ECDSA_NISTP384_SHA384, - SignatureScheme::ECDSA_NISTP521_SHA512, - ], - expected_ocsp_response: None, - requires_raw_public_keys: false, - raw_public_key_algorithms: None, - } - } -} - -#[derive(Debug)] -pub struct MockClientVerifier { - pub verified: fn() -> Result, - pub subjects: Vec, - pub mandatory: bool, - pub offered_schemes: Option>, - expect_raw_public_keys: bool, - raw_public_key_algorithms: Option, - parent: Arc, -} - -impl MockClientVerifier { - pub fn new( - verified: fn() -> Result, - kt: KeyType, - provider: &CryptoProvider, - ) -> Self { - Self { - parent: webpki_client_verifier_builder(get_client_root_store(kt), provider) - .build() - .unwrap(), - verified, - subjects: get_client_root_store(kt).subjects(), - mandatory: true, - offered_schemes: None, - expect_raw_public_keys: false, - raw_public_key_algorithms: Some(provider.signature_verification_algorithms), - } - } -} - -impl ClientCertVerifier for MockClientVerifier { - fn client_auth_mandatory(&self) -> bool { - self.mandatory - } - - fn root_hint_subjects(&self) -> &[DistinguishedName] { - &self.subjects - } - - fn verify_client_cert( - &self, - _end_entity: &CertificateDer<'_>, - _intermediates: &[CertificateDer<'_>], - _now: UnixTime, - ) -> Result { - (self.verified)() - } - - fn verify_tls12_signature( - &self, - message: &[u8], - cert: &CertificateDer<'_>, - dss: &DigitallySignedStruct, - ) -> Result { - if self.expect_raw_public_keys { - Ok(HandshakeSignatureValid::assertion()) - } else { - self.parent - .verify_tls12_signature(message, cert, dss) - } - } - - fn verify_tls13_signature( - &self, - message: &[u8], - cert: &CertificateDer<'_>, - dss: &DigitallySignedStruct, - ) -> Result { - if self.expect_raw_public_keys { - verify_tls13_signature_with_raw_key( - message, - &SubjectPublicKeyInfoDer::from(cert.as_ref()), - dss, - self.raw_public_key_algorithms - .as_ref() - .unwrap(), - ) - } else { - self.parent - .verify_tls13_signature(message, cert, dss) - } - } - - fn supported_verify_schemes(&self) -> Vec { - if let Some(schemes) = &self.offered_schemes { - schemes.clone() - } else { - self.parent.supported_verify_schemes() - } - } - - fn requires_raw_public_keys(&self) -> bool { - self.expect_raw_public_keys - } -} - -/// This allows injection/receipt of raw messages into a post-handshake connection. -/// -/// It consumes one of the peers, extracts its secrets, and then reconstitutes the -/// message encrypter/decrypter. It does not do fragmentation/joining. -pub struct RawTls { - encrypter: Box, - enc_seq: u64, - decrypter: Box, - dec_seq: u64, -} - -impl RawTls { - /// conn must be post-handshake, and must have been created with `enable_secret_extraction` - pub fn new_client(conn: ClientConnection) -> Self { - let suite = conn.negotiated_cipher_suite().unwrap(); - Self::new( - suite, - conn.dangerous_extract_secrets() - .unwrap(), - ) - } - - /// conn must be post-handshake, and must have been created with `enable_secret_extraction` - pub fn new_server(conn: ServerConnection) -> Self { - let suite = conn.negotiated_cipher_suite().unwrap(); - Self::new( - suite, - conn.dangerous_extract_secrets() - .unwrap(), - ) - } - - fn new(suite: SupportedCipherSuite, secrets: rustls::ExtractedSecrets) -> Self { - let rustls::ExtractedSecrets { - tx: (tx_seq, tx_keys), - rx: (rx_seq, rx_keys), - } = secrets; - - let encrypter = match (tx_keys, suite) { - ( - rustls::ConnectionTrafficSecrets::Aes256Gcm { key, iv }, - SupportedCipherSuite::Tls13(tls13), - ) => tls13.aead_alg.encrypter(key, iv), - - ( - rustls::ConnectionTrafficSecrets::Aes256Gcm { key, iv }, - SupportedCipherSuite::Tls12(tls12), - ) => tls12 - .aead_alg - .encrypter(key, &iv.as_ref()[..4], &iv.as_ref()[4..]), - - _ => todo!(), - }; - - let decrypter = match (rx_keys, suite) { - ( - rustls::ConnectionTrafficSecrets::Aes256Gcm { key, iv }, - SupportedCipherSuite::Tls13(tls13), - ) => tls13.aead_alg.decrypter(key, iv), - - ( - rustls::ConnectionTrafficSecrets::Aes256Gcm { key, iv }, - SupportedCipherSuite::Tls12(tls12), - ) => tls12 - .aead_alg - .decrypter(key, &iv.as_ref()[..4]), - - _ => todo!(), - }; - - Self { - encrypter, - enc_seq: tx_seq, - decrypter, - dec_seq: rx_seq, - } - } - - pub fn encrypt_and_send( - &mut self, - msg: &PlainMessage, - peer: &mut impl DerefMut>, - ) { - let data = self - .encrypter - .encrypt(msg.borrow_outbound(), self.enc_seq) - .unwrap() - .encode(); - self.enc_seq += 1; - peer.read_tls(&mut io::Cursor::new(data)) - .unwrap(); - } - - pub fn receive_and_decrypt( - &mut self, - peer: &mut impl DerefMut>, - f: impl Fn(Message), - ) { - let mut data = vec![]; - peer.write_tls(&mut io::Cursor::new(&mut data)) - .unwrap(); - - let mut reader = Reader::init(&data); - let content_type = ContentType::read(&mut reader).unwrap(); - let version = ProtocolVersion::read(&mut reader).unwrap(); - let len = u16::read(&mut reader).unwrap(); - let left = &mut data[5..]; - assert_eq!(len as usize, left.len()); - - let inbound = InboundOpaqueMessage::new(content_type, version, left); - let plain = self - .decrypter - .decrypt(inbound, self.dec_seq) - .unwrap(); - self.dec_seq += 1; - - let msg = Message::try_from(plain).unwrap(); - println!("receive_and_decrypt: {msg:?}"); - - f(msg); - } -} - -pub fn aes_128_gcm_with_1024_confidentiality_limit( - provider: CryptoProvider, -) -> Arc { - const CONFIDENTIALITY_LIMIT: u64 = 1024; - - // needed to extend lifetime of Tls13CipherSuite to 'static - static TLS13_LIMITED_SUITE: OnceLock = OnceLock::new(); - static TLS12_LIMITED_SUITE: OnceLock = OnceLock::new(); - - let tls13_limited = TLS13_LIMITED_SUITE.get_or_init(|| { - let tls13 = provider - .cipher_suites - .iter() - .find(|cs| cs.suite() == CipherSuite::TLS13_AES_128_GCM_SHA256) - .unwrap() - .tls13() - .unwrap(); - - rustls::Tls13CipherSuite { - common: rustls::crypto::CipherSuiteCommon { - confidentiality_limit: CONFIDENTIALITY_LIMIT, - ..tls13.common - }, - ..*tls13 - } - }); - - let tls12_limited = TLS12_LIMITED_SUITE.get_or_init(|| { - let SupportedCipherSuite::Tls12(tls12) = *provider - .cipher_suites - .iter() - .find(|cs| cs.suite() == CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) - .unwrap() - else { - unreachable!(); - }; - - rustls::Tls12CipherSuite { - common: rustls::crypto::CipherSuiteCommon { - confidentiality_limit: CONFIDENTIALITY_LIMIT, - ..tls12.common - }, - ..*tls12 - } - }); - - CryptoProvider { - cipher_suites: vec![ - SupportedCipherSuite::Tls13(tls13_limited), - SupportedCipherSuite::Tls12(tls12_limited), - ], - ..provider - } - .into() -} - -pub fn unsafe_plaintext_crypto_provider(provider: CryptoProvider) -> Arc { - static TLS13_PLAIN_SUITE: OnceLock = OnceLock::new(); - - let tls13 = TLS13_PLAIN_SUITE.get_or_init(|| { - let tls13 = provider - .cipher_suites - .iter() - .find(|cs| cs.suite() == CipherSuite::TLS13_AES_256_GCM_SHA384) - .unwrap() - .tls13() - .unwrap(); - - rustls::Tls13CipherSuite { - aead_alg: &plaintext::Aead, - common: rustls::crypto::CipherSuiteCommon { ..tls13.common }, - ..*tls13 - } - }); - - CryptoProvider { - cipher_suites: vec![SupportedCipherSuite::Tls13(tls13)], - ..provider - } - .into() -} - -mod plaintext { - use rustls::ConnectionTrafficSecrets; - use rustls::crypto::cipher::{ - AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, MessageDecrypter, MessageEncrypter, - OutboundPlainMessage, PrefixedPayload, Tls13AeadAlgorithm, UnsupportedOperationError, - }; - - use super::*; - - pub(super) struct Aead; - - impl Tls13AeadAlgorithm for Aead { - fn encrypter(&self, _key: AeadKey, _iv: Iv) -> Box { - Box::new(Encrypter) - } - - fn decrypter(&self, _key: AeadKey, _iv: Iv) -> Box { - Box::new(Decrypter) - } - - fn key_len(&self) -> usize { - 32 - } - - fn extract_keys( - &self, - _key: AeadKey, - _iv: Iv, - ) -> Result { - Err(UnsupportedOperationError) - } - } - - struct Encrypter; - - impl MessageEncrypter for Encrypter { - fn encrypt( - &mut self, - msg: OutboundPlainMessage<'_>, - _seq: u64, - ) -> Result { - let mut payload = PrefixedPayload::with_capacity(msg.payload.len()); - payload.extend_from_chunks(&msg.payload); - - Ok(OutboundOpaqueMessage::new( - ContentType::ApplicationData, - ProtocolVersion::TLSv1_2, - payload, - )) - } - - fn encrypted_payload_len(&self, payload_len: usize) -> usize { - payload_len - } - } - - struct Decrypter; - - impl MessageDecrypter for Decrypter { - fn decrypt<'a>( - &mut self, - msg: InboundOpaqueMessage<'a>, - _seq: u64, - ) -> Result, Error> { - Ok(msg.into_plain_message()) - } - } -} - -/// Deeply inefficient, test-only TLS encoding helpers -pub mod encoding { - use rustls::internal::msgs::codec::Codec; - use rustls::internal::msgs::enums::ExtensionType; - use rustls::{ - CipherSuite, ContentType, HandshakeType, NamedGroup, ProtocolVersion, SignatureScheme, - }; - - /// Return a client hello with mandatory extensions added to `extensions` - /// - /// The returned bytes are handshake-framed, but not message-framed. - pub fn basic_client_hello(mut extensions: Vec) -> Vec { - extensions.push(Extension::new_kx_groups()); - extensions.push(Extension::new_sig_algs()); - extensions.push(Extension::new_versions()); - extensions.push(Extension::new_dummy_key_share()); - client_hello_with_extensions(extensions) - } - - /// Return a client hello with exactly `extensions` - /// - /// The returned bytes are handshake-framed, but not message-framed. - pub fn client_hello_with_extensions(extensions: Vec) -> Vec { - client_hello( - ProtocolVersion::TLSv1_2, - &[0u8; 32], - &[0], - vec![ - CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - CipherSuite::TLS13_AES_128_GCM_SHA256, - ], - extensions, - ) - } - - pub fn client_hello( - legacy_version: ProtocolVersion, - random: &[u8; 32], - session_id: &[u8], - cipher_suites: Vec, - extensions: Vec, - ) -> Vec { - let mut out = vec![]; - - legacy_version.encode(&mut out); - out.extend_from_slice(random); - out.extend_from_slice(session_id); - cipher_suites.to_vec().encode(&mut out); - out.extend_from_slice(&[0x01, 0x00]); // only null compression - - let mut exts = vec![]; - for e in extensions { - e.typ.encode(&mut exts); - exts.extend_from_slice(&(e.body.len() as u16).to_be_bytes()); - exts.extend_from_slice(&e.body); - } - - out.extend(len_u16(exts)); - handshake_framing(HandshakeType::ClientHello, out) - } - - /// Apply handshake framing to `body`. - /// - /// This does not do fragmentation. - pub fn handshake_framing(ty: HandshakeType, body: Vec) -> Vec { - let mut body = len_u24(body); - body.splice(0..0, ty.to_array()); - body - } - - /// Apply message framing to `body`. - pub fn message_framing(ty: ContentType, vers: ProtocolVersion, body: Vec) -> Vec { - let mut body = len_u16(body); - body.splice(0..0, vers.to_array()); - body.splice(0..0, ty.to_array()); - body - } - - #[derive(Clone)] - pub struct Extension { - pub typ: ExtensionType, - pub body: Vec, - } - - impl Extension { - pub fn new_sig_algs() -> Extension { - Extension { - typ: ExtensionType::SignatureAlgorithms, - body: len_u16( - SignatureScheme::RSA_PKCS1_SHA256 - .to_array() - .to_vec(), - ), - } - } - - pub fn new_kx_groups() -> Extension { - Extension { - typ: ExtensionType::EllipticCurves, - body: len_u16(vector_of([NamedGroup::secp256r1].into_iter())), - } - } - - pub fn new_versions() -> Extension { - Extension { - typ: ExtensionType::SupportedVersions, - body: len_u8(vector_of( - [ProtocolVersion::TLSv1_3, ProtocolVersion::TLSv1_2].into_iter(), - )), - } - } - - pub fn new_dummy_key_share() -> Extension { - const SOME_POINT_ON_P256: &[u8] = &[ - 4, 41, 39, 177, 5, 18, 186, 227, 237, 220, 254, 70, 120, 40, 18, 139, 173, 41, 3, - 38, 153, 25, 247, 8, 96, 105, 200, 196, 223, 108, 115, 40, 56, 199, 120, 121, 100, - 234, 172, 0, 229, 146, 31, 177, 73, 138, 96, 244, 96, 103, 102, 179, 217, 104, 80, - 1, 85, 141, 26, 151, 78, 115, 65, 81, 62, - ]; - - let mut share = len_u16(SOME_POINT_ON_P256.to_vec()); - share.splice(0..0, NamedGroup::secp256r1.to_array()); - - Extension { - typ: ExtensionType::KeyShare, - body: len_u16(share), - } - } - } - - /// Prefix with u8 length - pub fn len_u8(mut body: Vec) -> Vec { - body.splice(0..0, [body.len() as u8]); - body - } - - /// Prefix with u16 length - pub fn len_u16(mut body: Vec) -> Vec { - body.splice(0..0, (body.len() as u16).to_be_bytes()); - body - } - - /// Prefix with u24 length - pub fn len_u24(mut body: Vec) -> Vec { - let len = (body.len() as u32).to_be_bytes(); - body.insert(0, len[1]); - body.insert(1, len[2]); - body.insert(2, len[3]); - body - } - - /// Encode each of `items` - pub fn vector_of<'a, T: Codec<'a>>(items: impl Iterator) -> Vec { - let mut body = Vec::new(); - - for i in items { - i.encode(&mut body); - } - body - } -} From c6b146928c231183a7c43ede0529fb6c01c023b7 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 14:55:37 +0100 Subject: [PATCH 222/403] rustls-bench: use rustls-test keys/certificates --- Cargo.lock | 1 + rustls-bench/Cargo.toml | 1 + rustls-bench/src/main.rs | 60 ++++++++++------------------------------ 3 files changed, 17 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4b545ee4bc0..ee91ef1f793 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2624,6 +2624,7 @@ dependencies = [ "clap", "rustls 0.23.27", "rustls-post-quantum", + "rustls-test", "tikv-jemallocator", ] diff --git a/rustls-bench/Cargo.toml b/rustls-bench/Cargo.toml index 36f70198b1d..0b7ff90f7e8 100644 --- a/rustls-bench/Cargo.toml +++ b/rustls-bench/Cargo.toml @@ -8,6 +8,7 @@ publish = false clap = { workspace = true } rustls = { path = "../rustls" } rustls-post-quantum = { path = "../rustls-post-quantum", optional = true } +rustls-test = { workspace = true } [features] default = [] diff --git a/rustls-bench/src/main.rs b/rustls-bench/src/main.rs index 73385f74f7f..707c0319d73 100644 --- a/rustls-bench/src/main.rs +++ b/rustls-bench/src/main.rs @@ -14,8 +14,6 @@ use std::{mem, thread}; use clap::{Parser, ValueEnum}; use rustls::client::{Resumption, UnbufferedClientConnection}; use rustls::crypto::CryptoProvider; -use rustls::pki_types::pem::PemObject; -use rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer}; use rustls::server::{ NoServerSessionStorage, ProducesTickets, ServerSessionMemoryCache, UnbufferedServerConnection, WebPkiClientVerifier, @@ -25,6 +23,7 @@ use rustls::{ CipherSuite, ClientConfig, ClientConnection, ConnectionCommon, Error, HandshakeKind, RootCertStore, ServerConfig, ServerConnection, SideData, }; +use rustls_test::KeyType; pub fn main() { let args = Args::parse(); @@ -111,7 +110,7 @@ struct Args { long, help = "Which key type to use for server and client authentication. The default is to run tests once for each key type." )] - key_type: Option, + key_type: Option, #[arg(long, help = "Which provider to test")] provider: Option, @@ -669,13 +668,13 @@ fn bench_memory( fn lookup_matching_benches( ciphersuite_name: &str, - key_type: Option, + key_type: Option, ) -> Vec { let r: Vec = ALL_BENCHMARKS .iter() .filter(|params| { format!("{:?}", params.ciphersuite).to_lowercase() == ciphersuite_name.to_lowercase() - && (key_type.is_none() || Some(params.key_type) == key_type) + && (key_type.is_none() || Some(params.key_type) == key_type.map(KeyType::from)) }) .cloned() .collect(); @@ -808,11 +807,9 @@ impl Parameters { fn client_config(&self) -> Arc { let mut root_store = RootCertStore::empty(); - root_store.add_parsable_certificates( - CertificateDer::pem_file_iter(self.proto.key_type.path_for("ca.cert")) - .unwrap() - .map(|result| result.unwrap()), - ); + root_store + .add(self.proto.key_type.ca_cert()) + .unwrap(); let cfg = ClientConfig::builder_with_provider( CryptoProvider { @@ -1035,50 +1032,23 @@ impl BenchmarkParam { } } -// copied from tests/api.rs #[derive(PartialEq, Clone, Copy, Debug, ValueEnum)] -enum KeyType { +enum RequestedKeyType { Rsa2048, EcdsaP256, EcdsaP384, Ed25519, } -impl KeyType { - fn path_for(&self, part: &str) -> String { - match self { - Self::Rsa2048 => format!("test-ca/rsa-2048/{part}"), - Self::EcdsaP256 => format!("test-ca/ecdsa-p256/{part}"), - Self::EcdsaP384 => format!("test-ca/ecdsa-p384/{part}"), - Self::Ed25519 => format!("test-ca/eddsa/{part}"), +impl From for KeyType { + fn from(val: RequestedKeyType) -> Self { + match val { + RequestedKeyType::Rsa2048 => Self::Rsa2048, + RequestedKeyType::EcdsaP256 => Self::EcdsaP256, + RequestedKeyType::EcdsaP384 => Self::EcdsaP384, + RequestedKeyType::Ed25519 => Self::Ed25519, } } - - fn get_chain(&self) -> Vec> { - CertificateDer::pem_file_iter(self.path_for("end.fullchain")) - .unwrap() - .map(|result| result.unwrap()) - .collect() - } - - fn get_key(&self) -> PrivateKeyDer<'static> { - PrivatePkcs8KeyDer::from_pem_file(self.path_for("end.key")) - .unwrap() - .into() - } - - fn get_client_chain(&self) -> Vec> { - CertificateDer::pem_file_iter(self.path_for("client.fullchain")) - .unwrap() - .map(|result| result.unwrap()) - .collect() - } - - fn get_client_key(&self) -> PrivateKeyDer<'static> { - PrivatePkcs8KeyDer::from_pem_file(self.path_for("client.key")) - .unwrap() - .into() - } } struct Unbuffered { From 34fb672790a4f8e88843e17ce085412e5965cbcf Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 19 May 2025 16:41:57 +0100 Subject: [PATCH 223/403] rustls-test: determine supported keytypes at runtime --- rustls-test/src/lib.rs | 22 +++++- rustls/tests/api.rs | 105 ++++++++++++++------------- rustls/tests/client_cert_verifier.rs | 11 +-- rustls/tests/server_cert_verifier.rs | 12 +-- 4 files changed, 86 insertions(+), 64 deletions(-) diff --git a/rustls-test/src/lib.rs b/rustls-test/src/lib.rs index 64e922bad15..1556c8ae7b2 100644 --- a/rustls-test/src/lib.rs +++ b/rustls-test/src/lib.rs @@ -302,7 +302,7 @@ pub enum KeyType { Ed25519, } -pub static ALL_KEY_TYPES: &[KeyType] = &[ +static ALL_KEY_TYPES: &[KeyType] = &[ KeyType::Rsa2048, KeyType::Rsa3072, KeyType::Rsa4096, @@ -312,7 +312,27 @@ pub static ALL_KEY_TYPES: &[KeyType] = &[ KeyType::Ed25519, ]; +static ALL_KEY_TYPES_EXCEPT_P521: &[KeyType] = &[ + KeyType::Rsa2048, + KeyType::Rsa3072, + KeyType::Rsa4096, + KeyType::EcdsaP256, + KeyType::EcdsaP384, + KeyType::Ed25519, +]; + impl KeyType { + pub fn all_for_provider(provider: &CryptoProvider) -> &'static [KeyType] { + match provider + .key_provider + .load_private_key(Self::EcdsaP521.get_key()) + .is_ok() + { + true => ALL_KEY_TYPES, + false => ALL_KEY_TYPES_EXCEPT_P521, + } + } + fn bytes_for(&self, part: &str) -> &'static [u8] { match self { Self::Rsa2048 => bytes_for("rsa-2048", part), diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 0851c9f95d6..94ee74d11ae 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -61,7 +61,7 @@ mod test_raw_keys { #[test] fn successful_raw_key_connection_and_correct_peer_certificates() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let client_config = make_client_config_with_raw_key_support(*kt, &provider); let server_config = make_server_config_with_raw_key_support(*kt, &provider); @@ -97,7 +97,7 @@ mod test_raw_keys { #[test] fn correct_certificate_type_extensions_from_client_hello() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let client_config = make_client_config_with_raw_key_support(*kt, &provider); let mut server_config = make_server_config_with_raw_key_support(*kt, &provider); @@ -116,7 +116,7 @@ mod test_raw_keys { #[test] fn only_client_supports_raw_keys() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let client_config_rpk = make_client_config_with_raw_key_support(*kt, &provider); let server_config = make_server_config(*kt, &provider); @@ -143,7 +143,7 @@ mod test_raw_keys { #[test] fn only_server_supports_raw_keys() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let client_config = make_client_config_with_versions(*kt, &[&rustls::version::TLS13], &provider); let server_config_rpk = make_server_config_with_raw_key_support(*kt, &provider); @@ -194,7 +194,7 @@ mod test_raw_keys { expected_result: Result<(), ErrorFromPeer>, ) { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let client_config = Arc::new(make_client_config(*kt, &provider)); let server_config_rpk = match server_requires_raw_keys { true => Arc::new(make_server_config_with_raw_key_support(*kt, &provider)), @@ -218,7 +218,7 @@ mod test_raw_keys { #[test] fn incorrectly_alter_server_hello() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let supported_suite = cipher_suite::TLS13_AES_256_GCM_SHA384; // Alter Server Hello server certificate extension and expect IncorrectCertificateTypeExtension error @@ -885,7 +885,7 @@ fn buffered_both_data_sent() { #[test] fn client_can_get_server_cert() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { for version in rustls::ALL_VERSIONS { let client_config = make_client_config_with_versions(*kt, &[version], &provider); let (mut client, mut server) = @@ -901,7 +901,7 @@ fn client_can_get_server_cert() { #[test] fn client_can_get_server_cert_after_resumption() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let server_config = make_server_config(*kt, &provider); for version in rustls::ALL_VERSIONS { let client_config = make_client_config_with_versions(*kt, &[version], &provider); @@ -995,7 +995,7 @@ fn client_only_attempts_resumption_with_compatible_security() { #[test] fn server_can_get_client_cert() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let server_config = Arc::new(make_server_config_with_mandatory_client_auth( *kt, &provider, )); @@ -1016,7 +1016,7 @@ fn server_can_get_client_cert() { #[test] fn server_can_get_client_cert_after_resumption() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let server_config = Arc::new(make_server_config_with_mandatory_client_auth( *kt, &provider, )); @@ -1042,7 +1042,7 @@ fn server_can_get_client_cert_after_resumption() { #[test] fn resumption_combinations() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let server_config = make_server_config(*kt, &provider); for version in rustls::ALL_VERSIONS { let client_config = make_client_config_with_versions(*kt, &[version], &provider); @@ -1527,7 +1527,7 @@ impl ResolvesServerCert for ServerCheckCertResolve { #[test] fn server_cert_resolve_with_sni() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let client_config = make_client_config(*kt, &provider); let mut server_config = make_server_config(*kt, &provider); @@ -1549,7 +1549,7 @@ fn server_cert_resolve_with_sni() { #[test] fn server_cert_resolve_with_alpn() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let mut client_config = make_client_config(*kt, &provider); client_config.alpn_protocols = vec!["foo".into(), "bar".into()]; @@ -1571,7 +1571,7 @@ fn server_cert_resolve_with_alpn() { #[test] fn client_trims_terminating_dot() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let client_config = make_client_config(*kt, &provider); let mut server_config = make_server_config(*kt, &provider); @@ -1678,7 +1678,7 @@ impl ResolvesServerCert for ServerCheckNoSni { #[test] fn client_with_sni_disabled_does_not_send_sni() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let mut server_config = make_server_config(*kt, &provider); server_config.cert_resolver = Arc::new(ServerCheckNoSni {}); let server_config = Arc::new(server_config); @@ -1701,7 +1701,7 @@ fn client_with_sni_disabled_does_not_send_sni() { #[test] fn client_checks_server_certificate_with_given_name() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let server_config = Arc::new(make_server_config(*kt, &provider)); for version in rustls::ALL_VERSIONS { @@ -1737,7 +1737,7 @@ fn client_checks_server_certificate_with_given_ip_address() { } let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let server_config = Arc::new(make_server_config(*kt, &provider)); for version in rustls::ALL_VERSIONS { @@ -1778,7 +1778,7 @@ fn client_checks_server_certificate_with_given_ip_address() { #[test] fn client_check_server_certificate_ee_revoked() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let server_config = Arc::new(make_server_config(*kt, &provider)); // Setup a server verifier that will check the EE certificate's revocation status. @@ -1809,7 +1809,7 @@ fn client_check_server_certificate_ee_revoked() { #[test] fn client_check_server_certificate_ee_unknown_revocation() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let server_config = Arc::new(make_server_config(*kt, &provider)); // Setup a server verifier builder that will check the EE certificate's revocation status, but not @@ -1866,7 +1866,7 @@ fn client_check_server_certificate_ee_unknown_revocation() { #[test] fn client_check_server_certificate_intermediate_revoked() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let server_config = Arc::new(make_server_config(*kt, &provider)); // Setup a server verifier builder that will check the full chain revocation status against a CRL @@ -1925,7 +1925,7 @@ fn client_check_server_certificate_intermediate_revoked() { #[test] fn client_check_server_certificate_ee_crl_expired() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let server_config = Arc::new(make_server_config(*kt, &provider)); // Setup a server verifier that will check the EE certificate's revocation status, with CRL expiration enforced. @@ -1983,7 +1983,7 @@ fn client_check_server_certificate_ee_crl_expired() { /// so isn't used by the other existing verifier tests. #[test] fn client_check_server_certificate_helper_api() { - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider::default_provider()) { let chain = kt.get_chain(); let correct_roots = get_client_root_store(*kt); let incorrect_roots = get_client_root_store(match kt { @@ -2165,7 +2165,7 @@ fn client_cert_resolve_default() { // Test that in the default configuration that a client cert resolver gets the expected // CA subject hints, and supported signature algorithms. let provider = provider::default_provider(); - for key_type in ALL_KEY_TYPES { + for key_type in KeyType::all_for_provider(&provider) { let server_config = Arc::new(make_server_config_with_mandatory_client_auth( *key_type, &provider, )); @@ -2187,7 +2187,7 @@ fn client_cert_resolve_server_no_hints() { // Test that a server can provide no hints and the client cert resolver gets the expected // arguments. let provider = provider::default_provider(); - for key_type in ALL_KEY_TYPES { + for key_type in KeyType::all_for_provider(&provider) { // Build a verifier with no hint subjects. let verifier = webpki_client_verifier_builder(get_client_root_store(*key_type), &provider) .clear_root_hint_subjects(); @@ -2203,7 +2203,7 @@ fn client_cert_resolve_server_added_hint() { // and the client cert resolver gets the expected arguments. let provider = provider::default_provider(); let extra_name = b"0\x1a1\x180\x16\x06\x03U\x04\x03\x0c\x0fponyland IDK CA".to_vec(); - for key_type in ALL_KEY_TYPES { + for key_type in KeyType::all_for_provider(&provider) { let expected_hint_subjects = vec![ key_type .ca_distinguished_name() @@ -2222,7 +2222,7 @@ fn client_cert_resolve_server_added_hint() { #[test] fn client_auth_works() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let server_config = Arc::new(make_server_config_with_mandatory_client_auth( *kt, &provider, )); @@ -2239,10 +2239,10 @@ fn client_auth_works() { #[test] fn client_mandatory_auth_client_revocation_works() { - for kt in ALL_KEY_TYPES { + let provider = provider::default_provider(); + for kt in KeyType::all_for_provider(&provider) { // Create a server configuration that includes a CRL that specifies the client certificate // is revoked. - let provider = provider::default_provider(); let relevant_crls = vec![kt.client_crl()]; // Only check the EE certificate status. See client_mandatory_auth_intermediate_revocation_works // for testing revocation status of the whole chain. @@ -2321,7 +2321,7 @@ fn client_mandatory_auth_client_revocation_works() { #[test] fn client_mandatory_auth_intermediate_revocation_works() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { // Create a server configuration that includes a CRL that specifies the intermediate certificate // is revoked. We check the full chain for revocation status (default), and allow unknown // revocation status so the EE's unknown revocation status isn't an error. @@ -2377,7 +2377,7 @@ fn client_mandatory_auth_intermediate_revocation_works() { #[test] fn client_optional_auth_client_revocation_works() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { // Create a server configuration that includes a CRL that specifies the client certificate // is revoked. let crls = vec![kt.client_crl()]; @@ -2887,7 +2887,7 @@ fn client_complete_io_for_handshake_eof() { #[test] fn client_complete_io_for_write() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let (mut client, mut server) = make_pair(*kt, &provider); do_handshake(&mut client, &mut server); @@ -2917,7 +2917,7 @@ fn client_complete_io_for_write() { #[test] fn buffered_client_complete_io_for_write() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let (mut client, mut server) = make_pair(*kt, &provider); do_handshake(&mut client, &mut server); @@ -2947,7 +2947,7 @@ fn buffered_client_complete_io_for_write() { #[test] fn client_complete_io_for_read() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let (mut client, mut server) = make_pair(*kt, &provider); do_handshake(&mut client, &mut server); @@ -2969,7 +2969,7 @@ fn client_complete_io_for_read() { #[test] fn server_complete_io_for_handshake() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let (mut client, mut server) = make_pair(*kt, &provider); assert!(server.is_handshaking()); @@ -2997,7 +2997,7 @@ fn server_complete_io_for_handshake_eof() { #[test] fn server_complete_io_for_write() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let (mut client, mut server) = make_pair(*kt, &provider); do_handshake(&mut client, &mut server); @@ -3026,7 +3026,7 @@ fn server_complete_io_for_write() { #[test] fn server_complete_io_for_write_eof() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let (mut client, mut server) = make_pair(*kt, &provider); do_handshake(&mut client, &mut server); @@ -3083,7 +3083,7 @@ impl std::io::Read for EofWriter { #[test] fn server_complete_io_for_read() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let (mut client, mut server) = make_pair(*kt, &provider); do_handshake(&mut client, &mut server); @@ -3122,7 +3122,7 @@ enum StreamKind { fn test_client_stream_write(stream_kind: StreamKind) { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let (mut client, mut server) = make_pair(*kt, &provider); let data = b"hello"; { @@ -3139,7 +3139,7 @@ fn test_client_stream_write(stream_kind: StreamKind) { fn test_server_stream_write(stream_kind: StreamKind) { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let (mut client, mut server) = make_pair(*kt, &provider); let data = b"hello"; { @@ -3208,7 +3208,7 @@ fn test_stream_read(read_kind: ReadKind, mut stream: impl BufRead, data: &[u8]) fn test_client_stream_read(stream_kind: StreamKind, read_kind: ReadKind) { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let (mut client, mut server) = make_pair(*kt, &provider); let data = b"world"; server.writer().write_all(data).unwrap(); @@ -3229,7 +3229,7 @@ fn test_client_stream_read(stream_kind: StreamKind, read_kind: ReadKind) { fn test_server_stream_read(stream_kind: StreamKind, read_kind: ReadKind) { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let (mut client, mut server) = make_pair(*kt, &provider); let data = b"world"; client.writer().write_all(data).unwrap(); @@ -3869,7 +3869,7 @@ fn do_exporter_test(client_config: ClientConfig, server_config: ServerConfig) { #[test] fn test_tls12_exporter() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let client_config = make_client_config_with_versions(*kt, &[&rustls::version::TLS12], &provider); let server_config = make_server_config(*kt, &provider); @@ -3881,7 +3881,7 @@ fn test_tls12_exporter() { #[test] fn test_tls13_exporter() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let client_config = make_client_config_with_versions(*kt, &[&rustls::version::TLS13], &provider); let server_config = make_server_config(*kt, &provider); @@ -4022,7 +4022,7 @@ fn test_ciphersuites() -> Vec<( #[test] fn negotiated_ciphersuite_default() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { do_suite_and_kx_test( make_client_config(*kt, &provider), make_server_config(*kt, &provider), @@ -5390,7 +5390,7 @@ mod test_quic { let server_params = &b"server params"[..]; let provider = provider::default_provider(); - for &kt in ALL_KEY_TYPES { + for &kt in KeyType::all_for_provider(&provider) { let client_config = make_client_config_with_versions(kt, &[&rustls::version::TLS13], &provider); let client_config = Arc::new(client_config); @@ -5754,7 +5754,7 @@ mod test_quic { #[test] fn test_quic_exporter() { let provider = provider::default_provider(); - for &kt in ALL_KEY_TYPES { + for &kt in KeyType::all_for_provider(&provider) { let client_config = make_client_config_with_versions(kt, &[&rustls::version::TLS13], &provider); let server_config = @@ -5810,7 +5810,7 @@ fn test_client_does_not_offer_sha1() { use rustls::internal::msgs::message::{MessagePayload, OutboundOpaqueMessage}; let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { for version in rustls::ALL_VERSIONS { let client_config = make_client_config_with_versions(*kt, &[version], &provider); let (mut client, _) = @@ -6313,7 +6313,7 @@ fn test_client_mtu_reduction() { } let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { let mut client_config = make_client_config(*kt, &provider); client_config.max_fragment_size = Some(64); let mut client = @@ -6408,7 +6408,7 @@ fn bad_client_max_fragment_sizes() { fn handshakes_complete_and_data_flows_with_gratuitious_max_fragment_sizes() { // general exercising of msgs::fragmenter and msgs::deframer let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { for version in rustls::ALL_VERSIONS { // no hidden significance to these numbers for frag_size in [37, 61, 101, 257] { @@ -6887,7 +6887,7 @@ fn test_no_warning_logging_during_successful_sessions() { CountingLogger::reset(); let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES { + for kt in KeyType::all_for_provider(&provider) { for version in rustls::ALL_VERSIONS { let client_config = make_client_config_with_versions(*kt, &[version], &provider); let (mut client, mut server) = @@ -8387,8 +8387,9 @@ fn tls12_connection_fails_after_key_reaches_confidentiality_limit() { #[test] fn test_keys_match_for_all_signing_key_types() { - for kt in ALL_KEY_TYPES { - let key = provider::default_provider() + let provider = provider::default_provider(); + for kt in KeyType::all_for_provider(&provider) { + let key = provider .key_provider .load_private_key(kt.get_client_key()) .unwrap(); diff --git a/rustls/tests/client_cert_verifier.rs b/rustls/tests/client_cert_verifier.rs index 381c16d430b..d25dcb3bf03 100644 --- a/rustls/tests/client_cert_verifier.rs +++ b/rustls/tests/client_cert_verifier.rs @@ -7,7 +7,7 @@ use super::*; mod common; use common::{ - ALL_KEY_TYPES, Arc, ErrorFromPeer, KeyType, MockClientVerifier, do_handshake_until_both_error, + Arc, ErrorFromPeer, KeyType, MockClientVerifier, do_handshake_until_both_error, do_handshake_until_error, make_client_config_with_versions, make_client_config_with_versions_with_auth, make_pair_for_arc_configs, server_config_builder, server_name, @@ -47,7 +47,7 @@ fn server_config_with_verifier( // Happy path, we resolve to a root, it is verified OK, should be able to connect fn client_verifier_works() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES.iter() { + for kt in KeyType::all_for_provider(&provider).iter() { let client_verifier = MockClientVerifier::new(ver_ok, *kt, &provider); let server_config = server_config_with_verifier(*kt, client_verifier); let server_config = Arc::new(server_config); @@ -67,7 +67,7 @@ fn client_verifier_works() { #[test] fn client_verifier_no_schemes() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES.iter() { + for kt in KeyType::all_for_provider(&provider).iter() { let mut client_verifier = MockClientVerifier::new(ver_ok, *kt, &provider); client_verifier.offered_schemes = Some(vec![]); let server_config = server_config_with_verifier(*kt, client_verifier); @@ -93,8 +93,9 @@ fn client_verifier_no_schemes() { #[test] fn client_verifier_no_auth_yes_root() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES.iter() { + for kt in KeyType::all_for_provider(&provider).iter() { let client_verifier = MockClientVerifier::new(ver_unreachable, *kt, &provider); + let server_config = server_config_with_verifier(*kt, client_verifier); let server_config = Arc::new(server_config); @@ -121,7 +122,7 @@ fn client_verifier_no_auth_yes_root() { // Triple checks we propagate the rustls::Error through fn client_verifier_fails_properly() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES.iter() { + for kt in KeyType::all_for_provider(&provider).iter() { let client_verifier = MockClientVerifier::new(ver_err, *kt, &provider); let server_config = server_config_with_verifier(*kt, client_verifier); let server_config = Arc::new(server_config); diff --git a/rustls/tests/server_cert_verifier.rs b/rustls/tests/server_cert_verifier.rs index b0d2508b65d..402ffe551a9 100644 --- a/rustls/tests/server_cert_verifier.rs +++ b/rustls/tests/server_cert_verifier.rs @@ -7,7 +7,7 @@ use super::*; mod common; use common::{ - ALL_KEY_TYPES, Altered, Arc, ErrorFromPeer, KeyType, MockServerVerifier, client_config_builder, + Altered, Arc, ErrorFromPeer, KeyType, MockServerVerifier, client_config_builder, client_config_builder_with_versions, do_handshake, do_handshake_until_both_error, do_handshake_until_error, make_client_config_with_versions, make_pair_for_arc_configs, make_server_config, server_config_builder, transfer_altered, @@ -33,7 +33,7 @@ use x509_parser::x509::X509Name; #[test] fn client_can_override_certificate_verification() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES.iter() { + for kt in KeyType::all_for_provider(&provider).iter() { let verifier = Arc::new(MockServerVerifier::accepts_anything()); let server_config = Arc::new(make_server_config(*kt, &provider)); @@ -54,7 +54,7 @@ fn client_can_override_certificate_verification() { #[test] fn client_can_override_certificate_verification_and_reject_certificate() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES.iter() { + for kt in KeyType::all_for_provider(&provider).iter() { let verifier = Arc::new(MockServerVerifier::rejects_certificate( Error::InvalidMessage(InvalidMessage::HandshakePayloadTooLarge), )); @@ -87,7 +87,7 @@ fn client_can_override_certificate_verification_and_reject_certificate() { #[test] fn client_can_override_certificate_verification_and_reject_tls12_signatures() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES.iter() { + for kt in KeyType::all_for_provider(&provider).iter() { let mut client_config = make_client_config_with_versions(*kt, &[&rustls::version::TLS12], &provider); let verifier = Arc::new(MockServerVerifier::rejects_tls12_signatures( @@ -118,7 +118,7 @@ fn client_can_override_certificate_verification_and_reject_tls12_signatures() { #[test] fn client_can_override_certificate_verification_and_reject_tls13_signatures() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES.iter() { + for kt in KeyType::all_for_provider(&provider).iter() { let mut client_config = make_client_config_with_versions( *kt, &[&rustls::version::TLS13], @@ -152,7 +152,7 @@ fn client_can_override_certificate_verification_and_reject_tls13_signatures() { #[test] fn client_can_override_certificate_verification_and_offer_no_signature_schemes() { let provider = provider::default_provider(); - for kt in ALL_KEY_TYPES.iter() { + for kt in KeyType::all_for_provider(&provider).iter() { let verifier = Arc::new(MockServerVerifier::offers_no_signature_schemes()); let server_config = Arc::new(make_server_config(*kt, &provider)); From 8bad61788b86120e40b007e179bc5b0a0ec05e16 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 21 May 2025 09:07:30 +0100 Subject: [PATCH 224/403] rustls-bench: enable and address more lints --- rustls-bench/src/main.rs | 49 +++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/rustls-bench/src/main.rs b/rustls-bench/src/main.rs index 707c0319d73..50f809116e5 100644 --- a/rustls-bench/src/main.rs +++ b/rustls-bench/src/main.rs @@ -2,14 +2,31 @@ // // Note: we don't use any of the standard 'cargo bench', 'test::Bencher', // etc. because it's unstable at the time of writing. - +#![warn( + clippy::alloc_instead_of_core, + clippy::clone_on_ref_ptr, + clippy::manual_let_else, + clippy::std_instead_of_core, + clippy::use_self, + clippy::upper_case_acronyms, + elided_lifetimes_in_paths, + trivial_casts, + trivial_numeric_casts, + unreachable_pub, + unused_import_braces, + unused_extern_crates, + unused_qualifications +)] + +use core::mem; +use core::num::NonZeroUsize; +use core::ops::{Deref, DerefMut}; +use core::time::Duration; use std::fs::File; use std::io::{self, Read, Write}; -use std::num::NonZeroUsize; -use std::ops::{Deref, DerefMut}; use std::sync::Arc; -use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; -use std::{mem, thread}; +use std::thread; +use std::time::{Instant, SystemTime, UNIX_EPOCH}; use clap::{Parser, ValueEnum}; use rustls::client::{Resumption, UnbufferedClientConnection}; @@ -198,11 +215,11 @@ enum Api { impl Api { fn use_buffered(&self) -> bool { - matches!(*self, Api::Both | Api::Buffered) + matches!(*self, Self::Both | Self::Buffered) } fn use_unbuffered(&self) -> bool { - matches!(*self, Api::Both | Api::Unbuffered) + matches!(*self, Self::Both | Self::Unbuffered) } } @@ -249,8 +266,8 @@ fn bench_handshake(params: &Parameters) { bench_handshake_buffered( 1, ResumptionParam::No, - client_config.clone(), - server_config.clone(), + Arc::clone(&client_config), + Arc::clone(&server_config), ¶ms.without_latency_measurement(), ); @@ -427,8 +444,8 @@ fn multithreaded( thread::scope(|s| { let threads = (0..count.into()) .map(|_| { - let client_config = client_config.clone(); - let server_config = server_config.clone(); + let client_config = Arc::clone(client_config); + let server_config = Arc::clone(server_config); s.spawn(|| f(client_config, server_config)) }) .collect::>(); @@ -771,7 +788,7 @@ impl Parameters { } WebPkiClientVerifier::builder_with_provider( client_auth_roots.into(), - provider.clone(), + Arc::clone(&provider), ) .build() .unwrap() @@ -1014,14 +1031,14 @@ impl Provider { #[derive(Clone)] struct BenchmarkParam { key_type: KeyType, - ciphersuite: rustls::CipherSuite, + ciphersuite: CipherSuite, version: &'static rustls::SupportedProtocolVersion, } impl BenchmarkParam { const fn new( key_type: KeyType, - ciphersuite: rustls::CipherSuite, + ciphersuite: CipherSuite, version: &'static rustls::SupportedProtocolVersion, ) -> Self { Self { @@ -1080,7 +1097,7 @@ impl Unbuffered { } } - fn handshake(&mut self, peer: &mut Unbuffered) { + fn handshake(&mut self, peer: &mut Self) { loop { let mut progress = false; @@ -1100,7 +1117,7 @@ impl Unbuffered { } } - fn swap_buffers(&mut self, peer: &mut Unbuffered) { + fn swap_buffers(&mut self, peer: &mut Self) { // our output becomes peer's input, and peer's input // becomes our output. mem::swap(&mut self.input, &mut peer.output); From 5c7975c12e3272ebeae6adb7cd76c70d52b91917 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 21 May 2025 09:12:53 +0100 Subject: [PATCH 225/403] rustls-test: enable and address more lints --- rustls-test/src/lib.rs | 82 +++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/rustls-test/src/lib.rs b/rustls-test/src/lib.rs index 1556c8ae7b2..27de79b4803 100644 --- a/rustls-test/src/lib.rs +++ b/rustls-test/src/lib.rs @@ -1,5 +1,21 @@ +#![warn( + clippy::alloc_instead_of_core, + clippy::clone_on_ref_ptr, + clippy::manual_let_else, + clippy::std_instead_of_core, + clippy::use_self, + clippy::upper_case_acronyms, + elided_lifetimes_in_paths, + trivial_casts, + trivial_numeric_casts, + unreachable_pub, + unused_import_braces, + unused_extern_crates, + unused_qualifications +)] + +use core::ops::DerefMut; use std::io; -use std::ops::DerefMut; use std::sync::Arc; use std::sync::OnceLock; @@ -245,7 +261,7 @@ pub enum Altered { pub fn transfer_altered(left: &mut Connection, filter: F, right: &mut Connection) -> usize where - F: Fn(&mut Message) -> Altered, + F: Fn(&mut Message<'_>) -> Altered, { let mut buf = [0u8; 262144]; let mut total = 0; @@ -322,7 +338,7 @@ static ALL_KEY_TYPES_EXCEPT_P521: &[KeyType] = &[ ]; impl KeyType { - pub fn all_for_provider(provider: &CryptoProvider) -> &'static [KeyType] { + pub fn all_for_provider(provider: &CryptoProvider) -> &'static [Self] { match provider .key_provider .load_private_key(Self::EcdsaP521.get_key()) @@ -453,13 +469,13 @@ impl KeyType { pub fn ca_distinguished_name(&self) -> &'static [u8] { match self { - KeyType::Rsa2048 => b"0\x1f1\x1d0\x1b\x06\x03U\x04\x03\x0c\x14ponytown RSA 2048 CA", - KeyType::Rsa3072 => b"0\x1f1\x1d0\x1b\x06\x03U\x04\x03\x0c\x14ponytown RSA 3072 CA", - KeyType::Rsa4096 => b"0\x1f1\x1d0\x1b\x06\x03U\x04\x03\x0c\x14ponytown RSA 4096 CA", - KeyType::EcdsaP256 => b"0\x211\x1f0\x1d\x06\x03U\x04\x03\x0c\x16ponytown ECDSA p256 CA", - KeyType::EcdsaP384 => b"0\x211\x1f0\x1d\x06\x03U\x04\x03\x0c\x16ponytown ECDSA p384 CA", - KeyType::EcdsaP521 => b"0\x211\x1f0\x1d\x06\x03U\x04\x03\x0c\x16ponytown ECDSA p521 CA", - KeyType::Ed25519 => b"0\x1c1\x1a0\x18\x06\x03U\x04\x03\x0c\x11ponytown EdDSA CA", + Self::Rsa2048 => b"0\x1f1\x1d0\x1b\x06\x03U\x04\x03\x0c\x14ponytown RSA 2048 CA", + Self::Rsa3072 => b"0\x1f1\x1d0\x1b\x06\x03U\x04\x03\x0c\x14ponytown RSA 3072 CA", + Self::Rsa4096 => b"0\x1f1\x1d0\x1b\x06\x03U\x04\x03\x0c\x14ponytown RSA 4096 CA", + Self::EcdsaP256 => b"0\x211\x1f0\x1d\x06\x03U\x04\x03\x0c\x16ponytown ECDSA p256 CA", + Self::EcdsaP384 => b"0\x211\x1f0\x1d\x06\x03U\x04\x03\x0c\x16ponytown ECDSA p384 CA", + Self::EcdsaP521 => b"0\x211\x1f0\x1d\x06\x03U\x04\x03\x0c\x16ponytown ECDSA p521 CA", + Self::Ed25519 => b"0\x1c1\x1a0\x18\x06\x03U\x04\x03\x0c\x11ponytown EdDSA CA", } } } @@ -467,7 +483,7 @@ impl KeyType { pub fn server_config_builder( provider: &CryptoProvider, ) -> rustls::ConfigBuilder { - rustls::ServerConfig::builder_with_provider(provider.clone().into()) + ServerConfig::builder_with_provider(provider.clone().into()) .with_safe_default_protocol_versions() .unwrap() } @@ -476,7 +492,7 @@ pub fn server_config_builder_with_versions( versions: &[&'static rustls::SupportedProtocolVersion], provider: &CryptoProvider, ) -> rustls::ConfigBuilder { - rustls::ServerConfig::builder_with_provider(provider.clone().into()) + ServerConfig::builder_with_provider(provider.clone().into()) .with_protocol_versions(versions) .unwrap() } @@ -484,7 +500,7 @@ pub fn server_config_builder_with_versions( pub fn client_config_builder( provider: &CryptoProvider, ) -> rustls::ConfigBuilder { - rustls::ClientConfig::builder_with_provider(provider.clone().into()) + ClientConfig::builder_with_provider(provider.clone().into()) .with_safe_default_protocol_versions() .unwrap() } @@ -493,7 +509,7 @@ pub fn client_config_builder_with_versions( versions: &[&'static rustls::SupportedProtocolVersion], provider: &CryptoProvider, ) -> rustls::ConfigBuilder { - rustls::ClientConfig::builder_with_provider(provider.clone().into()) + ClientConfig::builder_with_provider(provider.clone().into()) .with_protocol_versions(versions) .unwrap() } @@ -895,8 +911,8 @@ pub fn do_handshake_until_error( pub fn do_handshake_altered( client: ClientConnection, - alter_server_message: impl Fn(&mut Message) -> Altered, - alter_client_message: impl Fn(&mut Message) -> Altered, + alter_server_message: impl Fn(&mut Message<'_>) -> Altered, + alter_client_message: impl Fn(&mut Message<'_>) -> Altered, server: ServerConnection, ) -> Result<(), ErrorFromPeer> { let mut client: Connection = Connection::Client(client); @@ -1163,49 +1179,49 @@ impl ServerCertVerifier for MockServerVerifier { impl MockServerVerifier { pub fn accepts_anything() -> Self { - MockServerVerifier { + Self { cert_rejection_error: None, ..Default::default() } } pub fn expects_ocsp_response(response: &[u8]) -> Self { - MockServerVerifier { + Self { expected_ocsp_response: Some(response.to_vec()), ..Default::default() } } pub fn rejects_certificate(err: Error) -> Self { - MockServerVerifier { + Self { cert_rejection_error: Some(err), ..Default::default() } } pub fn rejects_tls12_signatures(err: Error) -> Self { - MockServerVerifier { + Self { tls12_signature_error: Some(err), ..Default::default() } } pub fn rejects_tls13_signatures(err: Error) -> Self { - MockServerVerifier { + Self { tls13_signature_error: Some(err), ..Default::default() } } pub fn offers_no_signature_schemes() -> Self { - MockServerVerifier { + Self { signature_schemes: vec![], ..Default::default() } } pub fn expects_raw_public_keys(provider: &CryptoProvider) -> Self { - MockServerVerifier { + Self { requires_raw_public_keys: true, raw_public_key_algorithms: Some(provider.signature_verification_algorithms), ..Default::default() @@ -1215,7 +1231,7 @@ impl MockServerVerifier { impl Default for MockServerVerifier { fn default() -> Self { - MockServerVerifier { + Self { cert_rejection_error: None, tls12_signature_error: None, tls13_signature_error: None, @@ -1427,7 +1443,7 @@ impl RawTls { pub fn receive_and_decrypt( &mut self, peer: &mut impl DerefMut>, - f: impl Fn(Message), + f: impl Fn(Message<'_>), ) { let mut data = vec![]; peer.write_tls(&mut io::Cursor::new(&mut data)) @@ -1690,8 +1706,8 @@ pub mod encoding { } impl Extension { - pub fn new_sig_algs() -> Extension { - Extension { + pub fn new_sig_algs() -> Self { + Self { typ: ExtensionType::SignatureAlgorithms, body: len_u16( SignatureScheme::RSA_PKCS1_SHA256 @@ -1701,15 +1717,15 @@ pub mod encoding { } } - pub fn new_kx_groups() -> Extension { - Extension { + pub fn new_kx_groups() -> Self { + Self { typ: ExtensionType::EllipticCurves, body: len_u16(vector_of([NamedGroup::secp256r1].into_iter())), } } - pub fn new_versions() -> Extension { - Extension { + pub fn new_versions() -> Self { + Self { typ: ExtensionType::SupportedVersions, body: len_u8(vector_of( [ProtocolVersion::TLSv1_3, ProtocolVersion::TLSv1_2].into_iter(), @@ -1717,7 +1733,7 @@ pub mod encoding { } } - pub fn new_dummy_key_share() -> Extension { + pub fn new_dummy_key_share() -> Self { const SOME_POINT_ON_P256: &[u8] = &[ 4, 41, 39, 177, 5, 18, 186, 227, 237, 220, 254, 70, 120, 40, 18, 139, 173, 41, 3, 38, 153, 25, 247, 8, 96, 105, 200, 196, 223, 108, 115, 40, 56, 199, 120, 121, 100, @@ -1728,7 +1744,7 @@ pub mod encoding { let mut share = len_u16(SOME_POINT_ON_P256.to_vec()); share.splice(0..0, NamedGroup::secp256r1.to_array()); - Extension { + Self { typ: ExtensionType::KeyShare, body: len_u16(share), } From 4e78f891e5734b18590ee7b84cde4c6a92406843 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 21 May 2025 09:17:26 +0100 Subject: [PATCH 226/403] bogo: enable and address more lints --- bogo/src/main.rs | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/bogo/src/main.rs b/bogo/src/main.rs index 065912c7788..f4e73131468 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -4,9 +4,23 @@ // https://boringssl.googlesource.com/boringssl/+/master/ssl/test // -#![allow(clippy::disallowed_types)] - -use std::fmt::{Debug, Formatter}; +#![warn( + clippy::alloc_instead_of_core, + clippy::clone_on_ref_ptr, + clippy::manual_let_else, + clippy::std_instead_of_core, + clippy::use_self, + clippy::upper_case_acronyms, + elided_lifetimes_in_paths, + trivial_casts, + trivial_numeric_casts, + unreachable_pub, + unused_import_braces, + unused_extern_crates, + unused_qualifications +)] + +use core::fmt::{Debug, Formatter}; use std::io::{self, Read, Write}; use std::sync::Arc; use std::{env, net, process, thread, time}; @@ -119,7 +133,7 @@ struct Options { impl Options { fn new() -> Self { let selected_provider = SelectedProvider::from_env(); - Options { + Self { port: 0, shim_id: 0, side: Side::Client, @@ -402,7 +416,7 @@ struct DummyServerAuth { impl DummyServerAuth { fn new(trusted_cert_file: &str) -> Self { - DummyServerAuth { + Self { parent: WebPkiServerVerifier::builder_with_provider( load_root_certs(trusted_cert_file), SelectedProvider::from_env() @@ -478,10 +492,10 @@ struct FixedSignatureSchemeServerCertResolver { } impl server::ResolvesServerCert for FixedSignatureSchemeServerCertResolver { - fn resolve(&self, client_hello: ClientHello) -> Option> { + fn resolve(&self, client_hello: ClientHello<'_>) -> Option> { let mut certkey = self.resolver.resolve(client_hello)?; Arc::make_mut(&mut certkey).key = Arc::new(FixedSignatureSchemeSigningKey { - key: certkey.key.clone(), + key: Arc::clone(&certkey.key), scheme: self.scheme, }); Some(certkey) @@ -507,7 +521,7 @@ impl client::ResolvesClientCert for FixedSignatureSchemeClientCertResolver { .resolver .resolve(root_hint_subjects, sigschemes)?; Arc::make_mut(&mut certkey).key = Arc::new(FixedSignatureSchemeSigningKey { - key: certkey.key.clone(), + key: Arc::clone(&certkey.key), scheme: self.scheme, }); Some(certkey) @@ -607,7 +621,7 @@ fn make_server_cfg(opts: &Options) -> Arc { opts.root_hint_subjects.clone(), )) } else { - server::WebPkiClientVerifier::no_client_auth() + WebPkiClientVerifier::no_client_auth() }; let cert = CertificateDer::pem_file_iter(&opts.cert_file) @@ -640,7 +654,7 @@ fn make_server_cfg(opts: &Options) -> Arc { if opts.use_signing_scheme > 0 { let scheme = lookup_scheme(opts.use_signing_scheme); cfg.cert_resolver = Arc::new(FixedSignatureSchemeServerCertResolver { - resolver: cfg.cert_resolver.clone(), + resolver: Arc::clone(&cfg.cert_resolver), scheme, }); } @@ -692,8 +706,8 @@ struct ClientCacheWithoutKxHints { } impl ClientCacheWithoutKxHints { - fn new(delay: u32) -> Arc { - Arc::new(ClientCacheWithoutKxHints { + fn new(delay: u32) -> Arc { + Arc::new(Self { delay, storage: Arc::new(client::ClientSessionMemoryCache::new(32)), }) @@ -748,7 +762,7 @@ impl client::ClientSessionStore for ClientCacheWithoutKxHints { } impl Debug for ClientCacheWithoutKxHints { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { // Note: we omit self.storage here as it may contain sensitive data. f.debug_struct("ClientCacheWithoutKxHints") .field("delay", &self.delay) @@ -811,7 +825,7 @@ fn make_client_cfg(opts: &Options) -> Arc { if !opts.cert_file.is_empty() && opts.use_signing_scheme > 0 { let scheme = lookup_scheme(opts.use_signing_scheme); cfg.client_auth_cert_resolver = Arc::new(FixedSignatureSchemeClientCertResolver { - resolver: cfg.client_auth_cert_resolver.clone(), + resolver: Arc::clone(&cfg.client_auth_cert_resolver), scheme, }); } From 7d8c26770ef44bad61c53be9246862f2672219a0 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 21 May 2025 10:34:34 +0100 Subject: [PATCH 227/403] rustls-fuzzing-provider: enable and address more lints --- rustls-fuzzing-provider/src/lib.rs | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/rustls-fuzzing-provider/src/lib.rs b/rustls-fuzzing-provider/src/lib.rs index fed5aa444ca..6afe5004a7f 100644 --- a/rustls-fuzzing-provider/src/lib.rs +++ b/rustls-fuzzing-provider/src/lib.rs @@ -1,3 +1,19 @@ +#![warn( + clippy::alloc_instead_of_core, + clippy::clone_on_ref_ptr, + clippy::manual_let_else, + clippy::std_instead_of_core, + clippy::use_self, + clippy::upper_case_acronyms, + elided_lifetimes_in_paths, + trivial_casts, + trivial_numeric_casts, + unreachable_pub, + unused_import_braces, + unused_extern_crates, + unused_qualifications +)] + use std::sync::Arc; use rustls::client::WebPkiServerVerifier; @@ -26,7 +42,7 @@ use rustls::{ pub fn provider() -> crypto::CryptoProvider { crypto::CryptoProvider { cipher_suites: vec![TLS13_FUZZING_SUITE, TLS_FUZZING_SUITE], - kx_groups: vec![&KeyExchangeGroup as &dyn crypto::SupportedKxGroup], + kx_groups: vec![&KeyExchangeGroup], signature_verification_algorithms: VERIFY_ALGORITHMS, secure_random: &Provider, key_provider: &Provider, @@ -55,8 +71,8 @@ pub fn server_cert_resolver() -> Arc { struct DummyCert(Arc); impl server::ResolvesServerCert for DummyCert { - fn resolve(&self, _client_hello: server::ClientHello) -> Option> { - Some(self.0.clone()) + fn resolve(&self, _client_hello: server::ClientHello<'_>) -> Option> { + Some(Arc::clone(&self.0)) } } @@ -137,7 +153,7 @@ impl hash::Context for HashContext { } fn fork(&self) -> Box { - Box::new(HashContext) + Box::new(Self) } fn finish(self: Box) -> hash::Output { @@ -274,7 +290,7 @@ struct Tls13Cipher; impl MessageEncrypter for Tls13Cipher { fn encrypt( &mut self, - m: OutboundPlainMessage, + m: OutboundPlainMessage<'_>, seq: u64, ) -> Result { let total_len = self.encrypted_payload_len(m.payload.len()); @@ -343,7 +359,7 @@ struct Tls12Cipher; impl MessageEncrypter for Tls12Cipher { fn encrypt( &mut self, - m: OutboundPlainMessage, + m: OutboundPlainMessage<'_>, seq: u64, ) -> Result { let total_len = self.encrypted_payload_len(m.payload.len()); @@ -443,7 +459,7 @@ pub struct SigningKey; impl sign::SigningKey for SigningKey { fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option> { match offered.contains(&SIGNATURE_SCHEME) { - true => Some(Box::new(SigningKey)), + true => Some(Box::new(Self)), false => None, } } From 66a3f3e15ceefd43ef12c1e056e7d1cc20f3ec5d Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 21 May 2025 10:38:18 +0100 Subject: [PATCH 228/403] provider-example: enable and address more lints --- provider-example/src/aead.rs | 6 +++--- provider-example/src/hash.rs | 4 ++-- provider-example/src/hmac.rs | 2 +- provider-example/src/hpke.rs | 2 +- provider-example/src/kx.rs | 13 +++++-------- provider-example/src/lib.rs | 15 +++++++++++++++ provider-example/src/sign.rs | 2 +- provider-example/src/verify.rs | 4 ++-- 8 files changed, 30 insertions(+), 18 deletions(-) diff --git a/provider-example/src/aead.rs b/provider-example/src/aead.rs index 94073ed7e00..6ac19fb9260 100644 --- a/provider-example/src/aead.rs +++ b/provider-example/src/aead.rs @@ -10,7 +10,7 @@ use rustls::crypto::cipher::{ }; use rustls::{ConnectionTrafficSecrets, ContentType, ProtocolVersion}; -pub struct Chacha20Poly1305; +pub(crate) struct Chacha20Poly1305; impl Tls13AeadAlgorithm for Chacha20Poly1305 { fn encrypter(&self, key: AeadKey, iv: Iv) -> Box { @@ -83,7 +83,7 @@ struct Tls13Cipher(chacha20poly1305::ChaCha20Poly1305, Iv); impl MessageEncrypter for Tls13Cipher { fn encrypt( &mut self, - m: OutboundPlainMessage, + m: OutboundPlainMessage<'_>, seq: u64, ) -> Result { let total_len = self.encrypted_payload_len(m.payload.len()); @@ -134,7 +134,7 @@ struct Tls12Cipher(chacha20poly1305::ChaCha20Poly1305, Iv); impl MessageEncrypter for Tls12Cipher { fn encrypt( &mut self, - m: OutboundPlainMessage, + m: OutboundPlainMessage<'_>, seq: u64, ) -> Result { let total_len = self.encrypted_payload_len(m.payload.len()); diff --git a/provider-example/src/hash.rs b/provider-example/src/hash.rs index 4f28b0f2e41..5d747335957 100644 --- a/provider-example/src/hash.rs +++ b/provider-example/src/hash.rs @@ -3,7 +3,7 @@ use alloc::boxed::Box; use rustls::crypto::hash; use sha2::Digest; -pub struct Sha256; +pub(crate) struct Sha256; impl hash::Hash for Sha256 { fn start(&self) -> Box { @@ -31,7 +31,7 @@ impl hash::Context for Sha256Context { } fn fork(&self) -> Box { - Box::new(Sha256Context(self.0.clone())) + Box::new(Self(self.0.clone())) } fn finish(self: Box) -> hash::Output { diff --git a/provider-example/src/hmac.rs b/provider-example/src/hmac.rs index 763dd71e092..34e0d1a34fb 100644 --- a/provider-example/src/hmac.rs +++ b/provider-example/src/hmac.rs @@ -4,7 +4,7 @@ use hmac::{Hmac, Mac}; use rustls::crypto; use sha2::{Digest, Sha256}; -pub struct Sha256Hmac; +pub(crate) struct Sha256Hmac; impl crypto::hmac::Hmac for Sha256Hmac { fn with_key(&self, key: &[u8]) -> Box { diff --git a/provider-example/src/hpke.rs b/provider-example/src/hpke.rs index 7d61f842763..07b9ef8e6c1 100644 --- a/provider-example/src/hpke.rs +++ b/provider-example/src/hpke.rs @@ -212,7 +212,7 @@ impl HpkeOpener for HpkeRsReceiver { } #[cfg(feature = "std")] -fn other_err(err: impl std::error::Error + Send + Sync + 'static) -> Error { +fn other_err(err: impl core::error::Error + Send + Sync + 'static) -> Error { Error::Other(OtherError(alloc::sync::Arc::new(err))) } diff --git a/provider-example/src/kx.rs b/provider-example/src/kx.rs index 80fb235bdcd..e6ad32bedfa 100644 --- a/provider-example/src/kx.rs +++ b/provider-example/src/kx.rs @@ -4,16 +4,13 @@ use crypto::SupportedKxGroup; use rustls::crypto; use rustls::ffdhe_groups::FfdheGroup; -pub struct KeyExchange { +pub(crate) struct KeyExchange { priv_key: x25519_dalek::EphemeralSecret, pub_key: x25519_dalek::PublicKey, } impl crypto::ActiveKeyExchange for KeyExchange { - fn complete( - self: Box, - peer: &[u8], - ) -> Result { + fn complete(self: Box, peer: &[u8]) -> Result { let peer_array: [u8; 32] = peer .try_into() .map_err(|_| rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare))?; @@ -35,12 +32,12 @@ impl crypto::ActiveKeyExchange for KeyExchange { } } -pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[&X25519 as &dyn SupportedKxGroup]; +pub(crate) const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[&X25519]; #[derive(Debug)] -pub struct X25519; +pub(crate) struct X25519; -impl crypto::SupportedKxGroup for X25519 { +impl SupportedKxGroup for X25519 { fn start(&self) -> Result, rustls::Error> { let priv_key = x25519_dalek::EphemeralSecret::random_from_rng(rand_core::OsRng); Ok(Box::new(KeyExchange { diff --git a/provider-example/src/lib.rs b/provider-example/src/lib.rs index e8daaa19a56..70e742e25c9 100644 --- a/provider-example/src/lib.rs +++ b/provider-example/src/lib.rs @@ -1,4 +1,19 @@ #![no_std] +#![warn( + clippy::alloc_instead_of_core, + clippy::clone_on_ref_ptr, + clippy::manual_let_else, + clippy::std_instead_of_core, + clippy::use_self, + clippy::upper_case_acronyms, + elided_lifetimes_in_paths, + trivial_casts, + trivial_numeric_casts, + unreachable_pub, + unused_import_braces, + unused_extern_crates, + unused_qualifications +)] extern crate alloc; #[cfg(feature = "std")] diff --git a/provider-example/src/sign.rs b/provider-example/src/sign.rs index 36f7beae815..48a8d939066 100644 --- a/provider-example/src/sign.rs +++ b/provider-example/src/sign.rs @@ -9,7 +9,7 @@ use rustls::{SignatureAlgorithm, SignatureScheme}; use signature::{RandomizedSigner, SignatureEncoding}; #[derive(Clone, Debug)] -pub struct EcdsaSigningKeyP256 { +pub(crate) struct EcdsaSigningKeyP256 { key: Arc, scheme: SignatureScheme, } diff --git a/provider-example/src/verify.rs b/provider-example/src/verify.rs index 5d3c5dbc276..6b2c9fffbfc 100644 --- a/provider-example/src/verify.rs +++ b/provider-example/src/verify.rs @@ -7,7 +7,7 @@ use rustls::pki_types::{ AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm, alg_id, }; -pub static ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms { +pub(crate) static ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms { all: &[RSA_PSS_SHA256, RSA_PKCS1_SHA256], mapping: &[ (SignatureScheme::RSA_PSS_SHA256, &[RSA_PSS_SHA256]), @@ -78,7 +78,7 @@ fn decode_spki_spk(spki_spk: &[u8]) -> Result { // public_key: unfortunately this is not a whole SPKI, but just the key material. // decode the two integers manually. let mut reader = der::SliceReader::new(spki_spk).map_err(|_| InvalidSignature)?; - let ne: [der::asn1::UintRef; 2] = reader + let ne: [der::asn1::UintRef<'_>; 2] = reader .decode() .map_err(|_| InvalidSignature)?; From 997e7beb8cf02b07e04be5639bece25fe69a07a5 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 21 May 2025 10:51:33 +0100 Subject: [PATCH 229/403] ci-bench: enable and address more lints --- ci-bench/src/benchmark.rs | 10 +++++----- ci-bench/src/callgrind.rs | 20 +++++++++---------- ci-bench/src/main.rs | 30 ++++++++++++++++++++++------ ci-bench/src/util.rs | 41 ++++++++++++++++++++------------------- 4 files changed, 60 insertions(+), 41 deletions(-) diff --git a/ci-bench/src/benchmark.rs b/ci-bench/src/benchmark.rs index 325de04b796..023e20f67de 100644 --- a/ci-bench/src/benchmark.rs +++ b/ci-bench/src/benchmark.rs @@ -12,7 +12,7 @@ use rustls_test::KeyType; /// Benchmarks can be invalid because of the following reasons: /// /// - Re-using an already defined benchmark name. -pub fn validate_benchmarks(benchmarks: &[Benchmark]) -> anyhow::Result<()> { +pub(crate) fn validate_benchmarks(benchmarks: &[Benchmark]) -> anyhow::Result<()> { // Detect duplicate definitions let duplicate_names: Vec<_> = benchmarks .iter() @@ -30,7 +30,7 @@ pub fn validate_benchmarks(benchmarks: &[Benchmark]) -> anyhow::Result<()> { } /// Get the reported instruction counts for the provided benchmark -pub fn get_reported_instr_count( +pub(crate) fn get_reported_instr_count( bench: &Benchmark, results: &FxHashMap<&str, InstructionCounts>, ) -> InstructionCounts { @@ -50,8 +50,8 @@ impl BenchmarkKind { /// Returns the [`ResumptionKind`] used in the handshake part of the benchmark pub fn resumption_kind(self) -> ResumptionKind { match self { - BenchmarkKind::Handshake(kind) => kind, - BenchmarkKind::Transfer => ResumptionKind::No, + Self::Handshake(kind) => kind, + Self::Transfer => ResumptionKind::No, } } } @@ -68,7 +68,7 @@ pub enum ResumptionKind { } impl ResumptionKind { - pub const ALL: &'static [ResumptionKind] = &[Self::No, Self::SessionId, Self::Tickets]; + pub const ALL: &'static [Self] = &[Self::No, Self::SessionId, Self::Tickets]; /// Returns a user-facing label that identifies the resumption kind pub fn label(&self) -> &'static str { diff --git a/ci-bench/src/callgrind.rs b/ci-bench/src/callgrind.rs index 4ff3a0f6639..085c8f96cdb 100644 --- a/ci-bench/src/callgrind.rs +++ b/ci-bench/src/callgrind.rs @@ -1,6 +1,6 @@ +use core::ops::Sub; use std::fs::File; use std::io::{BufRead, BufReader}; -use std::ops::Sub; use std::path::{Path, PathBuf}; use std::process::{Child, Command, Stdio}; @@ -13,7 +13,7 @@ use crate::benchmark::Benchmark; const CALLGRIND_OUTPUT_SUBDIR: &str = "callgrind"; /// A callgrind-based benchmark runner -pub struct CallgrindRunner { +pub(crate) struct CallgrindRunner { /// The path to the ci-bench executable /// /// This is necessary because the callgrind runner works by spawning child processes @@ -24,21 +24,21 @@ pub struct CallgrindRunner { impl CallgrindRunner { /// Returns a new callgrind-based benchmark runner - pub fn new(executable: String, output_dir: PathBuf) -> anyhow::Result { + pub(crate) fn new(executable: String, output_dir: PathBuf) -> anyhow::Result { Self::ensure_callgrind_available()?; let callgrind_output_dir = output_dir.join(CALLGRIND_OUTPUT_SUBDIR); std::fs::create_dir_all(&callgrind_output_dir) .context("Failed to create callgrind output directory")?; - Ok(CallgrindRunner { + Ok(Self { executable, output_dir: callgrind_output_dir, }) } /// Runs the benchmark at the specified index and returns the instruction counts for each side - pub fn run_bench( + pub(crate) fn run_bench( &self, benchmark_index: u32, bench: &Benchmark, @@ -194,16 +194,16 @@ fn parse_callgrind_output(file: &Path) -> anyhow::Result { /// The instruction counts, for each side, after running a benchmark #[derive(Copy, Clone)] -pub struct InstructionCounts { +pub(crate) struct InstructionCounts { pub client: u64, pub server: u64, } impl Sub for InstructionCounts { - type Output = InstructionCounts; + type Output = Self; fn sub(self, rhs: Self) -> Self::Output { - InstructionCounts { + Self { client: self.client - rhs.client, server: self.server - rhs.server, } @@ -211,7 +211,7 @@ impl Sub for InstructionCounts { } /// Returns the detailed instruction diff between the baseline and the candidate -pub fn diff(baseline: &Path, candidate: &Path, scenario: &str) -> anyhow::Result { +pub(crate) fn diff(baseline: &Path, candidate: &Path, scenario: &str) -> anyhow::Result { // callgrind_annotate formats the callgrind output file, suitable for comparison with // callgrind_differ let callgrind_annotate_base = Command::new("callgrind_annotate") @@ -279,7 +279,7 @@ impl CountInstructions { pub(crate) fn start() -> Self { #[cfg(target_os = "linux")] crabgrind::callgrind::toggle_collect(); - CountInstructions + Self } } diff --git a/ci-bench/src/main.rs b/ci-bench/src/main.rs index 3d2d3595960..6bef3768971 100644 --- a/ci-bench/src/main.rs +++ b/ci-bench/src/main.rs @@ -1,8 +1,24 @@ +#![warn( + clippy::alloc_instead_of_core, + clippy::clone_on_ref_ptr, + clippy::manual_let_else, + clippy::std_instead_of_core, + clippy::use_self, + clippy::upper_case_acronyms, + elided_lifetimes_in_paths, + trivial_casts, + trivial_numeric_casts, + unreachable_pub, + unused_import_braces, + unused_extern_crates, + unused_qualifications +)] + +use core::hint::black_box; +use core::mem; use std::collections::HashMap; use std::fs::File; -use std::hint::black_box; use std::io::{self, BufRead, BufReader, Write}; -use std::mem; use std::os::fd::{AsRawFd, FromRawFd}; use std::path::{Path, PathBuf}; use std::sync::Arc; @@ -102,8 +118,8 @@ impl Side { /// Returns the string representation of the side pub fn as_str(self) -> &'static str { match self { - Side::Client => "client", - Side::Server => "server", + Self::Client => "client", + Self::Server => "server", } } } @@ -299,12 +315,14 @@ fn all_benchmarks_params() -> Vec { ( derandomize(ring::default_provider()), ring::ALL_CIPHER_SUITES, + #[allow(trivial_casts)] &(ring_ticketer as fn() -> Arc), "ring", ), ( derandomize(aws_lc_rs::default_provider()), aws_lc_rs::ALL_CIPHER_SUITES, + #[allow(trivial_casts)] &(aws_lc_rs_ticketer as fn() -> Arc), "aws_lc_rs", ), @@ -534,7 +552,7 @@ impl BenchStepper for ClientSideStepper<'_> { async fn handshake(&mut self) -> anyhow::Result { let server_name = "localhost".try_into().unwrap(); - let mut client = ClientConnection::new(self.config.clone(), server_name).unwrap(); + let mut client = ClientConnection::new(Arc::clone(&self.config), server_name).unwrap(); client.set_buffer_limit(None); loop { @@ -610,7 +628,7 @@ impl BenchStepper for ServerSideStepper<'_> { type Endpoint = ServerConnection; async fn handshake(&mut self) -> anyhow::Result { - let mut server = ServerConnection::new(self.config.clone()).unwrap(); + let mut server = ServerConnection::new(Arc::clone(&self.config)).unwrap(); server.set_buffer_limit(None); while server.is_handshaking() { diff --git a/ci-bench/src/util.rs b/ci-bench/src/util.rs index f924d0d641f..8ac4b34b4c2 100644 --- a/ci-bench/src/util.rs +++ b/ci-bench/src/util.rs @@ -1,15 +1,16 @@ -pub mod async_io { +pub(crate) mod async_io { //! Async IO building blocks required for sharing code between the instruction count and //! wall-time benchmarks - use std::cell::{Cell, RefCell}; + use core::cell::{Cell, RefCell}; + use core::future::Future; + use core::pin::{Pin, pin}; + use core::task::{Poll, RawWaker, RawWakerVTable, Waker}; + use core::{ptr, task}; use std::collections::VecDeque; use std::fs::File; - use std::future::Future; - use std::pin::{Pin, pin}; + use std::io; use std::rc::Rc; - use std::task::{Poll, RawWaker, RawWakerVTable, Waker}; - use std::{io, ptr, task}; use async_trait::async_trait; @@ -21,7 +22,7 @@ pub mod async_io { /// Useful when counting CPU instructions, because the server and the client side of the /// connection run in two separate processes and communicate through stdio using blocking /// operations. - pub fn block_on_single_poll( + pub(crate) fn block_on_single_poll( future: impl Future>, ) -> anyhow::Result<()> { // We don't need a waker, because the future will complete in one go @@ -44,7 +45,7 @@ pub mod async_io { /// /// Using this together with blocking futures can lead to deadlocks (i.e. when one of the /// futures is blocked while it waits on a message from the other). - pub fn block_on_concurrent( + pub(crate) fn block_on_concurrent( x: impl Future>, y: impl Future>, ) -> (anyhow::Result<()>, anyhow::Result<()>) { @@ -100,14 +101,14 @@ pub mod async_io { /// Read bytes asynchronously #[async_trait(?Send)] - pub trait AsyncRead { + pub(crate) trait AsyncRead { async fn read(&mut self, buf: &mut [u8]) -> io::Result; async fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()>; } /// Write bytes asynchronously #[async_trait(?Send)] - pub trait AsyncWrite { + pub(crate) trait AsyncWrite { async fn write_all(&mut self, buf: &[u8]) -> io::Result<()>; async fn flush(&mut self) -> io::Result<()>; } @@ -138,14 +139,14 @@ pub mod async_io { /// Creates an unidirectional byte pipe of the given capacity, suitable for async reading and /// writing - pub fn async_pipe(capacity: usize) -> (AsyncSender, AsyncReceiver) { + pub(crate) fn async_pipe(capacity: usize) -> (AsyncSender, AsyncReceiver) { let open = Rc::new(Cell::new(true)); let buf = Rc::new(RefCell::new(VecDeque::with_capacity(capacity))); ( AsyncSender { inner: AsyncPipeSide { - open: open.clone(), - buf: buf.clone(), + open: Rc::clone(&open), + buf: Rc::clone(&buf), }, }, AsyncReceiver { @@ -155,12 +156,12 @@ pub mod async_io { } /// The sender end of an asynchronous byte pipe - pub struct AsyncSender { + pub(crate) struct AsyncSender { inner: AsyncPipeSide, } /// The receiver end of an asynchronous byte pipe - pub struct AsyncReceiver { + pub(crate) struct AsyncReceiver { inner: AsyncPipeSide, } @@ -347,7 +348,7 @@ pub mod async_io { } } -pub mod transport { +pub(crate) mod transport { //! Custom functions to interact between rustls clients and a servers. //! //! The goal of these functions is to ensure messages are exchanged in chunks of a fixed size, to make @@ -375,7 +376,7 @@ pub mod transport { /// length, followed by the message itself. /// /// The receiving end should use [`read_handshake_message`] to process the transmission. - pub async fn send_handshake_message( + pub(crate) async fn send_handshake_message( conn: &mut ConnectionCommon, writer: &mut dyn AsyncWrite, buf: &mut [u8], @@ -413,7 +414,7 @@ pub mod transport { /// /// Used in combination with [`send_handshake_message`] (see that function's documentation for /// more details). - pub async fn read_handshake_message( + pub(crate) async fn read_handshake_message( conn: &mut ConnectionCommon, reader: &mut dyn AsyncRead, buf: &mut [u8], @@ -449,7 +450,7 @@ pub mod transport { /// Reads plaintext until the reader reaches EOF, using a bounded amount of memory. /// /// Returns the amount of plaintext bytes received. - pub async fn read_plaintext_to_end_bounded( + pub(crate) async fn read_plaintext_to_end_bounded( client: &mut ClientConnection, reader: &mut dyn AsyncRead, ) -> anyhow::Result { @@ -501,7 +502,7 @@ pub mod transport { } /// Writes a plaintext of size `plaintext_size`, using a bounded amount of memory - pub async fn write_all_plaintext_bounded( + pub(crate) async fn write_all_plaintext_bounded( server: &mut ServerConnection, writer: &mut dyn AsyncWrite, plaintext_size: usize, From 70fc076e6d813d742ba6070d11269af04a499ad6 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 21 May 2025 10:58:09 +0100 Subject: [PATCH 230/403] openssl-test: enable and address more lints --- openssl-tests/src/ffdhe.rs | 4 +- openssl-tests/src/ffdhe_kx_with_openssl.rs | 12 +++--- openssl-tests/src/lib.rs | 15 ++++++++ openssl-tests/src/raw_key_openssl_interop.rs | 40 +++++++------------- openssl-tests/src/utils.rs | 6 +-- openssl-tests/src/validate_ffdhe_params.rs | 8 ++-- 6 files changed, 44 insertions(+), 41 deletions(-) diff --git a/openssl-tests/src/ffdhe.rs b/openssl-tests/src/ffdhe.rs index 20bd634b36f..6266c910204 100644 --- a/openssl-tests/src/ffdhe.rs +++ b/openssl-tests/src/ffdhe.rs @@ -7,11 +7,11 @@ use rustls::ffdhe_groups::FfdheGroup; use rustls::{CipherSuite, NamedGroup, SupportedCipherSuite, Tls12CipherSuite}; /// The (test-only) TLS1.2 ciphersuite TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 -pub static TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = +pub(crate) static TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = SupportedCipherSuite::Tls12(&TLS12_DHE_RSA_WITH_AES_128_GCM_SHA256); #[derive(Debug)] -pub struct FfdheKxGroup(pub NamedGroup, pub FfdheGroup<'static>); +pub(crate) struct FfdheKxGroup(pub NamedGroup, pub FfdheGroup<'static>); impl SupportedKxGroup for FfdheKxGroup { fn start(&self) -> Result, rustls::Error> { diff --git a/openssl-tests/src/ffdhe_kx_with_openssl.rs b/openssl-tests/src/ffdhe_kx_with_openssl.rs index 19ed8c54970..f3d7a0c7180 100644 --- a/openssl-tests/src/ffdhe_kx_with_openssl.rs +++ b/openssl-tests/src/ffdhe_kx_with_openssl.rs @@ -31,13 +31,13 @@ fn test_rustls_server_with_ffdhe_kx( let message = "Hello from rustls!\n"; - let listener = std::net::TcpListener::bind(("localhost", 0)).unwrap(); + let listener = TcpListener::bind(("localhost", 0)).unwrap(); let port = listener.local_addr().unwrap().port(); - let server_thread = std::thread::spawn(move || { + let server_thread = thread::spawn(move || { let config = Arc::new(server_config_with_ffdhe_kx(protocol_version)); for _ in 0..iters { - let mut server = rustls::ServerConnection::new(config.clone()).unwrap(); + let mut server = rustls::ServerConnection::new(Arc::clone(&config)).unwrap(); let (mut tcp_stream, _addr) = listener.accept().unwrap(); server .writer() @@ -102,11 +102,11 @@ fn test_rustls_client_with_ffdhe_kx(iters: usize) { let listener = TcpListener::bind(("localhost", 0)).unwrap(); let port = listener.local_addr().unwrap().port(); - let server_thread = std::thread::spawn(move || { + let server_thread = thread::spawn(move || { for stream in listener.incoming().take(iters) { match stream { Ok(stream) => { - let acceptor = acceptor.clone(); + let acceptor = Arc::clone(&acceptor); thread::spawn(move || { let mut stream = acceptor.accept(stream).unwrap(); let mut buf = String::new(); @@ -123,7 +123,7 @@ fn test_rustls_client_with_ffdhe_kx(iters: usize) { // client: for _ in 0..iters { - let mut tcp_stream = std::net::TcpStream::connect(("localhost", port)).unwrap(); + let mut tcp_stream = TcpStream::connect(("localhost", port)).unwrap(); let mut client = rustls::client::ClientConnection::new( client_config_with_ffdhe_kx().into(), "localhost".try_into().unwrap(), diff --git a/openssl-tests/src/lib.rs b/openssl-tests/src/lib.rs index aeda47ff258..df77818f5c4 100644 --- a/openssl-tests/src/lib.rs +++ b/openssl-tests/src/lib.rs @@ -1,4 +1,19 @@ #![cfg(test)] +#![warn( + clippy::alloc_instead_of_core, + clippy::clone_on_ref_ptr, + clippy::manual_let_else, + clippy::std_instead_of_core, + clippy::use_self, + clippy::upper_case_acronyms, + elided_lifetimes_in_paths, + trivial_casts, + trivial_numeric_casts, + unreachable_pub, + unused_import_braces, + unused_extern_crates, + unused_qualifications +)] mod ffdhe; mod ffdhe_kx_with_openssl; diff --git a/openssl-tests/src/raw_key_openssl_interop.rs b/openssl-tests/src/raw_key_openssl_interop.rs index c6857330d69..a6d8b50aadf 100644 --- a/openssl-tests/src/raw_key_openssl_interop.rs +++ b/openssl-tests/src/raw_key_openssl_interop.rs @@ -90,11 +90,9 @@ mod client { impl SimpleRpkServerCertVerifier { fn new(trusted_spki: Vec>) -> Self { - SimpleRpkServerCertVerifier { + Self { trusted_spki, - supported_algs: Arc::new(provider::default_provider()) - .clone() - .signature_verification_algorithms, + supported_algs: provider::default_provider().signature_verification_algorithms, } } } @@ -107,15 +105,13 @@ mod client { _server_name: &ServerName<'_>, _ocsp_response: &[u8], _now: UnixTime, - ) -> Result { + ) -> Result { let end_entity_as_spki = SubjectPublicKeyInfoDer::from(end_entity.as_ref()); match self .trusted_spki .contains(&end_entity_as_spki) { - false => Err(rustls::Error::InvalidCertificate( - CertificateError::UnknownIssuer, - )), + false => Err(Error::InvalidCertificate(CertificateError::UnknownIssuer)), true => Ok(ServerCertVerified::assertion()), } } @@ -125,10 +121,8 @@ mod client { _message: &[u8], _cert: &CertificateDer<'_>, _dss: &DigitallySignedStruct, - ) -> Result { - Err(rustls::Error::PeerIncompatible( - PeerIncompatible::Tls12NotOffered, - )) + ) -> Result { + Err(Error::PeerIncompatible(PeerIncompatible::Tls12NotOffered)) } fn verify_tls13_signature( @@ -136,7 +130,7 @@ mod client { message: &[u8], cert: &CertificateDer<'_>, dss: &DigitallySignedStruct, - ) -> Result { + ) -> Result { verify_tls13_signature_with_raw_key( message, &SubjectPublicKeyInfoDer::from(cert.as_ref()), @@ -254,12 +248,10 @@ mod server { } impl SimpleRpkClientCertVerifier { - pub fn new(trusted_spki: Vec>) -> Self { + pub(crate) fn new(trusted_spki: Vec>) -> Self { Self { trusted_spki, - supported_algs: Arc::new(provider::default_provider()) - .clone() - .signature_verification_algorithms, + supported_algs: provider::default_provider().signature_verification_algorithms, } } } @@ -274,15 +266,13 @@ mod server { end_entity: &CertificateDer<'_>, _intermediates: &[CertificateDer<'_>], _now: UnixTime, - ) -> Result { + ) -> Result { let end_entity_as_spki = SubjectPublicKeyInfoDer::from(end_entity.as_ref()); match self .trusted_spki .contains(&end_entity_as_spki) { - false => Err(rustls::Error::InvalidCertificate( - CertificateError::UnknownIssuer, - )), + false => Err(Error::InvalidCertificate(CertificateError::UnknownIssuer)), true => Ok(ClientCertVerified::assertion()), } } @@ -292,10 +282,8 @@ mod server { _message: &[u8], _cert: &CertificateDer<'_>, _dss: &DigitallySignedStruct, - ) -> Result { - Err(rustls::Error::PeerIncompatible( - PeerIncompatible::Tls12NotOffered, - )) + ) -> Result { + Err(Error::PeerIncompatible(PeerIncompatible::Tls12NotOffered)) } fn verify_tls13_signature( @@ -303,7 +291,7 @@ mod server { message: &[u8], cert: &CertificateDer<'_>, dss: &DigitallySignedStruct, - ) -> Result { + ) -> Result { verify_tls13_signature_with_raw_key( message, &SubjectPublicKeyInfoDer::from(cert.as_ref()), diff --git a/openssl-tests/src/utils.rs b/openssl-tests/src/utils.rs index ae16a2bb36a..078613e9f85 100644 --- a/openssl-tests/src/utils.rs +++ b/openssl-tests/src/utils.rs @@ -1,6 +1,6 @@ use once_cell::sync::Lazy; -pub fn verify_openssl3_available() { +pub(crate) fn verify_openssl3_available() { static VERIFIED: Lazy<()> = Lazy::new(verify_openssl3_available_internal); *VERIFIED } @@ -15,11 +15,11 @@ fn verify_openssl3_available_internal() { panic!( "OpenSSL exited with an error status: {}\n{}", output.status, - std::str::from_utf8(&output.stderr).unwrap_or_default() + str::from_utf8(&output.stderr).unwrap_or_default() ); } Ok(output) => { - let version_str = std::str::from_utf8(&output.stdout).unwrap(); + let version_str = str::from_utf8(&output.stdout).unwrap(); let parts = version_str .split(' ') .collect::>(); diff --git a/openssl-tests/src/validate_ffdhe_params.rs b/openssl-tests/src/validate_ffdhe_params.rs index 76bab5471af..d7beafccab2 100644 --- a/openssl-tests/src/validate_ffdhe_params.rs +++ b/openssl-tests/src/validate_ffdhe_params.rs @@ -64,7 +64,7 @@ fn get_ffdhe_params_from_openssl(ffdhe_group: NamedGroup) -> (Vec, Vec) /// Parse PEM-encoded DH parameters, returning `(p, g)` fn parse_dh_params_pem(data: &[u8]) -> (Vec, Vec) { - let output_str = std::str::from_utf8(data).unwrap(); + let output_str = str::from_utf8(data).unwrap(); let output_str_lines = output_str.lines().collect::>(); assert_eq!(output_str_lines[0], "-----BEGIN DH PARAMETERS-----"); @@ -86,10 +86,10 @@ fn parse_dh_params_pem(data: &[u8]) -> (Vec, Vec) { .unwrap(); let res: asn1::ParseResult<_> = asn1::parse(&base64_decoded, |d| { - d.read_element::()? + d.read_element::>()? .parse(|d| { - let p = d.read_element::()?; - let g = d.read_element::()?; + let p = d.read_element::>()?; + let g = d.read_element::>()?; Ok((p, g)) }) }); From 7a65fc62ff0d35905d61b7d418280edadc4dda09 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 21 May 2025 11:06:42 +0100 Subject: [PATCH 231/403] rustfmt: synchronise unstable and stable configs --- .rustfmt.toml | 1 + .rustfmt.unstable.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/.rustfmt.toml b/.rustfmt.toml index c72ffcd3f73..6388c7aeea2 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,2 +1,3 @@ +# keep in sync with .rustfmt.unstable.toml chain_width = 40 style_edition = "2024" diff --git a/.rustfmt.unstable.toml b/.rustfmt.unstable.toml index 521dae776b2..1a3d4f9bb79 100644 --- a/.rustfmt.unstable.toml +++ b/.rustfmt.unstable.toml @@ -1,5 +1,6 @@ # keep in sync with .rustfmt.toml chain_width = 40 +style_edition = "2024" # format imports group_imports = "StdExternalCrate" From 5c96d83b5da97ba500dce2253ffb8fcf7bc3fef5 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 21 May 2025 11:10:15 +0100 Subject: [PATCH 232/403] reformat imports with nightly rustfmt --- ci-bench/src/benchmark.rs | 2 +- rustls-test/src/lib.rs | 14 ++++++-------- rustls/benches/benchmarks.rs | 5 ++--- rustls/src/client/hs.rs | 7 ++----- rustls/src/conn.rs | 3 ++- rustls/src/conn/kernel.rs | 3 +-- rustls/src/crypto/signer.rs | 3 +-- rustls/src/error.rs | 3 ++- rustls/src/lib.rs | 3 +-- rustls/tests/api.rs | 1 - rustls/tests/client_cert_verifier.rs | 1 - rustls/tests/server_cert_verifier.rs | 3 --- 12 files changed, 18 insertions(+), 30 deletions(-) diff --git a/ci-bench/src/benchmark.rs b/ci-bench/src/benchmark.rs index 023e20f67de..1ecea0a7b9e 100644 --- a/ci-bench/src/benchmark.rs +++ b/ci-bench/src/benchmark.rs @@ -2,10 +2,10 @@ use std::sync::Arc; use fxhash::FxHashMap; use itertools::Itertools; +use rustls_test::KeyType; use crate::Side; use crate::callgrind::InstructionCounts; -use rustls_test::KeyType; /// Validates a benchmark collection, returning an error if the provided benchmarks are invalid /// diff --git a/rustls-test/src/lib.rs b/rustls-test/src/lib.rs index 27de79b4803..6713bd9d4d0 100644 --- a/rustls-test/src/lib.rs +++ b/rustls-test/src/lib.rs @@ -16,14 +16,7 @@ use core::ops::DerefMut; use std::io; -use std::sync::Arc; -use std::sync::OnceLock; - -use rustls::pki_types::pem::PemObject; -use rustls::pki_types::{ - CertificateDer, CertificateRevocationListDer, PrivateKeyDer, PrivatePkcs8KeyDer, ServerName, - SubjectPublicKeyInfoDer, UnixTime, -}; +use std::sync::{Arc, OnceLock}; use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; use rustls::client::{ @@ -36,6 +29,11 @@ use rustls::crypto::{ }; use rustls::internal::msgs::codec::{Codec, Reader}; use rustls::internal::msgs::message::{Message, OutboundOpaqueMessage, PlainMessage}; +use rustls::pki_types::pem::PemObject; +use rustls::pki_types::{ + CertificateDer, CertificateRevocationListDer, PrivateKeyDer, PrivatePkcs8KeyDer, ServerName, + SubjectPublicKeyInfoDer, UnixTime, +}; use rustls::server::danger::{ClientCertVerified, ClientCertVerifier}; use rustls::server::{ AlwaysResolvesServerRawPublicKeys, ClientCertVerifierBuilder, UnbufferedServerConnection, diff --git a/rustls/benches/benchmarks.rs b/rustls/benches/benchmarks.rs index 070e6cf8e5d..5aebc995f0c 100644 --- a/rustls/benches/benchmarks.rs +++ b/rustls/benches/benchmarks.rs @@ -1,13 +1,12 @@ #![cfg(feature = "ring")] #![allow(clippy::disallowed_types)] -use bencher::{Bencher, benchmark_group, benchmark_main}; -use rustls::crypto::ring as provider; - 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) { diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index e1ce25454cb..ca6e5efecd0 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -6,10 +6,9 @@ use core::ops::Deref; use pki_types::ServerName; -use super::ResolvesClientCert; -use super::Tls12Resumption; #[cfg(feature = "tls12")] use super::tls12; +use super::{ResolvesClientCert, Tls12Resumption}; use crate::SupportedCipherSuite; #[cfg(feature = "logging")] use crate::bs_debug; @@ -29,12 +28,10 @@ use crate::msgs::base::Payload; use crate::msgs::enums::{ CertificateType, Compression, ECPointFormat, ExtensionType, PskKeyExchangeMode, }; -use crate::msgs::handshake::ProtocolName; -use crate::msgs::handshake::SupportedProtocolVersions; use crate::msgs::handshake::{ CertificateStatusRequest, ClientExtension, ClientHelloPayload, ClientSessionTicket, HandshakeMessagePayload, HandshakePayload, HasServerExtensions, HelloRetryRequest, - KeyShareEntry, Random, SessionId, + KeyShareEntry, ProtocolName, Random, SessionId, SupportedProtocolVersions, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; diff --git a/rustls/src/conn.rs b/rustls/src/conn.rs index 790021bafc5..1d601b04bcf 100644 --- a/rustls/src/conn.rs +++ b/rustls/src/conn.rs @@ -2,10 +2,11 @@ use alloc::boxed::Box; use core::fmt::Debug; use core::mem; use core::ops::{Deref, DerefMut, Range}; -use kernel::KernelConnection; #[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}; diff --git a/rustls/src/conn/kernel.rs b/rustls/src/conn/kernel.rs index f6982ce8857..b90fad390dd 100644 --- a/rustls/src/conn/kernel.rs +++ b/rustls/src/conn/kernel.rs @@ -53,9 +53,8 @@ //! [`CipherSuiteCommon::confidentiality_limit`]: crate::CipherSuiteCommon::confidentiality_limit //! [`KernelConnection`]: crate::kernel::KernelConnection -use core::marker::PhantomData; - use alloc::boxed::Box; +use core::marker::PhantomData; use crate::client::ClientConnectionData; use crate::common_state::Protocol; diff --git a/rustls/src/crypto/signer.rs b/rustls/src/crypto/signer.rs index 77bf402c75f..dbf4224081f 100644 --- a/rustls/src/crypto/signer.rs +++ b/rustls/src/crypto/signer.rs @@ -4,6 +4,7 @@ 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}; @@ -11,8 +12,6 @@ use crate::server::{ClientHello, ParsedCertificate, ResolvesServerCert}; use crate::sync::Arc; use crate::x509; -use super::CryptoProvider; - /// An abstract signing key. /// /// This interface is used by rustls to use a private signing key diff --git a/rustls/src/error.rs b/rustls/src/error.rs index 76569c1d4f8..264f4025fbd 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -950,12 +950,13 @@ mod tests { 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; - use pki_types::ServerName; #[test] fn certificate_error_equality() { diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 1898ba2f40d..fe0fa05f253 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -545,10 +545,9 @@ pub mod unbuffered { // The public interface is: pub use crate::builder::{ConfigBuilder, ConfigSide, WantsVerifier, WantsVersions}; pub use crate::common_state::{CommonState, HandshakeKind, IoState, Side}; -pub use crate::conn::kernel; #[cfg(feature = "std")] pub use crate::conn::{Connection, Reader, Writer}; -pub use crate::conn::{ConnectionCommon, SideData}; +pub use crate::conn::{ConnectionCommon, SideData, kernel}; pub use crate::enums::{ AlertDescription, CertificateCompressionAlgorithm, CipherSuite, ContentType, HandshakeType, ProtocolVersion, SignatureAlgorithm, SignatureScheme, diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 94ee74d11ae..ed199cfdc1e 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -10,7 +10,6 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::{fmt, mem}; use pki_types::{CertificateDer, IpAddr, ServerName, UnixTime}; - use rustls::client::{ResolvesClientCert, Resumption, verify_server_cert_signed_by_trust_anchor}; use rustls::crypto::{ActiveKeyExchange, CryptoProvider, SharedSecret, SupportedKxGroup}; use rustls::internal::msgs::base::Payload; diff --git a/rustls/tests/client_cert_verifier.rs b/rustls/tests/client_cert_verifier.rs index d25dcb3bf03..2ac7461d864 100644 --- a/rustls/tests/client_cert_verifier.rs +++ b/rustls/tests/client_cert_verifier.rs @@ -12,7 +12,6 @@ use common::{ make_client_config_with_versions_with_auth, make_pair_for_arc_configs, server_config_builder, server_name, }; - use rustls::server::danger::ClientCertVerified; use rustls::{ AlertDescription, ClientConnection, Error, InvalidMessage, ServerConfig, ServerConnection, diff --git a/rustls/tests/server_cert_verifier.rs b/rustls/tests/server_cert_verifier.rs index 402ffe551a9..f989f3914c6 100644 --- a/rustls/tests/server_cert_verifier.rs +++ b/rustls/tests/server_cert_verifier.rs @@ -12,9 +12,7 @@ use common::{ do_handshake_until_error, make_client_config_with_versions, make_pair_for_arc_configs, make_server_config, server_config_builder, transfer_altered, }; - use pki_types::{CertificateDer, ServerName}; - use rustls::client::WebPkiServerVerifier; use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; use rustls::internal::msgs::handshake::{ClientExtension, HandshakePayload}; @@ -26,7 +24,6 @@ use rustls::{ AlertDescription, CertificateError, DigitallySignedStruct, DistinguishedName, Error, InvalidMessage, RootCertStore, }; - use x509_parser::prelude::FromDer; use x509_parser::x509::X509Name; From 91e33db8bb124dd8a6ab1b42a16fed18c71d0ee6 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 21 May 2025 13:48:53 +0100 Subject: [PATCH 233/403] ci: use latest nightly for nightly formatting --- .github/workflows/build.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 27f732cd614..f5fba4a5e6c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -445,10 +445,9 @@ jobs: with: persist-credentials: false - name: Install rust nightly toolchain - uses: dtolnay/rust-toolchain@master + uses: dtolnay/rust-toolchain@nightly with: components: rustfmt - toolchain: nightly-2024-02-21 - name: Check formatting (unstable) run: cargo fmt --all -- --check --config-path .rustfmt.unstable.toml continue-on-error: true From b10bb2db22d9408a01b03d3c4bae911c5ca17dc9 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 21 May 2025 14:18:39 +0100 Subject: [PATCH 234/403] Fix prerelease docs publishing The intention is that these appear at https://rustls.dev/docs/ but this was broken in af0229b8e9f4ba759490f69d626d81cbc5a03434 because we stopped copying across all cargo doc's output files. That meant https://rustls.dev/docs/ appeared without its CSS. --- .github/workflows/docs.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 82f7a17d9ac..e937cfed4a5 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -71,7 +71,8 @@ jobs: # lockfile causes deployment step to go wrong, due to permissions rm -f target/doc/.lock # move the result into website root - mv target/doc/rustls target/website/docs + mv target/doc/* target/website/ + mv target/website/rustls target/website/docs - name: Package and upload artifact uses: actions/upload-pages-artifact@v3 From d2fe8ab25e86bc344588f0e43e12965bccbf73da Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 29 Nov 2024 18:20:24 +0000 Subject: [PATCH 235/403] rustls-bench: filter all benches by supported key types --- rustls-bench/src/main.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/rustls-bench/src/main.rs b/rustls-bench/src/main.rs index 50f809116e5..34445ce23a3 100644 --- a/rustls-bench/src/main.rs +++ b/rustls-bench/src/main.rs @@ -51,7 +51,10 @@ pub fn main() { plaintext_size, max_fragment_size, } => { - for bench in lookup_matching_benches(cipher_suite, args.key_type).iter() { + let provider = args + .provider + .unwrap_or_else(Provider::choose_default); + for bench in lookup_matching_benches(cipher_suite, args.key_type, &provider).iter() { bench_bulk( &Parameters::new(bench, &args) .with_plaintext_size(*plaintext_size) @@ -64,8 +67,10 @@ pub fn main() { | Command::HandshakeResume { cipher_suite } | Command::HandshakeTicket { cipher_suite } => { let resume = ResumptionParam::from_subcommand(args.command()); - - for bench in lookup_matching_benches(cipher_suite, args.key_type).iter() { + let provider = args + .provider + .unwrap_or_else(Provider::choose_default); + for bench in lookup_matching_benches(cipher_suite, args.key_type, &provider).iter() { bench_handshake( &Parameters::new(bench, &args) .with_client_auth(ClientAuth::No) @@ -77,7 +82,10 @@ pub fn main() { cipher_suite, count, } => { - for bench in lookup_matching_benches(cipher_suite, args.key_type).iter() { + let provider = args + .provider + .unwrap_or_else(Provider::choose_default); + for bench in lookup_matching_benches(cipher_suite, args.key_type, &provider).iter() { let params = Parameters::new(bench, &args); let client_config = params.client_config(); let server_config = params.server_config(); @@ -686,12 +694,14 @@ fn bench_memory( fn lookup_matching_benches( ciphersuite_name: &str, key_type: Option, + provider: &Provider, ) -> Vec { let r: Vec = ALL_BENCHMARKS .iter() .filter(|params| { format!("{:?}", params.ciphersuite).to_lowercase() == ciphersuite_name.to_lowercase() && (key_type.is_none() || Some(params.key_type) == key_type.map(KeyType::from)) + && provider.supports_benchmark(params) }) .cloned() .collect(); From ca7e2b20e411a41d2c7355138e30db668142b179 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 21 Nov 2024 20:08:00 +0000 Subject: [PATCH 236/403] rustls-bench: support graviola This introduces a patch, so that rustls-bench -> rustls is the same crate as rustls-bench -> rustls-graviola -> rustls. --- Cargo.lock | 64 ++++++++++++++++++++++------------------ Cargo.toml | 6 ++++ rustls-bench/Cargo.toml | 2 ++ rustls-bench/src/main.rs | 17 +++++++++-- 4 files changed, 58 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ee91ef1f793..c89c67280a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -481,7 +481,7 @@ dependencies = [ "base64", "env_logger", "nix", - "rustls 0.23.27", + "rustls", "rustls-post-quantum", ] @@ -1258,6 +1258,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "graviola" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00678994ed89e22df4c4d99e3105b0ae69206d4b9aaeaeec3a52c2bec55c1f01" +dependencies = [ + "cfg-if", + "getrandom 0.3.2", +] + [[package]] name = "group" version = "0.13.0" @@ -1346,7 +1356,7 @@ dependencies = [ "once_cell", "rand 0.9.1", "ring", - "rustls 0.23.27 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls", "thiserror 2.0.12", "tinyvec", "tokio", @@ -1371,7 +1381,7 @@ dependencies = [ "parking_lot", "rand 0.9.1", "resolv-conf", - "rustls 0.23.27 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls", "smallvec", "thiserror 2.0.12", "tokio", @@ -2602,27 +2612,13 @@ dependencies = [ "zlib-rs", ] -[[package]] -name = "rustls" -version = "0.23.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" -dependencies = [ - "aws-lc-rs", - "log", - "once_cell", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - [[package]] name = "rustls-bench" version = "0.1.0" dependencies = [ "clap", - "rustls 0.23.27", + "rustls", + "rustls-graviola", "rustls-post-quantum", "rustls-test", "tikv-jemallocator", @@ -2640,7 +2636,7 @@ dependencies = [ "fxhash", "itertools 0.14.0", "rayon", - "rustls 0.23.27", + "rustls", "rustls-test", "tikv-jemallocator", ] @@ -2652,7 +2648,7 @@ dependencies = [ "hickory-resolver", "regex", "ring", - "rustls 0.23.27", + "rustls", "tokio", ] @@ -2667,7 +2663,7 @@ dependencies = [ "log", "mio", "rcgen", - "rustls 0.23.27", + "rustls", "serde", "tokio", "webpki-roots 1.0.0", @@ -2678,7 +2674,17 @@ name = "rustls-fuzzing-provider" version = "0.1.0" dependencies = [ "env_logger", - "rustls 0.23.27", + "rustls", +] + +[[package]] +name = "rustls-graviola" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51c72f95752eab205ea6e623eb35e14e6767640be83f0d210ba64c76f7105525" +dependencies = [ + "graviola", + "rustls", ] [[package]] @@ -2690,7 +2696,7 @@ dependencies = [ "num-bigint", "once_cell", "openssl", - "rustls 0.23.27", + "rustls", ] [[package]] @@ -2705,7 +2711,7 @@ version = "0.2.2" dependencies = [ "criterion", "env_logger", - "rustls 0.23.27", + "rustls", "webpki-roots 1.0.0", ] @@ -2726,7 +2732,7 @@ dependencies = [ "rand_core 0.6.4", "rcgen", "rsa", - "rustls 0.23.27", + "rustls", "sha2", "signature", "webpki-roots 1.0.0", @@ -2738,7 +2744,7 @@ name = "rustls-provider-test" version = "0.1.0" dependencies = [ "hex", - "rustls 0.23.27", + "rustls", "rustls-provider-example", "serde", "serde_json", @@ -2748,7 +2754,7 @@ dependencies = [ name = "rustls-test" version = "0.1.0" dependencies = [ - "rustls 0.23.27", + "rustls", ] [[package]] @@ -3151,7 +3157,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "rustls 0.23.27 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index 0e3fb6a9a6c..6248d09d964 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,6 +81,7 @@ rcgen = { version = "0.13", features = ["pem", "aws_lc_rs"], default-features = regex = "1" ring = "0.17" rsa = { version = "0.9", features = ["sha2"], default-features = false } +rustls-graviola = { version = "0.2" } rustls-test = { path = "rustls-test/" } serde = { version = "1", features = ["derive"] } serde_json = "1" @@ -100,3 +101,8 @@ zlib-rs = "0.5" [profile.bench] codegen-units = 1 lto = true + +# ensure all our tests are against the local copy, never +# against the latest _published_ copy. +[patch.crates-io] +rustls = { path = "rustls" } diff --git a/rustls-bench/Cargo.toml b/rustls-bench/Cargo.toml index 0b7ff90f7e8..89d8e725369 100644 --- a/rustls-bench/Cargo.toml +++ b/rustls-bench/Cargo.toml @@ -7,6 +7,7 @@ publish = false [dependencies] clap = { workspace = true } rustls = { path = "../rustls" } +rustls-graviola = { workspace = true, optional = true } rustls-post-quantum = { path = "../rustls-post-quantum", optional = true } rustls-test = { workspace = true } @@ -14,6 +15,7 @@ rustls-test = { workspace = true } default = [] aws-lc-rs = ["rustls/aws-lc-rs"] fips = ["rustls/fips", "aws-lc-rs"] +graviola = ["dep:rustls-graviola"] post-quantum = ["dep:rustls-post-quantum"] ring = ["rustls/ring"] diff --git a/rustls-bench/src/main.rs b/rustls-bench/src/main.rs index 34445ce23a3..79a0cff8a20 100644 --- a/rustls-bench/src/main.rs +++ b/rustls-bench/src/main.rs @@ -954,6 +954,8 @@ enum Provider { AwsLcRs, #[cfg(all(feature = "aws-lc-rs", feature = "fips"))] AwsLcRsFips, + #[cfg(feature = "graviola")] + Graviola, #[cfg(feature = "post-quantum")] PostQuantum, #[cfg(feature = "ring")] @@ -969,6 +971,8 @@ impl Provider { Self::AwsLcRs => rustls::crypto::aws_lc_rs::default_provider(), #[cfg(all(feature = "aws-lc-rs", feature = "fips"))] Self::AwsLcRsFips => rustls::crypto::default_fips_provider(), + #[cfg(feature = "graviola")] + Self::Graviola => rustls_graviola::default_provider(), #[cfg(feature = "post-quantum")] Self::PostQuantum => rustls_post_quantum::provider(), #[cfg(feature = "ring")] @@ -983,6 +987,8 @@ impl Provider { Self::AwsLcRs => rustls::crypto::aws_lc_rs::Ticketer::new(), #[cfg(all(feature = "aws-lc-rs", feature = "fips"))] Self::AwsLcRsFips => rustls::crypto::aws_lc_rs::Ticketer::new(), + #[cfg(feature = "graviola")] + Self::Graviola => rustls_graviola::Ticketer::new(), #[cfg(feature = "post-quantum")] Self::PostQuantum => rustls::crypto::aws_lc_rs::Ticketer::new(), #[cfg(feature = "ring")] @@ -1007,8 +1013,12 @@ impl Provider { } fn supports_key_type(&self, _key_type: KeyType) -> bool { - // currently all providers support all key types - true + match self { + #[cfg(feature = "graviola")] + Self::Graviola => !matches!(_key_type, KeyType::Ed25519), + // all other providers support all key types + _ => true, + } } fn choose_default() -> Self { @@ -1021,6 +1031,9 @@ impl Provider { #[cfg(all(feature = "aws-lc-rs", feature = "fips"))] available.push(Self::AwsLcRsFips); + #[cfg(feature = "graviola")] + available.push(Self::Graviola); + #[cfg(feature = "post-quantum")] available.push(Self::PostQuantum); From 79677ced0fb9dc5d85e1c0bee8ec16d182ceb91f Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 22 May 2025 12:29:21 +0100 Subject: [PATCH 237/403] README.md: add graviola to providers, and sort --- README.md | 7 +++++-- rustls/src/lib.rs | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f467d715cb7..5b8f012443b 100644 --- a/README.md +++ b/README.md @@ -90,15 +90,18 @@ selected. The community has also started developing third-party providers for Rustls: -* [`rustls-mbedtls-provider`] - a provider that uses [`mbedtls`] for cryptography. -* [`rustls-openssl`] - a provider that uses [OpenSSL] for cryptography. * [`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 diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index fe0fa05f253..72cd3128107 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -56,15 +56,18 @@ //! //! The community has also started developing third-party providers for Rustls: //! -//! * [`rustls-mbedtls-provider`] - a provider that uses [`mbedtls`] for cryptography. -//! * [`rustls-openssl`] - a provider that uses [OpenSSL] for cryptography. //! * [`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 From 9b8f2541e8455dbafc30b860f80df0c2b0efbc84 Mon Sep 17 00:00:00 2001 From: Christopher Patton Date: Fri, 23 May 2025 12:44:04 -0700 Subject: [PATCH 238/403] Fix bug in crypto::aws_lc_rs::pq::hybrid::Layout The share splitter function swaps the order of the shares whenever `post_quantum_first` is `true`. --- rustls/src/crypto/aws_lc_rs/pq/hybrid.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/rustls/src/crypto/aws_lc_rs/pq/hybrid.rs b/rustls/src/crypto/aws_lc_rs/pq/hybrid.rs index 2611bc9085f..8e30d782edc 100644 --- a/rustls/src/crypto/aws_lc_rs/pq/hybrid.rs +++ b/rustls/src/crypto/aws_lc_rs/pq/hybrid.rs @@ -174,6 +174,7 @@ impl Layout { 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], @@ -184,8 +185,14 @@ impl Layout { } Some(match self.post_quantum_first { - true => share.split_at(post_quantum_share_len), - false => share.split_at(self.classical_share_len), + 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) + } }) } From b2e9c2c020b058943a08c03bfc84c81d2bb9e6b2 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 26 May 2025 15:18:56 +0100 Subject: [PATCH 239/403] Implement `SECP256R1MLKEM768` hybrid --- rustls/src/crypto/aws_lc_rs/mod.rs | 6 +++++- rustls/src/crypto/aws_lc_rs/pq/mod.rs | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/rustls/src/crypto/aws_lc_rs/mod.rs b/rustls/src/crypto/aws_lc_rs/mod.rs index fe631bfc9f7..6795db5d558 100644 --- a/rustls/src/crypto/aws_lc_rs/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/mod.rs @@ -229,7 +229,7 @@ static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms /// [`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, X25519MLKEM768}; + pub use super::pq::{MLKEM768, SECP256R1MLKEM768, X25519MLKEM768}; } /// A list of the default key exchange groups supported by this provider. @@ -250,11 +250,15 @@ pub static DEFAULT_KX_GROUPS: &[&dyn SupportedKxGroup] = &[ 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, ]; diff --git a/rustls/src/crypto/aws_lc_rs/pq/mod.rs b/rustls/src/crypto/aws_lc_rs/pq/mod.rs index ecb5ab3bf83..a2252da506b 100644 --- a/rustls/src/crypto/aws_lc_rs/pq/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/pq/mod.rs @@ -20,6 +20,21 @@ pub static X25519MLKEM768: &dyn SupportedKxGroup = &hybrid::Hybrid { }, }; +/// This is the [SECP256R1MLKEM768] key exchange. +/// +/// [SECP256R1MLKEM768]: +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 @@ -28,5 +43,6 @@ 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; From d4972194f2829e90304040aa991416580d0a45f0 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 26 May 2025 15:41:32 +0100 Subject: [PATCH 240/403] tlsclient-mio: add option to customise key exchanges --- examples/src/bin/tlsclient-mio.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/examples/src/bin/tlsclient-mio.rs b/examples/src/bin/tlsclient-mio.rs index 2aa20752480..0023e6f4ccd 100644 --- a/examples/src/bin/tlsclient-mio.rs +++ b/examples/src/bin/tlsclient-mio.rs @@ -27,7 +27,7 @@ use std::{process, str}; use clap::Parser; use mio::net::TcpStream; use rustls::RootCertStore; -use rustls::crypto::{CryptoProvider, aws_lc_rs as provider}; +use rustls::crypto::{CryptoProvider, SupportedKxGroup, aws_lc_rs as provider}; use rustls::pki_types::pem::PemObject; use rustls::pki_types::{CertificateDer, PrivateKeyDer, ServerName}; @@ -232,6 +232,10 @@ struct Args { #[clap(long)] suite: Vec, + /// Disable default key exchange list, and use KX instead. Maybe be used multiple times. + #[clap(long)] + key_exchange: Vec, + /// Send ALPN extension containing PROTOCOL. /// May be used multiple times to offer several protocols. #[clap(long)] @@ -283,6 +287,19 @@ fn find_suite(name: &str) -> Option { None } +/// Find a key exchange with the given name +fn find_key_exchange(name: &str) -> &'static dyn SupportedKxGroup { + for kx_group in provider::ALL_KX_GROUPS { + let kx_name = format!("{:?}", kx_group.name()).to_lowercase(); + + if kx_name == name.to_string().to_lowercase() { + return *kx_group; + } + } + + panic!("cannot find key exchange with name '{name}'"); +} + /// Make a vector of ciphersuites named in `suites` fn lookup_suites(suites: &[String]) -> Vec { let mut out = Vec::new(); @@ -412,6 +429,14 @@ fn make_config(args: &Args) -> Arc { provider::DEFAULT_CIPHER_SUITES.to_vec() }; + let kx_groups = match args.key_exchange.as_slice() { + [] => provider::DEFAULT_KX_GROUPS.to_vec(), + items => items + .iter() + .map(|kx| find_key_exchange(kx)) + .collect::>(), + }; + let versions = if !args.protover.is_empty() { lookup_versions(&args.protover) } else { @@ -421,6 +446,7 @@ fn make_config(args: &Args) -> Arc { let config = rustls::ClientConfig::builder_with_provider( CryptoProvider { cipher_suites: suites, + kx_groups, ..provider::default_provider() } .into(), From 29ea6ce74ebcaed5dce7593c4fe8568293e0a3f3 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 26 May 2025 15:49:13 +0100 Subject: [PATCH 241/403] ci: quick interop test for secp256r1mlkem768 --- .github/workflows/daily-tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/daily-tests.yml b/.github/workflows/daily-tests.yml index f3f52c1c66b..20f88d5bd77 100644 --- a/.github/workflows/daily-tests.yml +++ b/.github/workflows/daily-tests.yml @@ -131,6 +131,8 @@ jobs: - name: Check rustls-post-quantum client run: cargo run --locked -p rustls-post-quantum --example client | grep 'kex=X25519MLKEM768' + - name: Smoke test for secp256r1mlkem768 interop + run: cargo run --locked -p rustls-examples --bin tlsclient-mio -- --http --key-exchange secp256r1mlkem768 --verbose openquantumsafe.org feature-powerset: name: Feature Powerset From 75f94f029eb78821ec921821de11c1893d8230f1 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 26 May 2025 16:25:16 +0100 Subject: [PATCH 242/403] Exercise each of `ALL_KX_GROUPS` against itself "Exercise" is used pointedly here to avoid suggestion that this is a meaningful test. --- rustls/tests/api.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index ed199cfdc1e..c34d608be6c 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -5871,6 +5871,26 @@ fn test_client_config_keyshare_mismatch() { assert!(do_handshake_until_error(&mut client, &mut server).is_err()); } +#[test] +fn exercise_all_key_exchange_methods() { + for version in rustls::ALL_VERSIONS { + for kx_group in provider::ALL_KX_GROUPS { + if !kx_group.usable_for_version(version.version) { + continue; + } + + let provider = provider::default_provider(); + let client_config = + make_client_config_with_kx_groups(KeyType::Rsa2048, vec![*kx_group], &provider); + let server_config = + make_server_config_with_kx_groups(KeyType::Rsa2048, vec![*kx_group], &provider); + let (mut client, mut server) = make_pair_for_configs(client_config, server_config); + assert!(do_handshake_until_error(&mut client, &mut server).is_ok()); + println!("kx_group {:?} is self-consistent", kx_group.name()); + } + } +} + #[cfg(feature = "tls12")] #[test] fn test_client_sends_helloretryrequest() { From 0987991eb3c19a1290ecb211a1105e7678cc6b25 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 23 May 2025 14:14:44 +0100 Subject: [PATCH 243/403] Convert `test_client_does_not_offer_sha1` into a unit test --- rustls/src/client/test.rs | 19 ++++++++++++++++++ rustls/tests/api.rs | 42 --------------------------------------- 2 files changed, 19 insertions(+), 42 deletions(-) diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs index dbe68d26c8b..e1ed36dcb29 100644 --- a/rustls/src/client/test.rs +++ b/rustls/src/client/test.rs @@ -4,6 +4,7 @@ use std::prelude::v1::*; use pki_types::{CertificateDer, ServerName}; use crate::client::{ClientConfig, ClientConnection, Resumption, Tls12Resumption}; +use crate::enums::SignatureScheme; use crate::msgs::codec::Reader; use crate::msgs::handshake::{ClientHelloPayload, HandshakeMessagePayload, HandshakePayload}; use crate::msgs::message::{Message, MessagePayload, OutboundOpaqueMessage}; @@ -29,6 +30,24 @@ mod tests { let ch = client_hello_sent_for_config(config).unwrap(); assert!(ch.ticket_extension().is_none()); } + + #[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(); + let sigalgs = ch.sigalgs_extension().unwrap(); + assert!( + !sigalgs.contains(&SignatureScheme::RSA_PKCS1_SHA1), + "sha1 unexpectedly offered" + ); + } + } } fn client_hello_sent_for_config(config: ClientConfig) -> Result { diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index c34d608be6c..a0f60c478f3 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -5801,48 +5801,6 @@ mod test_quic { } } // mod test_quic -#[test] -fn test_client_does_not_offer_sha1() { - use rustls::HandshakeType; - use rustls::internal::msgs::codec::Reader; - use rustls::internal::msgs::handshake::HandshakePayload; - use rustls::internal::msgs::message::{MessagePayload, OutboundOpaqueMessage}; - - let provider = provider::default_provider(); - for kt in KeyType::all_for_provider(&provider) { - for version in rustls::ALL_VERSIONS { - let client_config = make_client_config_with_versions(*kt, &[version], &provider); - let (mut client, _) = - make_pair_for_configs(client_config, make_server_config(*kt, &provider)); - - assert!(client.wants_write()); - let mut buf = [0u8; 262144]; - let sz = client - .write_tls(&mut buf.as_mut()) - .unwrap(); - let msg = OutboundOpaqueMessage::read(&mut Reader::init(&buf[..sz])).unwrap(); - let msg = Message::try_from(msg.into_plain_message()).unwrap(); - assert!(msg.is_handshake_type(HandshakeType::ClientHello)); - - let client_hello = match msg.payload { - MessagePayload::Handshake { parsed, .. } => match parsed.payload { - HandshakePayload::ClientHello(ch) => ch, - _ => unreachable!(), - }, - _ => unreachable!(), - }; - - let sigalgs = client_hello - .sigalgs_extension() - .unwrap(); - assert!( - !sigalgs.contains(&SignatureScheme::RSA_PKCS1_SHA1), - "sha1 unexpectedly offered" - ); - } - } -} - #[test] fn test_client_config_keyshare() { let provider = provider::default_provider(); From cd950922fc65af0f9c9c605568c46d95406209bb Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 23 May 2025 15:13:01 +0100 Subject: [PATCH 244/403] Convert `test_client_rejects_hrr_with_varied_session_id` into unit test --- rustls/src/client/test.rs | 51 +++++++++++++++++++-- rustls/src/msgs/message/mod.rs | 7 +++ rustls/src/msgs/message_test.rs | 9 ++++ rustls/tests/api.rs | 78 --------------------------------- 4 files changed, 63 insertions(+), 82 deletions(-) diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs index e1ed36dcb29..5c5e07d9004 100644 --- a/rustls/src/client/test.rs +++ b/rustls/src/client/test.rs @@ -1,14 +1,19 @@ #![cfg(any(feature = "ring", feature = "aws_lc_rs"))] use std::prelude::v1::*; +use std::vec; use pki_types::{CertificateDer, ServerName}; use crate::client::{ClientConfig, ClientConnection, Resumption, Tls12Resumption}; -use crate::enums::SignatureScheme; +use crate::enums::{CipherSuite, HandshakeType, ProtocolVersion, SignatureScheme}; +use crate::msgs::base::PayloadU16; use crate::msgs::codec::Reader; -use crate::msgs::handshake::{ClientHelloPayload, HandshakeMessagePayload, HandshakePayload}; -use crate::msgs::message::{Message, MessagePayload, OutboundOpaqueMessage}; -use crate::{Error, RootCertStore}; +use crate::msgs::handshake::{ + ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, HelloRetryExtension, + HelloRetryRequest, SessionId, +}; +use crate::msgs::message::{Message, MessagePayload, OutboundOpaqueMessage, PlainMessage}; +use crate::{Error, PeerMisbehaved, RootCertStore}; #[macro_rules_attribute::apply(test_for_each_provider)] mod tests { @@ -48,6 +53,44 @@ mod tests { ); } } + + #[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 { + typ: HandshakeType::HelloRetryRequest, + payload: HandshakePayload::HelloRetryRequest(HelloRetryRequest { + cipher_suite: CipherSuite::TLS13_AES_128_GCM_SHA256, + legacy_version: ProtocolVersion::TLSv1_2, + session_id: SessionId::empty(), + extensions: vec![HelloRetryExtension::Cookie(PayloadU16::new(vec![ + 1, 2, 3, 4, + ]))], + }), + }), + }; + + conn.read_tls(&mut hrr.into_wire_bytes().as_slice()) + .unwrap(); + assert_eq!( + conn.process_new_packets().unwrap_err(), + PeerMisbehaved::IllegalHelloRetryRequestWithWrongSessionId.into() + ); + } } fn client_hello_sent_for_config(config: ClientConfig) -> Result { diff --git a/rustls/src/msgs/message/mod.rs b/rustls/src/msgs/message/mod.rs index aeb35c850c1..2a8e1112c22 100644 --- a/rustls/src/msgs/message/mod.rs +++ b/rustls/src/msgs/message/mod.rs @@ -206,6 +206,13 @@ impl Message<'_> { payload: payload.into_owned(), } } + + #[cfg(test)] + pub(crate) fn into_wire_bytes(self) -> Vec { + PlainMessage::from(self) + .into_unencrypted_opaque() + .encode() + } } impl TryFrom for Message<'static> { diff --git a/rustls/src/msgs/message_test.rs b/rustls/src/msgs/message_test.rs index 013f41eb565..965a3572e00 100644 --- a/rustls/src/msgs/message_test.rs +++ b/rustls/src/msgs/message_test.rs @@ -113,3 +113,12 @@ fn debug_payload() { 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/rustls/tests/api.rs b/rustls/tests/api.rs index a0f60c478f3..b47b2ff4dad 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -5971,84 +5971,6 @@ fn test_client_sends_helloretryrequest() { )); } -#[test] -fn test_client_rejects_hrr_with_varied_session_id() { - use rustls::internal::msgs::handshake::SessionId; - let different_session_id = - SessionId::random(provider::default_provider().secure_random).unwrap(); - - let assert_client_sends_hello_with_secp384 = |msg: &mut Message| -> Altered { - match &mut msg.payload { - MessagePayload::Handshake { parsed, encoded } => match &mut parsed.payload { - HandshakePayload::ClientHello(ch) => { - let keyshares = ch - .keyshare_extension() - .expect("missing key share extension"); - assert_eq!(keyshares.len(), 1); - assert_eq!(keyshares[0].group(), rustls::NamedGroup::secp384r1); - - ch.session_id = different_session_id; - *encoded = Payload::new(parsed.get_encoding()); - } - _ => panic!("unexpected handshake message {parsed:?}"), - }, - _ => panic!("unexpected non-handshake message {msg:?}"), - }; - Altered::InPlace - }; - - let assert_server_requests_retry_and_echoes_session_id = |msg: &mut Message| -> Altered { - match &msg.payload { - MessagePayload::Handshake { parsed, .. } => match &parsed.payload { - HandshakePayload::HelloRetryRequest(hrr) => { - let group = hrr.requested_key_share_group(); - assert_eq!(group, Some(rustls::NamedGroup::X25519)); - - assert_eq!(hrr.session_id, different_session_id); - } - _ => panic!("unexpected handshake message {parsed:?}"), - }, - MessagePayload::ChangeCipherSpec(_) => (), - _ => panic!("unexpected non-handshake message {msg:?}"), - }; - Altered::InPlace - }; - - // client prefers a secp384r1 key share, server only accepts x25519 - let provider = provider::default_provider(); - let client_config = make_client_config_with_kx_groups( - KeyType::Rsa2048, - vec![provider::kx_group::SECP384R1, provider::kx_group::X25519], - &provider, - ); - - let server_config = make_server_config_with_kx_groups( - KeyType::Rsa2048, - vec![provider::kx_group::X25519], - &provider, - ); - - let (client, server) = make_pair_for_configs(client_config, server_config); - let (mut client, mut server) = (client.into(), server.into()); - transfer_altered( - &mut client, - assert_client_sends_hello_with_secp384, - &mut server, - ); - server.process_new_packets().unwrap(); - transfer_altered( - &mut server, - assert_server_requests_retry_and_echoes_session_id, - &mut client, - ); - assert_eq!( - client.process_new_packets(), - Err(Error::PeerMisbehaved( - PeerMisbehaved::IllegalHelloRetryRequestWithWrongSessionId - )) - ); -} - #[cfg(feature = "tls12")] #[test] fn test_client_attempts_to_use_unsupported_kx_group() { From e1579fe10ea49ed0f98e1c59cb5db96bbc99874e Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 23 May 2025 15:21:42 +0100 Subject: [PATCH 245/403] Simplify `test_client_sends_share_for_less_preferred_group` --- rustls/tests/api.rs | 63 +++++++++++++-------------------------------- 1 file changed, 18 insertions(+), 45 deletions(-) diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index b47b2ff4dad..cba5120282a 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -6065,6 +6065,13 @@ fn test_client_sends_share_for_less_preferred_group() { // first handshake let (mut client_1, mut server) = make_pair_for_configs(client_config_1, server_config.clone()); do_handshake_until_error(&mut client_1, &mut server).unwrap(); + assert_eq!( + client_1 + .negotiated_key_exchange_group() + .map(|kxg| kxg.name()), + Some(NamedGroup::secp384r1) + ); + assert_eq!(client_1.handshake_kind(), Some(HandshakeKind::Full)); let ops = shared_storage.ops(); println!("storage {ops:#?}"); @@ -6074,53 +6081,19 @@ fn test_client_sends_share_for_less_preferred_group() { ClientStorageOp::SetKxHint(_, rustls::NamedGroup::secp384r1) )); - // second handshake (this must HRR to the most-preferred group) - let assert_client_sends_secp384_share = |msg: &mut Message| -> Altered { - match &msg.payload { - MessagePayload::Handshake { parsed, .. } => match &parsed.payload { - HandshakePayload::ClientHello(ch) => { - let keyshares = ch - .keyshare_extension() - .expect("missing key share extension"); - assert_eq!(keyshares.len(), 1); - assert_eq!(keyshares[0].group(), rustls::NamedGroup::secp384r1); - } - _ => panic!("unexpected handshake message {parsed:?}"), - }, - _ => panic!("unexpected non-handshake message {msg:?}"), - }; - Altered::InPlace - }; - - let assert_server_requests_retry_to_x25519 = |msg: &mut Message| -> Altered { - match &msg.payload { - MessagePayload::Handshake { parsed, .. } => match &parsed.payload { - HandshakePayload::HelloRetryRequest(hrr) => { - let group = hrr.requested_key_share_group(); - assert_eq!(group, Some(rustls::NamedGroup::X25519)); - } - _ => panic!("unexpected handshake message {parsed:?}"), - }, - MessagePayload::ChangeCipherSpec(_) => (), - _ => panic!("unexpected non-handshake message {msg:?}"), - }; - Altered::InPlace - }; - - let (client_2, server) = make_pair_for_configs(client_config_2, server_config); - let (mut client_2, mut server) = (client_2.into(), server.into()); - transfer_altered( - &mut client_2, - assert_client_sends_secp384_share, - &mut server, + // second handshake; HRR'd from secp384r1 to X25519 + let (mut client_2, mut server) = make_pair_for_configs(client_config_2, server_config); + do_handshake(&mut client_2, &mut server); + assert_eq!( + client_2 + .negotiated_key_exchange_group() + .map(|kxg| kxg.name()), + Some(NamedGroup::X25519) ); - server.process_new_packets().unwrap(); - transfer_altered( - &mut server, - assert_server_requests_retry_to_x25519, - &mut client_2, + assert_eq!( + client_2.handshake_kind(), + Some(HandshakeKind::FullWithHelloRetryRequest) ); - client_2.process_new_packets().unwrap(); } #[cfg(feature = "tls12")] From fd9078086431e759bd6beba0374ddbae0ee695a7 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 23 May 2025 16:02:58 +0100 Subject: [PATCH 246/403] Convert `test_client_rejects_no_extended_master_secret(...)` to unit test --- rustls/src/client/test.rs | 55 ++++++++++++++++++++++++++++++++++++--- rustls/tests/api.rs | 29 --------------------- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs index 5c5e07d9004..270e176f2c6 100644 --- a/rustls/src/client/test.rs +++ b/rustls/src/client/test.rs @@ -8,12 +8,14 @@ use crate::client::{ClientConfig, ClientConnection, Resumption, Tls12Resumption} use crate::enums::{CipherSuite, HandshakeType, ProtocolVersion, SignatureScheme}; use crate::msgs::base::PayloadU16; use crate::msgs::codec::Reader; +use crate::msgs::enums::Compression; use crate::msgs::handshake::{ ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, HelloRetryExtension, - HelloRetryRequest, SessionId, + HelloRetryRequest, Random, ServerHelloPayload, SessionId, }; -use crate::msgs::message::{Message, MessagePayload, OutboundOpaqueMessage, PlainMessage}; -use crate::{Error, PeerMisbehaved, RootCertStore}; +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 { @@ -91,6 +93,53 @@ mod tests { 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( + Arc::clone(&config), + 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 { + typ: HandshakeType::ServerHello, + payload: 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: vec![], + }), + }), + }; + conn.read_tls(&mut sh.into_wire_bytes().as_slice()) + .unwrap(); + + assert_eq!( + conn.process_new_packets(), + Err(PeerIncompatible::ExtendedMasterSecretExtensionRequired.into()) + ); + } } fn client_hello_sent_for_config(config: ClientConfig) -> Result { diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index cba5120282a..9b7bc1b5239 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -6429,35 +6429,6 @@ fn test_client_rejects_illegal_tls13_ccs() { ); } -#[cfg(feature = "tls12")] -#[test] -fn test_client_rejects_no_extended_master_secret_extension_when_require_ems_or_fips() { - let key_type = KeyType::Rsa2048; - let provider = provider::default_provider(); - let mut client_config = make_client_config(key_type, &provider); - if provider_is_fips() { - assert!(client_config.require_ems); - } else { - client_config.require_ems = true; - } - let mut server_config = finish_server_config( - key_type, - server_config_builder_with_versions(&[&rustls::version::TLS12], &provider), - ); - server_config.require_ems = false; - let (client, server) = make_pair_for_configs(client_config, server_config); - let (mut client, mut server) = (client.into(), server.into()); - transfer_altered(&mut client, remove_ems_request, &mut server); - server.process_new_packets().unwrap(); - transfer_altered(&mut server, |_| Altered::InPlace, &mut client); - assert_eq!( - client.process_new_packets(), - Err(Error::PeerIncompatible( - PeerIncompatible::ExtendedMasterSecretExtensionRequired - )) - ); -} - #[cfg(feature = "tls12")] #[test] fn test_server_rejects_no_extended_master_secret_extension_when_require_ems_or_fips() { From 6e0aef63e439c3c3d8e11fd4bfdcdcade5ceda42 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 23 May 2025 16:49:08 +0100 Subject: [PATCH 247/403] Convert `test_server_rejects_no_extended_master_secret(...)` to unit test --- rustls/src/server/test.rs | 71 +++++++++++++++++++++++++++++++++++++-- rustls/tests/api.rs | 40 ---------------------- 2 files changed, 68 insertions(+), 43 deletions(-) diff --git a/rustls/src/server/test.rs b/rustls/src/server/test.rs index 52ea61316e2..07b14a1a12b 100644 --- a/rustls/src/server/test.rs +++ b/rustls/src/server/test.rs @@ -3,8 +3,9 @@ use std::vec; use super::ServerConnectionData; use crate::common_state::Context; +use crate::enums::{CipherSuite, SignatureScheme}; use crate::msgs::codec::{Codec, LengthPrefixedBuffer, ListLength}; -use crate::msgs::enums::{Compression, ExtensionType}; +use crate::msgs::enums::{Compression, ExtensionType, NamedGroup}; use crate::msgs::handshake::{ ClientExtension, ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, Random, SessionId, @@ -66,14 +67,78 @@ fn test_process_client_hello(hello: ClientHelloPayload) -> Result<(), Error> { .map(|_| ()) } +#[macro_rules_attribute::apply(test_for_each_provider)] +mod tests { + use super::super::*; + use crate::pki_types::pem::PemObject; + use crate::pki_types::{CertificateDer, PrivateKeyDer}; + use crate::server::{ServerConfig, ServerConnection}; + use crate::sync::Arc; + use crate::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 config = config.into(); + let mut conn = ServerConnection::new(Arc::clone(&config)).unwrap(); + + let sh = Message { + version: ProtocolVersion::TLSv1_3, + payload: MessagePayload::handshake(HandshakeMessagePayload { + typ: HandshakeType::ClientHello, + payload: HandshakePayload::ClientHello(minimal_client_hello()), + }), + }; + conn.read_tls(&mut sh.into_wire_bytes().as_slice()) + .unwrap(); + + assert_eq!( + conn.process_new_packets(), + Err(Error::PeerIncompatible( + PeerIncompatible::ExtendedMasterSecretExtensionRequired + )) + ); + } + + 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> { + vec![ + CertificateDer::from(&include_bytes!("../../../test-ca/rsa-2048/end.der")[..]), + CertificateDer::from(&include_bytes!("../../../test-ca/rsa-2048/inter.der")[..]), + ] + } +} + fn minimal_client_hello() -> ClientHelloPayload { ClientHelloPayload { client_version: ProtocolVersion::TLSv1_3, random: Random::from([0u8; 32]), session_id: SessionId::empty(), - cipher_suites: vec![], + cipher_suites: vec![CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256], compression_methods: vec![Compression::Null], - extensions: vec![ClientExtension::SignatureAlgorithms(vec![])], + extensions: vec![ + ClientExtension::SignatureAlgorithms(vec![SignatureScheme::RSA_PSS_SHA256]), + ClientExtension::NamedGroups(vec![NamedGroup::X25519, NamedGroup::secp256r1]), + ], } } diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 9b7bc1b5239..67b9c5fc28f 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -6429,46 +6429,6 @@ fn test_client_rejects_illegal_tls13_ccs() { ); } -#[cfg(feature = "tls12")] -#[test] -fn test_server_rejects_no_extended_master_secret_extension_when_require_ems_or_fips() { - let key_type = KeyType::Rsa2048; - let provider = provider::default_provider(); - let client_config = make_client_config(key_type, &provider); - let mut server_config = finish_server_config( - key_type, - server_config_builder_with_versions(&[&rustls::version::TLS12], &provider), - ); - if provider_is_fips() { - assert!(server_config.require_ems); - } else { - server_config.require_ems = true; - } - let (client, server) = make_pair_for_configs(client_config, server_config); - let (mut client, mut server) = (client.into(), server.into()); - transfer_altered(&mut client, remove_ems_request, &mut server); - assert_eq!( - server.process_new_packets(), - Err(Error::PeerIncompatible( - PeerIncompatible::ExtendedMasterSecretExtensionRequired - )) - ); -} - -#[cfg(feature = "tls12")] -fn remove_ems_request(msg: &mut Message) -> Altered { - if let MessagePayload::Handshake { parsed, encoded } = &mut msg.payload { - if let HandshakePayload::ClientHello(ch) = &mut parsed.payload { - ch.extensions - .retain(|ext| !matches!(ext, ClientExtension::ExtendedMasterSecretRequest)) - } - - *encoded = Payload::new(parsed.get_encoding()); - } - - Altered::InPlace -} - /// https://github.com/rustls/rustls/issues/797 #[cfg(feature = "tls12")] #[test] From c1c420a08b455dbcff12a311676911a7dde7d5c2 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 23 May 2025 17:04:37 +0100 Subject: [PATCH 248/403] Convert `hybrid_kx_component_share_offered_if_supported_seperately` to unit test --- rustls/src/client/test.rs | 25 ++++++++++++++++++++- rustls/tests/api.rs | 46 --------------------------------------- 2 files changed, 24 insertions(+), 47 deletions(-) diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs index 270e176f2c6..39ba9fe9927 100644 --- a/rustls/src/client/test.rs +++ b/rustls/src/client/test.rs @@ -8,7 +8,7 @@ use crate::client::{ClientConfig, ClientConnection, Resumption, Tls12Resumption} use crate::enums::{CipherSuite, HandshakeType, ProtocolVersion, SignatureScheme}; use crate::msgs::base::PayloadU16; use crate::msgs::codec::Reader; -use crate::msgs::enums::Compression; +use crate::msgs::enums::{Compression, NamedGroup}; use crate::msgs::handshake::{ ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, HelloRetryExtension, HelloRetryRequest, Random, ServerHelloPayload, SessionId, @@ -142,6 +142,29 @@ mod tests { } } +// 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.keyshare_extension().unwrap(); + assert_eq!(key_shares.len(), 2); + assert_eq!(key_shares[0].group, NamedGroup::X25519MLKEM768); + assert_eq!(key_shares[1].group, NamedGroup::X25519); +} + fn client_hello_sent_for_config(config: ClientConfig) -> Result { let mut conn = ClientConnection::new(config.into(), ServerName::try_from("localhost").unwrap())?; diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 67b9c5fc28f..b5e34c10b93 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -8276,32 +8276,6 @@ fn large_client_hello_acceptor() { } } -#[test] -fn hybrid_kx_component_share_offered_if_supported_seperately() { - let kt = KeyType::Rsa2048; - let client_config = finish_client_config( - kt, - ClientConfig::builder_with_provider( - CryptoProvider { - kx_groups: vec![&FakeHybrid, provider::kx_group::SECP384R1], - ..provider::default_provider() - } - .into(), - ) - .with_safe_default_protocol_versions() - .unwrap(), - ); - let server_config = make_server_config(kt, &provider::default_provider()); - - let (client, server) = make_pair_for_configs(client_config, server_config); - let (mut client, mut server) = (client.into(), server.into()); - transfer_altered( - &mut client, - assert_client_sends_hello_with_two_key_shares, - &mut server, - ); -} - #[test] fn hybrid_kx_component_share_not_offered_unless_supported_seperately() { let kt = KeyType::Rsa2048; @@ -8394,26 +8368,6 @@ impl ActiveKeyExchange for FakeHybridActive { } } -fn assert_client_sends_hello_with_two_key_shares(msg: &mut Message) -> Altered { - match &mut msg.payload { - MessagePayload::Handshake { parsed, .. } => match &mut parsed.payload { - HandshakePayload::ClientHello(ch) => { - let keyshares = ch - .keyshare_extension() - .expect("missing key share extension"); - assert_eq!(keyshares.len(), 2); - assert_eq!(keyshares[0].group(), FakeHybrid.name()); - assert_eq!(keyshares[0].get_encoding(), b"\x12\x34\x00\x06hybrid"); - assert_eq!(keyshares[1].group(), NamedGroup::secp384r1); - assert_eq!(keyshares[1].get_encoding(), b"\x00\x18\x00\x09classical"); - } - _ => panic!("unexpected handshake message {parsed:?}"), - }, - _ => panic!("unexpected non-handshake message {msg:?}"), - }; - Altered::InPlace -} - fn assert_client_sends_hello_with_one_hybrid_key_share(msg: &mut Message) -> Altered { match &mut msg.payload { MessagePayload::Handshake { parsed, .. } => match &mut parsed.payload { From 6ad4df5e00bb308584f4769380388b832cef2b60 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 23 May 2025 17:12:56 +0100 Subject: [PATCH 249/403] Convert `hybrid_kx_component_share_not_offered_unless_supported_seperately` to unit test --- rustls/src/client/test.rs | 23 ++++++++++++++++++++ rustls/tests/api.rs | 44 --------------------------------------- 2 files changed, 23 insertions(+), 44 deletions(-) diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs index 39ba9fe9927..b61d909f927 100644 --- a/rustls/src/client/test.rs +++ b/rustls/src/client/test.rs @@ -5,6 +5,7 @@ use std::vec; use pki_types::{CertificateDer, ServerName}; use crate::client::{ClientConfig, ClientConnection, Resumption, Tls12Resumption}; +use crate::crypto::CryptoProvider; use crate::enums::{CipherSuite, HandshakeType, ProtocolVersion, SignatureScheme}; use crate::msgs::base::PayloadU16; use crate::msgs::codec::Reader; @@ -165,6 +166,28 @@ fn hybrid_kx_component_share_offered_if_supported_separately() { 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.keyshare_extension().unwrap(); + assert_eq!(key_shares.len(), 1); + assert_eq!(key_shares[0].group, NamedGroup::X25519MLKEM768); +} + fn client_hello_sent_for_config(config: ClientConfig) -> Result { let mut conn = ClientConnection::new(config.into(), ServerName::try_from("localhost").unwrap())?; diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index b5e34c10b93..dbf705ca24e 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -8276,32 +8276,6 @@ fn large_client_hello_acceptor() { } } -#[test] -fn hybrid_kx_component_share_not_offered_unless_supported_seperately() { - let kt = KeyType::Rsa2048; - let client_config = finish_client_config( - kt, - ClientConfig::builder_with_provider( - CryptoProvider { - kx_groups: vec![&FakeHybrid], - ..provider::default_provider() - } - .into(), - ) - .with_safe_default_protocol_versions() - .unwrap(), - ); - let server_config = make_server_config(kt, &provider::default_provider()); - - let (client, server) = make_pair_for_configs(client_config, server_config); - let (mut client, mut server) = (client.into(), server.into()); - transfer_altered( - &mut client, - assert_client_sends_hello_with_one_hybrid_key_share, - &mut server, - ); -} - #[test] fn hybrid_kx_component_share_offered_but_server_chooses_something_else() { let kt = KeyType::Rsa2048; @@ -8368,22 +8342,4 @@ impl ActiveKeyExchange for FakeHybridActive { } } -fn assert_client_sends_hello_with_one_hybrid_key_share(msg: &mut Message) -> Altered { - match &mut msg.payload { - MessagePayload::Handshake { parsed, .. } => match &mut parsed.payload { - HandshakePayload::ClientHello(ch) => { - let keyshares = ch - .keyshare_extension() - .expect("missing key share extension"); - assert_eq!(keyshares.len(), 1); - assert_eq!(keyshares[0].group(), FakeHybrid.name()); - assert_eq!(keyshares[0].get_encoding(), b"\x12\x34\x00\x06hybrid"); - } - _ => panic!("unexpected handshake message {parsed:?}"), - }, - _ => panic!("unexpected non-handshake message {msg:?}"), - }; - Altered::InPlace -} - const CONFIDENTIALITY_LIMIT: u64 = 1024; From 70d00af33472dacd63f14af3b65a2a45852a66ec Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 27 May 2025 08:16:15 +0100 Subject: [PATCH 250/403] KeyShareEntry: remove test-only accessor --- rustls/src/msgs/handshake.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 2926c85807b..aefcc0c2845 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -422,10 +422,6 @@ impl KeyShareEntry { payload: PayloadU16::new(payload.into()), } } - - pub fn group(&self) -> NamedGroup { - self.group - } } impl Codec<'_> for KeyShareEntry { From 5f7c467d3a5ba7892e5583cecdda838dd23f2349 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 29 May 2025 13:13:41 +0100 Subject: [PATCH 251/403] Disable `clippy::clone_on_ref_ptr` lint This is not contributing significantly to code quality. In cases where an `Arc` is cloned into an upcast of `Arc` (where `T: Trait`) it actively makes the code less readable by forcing the repetition of `Arc::::clone`. --- bogo/src/main.rs | 1 - ci-bench/src/main.rs | 1 - openssl-tests/src/lib.rs | 1 - provider-example/src/lib.rs | 1 - rustls-bench/src/main.rs | 1 - rustls-fuzzing-provider/src/lib.rs | 1 - rustls-test/src/lib.rs | 1 - rustls/src/lib.rs | 1 - 8 files changed, 8 deletions(-) diff --git a/bogo/src/main.rs b/bogo/src/main.rs index f4e73131468..ce5b06487f0 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -6,7 +6,6 @@ #![warn( clippy::alloc_instead_of_core, - clippy::clone_on_ref_ptr, clippy::manual_let_else, clippy::std_instead_of_core, clippy::use_self, diff --git a/ci-bench/src/main.rs b/ci-bench/src/main.rs index 6bef3768971..c08ba96ec34 100644 --- a/ci-bench/src/main.rs +++ b/ci-bench/src/main.rs @@ -1,6 +1,5 @@ #![warn( clippy::alloc_instead_of_core, - clippy::clone_on_ref_ptr, clippy::manual_let_else, clippy::std_instead_of_core, clippy::use_self, diff --git a/openssl-tests/src/lib.rs b/openssl-tests/src/lib.rs index df77818f5c4..b89bf930625 100644 --- a/openssl-tests/src/lib.rs +++ b/openssl-tests/src/lib.rs @@ -1,7 +1,6 @@ #![cfg(test)] #![warn( clippy::alloc_instead_of_core, - clippy::clone_on_ref_ptr, clippy::manual_let_else, clippy::std_instead_of_core, clippy::use_self, diff --git a/provider-example/src/lib.rs b/provider-example/src/lib.rs index 70e742e25c9..4080b0e28eb 100644 --- a/provider-example/src/lib.rs +++ b/provider-example/src/lib.rs @@ -1,7 +1,6 @@ #![no_std] #![warn( clippy::alloc_instead_of_core, - clippy::clone_on_ref_ptr, clippy::manual_let_else, clippy::std_instead_of_core, clippy::use_self, diff --git a/rustls-bench/src/main.rs b/rustls-bench/src/main.rs index 79a0cff8a20..dd025941c0e 100644 --- a/rustls-bench/src/main.rs +++ b/rustls-bench/src/main.rs @@ -4,7 +4,6 @@ // etc. because it's unstable at the time of writing. #![warn( clippy::alloc_instead_of_core, - clippy::clone_on_ref_ptr, clippy::manual_let_else, clippy::std_instead_of_core, clippy::use_self, diff --git a/rustls-fuzzing-provider/src/lib.rs b/rustls-fuzzing-provider/src/lib.rs index 6afe5004a7f..0bf1a5a7463 100644 --- a/rustls-fuzzing-provider/src/lib.rs +++ b/rustls-fuzzing-provider/src/lib.rs @@ -1,6 +1,5 @@ #![warn( clippy::alloc_instead_of_core, - clippy::clone_on_ref_ptr, clippy::manual_let_else, clippy::std_instead_of_core, clippy::use_self, diff --git a/rustls-test/src/lib.rs b/rustls-test/src/lib.rs index 6713bd9d4d0..b4d1d4821f5 100644 --- a/rustls-test/src/lib.rs +++ b/rustls-test/src/lib.rs @@ -1,6 +1,5 @@ #![warn( clippy::alloc_instead_of_core, - clippy::clone_on_ref_ptr, clippy::manual_let_else, clippy::std_instead_of_core, clippy::use_self, diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 72cd3128107..451036b0016 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -333,7 +333,6 @@ #![cfg_attr(not(any(read_buf, bench, coverage_nightly)), forbid(unstable_features))] #![warn( clippy::alloc_instead_of_core, - clippy::clone_on_ref_ptr, clippy::manual_let_else, clippy::std_instead_of_core, clippy::use_self, From ca468df0b115cf9620b27c94012b02fcdd247d87 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 29 May 2025 18:04:16 +0100 Subject: [PATCH 252/403] Eliminate use of `Arc::clone` --- bogo/src/main.rs | 12 +++--- ci-bench/src/main.rs | 4 +- examples/src/bin/simple_0rtt_client.rs | 2 +- examples/src/bin/tlsserver-mio.rs | 3 +- examples/src/bin/unbuffered-async-client.rs | 2 +- examples/src/bin/unbuffered-client.rs | 2 +- openssl-tests/src/ffdhe_kx_with_openssl.rs | 4 +- rustls-bench/src/main.rs | 22 +++++----- rustls-fuzzing-provider/src/lib.rs | 2 +- rustls-test/src/lib.rs | 4 +- rustls/src/client/client_conn.rs | 10 ++--- rustls/src/client/handy.rs | 2 +- rustls/src/client/test.rs | 8 ++-- rustls/src/client/tls13.rs | 6 +-- rustls/src/compress.rs | 4 +- rustls/src/crypto/aws_lc_rs/sign.rs | 6 +-- rustls/src/crypto/ring/sign.rs | 6 +-- rustls/src/crypto/signer.rs | 4 +- rustls/src/msgs/persist.rs | 2 +- rustls/src/quic.rs | 2 +- rustls/src/server/handy.rs | 2 +- rustls/src/server/server_conn.rs | 6 +-- rustls/src/server/test.rs | 4 +- rustls/src/webpki/client_verifier.rs | 2 +- rustls/src/webpki/server_verifier.rs | 2 +- rustls/tests/api.rs | 45 +++++++++++---------- rustls/tests/client_cert_verifier.rs | 4 +- 27 files changed, 84 insertions(+), 88 deletions(-) diff --git a/bogo/src/main.rs b/bogo/src/main.rs index ce5b06487f0..a305eac143d 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -494,7 +494,7 @@ impl server::ResolvesServerCert for FixedSignatureSchemeServerCertResolver { fn resolve(&self, client_hello: ClientHello<'_>) -> Option> { let mut certkey = self.resolver.resolve(client_hello)?; Arc::make_mut(&mut certkey).key = Arc::new(FixedSignatureSchemeSigningKey { - key: Arc::clone(&certkey.key), + key: certkey.key.clone(), scheme: self.scheme, }); Some(certkey) @@ -520,7 +520,7 @@ impl client::ResolvesClientCert for FixedSignatureSchemeClientCertResolver { .resolver .resolve(root_hint_subjects, sigschemes)?; Arc::make_mut(&mut certkey).key = Arc::new(FixedSignatureSchemeSigningKey { - key: Arc::clone(&certkey.key), + key: certkey.key.clone(), scheme: self.scheme, }); Some(certkey) @@ -653,7 +653,7 @@ fn make_server_cfg(opts: &Options) -> Arc { if opts.use_signing_scheme > 0 { let scheme = lookup_scheme(opts.use_signing_scheme); cfg.cert_resolver = Arc::new(FixedSignatureSchemeServerCertResolver { - resolver: Arc::clone(&cfg.cert_resolver), + resolver: cfg.cert_resolver.clone(), scheme, }); } @@ -824,7 +824,7 @@ fn make_client_cfg(opts: &Options) -> Arc { if !opts.cert_file.is_empty() && opts.use_signing_scheme > 0 { let scheme = lookup_scheme(opts.use_signing_scheme); cfg.client_auth_cert_resolver = Arc::new(FixedSignatureSchemeClientCertResolver { - resolver: Arc::clone(&cfg.client_auth_cert_resolver), + resolver: cfg.client_auth_cert_resolver.clone(), scheme, }); } @@ -1764,7 +1764,7 @@ pub fn main() { ); if opts.side == Side::Server { - let scfg = Arc::clone(scfg.as_ref().unwrap()); + let scfg = scfg.as_ref().cloned().unwrap(); ServerConnection::new(scfg) .unwrap() .into() @@ -1772,7 +1772,7 @@ pub fn main() { let server_name = ServerName::try_from(opts.host_name.as_str()) .unwrap() .to_owned(); - let ccfg = Arc::clone(ccfg.as_ref().unwrap()); + let ccfg = ccfg.as_ref().cloned().unwrap(); ClientConnection::new(ccfg, server_name) .unwrap() diff --git a/ci-bench/src/main.rs b/ci-bench/src/main.rs index c08ba96ec34..de6772fbef8 100644 --- a/ci-bench/src/main.rs +++ b/ci-bench/src/main.rs @@ -551,7 +551,7 @@ impl BenchStepper for ClientSideStepper<'_> { async fn handshake(&mut self) -> anyhow::Result { let server_name = "localhost".try_into().unwrap(); - let mut client = ClientConnection::new(Arc::clone(&self.config), server_name).unwrap(); + let mut client = ClientConnection::new(self.config.clone(), server_name).unwrap(); client.set_buffer_limit(None); loop { @@ -627,7 +627,7 @@ impl BenchStepper for ServerSideStepper<'_> { type Endpoint = ServerConnection; async fn handshake(&mut self) -> anyhow::Result { - let mut server = ServerConnection::new(Arc::clone(&self.config)).unwrap(); + let mut server = ServerConnection::new(self.config.clone()).unwrap(); server.set_buffer_limit(None); while server.is_handshaking() { diff --git a/examples/src/bin/simple_0rtt_client.rs b/examples/src/bin/simple_0rtt_client.rs index 7e875a83fb9..527ebd6a1f3 100644 --- a/examples/src/bin/simple_0rtt_client.rs +++ b/examples/src/bin/simple_0rtt_client.rs @@ -27,7 +27,7 @@ fn start_connection(config: &Arc, domain_name: &str, port: let server_name = ServerName::try_from(domain_name) .expect("invalid DNS name") .to_owned(); - let mut conn = rustls::ClientConnection::new(Arc::clone(config), server_name).unwrap(); + let mut conn = rustls::ClientConnection::new(config.clone(), server_name).unwrap(); let mut sock = TcpStream::connect(format!("{domain_name}:{port}")).unwrap(); sock.set_nodelay(true).unwrap(); let request = format!( diff --git a/examples/src/bin/tlsserver-mio.rs b/examples/src/bin/tlsserver-mio.rs index b156d34a49b..1ca5319dd0a 100644 --- a/examples/src/bin/tlsserver-mio.rs +++ b/examples/src/bin/tlsserver-mio.rs @@ -78,8 +78,7 @@ impl TlsServer { Ok((socket, addr)) => { debug!("Accepting new connection from {addr:?}"); - let tls_conn = - rustls::ServerConnection::new(Arc::clone(&self.tls_config)).unwrap(); + let tls_conn = rustls::ServerConnection::new(self.tls_config.clone()).unwrap(); let mode = self.mode.clone(); let token = mio::Token(self.next_id); diff --git a/examples/src/bin/unbuffered-async-client.rs b/examples/src/bin/unbuffered-async-client.rs index 851c01256a1..15081a627b4 100644 --- a/examples/src/bin/unbuffered-async-client.rs +++ b/examples/src/bin/unbuffered-async-client.rs @@ -47,7 +47,7 @@ async fn converse( incoming_tls: &mut [u8], outgoing_tls: &mut Vec, ) -> Result<(), Box> { - let mut conn = UnbufferedClientConnection::new(Arc::clone(config), SERVER_NAME.try_into()?)?; + let mut conn = UnbufferedClientConnection::new(config.clone(), SERVER_NAME.try_into()?)?; let mut sock = TcpStream::connect(format!("{SERVER_NAME}:{PORT}")).await?; let mut incoming_used = 0; diff --git a/examples/src/bin/unbuffered-client.rs b/examples/src/bin/unbuffered-client.rs index d502c631185..2212b3c4343 100644 --- a/examples/src/bin/unbuffered-client.rs +++ b/examples/src/bin/unbuffered-client.rs @@ -44,7 +44,7 @@ fn converse( incoming_tls: &mut [u8], outgoing_tls: &mut Vec, ) -> Result<(), Box> { - let mut conn = UnbufferedClientConnection::new(Arc::clone(config), SERVER_NAME.try_into()?)?; + let mut conn = UnbufferedClientConnection::new(config.clone(), SERVER_NAME.try_into()?)?; let mut sock = TcpStream::connect(format!("{SERVER_NAME}:{PORT}"))?; let mut incoming_used = 0; diff --git a/openssl-tests/src/ffdhe_kx_with_openssl.rs b/openssl-tests/src/ffdhe_kx_with_openssl.rs index f3d7a0c7180..c3f57ee7689 100644 --- a/openssl-tests/src/ffdhe_kx_with_openssl.rs +++ b/openssl-tests/src/ffdhe_kx_with_openssl.rs @@ -37,7 +37,7 @@ fn test_rustls_server_with_ffdhe_kx( let server_thread = thread::spawn(move || { let config = Arc::new(server_config_with_ffdhe_kx(protocol_version)); for _ in 0..iters { - let mut server = rustls::ServerConnection::new(Arc::clone(&config)).unwrap(); + let mut server = rustls::ServerConnection::new(config.clone()).unwrap(); let (mut tcp_stream, _addr) = listener.accept().unwrap(); server .writer() @@ -106,7 +106,7 @@ fn test_rustls_client_with_ffdhe_kx(iters: usize) { for stream in listener.incoming().take(iters) { match stream { Ok(stream) => { - let acceptor = Arc::clone(&acceptor); + let acceptor = acceptor.clone(); thread::spawn(move || { let mut stream = acceptor.accept(stream).unwrap(); let mut buf = String::new(); diff --git a/rustls-bench/src/main.rs b/rustls-bench/src/main.rs index dd025941c0e..aa814946ebe 100644 --- a/rustls-bench/src/main.rs +++ b/rustls-bench/src/main.rs @@ -273,8 +273,8 @@ fn bench_handshake(params: &Parameters) { bench_handshake_buffered( 1, ResumptionParam::No, - Arc::clone(&client_config), - Arc::clone(&server_config), + client_config.clone(), + server_config.clone(), ¶ms.without_latency_measurement(), ); @@ -329,10 +329,10 @@ fn bench_handshake_buffered( let mut client = time(&mut client_time, || { let server_name = "localhost".try_into().unwrap(); - ClientConnection::new(Arc::clone(&client_config), server_name).unwrap() + ClientConnection::new(client_config.clone(), server_name).unwrap() }); let mut server = time(&mut server_time, || { - ServerConnection::new(Arc::clone(&server_config)).unwrap() + ServerConnection::new(server_config.clone()).unwrap() }); time(&mut server_time, || { @@ -386,10 +386,10 @@ fn bench_handshake_unbuffered( let client = time(&mut client_time, || { let server_name = "localhost".try_into().unwrap(); - UnbufferedClientConnection::new(Arc::clone(&client_config), server_name).unwrap() + UnbufferedClientConnection::new(client_config.clone(), server_name).unwrap() }); let server = time(&mut server_time, || { - UnbufferedServerConnection::new(Arc::clone(&server_config)).unwrap() + UnbufferedServerConnection::new(server_config.clone()).unwrap() }); // nb. buffer allocation is outside the library, so is outside the benchmark scope @@ -451,8 +451,8 @@ fn multithreaded( thread::scope(|s| { let threads = (0..count.into()) .map(|_| { - let client_config = Arc::clone(client_config); - let server_config = Arc::clone(server_config); + let client_config = client_config.clone(); + let server_config = server_config.clone(); s.spawn(|| f(client_config, server_config)) }) .collect::>(); @@ -661,9 +661,9 @@ fn bench_memory( let mut buffers = TempBuffers::new(); for _i in 0..conn_count { - servers.push(ServerConnection::new(Arc::clone(&server_config)).unwrap()); + servers.push(ServerConnection::new(server_config.clone()).unwrap()); let server_name = "localhost".try_into().unwrap(); - clients.push(ClientConnection::new(Arc::clone(&client_config), server_name).unwrap()); + clients.push(ClientConnection::new(client_config.clone(), server_name).unwrap()); } for _step in 0..5 { @@ -797,7 +797,7 @@ impl Parameters { } WebPkiClientVerifier::builder_with_provider( client_auth_roots.into(), - Arc::clone(&provider), + provider.clone(), ) .build() .unwrap() diff --git a/rustls-fuzzing-provider/src/lib.rs b/rustls-fuzzing-provider/src/lib.rs index 0bf1a5a7463..b30c418aca2 100644 --- a/rustls-fuzzing-provider/src/lib.rs +++ b/rustls-fuzzing-provider/src/lib.rs @@ -71,7 +71,7 @@ struct DummyCert(Arc); impl server::ResolvesServerCert for DummyCert { fn resolve(&self, _client_hello: server::ClientHello<'_>) -> Option> { - Some(Arc::clone(&self.0)) + Some(self.0.clone()) } } diff --git a/rustls-test/src/lib.rs b/rustls-test/src/lib.rs index b4d1d4821f5..696e039ad1f 100644 --- a/rustls-test/src/lib.rs +++ b/rustls-test/src/lib.rs @@ -782,8 +782,8 @@ pub fn make_pair_for_arc_configs( server_config: &Arc, ) -> (ClientConnection, ServerConnection) { ( - ClientConnection::new(Arc::clone(client_config), server_name("localhost")).unwrap(), - ServerConnection::new(Arc::clone(server_config)).unwrap(), + ClientConnection::new(client_config.clone(), server_name("localhost")).unwrap(), + ServerConnection::new(server_config.clone()).unwrap(), ) } diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index 305badfb736..aa1f9fde35f 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -313,9 +313,9 @@ impl ClientConfig { // 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(Arc::clone( - CryptoProvider::get_default_or_install_from_crate_features(), - )) + Self::builder_with_provider( + CryptoProvider::get_default_or_install_from_crate_features().clone(), + ) .with_protocol_versions(versions) .unwrap() } @@ -703,7 +703,7 @@ mod connection { /// we behave in the TLS protocol, `name` is the /// name of the server we want to talk to. pub fn new(config: Arc, name: ServerName<'static>) -> Result { - Self::new_with_alpn(Arc::clone(&config), name, config.alpn_protocols.clone()) + Self::new_with_alpn(config.clone(), name, config.alpn_protocols.clone()) } /// Make a new ClientConnection with custom ALPN protocols. @@ -875,7 +875,7 @@ 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, name: ServerName<'static>) -> Result { - Self::new_with_alpn(Arc::clone(&config), name, config.alpn_protocols.clone()) + Self::new_with_alpn(config.clone(), name, config.alpn_protocols.clone()) } /// Make a new UnbufferedClientConnection with custom ALPN protocols. diff --git a/rustls/src/client/handy.rs b/rustls/src/client/handy.rs index 1097156374d..3ad3073bbd7 100644 --- a/rustls/src/client/handy.rs +++ b/rustls/src/client/handy.rs @@ -228,7 +228,7 @@ impl client::ResolvesClientCert for AlwaysResolvesClientRawPublicKeys { _root_hint_subjects: &[&[u8]], _sigschemes: &[SignatureScheme], ) -> Option> { - Some(Arc::clone(&self.0)) + Some(self.0.clone()) } fn only_raw_public_keys(&self) -> bool { diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs index b61d909f927..d3638c70083 100644 --- a/rustls/src/client/test.rs +++ b/rustls/src/client/test.rs @@ -111,11 +111,9 @@ mod tests { } let config = Arc::new(config); - let mut conn = ClientConnection::new( - Arc::clone(&config), - ServerName::try_from("localhost").unwrap(), - ) - .unwrap(); + let mut conn = + ClientConnection::new(config.clone(), ServerName::try_from("localhost").unwrap()) + .unwrap(); let mut sent = Vec::new(); conn.write_tls(&mut sent).unwrap(); diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index 90ce762cc93..128a4c60af3 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -1423,8 +1423,8 @@ impl State for ExpectFinished { } let st = ExpectTraffic { - config: Arc::clone(&st.config), - session_storage: Arc::clone(&st.config.resumption.store), + config: st.config.clone(), + session_storage: st.config.resumption.store.clone(), server_name: st.server_name, suite: st.suite, transcript: st.transcript, @@ -1479,7 +1479,7 @@ impl ExpectTraffic { #[allow(unused_mut)] let mut value = persist::Tls13ClientSessionValue::new( self.suite, - Arc::clone(&nst.ticket), + nst.ticket.clone(), secret.as_ref(), cx.peer_certificates .cloned() diff --git a/rustls/src/compress.rs b/rustls/src/compress.rs index ffce77669f3..d34cbaff096 100644 --- a/rustls/src/compress.rs +++ b/rustls/src/compress.rs @@ -358,7 +358,7 @@ impl CompressionCache { if item.algorithm == algorithm && item.original == encoding { // this item is now MRU let item = cache.remove(i).unwrap(); - cache.push_back(Arc::clone(&item)); + cache.push_back(item.clone()); return Ok(item); } } @@ -384,7 +384,7 @@ impl CompressionCache { if cache.len() == max_size { cache.pop_front(); } - cache.push_back(Arc::clone(&new_entry)); + cache.push_back(new_entry.clone()); Ok(new_entry) } diff --git a/rustls/src/crypto/aws_lc_rs/sign.rs b/rustls/src/crypto/aws_lc_rs/sign.rs index 8f8c5f6127f..0c874abf922 100644 --- a/rustls/src/crypto/aws_lc_rs/sign.rs +++ b/rustls/src/crypto/aws_lc_rs/sign.rs @@ -131,7 +131,7 @@ impl SigningKey for RsaSigningKey { ALL_RSA_SCHEMES .iter() .find(|scheme| offered.contains(scheme)) - .map(|scheme| RsaSigner::new(Arc::clone(&self.key), *scheme)) + .map(|scheme| RsaSigner::new(self.key.clone(), *scheme)) } fn public_key(&self) -> Option> { @@ -251,7 +251,7 @@ impl SigningKey for EcdsaSigningKey { fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option> { if offered.contains(&self.scheme) { Some(Box::new(EcdsaSigner { - key: Arc::clone(&self.key), + key: self.key.clone(), scheme: self.scheme, })) } else { @@ -346,7 +346,7 @@ impl SigningKey for Ed25519SigningKey { fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option> { if offered.contains(&self.scheme) { Some(Box::new(Ed25519Signer { - key: Arc::clone(&self.key), + key: self.key.clone(), scheme: self.scheme, })) } else { diff --git a/rustls/src/crypto/ring/sign.rs b/rustls/src/crypto/ring/sign.rs index 426d03eeea1..ad318270a99 100644 --- a/rustls/src/crypto/ring/sign.rs +++ b/rustls/src/crypto/ring/sign.rs @@ -124,7 +124,7 @@ impl SigningKey for RsaSigningKey { ALL_RSA_SCHEMES .iter() .find(|scheme| offered.contains(scheme)) - .map(|scheme| RsaSigner::new(Arc::clone(&self.key), *scheme)) + .map(|scheme| RsaSigner::new(self.key.clone(), *scheme)) } fn public_key(&self) -> Option> { @@ -285,7 +285,7 @@ impl SigningKey for EcdsaSigningKey { fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option> { if offered.contains(&self.scheme) { Some(Box::new(EcdsaSigner { - key: Arc::clone(&self.key), + key: self.key.clone(), scheme: self.scheme, })) } else { @@ -379,7 +379,7 @@ impl SigningKey for Ed25519SigningKey { fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option> { if offered.contains(&self.scheme) { Some(Box::new(Ed25519Signer { - key: Arc::clone(&self.key), + key: self.key.clone(), scheme: self.scheme, })) } else { diff --git a/rustls/src/crypto/signer.rs b/rustls/src/crypto/signer.rs index dbf4224081f..76a6189bc52 100644 --- a/rustls/src/crypto/signer.rs +++ b/rustls/src/crypto/signer.rs @@ -107,7 +107,7 @@ impl ResolvesClientCert for SingleCertAndKey { _root_hint_subjects: &[&[u8]], _sigschemes: &[SignatureScheme], ) -> Option> { - Some(Arc::clone(&self.0)) + Some(self.0.clone()) } fn has_certs(&self) -> bool { @@ -117,7 +117,7 @@ impl ResolvesClientCert for SingleCertAndKey { impl ResolvesServerCert for SingleCertAndKey { fn resolve(&self, _client_hello: ClientHello<'_>) -> Option> { - Some(Arc::clone(&self.0)) + Some(self.0.clone()) } } diff --git a/rustls/src/msgs/persist.rs b/rustls/src/msgs/persist.rs index 8ddec1699c9..88960daf99f 100644 --- a/rustls/src/msgs/persist.rs +++ b/rustls/src/msgs/persist.rs @@ -189,7 +189,7 @@ impl Tls12ClientSessionValue { } pub(crate) fn ticket(&mut self) -> Arc { - Arc::clone(&self.common.ticket) + self.common.ticket.clone() } pub(crate) fn extended_ms(&self) -> bool { diff --git a/rustls/src/quic.rs b/rustls/src/quic.rs index df806eca0c4..b4174391b60 100644 --- a/rustls/src/quic.rs +++ b/rustls/src/quic.rs @@ -165,7 +165,7 @@ mod connection { params: Vec, ) -> Result { Self::new_with_alpn( - Arc::clone(&config), + config.clone(), quic_version, name, params, diff --git a/rustls/src/server/handy.rs b/rustls/src/server/handy.rs index 710a1f28411..f11ca373803 100644 --- a/rustls/src/server/handy.rs +++ b/rustls/src/server/handy.rs @@ -182,7 +182,7 @@ impl AlwaysResolvesServerRawPublicKeys { impl server::ResolvesServerCert for AlwaysResolvesServerRawPublicKeys { fn resolve(&self, _client_hello: ClientHello<'_>) -> Option> { - Some(Arc::clone(&self.0)) + Some(self.0.clone()) } fn only_raw_public_keys(&self) -> bool { diff --git a/rustls/src/server/server_conn.rs b/rustls/src/server/server_conn.rs index 47a84945616..ee6830ab188 100644 --- a/rustls/src/server/server_conn.rs +++ b/rustls/src/server/server_conn.rs @@ -455,9 +455,9 @@ impl ServerConfig { // 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(Arc::clone( - CryptoProvider::get_default_or_install_from_crate_features(), - )) + Self::builder_with_provider( + CryptoProvider::get_default_or_install_from_crate_features().clone(), + ) .with_protocol_versions(versions) .unwrap() } diff --git a/rustls/src/server/test.rs b/rustls/src/server/test.rs index 07b14a1a12b..977f4b1d837 100644 --- a/rustls/src/server/test.rs +++ b/rustls/src/server/test.rs @@ -73,7 +73,6 @@ mod tests { use crate::pki_types::pem::PemObject; use crate::pki_types::{CertificateDer, PrivateKeyDer}; use crate::server::{ServerConfig, ServerConnection}; - use crate::sync::Arc; use crate::version; #[cfg(feature = "tls12")] @@ -92,8 +91,7 @@ mod tests { } else { config.require_ems = true; } - let config = config.into(); - let mut conn = ServerConnection::new(Arc::clone(&config)).unwrap(); + let mut conn = ServerConnection::new(config.into()).unwrap(); let sh = Message { version: ProtocolVersion::TLSv1_3, diff --git a/rustls/src/webpki/client_verifier.rs b/rustls/src/webpki/client_verifier.rs index 78bb7720ed0..060f0f77937 100644 --- a/rustls/src/webpki/client_verifier.rs +++ b/rustls/src/webpki/client_verifier.rs @@ -274,7 +274,7 @@ impl WebPkiClientVerifier { pub fn builder(roots: Arc) -> ClientCertVerifierBuilder { Self::builder_with_provider( roots, - Arc::clone(CryptoProvider::get_default_or_install_from_crate_features()), + CryptoProvider::get_default_or_install_from_crate_features().clone(), ) } diff --git a/rustls/src/webpki/server_verifier.rs b/rustls/src/webpki/server_verifier.rs index 9405c123a23..5aa9235054e 100644 --- a/rustls/src/webpki/server_verifier.rs +++ b/rustls/src/webpki/server_verifier.rs @@ -153,7 +153,7 @@ impl WebPkiServerVerifier { pub fn builder(roots: Arc) -> ServerCertVerifierBuilder { Self::builder_with_provider( roots, - Arc::clone(CryptoProvider::get_default_or_install_from_crate_features()), + CryptoProvider::get_default_or_install_from_crate_features().clone(), ) } diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index dbf705ca24e..189cb432809 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -973,8 +973,9 @@ fn client_only_attempts_resumption_with_compatible_security() { let mut client_config = make_client_config_with_versions_with_auth(kt, &[version], &provider); client_config.resumption = base_client_config.resumption.clone(); - client_config.client_auth_cert_resolver = - Arc::clone(&base_client_config.client_auth_cert_resolver); + client_config.client_auth_cert_resolver = base_client_config + .client_auth_cert_resolver + .clone(); CountingLogger::reset(); let (mut client, mut server) = @@ -1689,7 +1690,7 @@ fn client_with_sni_disabled_does_not_send_sni() { let mut client = ClientConnection::new(Arc::new(client_config), server_name("value-not-sent")) .unwrap(); - let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); + let mut server = ServerConnection::new(server_config.clone()).unwrap(); let err = do_handshake_until_error(&mut client, &mut server); assert!(err.is_err()); @@ -1710,7 +1711,7 @@ fn client_checks_server_certificate_with_given_name() { server_name("not-the-right-hostname.com"), ) .unwrap(); - let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); + let mut server = ServerConnection::new(server_config.clone()).unwrap(); let err = do_handshake_until_error(&mut client, &mut server); assert_eq!( @@ -1791,7 +1792,7 @@ fn client_check_server_certificate_ee_revoked() { make_client_config_with_verifier(&[version], builder.clone(), &provider); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); - let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); + let mut server = ServerConnection::new(server_config.clone()).unwrap(); // We expect the handshake to fail since the server's EE certificate is revoked. let err = do_handshake_until_error(&mut client, &mut server); @@ -1835,7 +1836,7 @@ fn client_check_server_certificate_ee_unknown_revocation() { ); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); - let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); + let mut server = ServerConnection::new(server_config.clone()).unwrap(); // We expect if we use the forbid_unknown_verifier that the handshake will fail since the // server's EE certificate's revocation status is unknown given the CRLs we've provided. @@ -1855,7 +1856,7 @@ fn client_check_server_certificate_ee_unknown_revocation() { ); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); - let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); + let mut server = ServerConnection::new(server_config.clone()).unwrap(); let res = do_handshake_until_error(&mut client, &mut server); assert!(res.is_ok()); } @@ -1893,7 +1894,7 @@ fn client_check_server_certificate_intermediate_revoked() { ); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); - let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); + let mut server = ServerConnection::new(server_config.clone()).unwrap(); // We expect the handshake to fail when using the full chain verifier since the intermediate's // EE certificate is revoked. @@ -1912,7 +1913,7 @@ fn client_check_server_certificate_intermediate_revoked() { ); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); - let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); + let mut server = ServerConnection::new(server_config.clone()).unwrap(); // We expect the handshake to succeed when we use the verifier that only checks the EE certificate // revocation status. The revoked intermediate status should not be checked. let res = do_handshake_until_error(&mut client, &mut server); @@ -1950,7 +1951,7 @@ fn client_check_server_certificate_ee_crl_expired() { ); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); - let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); + let mut server = ServerConnection::new(server_config.clone()).unwrap(); // We expect the handshake to fail since the CRL is expired. let err = do_handshake_until_error(&mut client, &mut server); @@ -1968,7 +1969,7 @@ fn client_check_server_certificate_ee_crl_expired() { ); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); - let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); + let mut server = ServerConnection::new(server_config.clone()).unwrap(); // We expect the handshake to succeed when CRL expiration is ignored. let res = do_handshake_until_error(&mut client, &mut server); @@ -3550,7 +3551,7 @@ fn server_exposes_offered_sni_even_if_resolver_fails() { for version in rustls::ALL_VERSIONS { let client_config = make_client_config_with_versions(kt, &[version], &provider); - let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); + let mut server = ServerConnection::new(server_config.clone()).unwrap(); let mut client = ClientConnection::new(Arc::new(client_config), server_name("thisdoesNOTexist.com")) .unwrap(); @@ -3585,7 +3586,7 @@ fn sni_resolver_works() { server_config.cert_resolver = Arc::new(resolver); let server_config = Arc::new(server_config); - let mut server1 = ServerConnection::new(Arc::clone(&server_config)).unwrap(); + let mut server1 = ServerConnection::new(server_config.clone()).unwrap(); let mut client1 = ClientConnection::new( Arc::new(make_client_config(kt, &provider)), server_name("localhost"), @@ -3594,7 +3595,7 @@ fn sni_resolver_works() { let err = do_handshake_until_error(&mut client1, &mut server1); assert_eq!(err, Ok(())); - let mut server2 = ServerConnection::new(Arc::clone(&server_config)).unwrap(); + let mut server2 = ServerConnection::new(server_config.clone()).unwrap(); let mut client2 = ClientConnection::new( Arc::new(make_client_config(kt, &provider)), server_name("notlocalhost"), @@ -3677,7 +3678,7 @@ fn sni_resolver_lower_cases_configured_names() { server_config.cert_resolver = Arc::new(resolver); let server_config = Arc::new(server_config); - let mut server1 = ServerConnection::new(Arc::clone(&server_config)).unwrap(); + let mut server1 = ServerConnection::new(server_config.clone()).unwrap(); let mut client1 = ClientConnection::new( Arc::new(make_client_config(kt, &provider)), server_name("localhost"), @@ -3708,7 +3709,7 @@ fn sni_resolver_lower_cases_queried_names() { server_config.cert_resolver = Arc::new(resolver); let server_config = Arc::new(server_config); - let mut server1 = ServerConnection::new(Arc::clone(&server_config)).unwrap(); + let mut server1 = ServerConnection::new(server_config.clone()).unwrap(); let mut client1 = ClientConnection::new( Arc::new(make_client_config(kt, &provider)), server_name("LOCALHOST"), @@ -5194,7 +5195,7 @@ mod test_quic { // full handshake let mut client = quic::ClientConnection::new( - Arc::clone(&client_config), + client_config.clone(), quic::Version::V1, server_name("localhost"), client_params.into(), @@ -5202,7 +5203,7 @@ mod test_quic { .unwrap(); let mut server = quic::ServerConnection::new( - Arc::clone(&server_config), + server_config.clone(), quic::Version::V1, server_params.into(), ) @@ -5246,7 +5247,7 @@ mod test_quic { // 0-RTT handshake let mut client = quic::ClientConnection::new( - Arc::clone(&client_config), + client_config.clone(), quic::Version::V1, server_name("localhost"), client_params.into(), @@ -5259,7 +5260,7 @@ mod test_quic { ); let mut server = quic::ServerConnection::new( - Arc::clone(&server_config), + server_config.clone(), quic::Version::V1, server_params.into(), ) @@ -5298,7 +5299,7 @@ mod test_quic { .unwrap(); let mut server = quic::ServerConnection::new( - Arc::clone(&server_config), + server_config.clone(), quic::Version::V1, server_params.into(), ) @@ -5773,7 +5774,7 @@ mod test_quic { ); let client_config = Arc::new(client_config); let mut client = quic::ClientConnection::new( - Arc::clone(&client_config), + client_config.clone(), quic::Version::V1, server_name("localhost"), b"client params"[..].into(), diff --git a/rustls/tests/client_cert_verifier.rs b/rustls/tests/client_cert_verifier.rs index 2ac7461d864..a0a686118c2 100644 --- a/rustls/tests/client_cert_verifier.rs +++ b/rustls/tests/client_cert_verifier.rs @@ -100,7 +100,7 @@ fn client_verifier_no_auth_yes_root() { for version in rustls::ALL_VERSIONS { let client_config = make_client_config_with_versions(*kt, &[version], &provider); - let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); + let mut server = ServerConnection::new(server_config.clone()).unwrap(); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); let errs = do_handshake_until_both_error(&mut client, &mut server); @@ -129,7 +129,7 @@ fn client_verifier_fails_properly() { for version in rustls::ALL_VERSIONS { let client_config = make_client_config_with_versions_with_auth(*kt, &[version], &provider); - let mut server = ServerConnection::new(Arc::clone(&server_config)).unwrap(); + let mut server = ServerConnection::new(server_config.clone()).unwrap(); let mut client = ClientConnection::new(Arc::new(client_config), server_name("localhost")).unwrap(); let err = do_handshake_until_error(&mut client, &mut server); From 01f14c14f2532431da32f707778bb4e9e3024b2d Mon Sep 17 00:00:00 2001 From: Frando Date: Fri, 30 May 2025 10:26:55 +0200 Subject: [PATCH 253/403] feat: expose the number of received TLS1.3 resumption tickets This adds a public function to get the count of TLS1.3 resumption tickets that were received in a client-side rustls session. Before, this information was not available outside of the session store. Downstream users may want to access this, though, to keep a connection open until tickets are received. When doing a 0RTT connection, it may happen that the application-side logic is done before the tickets are received. In that case, if expecting to do further 0rtt connections in the future, it may be beneficial to keep the connection open until the tickets are received. With this patch, this is possible without having to wrap or hack around the session store. --- rustls/src/client/client_conn.rs | 10 ++++++++++ rustls/src/client/tls13.rs | 4 ++++ rustls/src/common_state.rs | 2 ++ rustls/src/quic.rs | 5 +++++ rustls/tests/api.rs | 4 +++- rustls/tests/unbuffered.rs | 10 +++++++++- 6 files changed, 33 insertions(+), 2 deletions(-) diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index aa1f9fde35f..d66664cd9c2 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -774,6 +774,11 @@ mod connection { 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()`]: @@ -919,6 +924,11 @@ impl UnbufferedClientConnection { .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 { diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index 128a4c60af3..148505b3e26 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -1527,6 +1527,10 @@ impl ExpectTraffic { 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) } diff --git a/rustls/src/common_state.rs b/rustls/src/common_state.rs index 171767aff4b..07c8dd3492f 100644 --- a/rustls/src/common_state.rs +++ b/rustls/src/common_state.rs @@ -60,6 +60,7 @@ pub struct CommonState { temper_counters: TemperCounters, pub(crate) refresh_traffic_keys_pending: bool, pub(crate) fips: bool, + pub(crate) tls13_tickets_received: u32, } impl CommonState { @@ -92,6 +93,7 @@ impl CommonState { temper_counters: TemperCounters::default(), refresh_traffic_keys_pending: false, fips: false, + tls13_tickets_received: 0, } } diff --git a/rustls/src/quic.rs b/rustls/src/quic.rs index b4174391b60..d1d4e8b2d66 100644 --- a/rustls/src/quic.rs +++ b/rustls/src/quic.rs @@ -219,6 +219,11 @@ mod connection { 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 { diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 189cb432809..aea45487281 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -4753,6 +4753,7 @@ fn tls13_stateful_resumption() { // full handshake let (mut client, mut server) = make_pair_for_arc_configs(&client_config, &server_config); let (full_c2s, full_s2c) = do_handshake(&mut client, &mut server); + assert_eq!(client.tls13_tickets_received(), 2); assert_eq!(storage.puts(), 2); assert_eq!(storage.gets(), 0); assert_eq!(storage.takes(), 0); @@ -5234,6 +5235,7 @@ mod test_quic { assert!(!server.is_handshaking()); assert!(compatible_keys(&server_1rtt, &client_1rtt)); assert!(!compatible_keys(&server_hs, &server_1rtt)); + assert!( step(&mut client, &mut server) .unwrap() @@ -5244,6 +5246,7 @@ mod test_quic { .unwrap() .is_none() ); + assert_eq!(client.tls13_tickets_received(), 2); // 0-RTT handshake let mut client = quic::ClientConnection::new( @@ -5286,7 +5289,6 @@ mod test_quic { .unwrap() .unwrap(); assert!(client.is_early_data_accepted()); - // 0-RTT rejection { let client_config = (*client_config).clone(); diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index e32b051371f..4f32bf92296 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -216,13 +216,21 @@ fn early_data() { let client_config = Arc::new(client_config); // first handshake allows the second to be a resumption and use 0-RTT - run( + let outcome = run( client_config.clone(), &mut NO_ACTIONS.clone(), server_config.clone(), &mut NO_ACTIONS.clone(), ); + assert_eq!( + outcome + .client + .unwrap() + .tls13_tickets_received(), + 2 + ); + let mut client_actions = Actions { early_data_to_send: Some(expected), ..NO_ACTIONS From a7bd5c2162e8cc8e685a93553b9e16e837192617 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 28 May 2025 13:35:45 +0100 Subject: [PATCH 254/403] Convert `server_picks_ffdhe_group_when_clienthello_(...)` into unit test --- rustls/src/server/test.rs | 96 ++++++++++++++++++++++++++++++++++++++- rustls/tests/api_ffdhe.rs | 36 --------------- 2 files changed, 95 insertions(+), 37 deletions(-) diff --git a/rustls/src/server/test.rs b/rustls/src/server/test.rs index 977f4b1d837..b5322d6f23d 100644 --- a/rustls/src/server/test.rs +++ b/rustls/src/server/test.rs @@ -70,10 +70,15 @@ fn test_process_client_hello(hello: ClientHelloPayload) -> Result<(), Error> { #[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::pki_types::pem::PemObject; use crate::pki_types::{CertificateDer, PrivateKeyDer}; use crate::server::{ServerConfig, ServerConnection}; - use crate::version; + use crate::sync::Arc; + use crate::{CipherSuiteCommon, SupportedCipherSuite, Tls12CipherSuite, version}; #[cfg(feature = "tls12")] #[test] @@ -111,6 +116,43 @@ mod tests { ); } + #[cfg(feature = "tls12")] + #[test] + fn server_picks_ffdhe_group_when_clienthello_has_no_ffdhe_group_in_groups_ext() { + let provider = CryptoProvider { + kx_groups: vec![FAKE_FFDHE_GROUP], + cipher_suites: vec![TLS_DHE_RSA_WITH_AES_128_GCM_SHA256], + ..super::provider::default_provider() + }; + let 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(); + + let mut conn = ServerConnection::new(config.into()).unwrap(); + + let mut ch = minimal_client_hello(); + ch.cipher_suites + .push(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256.suite()); + let ch = Message { + version: ProtocolVersion::TLSv1_3, + payload: MessagePayload::handshake(HandshakeMessagePayload { + typ: HandshakeType::ClientHello, + payload: HandshakePayload::ClientHello(ch), + }), + }; + 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()); + } + fn server_key() -> PrivateKeyDer<'static> { PrivateKeyDer::from_pem_reader( &mut include_bytes!("../../../test-ca/rsa-2048/end.key").as_slice(), @@ -124,6 +166,58 @@ mod tests { CertificateDer::from(&include_bytes!("../../../test-ca/rsa-2048/inter.der")[..]), ] } + + 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, Error> { + Ok(Box::new(ActiveFakeFfdhe)) + } + } + + #[derive(Debug)] + struct ActiveFakeFfdhe; + + impl ActiveKeyExchange for ActiveFakeFfdhe { + #[cfg_attr(coverage_nightly, coverage(off))] + fn complete( + self: Box, + _peer_pub_key: &[u8], + ) -> Result { + 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 { diff --git a/rustls/tests/api_ffdhe.rs b/rustls/tests/api_ffdhe.rs index f915f9d39e8..35dab25e4ca 100644 --- a/rustls/tests/api_ffdhe.rs +++ b/rustls/tests/api_ffdhe.rs @@ -71,42 +71,6 @@ fn ffdhe_ciphersuite() { } } -#[test] -fn server_picks_ffdhe_group_when_clienthello_has_no_ffdhe_group_in_groups_ext() { - fn clear_named_groups_ext(msg: &mut Message) -> Altered { - if let MessagePayload::Handshake { parsed, encoded } = &mut msg.payload { - if let HandshakePayload::ClientHello(ch) = &mut parsed.payload { - for mut ext in ch.extensions.iter_mut() { - if let ClientExtension::NamedGroups(ngs) = &mut ext { - ngs.clear(); - ngs.push(NamedGroup::X448); - } - } - } - *encoded = Payload::new(parsed.get_encoding()); - } - Altered::InPlace - } - - let client_config = finish_client_config( - KeyType::Rsa2048, - rustls::ClientConfig::builder_with_provider(ffdhe::ffdhe_provider().into()) - .with_protocol_versions(&[&rustls::version::TLS12]) - .unwrap(), - ); - let server_config = finish_server_config( - KeyType::Rsa2048, - rustls::ServerConfig::builder_with_provider(ffdhe::ffdhe_provider().into()) - .with_protocol_versions(&[&rustls::version::TLS12]) - .unwrap(), - ); - - let (client, server) = make_pair_for_configs(client_config, server_config); - let (mut client, mut server) = (client.into(), server.into()); - transfer_altered(&mut client, clear_named_groups_ext, &mut server); - assert!(server.process_new_packets().is_ok()); -} - #[test] fn server_picks_ffdhe_group_when_clienthello_has_no_groups_ext() { fn remove_named_groups_ext(msg: &mut Message) -> Altered { From bbf724515cfec79261d0779bad468c73e6c6d4db Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 28 May 2025 14:38:35 +0100 Subject: [PATCH 255/403] Convert `server_picks_ffdhe_group_when_(...)` into unit test --- rustls/src/server/test.rs | 50 ++++++++++++++++++++++++++++++++------- rustls/tests/api_ffdhe.rs | 32 ------------------------- 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/rustls/src/server/test.rs b/rustls/src/server/test.rs index b5322d6f23d..fbc86cadc63 100644 --- a/rustls/src/server/test.rs +++ b/rustls/src/server/test.rs @@ -119,28 +119,54 @@ mod tests { #[cfg(feature = "tls12")] #[test] fn server_picks_ffdhe_group_when_clienthello_has_no_ffdhe_group_in_groups_ext() { - let provider = CryptoProvider { - kx_groups: vec![FAKE_FFDHE_GROUP], - cipher_suites: vec![TLS_DHE_RSA_WITH_AES_128_GCM_SHA256], - ..super::provider::default_provider() - }; - let config = ServerConfig::builder_with_provider(provider.into()) + 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 conn = ServerConnection::new(config.into()).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 + .retain(|ext| ext.ext_type() != ExtensionType::EllipticCurves); + + 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 { typ: HandshakeType::ClientHello, - payload: HandshakePayload::ClientHello(ch), + payload: HandshakePayload::ClientHello(client_hello), }), }; conn.read_tls(&mut ch.into_wire_bytes().as_slice()) @@ -167,6 +193,14 @@ mod tests { ] } + 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)] diff --git a/rustls/tests/api_ffdhe.rs b/rustls/tests/api_ffdhe.rs index 35dab25e4ca..efba2cf277e 100644 --- a/rustls/tests/api_ffdhe.rs +++ b/rustls/tests/api_ffdhe.rs @@ -71,38 +71,6 @@ fn ffdhe_ciphersuite() { } } -#[test] -fn server_picks_ffdhe_group_when_clienthello_has_no_groups_ext() { - fn remove_named_groups_ext(msg: &mut Message) -> Altered { - if let MessagePayload::Handshake { parsed, encoded } = &mut msg.payload { - if let HandshakePayload::ClientHello(ch) = &mut parsed.payload { - ch.extensions - .retain(|ext| !matches!(ext, ClientExtension::NamedGroups(_))); - } - *encoded = Payload::new(parsed.get_encoding()); - } - Altered::InPlace - } - - let client_config = finish_client_config( - KeyType::Rsa2048, - rustls::ClientConfig::builder_with_provider(ffdhe::ffdhe_provider().into()) - .with_protocol_versions(&[&rustls::version::TLS12]) - .unwrap(), - ); - let server_config = finish_server_config( - KeyType::Rsa2048, - rustls::ServerConfig::builder_with_provider(ffdhe::ffdhe_provider().into()) - .with_safe_default_protocol_versions() - .unwrap(), - ); - - let (client, server) = make_pair_for_configs(client_config, server_config); - let (mut client, mut server) = (client.into(), server.into()); - transfer_altered(&mut client, remove_named_groups_ext, &mut server); - assert!(server.process_new_packets().is_ok()); -} - #[test] fn server_avoids_dhe_cipher_suites_when_client_has_no_known_dhe_in_groups_ext() { use rustls::{CipherSuite, NamedGroup}; From f48beaaba59a7aaf2475ac0e8a6339cf53f7690a Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 28 May 2025 14:45:56 +0100 Subject: [PATCH 256/403] Convert `server_accepts_client_with_no_ecpoints(..)` into unit test --- rustls/src/server/test.rs | 22 ++++++++++++++++++++++ rustls/tests/api_ffdhe.rs | 36 ------------------------------------ 2 files changed, 22 insertions(+), 36 deletions(-) diff --git a/rustls/src/server/test.rs b/rustls/src/server/test.rs index fbc86cadc63..5d02cf1fdbb 100644 --- a/rustls/src/server/test.rs +++ b/rustls/src/server/test.rs @@ -158,6 +158,28 @@ mod tests { ); } + #[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 + .retain(|ext| ext.ext_type() != ExtensionType::ECPointFormats); + + 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, diff --git a/rustls/tests/api_ffdhe.rs b/rustls/tests/api_ffdhe.rs index efba2cf277e..2e4bff4cec5 100644 --- a/rustls/tests/api_ffdhe.rs +++ b/rustls/tests/api_ffdhe.rs @@ -5,10 +5,6 @@ mod common; use common::*; use rustls::crypto::CryptoProvider; -use rustls::internal::msgs::base::Payload; -use rustls::internal::msgs::codec::Codec; -use rustls::internal::msgs::handshake::{ClientExtension, HandshakePayload}; -use rustls::internal::msgs::message::{Message, MessagePayload}; use rustls::version::{TLS12, TLS13}; use rustls::{CipherSuite, ClientConfig, NamedGroup}; @@ -127,38 +123,6 @@ fn server_avoids_dhe_cipher_suites_when_client_has_no_known_dhe_in_groups_ext() ) } -#[test] -fn server_accepts_client_with_no_ecpoints_extension_and_only_ffdhe_cipher_suites() { - fn remove_ecpoints_ext(msg: &mut Message) -> Altered { - if let MessagePayload::Handshake { parsed, encoded } = &mut msg.payload { - if let HandshakePayload::ClientHello(ch) = &mut parsed.payload { - ch.extensions - .retain(|ext| !matches!(ext, ClientExtension::EcPointFormats(_))); - } - *encoded = Payload::new(parsed.get_encoding()); - } - Altered::InPlace - } - - let client_config = finish_client_config( - KeyType::Rsa2048, - rustls::ClientConfig::builder_with_provider(ffdhe::ffdhe_provider().into()) - .with_protocol_versions(&[&rustls::version::TLS12]) - .unwrap(), - ); - let server_config = finish_server_config( - KeyType::Rsa2048, - rustls::ServerConfig::builder_with_provider(ffdhe::ffdhe_provider().into()) - .with_safe_default_protocol_versions() - .unwrap(), - ); - - let (client, server) = make_pair_for_configs(client_config, server_config); - let (mut client, mut server) = (client.into(), server.into()); - transfer_altered(&mut client, remove_ecpoints_ext, &mut server); - assert!(server.process_new_packets().is_ok()); -} - #[test] fn server_avoids_cipher_suite_with_no_common_kx_groups() { let server_config = finish_server_config( From 62e2aa4109108a23414bbba1b66a6cf2c496fd57 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 28 May 2025 15:21:07 +0100 Subject: [PATCH 257/403] Convert `cas_extension_in_client_hello_if_(...)` to unit test --- rustls/src/client/test.rs | 77 +++++++++++++++++++++++++++- rustls/tests/server_cert_verifier.rs | 67 ++---------------------- 2 files changed, 79 insertions(+), 65 deletions(-) diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs index d3638c70083..f4726ab9481 100644 --- a/rustls/src/client/test.rs +++ b/rustls/src/client/test.rs @@ -21,7 +21,10 @@ use crate::{Error, PeerIncompatible, PeerMisbehaved, RootCertStore}; #[macro_rules_attribute::apply(test_for_each_provider)] mod tests { use super::super::*; - use crate::version; + use crate::msgs::handshake::ClientExtension; + use crate::pki_types::UnixTime; + use crate::verify::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; + use crate::{DigitallySignedStruct, DistinguishedName, version}; /// Tests that session_ticket(35) extension /// is not sent if the client does not support TLS 1.2. @@ -139,6 +142,78 @@ mod tests { 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 + .iter() + .any(|ext| matches!(ext, ClientExtension::AuthorityNames(_))), + cas_extension_expected + ); + } + } + + #[derive(Clone, Debug)] + struct ServerVerifierWithAuthorityNames(Vec); + + 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 { + unreachable!() + } + + #[cfg_attr(coverage_nightly, coverage(off))] + fn verify_tls12_signature( + &self, + _message: &[u8], + _cert: &CertificateDer<'_>, + _dss: &DigitallySignedStruct, + ) -> Result { + unreachable!() + } + + #[cfg_attr(coverage_nightly, coverage(off))] + fn verify_tls13_signature( + &self, + _message: &[u8], + _cert: &CertificateDer<'_>, + _dss: &DigitallySignedStruct, + ) -> Result { + unreachable!() + } + + fn supported_verify_schemes(&self) -> Vec { + vec![SignatureScheme::RSA_PKCS1_SHA1] + } + } } // invalid with fips, as we can't offer X25519 separately diff --git a/rustls/tests/server_cert_verifier.rs b/rustls/tests/server_cert_verifier.rs index f989f3914c6..30a5600d590 100644 --- a/rustls/tests/server_cert_verifier.rs +++ b/rustls/tests/server_cert_verifier.rs @@ -7,19 +7,15 @@ use super::*; mod common; use common::{ - Altered, Arc, ErrorFromPeer, KeyType, MockServerVerifier, client_config_builder, - client_config_builder_with_versions, do_handshake, do_handshake_until_both_error, - do_handshake_until_error, make_client_config_with_versions, make_pair_for_arc_configs, - make_server_config, server_config_builder, transfer_altered, + Arc, ErrorFromPeer, KeyType, MockServerVerifier, client_config_builder, do_handshake, + do_handshake_until_both_error, do_handshake_until_error, make_client_config_with_versions, + make_pair_for_arc_configs, make_server_config, server_config_builder, }; use pki_types::{CertificateDer, ServerName}; use rustls::client::WebPkiServerVerifier; use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; -use rustls::internal::msgs::handshake::{ClientExtension, HandshakePayload}; -use rustls::internal::msgs::message::{Message, MessagePayload}; use rustls::server::{ClientHello, ResolvesServerCert}; use rustls::sign::CertifiedKey; -use rustls::version::{TLS12, TLS13}; use rustls::{ AlertDescription, CertificateError, DigitallySignedStruct, DistinguishedName, Error, InvalidMessage, RootCertStore, @@ -176,63 +172,6 @@ fn client_can_override_certificate_verification_and_offer_no_signature_schemes() } } -#[test] -fn cas_extension_in_client_hello_if_server_verifier_requests_it() { - let provider = provider::default_provider(); - let server_config = Arc::new(make_server_config(KeyType::Rsa2048, &provider)); - - let mut root_cert_store = RootCertStore::empty(); - root_cert_store - .add(KeyType::Rsa2048.ca_cert()) - .unwrap(); - - let server_verifier = WebPkiServerVerifier::builder_with_provider( - Arc::new(root_cert_store), - Arc::new(provider.clone()), - ) - .build() - .unwrap(); - let cas_sending_server_verifier = Arc::new(ServerCertVerifierWithCasExt { - verifier: server_verifier.clone(), - ca_names: vec![ - KeyType::Rsa2048 - .ca_distinguished_name() - .to_vec() - .into(), - ], - }); - - for (protocol_version, cas_extension_expected) in [(&TLS12, false), (&TLS13, true)] { - let client_config = Arc::new( - client_config_builder_with_versions(&[protocol_version], &provider) - .dangerous() - .with_custom_certificate_verifier(cas_sending_server_verifier.clone()) - .with_no_client_auth(), - ); - - let expect_cas_extension = |msg: &mut Message<'_>| -> Altered { - if let MessagePayload::Handshake { parsed, .. } = &msg.payload { - if let HandshakePayload::ClientHello(ch) = &parsed.payload { - assert_eq!( - ch.extensions - .iter() - .any(|ext| matches!(ext, ClientExtension::AuthorityNames(_))), - cas_extension_expected - ); - println!( - "cas extension expectation met! cas_extension_expected: {cas_extension_expected}" - ); - } - } - Altered::InPlace - }; - - let (client, server) = make_pair_for_arc_configs(&client_config, &server_config); - let (mut client, mut server) = (client.into(), server.into()); - transfer_altered(&mut client, expect_cas_extension, &mut server); - } -} - #[test] fn client_can_request_certain_trusted_cas() { let provider = provider::default_provider(); From 67d324b05076246242294367dca6b9c962bef152 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 28 May 2025 16:55:59 +0100 Subject: [PATCH 258/403] Convert `test_raw_keys::alter_client_hello` into unit tests --- rustls/src/server/test.rs | 108 +++++++++++++++++++++++++++++++++++--- rustls/tests/api.rs | 81 +--------------------------- 2 files changed, 102 insertions(+), 87 deletions(-) diff --git a/rustls/src/server/test.rs b/rustls/src/server/test.rs index 5d02cf1fdbb..6beebd995fa 100644 --- a/rustls/src/server/test.rs +++ b/rustls/src/server/test.rs @@ -4,11 +4,12 @@ use std::vec; use super::ServerConnectionData; use crate::common_state::Context; use crate::enums::{CipherSuite, SignatureScheme}; +use crate::msgs::base::PayloadU16; use crate::msgs::codec::{Codec, LengthPrefixedBuffer, ListLength}; use crate::msgs::enums::{Compression, ExtensionType, NamedGroup}; use crate::msgs::handshake::{ - ClientExtension, ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, Random, - SessionId, + ClientExtension, ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, KeyShareEntry, + Random, SessionId, SupportedProtocolVersions, }; use crate::msgs::message::{Message, MessagePayload}; use crate::{ @@ -74,9 +75,11 @@ mod tests { use crate::crypto::{ ActiveKeyExchange, CryptoProvider, KeyExchangeAlgorithm, SupportedKxGroup, }; + use crate::msgs::enums::CertificateType; use crate::pki_types::pem::PemObject; use crate::pki_types::{CertificateDer, PrivateKeyDer}; - use crate::server::{ServerConfig, ServerConnection}; + use crate::server::{AlwaysResolvesServerRawPublicKeys, ServerConfig, ServerConnection}; + use crate::sign::CertifiedKey; use crate::sync::Arc; use crate::{CipherSuiteCommon, SupportedCipherSuite, Tls12CipherSuite, version}; @@ -98,14 +101,17 @@ mod tests { } let mut conn = ServerConnection::new(config.into()).unwrap(); - let sh = Message { + let mut ch = minimal_client_hello(); + ch.extensions + .retain(|ext| ext.ext_type() != ExtensionType::ExtendedMasterSecret); + let ch = Message { version: ProtocolVersion::TLSv1_3, payload: MessagePayload::handshake(HandshakeMessagePayload { typ: HandshakeType::ClientHello, - payload: HandshakePayload::ClientHello(minimal_client_hello()), + payload: HandshakePayload::ClientHello(ch), }), }; - conn.read_tls(&mut sh.into_wire_bytes().as_slice()) + conn.read_tls(&mut ch.into_wire_bytes().as_slice()) .unwrap(); assert_eq!( @@ -201,6 +207,82 @@ mod tests { 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 + .push(ClientExtension::ClientCertTypes(vec![ + CertificateType::X509, + ])); + let ch = Message { + version: ProtocolVersion::TLSv1_3, + payload: MessagePayload::handshake(HandshakeMessagePayload { + typ: HandshakeType::ClientHello, + payload: 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 + .push(ClientExtension::ServerCertTypes(vec![ + CertificateType::X509, + ])); + let ch = Message { + version: ProtocolVersion::TLSv1_3, + payload: MessagePayload::handshake(HandshakeMessagePayload { + typ: HandshakeType::ClientHello, + payload: 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(), @@ -281,11 +363,23 @@ fn minimal_client_hello() -> 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], + cipher_suites: vec![ + CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + CipherSuite::TLS13_AES_128_GCM_SHA256, + ], compression_methods: vec![Compression::Null], extensions: vec![ ClientExtension::SignatureAlgorithms(vec![SignatureScheme::RSA_PSS_SHA256]), ClientExtension::NamedGroups(vec![NamedGroup::X25519, NamedGroup::secp256r1]), + ClientExtension::SupportedVersions(SupportedProtocolVersions { + tls12: true, + tls13: true, + }), + ClientExtension::KeyShare(vec![KeyShareEntry { + group: NamedGroup::X25519, + payload: PayloadU16::new(vec![0xab; 32]), + }]), + ClientExtension::ExtendedMasterSecretRequest, ], } } diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index aea45487281..be861afd62d 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -15,7 +15,7 @@ use rustls::crypto::{ActiveKeyExchange, CryptoProvider, SharedSecret, SupportedK use rustls::internal::msgs::base::Payload; use rustls::internal::msgs::codec::Codec; use rustls::internal::msgs::enums::{AlertLevel, CertificateType, ExtensionType}; -use rustls::internal::msgs::handshake::{ClientExtension, HandshakePayload, ServerExtension}; +use rustls::internal::msgs::handshake::{HandshakePayload, ServerExtension}; use rustls::internal::msgs::message::{Message, MessagePayload, PlainMessage}; use rustls::server::{ClientHello, ParsedCertificate, ResolvesServerCert}; use rustls::{ @@ -166,54 +166,6 @@ mod test_raw_keys { } } - #[test] - fn alter_client_hello() { - connect_with_altered_certificate_type_extension( - true, - Some(&vec![CertificateType::X509]), - None, - Err(ErrorFromPeer::Server(Error::PeerIncompatible( - PeerIncompatible::IncorrectCertificateTypeExtension, - ))), - ); - connect_with_altered_certificate_type_extension( - true, - None, - Some(&vec![CertificateType::X509]), - Err(ErrorFromPeer::Server(Error::PeerIncompatible( - PeerIncompatible::IncorrectCertificateTypeExtension, - ))), - ); - } - - fn connect_with_altered_certificate_type_extension( - server_requires_raw_keys: bool, - server_cert_types: Option<&Vec>, - client_cert_types: Option<&Vec>, - expected_result: Result<(), ErrorFromPeer>, - ) { - let provider = provider::default_provider(); - for kt in KeyType::all_for_provider(&provider) { - let client_config = Arc::new(make_client_config(*kt, &provider)); - let server_config_rpk = match server_requires_raw_keys { - true => Arc::new(make_server_config_with_raw_key_support(*kt, &provider)), - false => Arc::new(make_server_config(*kt, &provider)), - }; - - // Alter Client Hello client certificate extension - let (client, server) = make_pair_for_arc_configs(&client_config, &server_config_rpk); - let cert_altered = do_handshake_altered( - client, - |_: &mut Message| -> Altered { Altered::InPlace }, - |msg: &mut Message| { - alter_client_hello_message(msg, server_cert_types, client_cert_types) - }, - server, - ); - assert_eq!(cert_altered, expected_result) - } - } - #[test] fn incorrectly_alter_server_hello() { let provider = provider::default_provider(); @@ -313,37 +265,6 @@ mod test_raw_keys { } } - fn alter_client_hello_message( - msg: &mut Message, - server_cert_types: Option<&Vec>, - client_cert_types: Option<&Vec>, - ) -> Altered { - if let MessagePayload::Handshake { parsed, encoded } = &mut msg.payload { - if let HandshakePayload::ClientHello(ch) = &mut parsed.payload { - for extension in ch.extensions.iter_mut() { - if let ClientExtension::ClientCertTypes(cert_type) = extension { - if let Some(client_cert_types) = client_cert_types { - cert_type.clear(); - if !client_cert_types.is_empty() { - cert_type.extend_from_slice(client_cert_types) - } - } - }; - if let ClientExtension::ServerCertTypes(cert_type) = extension { - if let Some(server_cert_types) = server_cert_types { - cert_type.clear(); - if !server_cert_types.is_empty() { - cert_type.extend_from_slice(server_cert_types) - } - } - }; - } - } - *encoded = Payload::new(parsed.get_encoding()); - } - Altered::InPlace - } - fn alter_server_hello_message( msg: &mut Message, server_cert_type: Option<&CertificateType>, From c975fa238655fe8f4e23f4f12d265ffcd43cee82 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 28 May 2025 18:12:45 +0100 Subject: [PATCH 259/403] Convert `test_raw_keys::incorrectly_alter_server_hello` into unit tests --- rustls/src/client/test.rs | 251 +++++++++++++++++++++++++++++++++++++- rustls/tests/api.rs | 214 +------------------------------- 2 files changed, 249 insertions(+), 216 deletions(-) diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs index f4726ab9481..faedaed364e 100644 --- a/rustls/src/client/test.rs +++ b/rustls/src/client/test.rs @@ -20,11 +20,21 @@ 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::msgs::handshake::ClientExtension; - use crate::pki_types::UnixTime; + use crate::client::AlwaysResolvesClientRawPublicKeys; + use crate::crypto::cipher::MessageEncrypter; + use crate::crypto::tls13::OkmBlock; + use crate::msgs::enums::CertificateType; + use crate::msgs::handshake::{ClientExtension, KeyShareEntry, ServerExtension}; + 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, version}; + use crate::{DigitallySignedStruct, DistinguishedName, KeyLog, version}; /// Tests that session_ticket(35) extension /// is not sent if the client does not support TLS 1.2. @@ -170,6 +180,149 @@ mod tests { } } + #[test] + fn test_client_requiring_rpk_rejects_server_that_only_offers_x509_id_by_omission() { + assert_eq!( + client_requiring_rpk_receives_server_ee(vec![]), + 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(vec![ServerExtension::ServerCertType( + CertificateType::X509 + )]), + 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(vec![ServerExtension::ServerCertType( + CertificateType::RawPublicKey + )]), + Err(PeerIncompatible::IncorrectCertificateTypeExtension.into()) + ); + } + + #[test] + fn test_client_requiring_rpk_rejects_server_that_only_demands_x509() { + assert_eq!( + client_requiring_rpk_receives_server_ee(vec![ + ServerExtension::ClientCertType(CertificateType::X509), + ServerExtension::ServerCertType(CertificateType::RawPublicKey) + ]), + Err(PeerIncompatible::IncorrectCertificateTypeExtension.into()) + ); + } + + #[test] + fn test_client_requiring_rpk_accepts_rpk_server() { + assert_eq!( + client_requiring_rpk_receives_server_ee(vec![ + ServerExtension::ClientCertType(CertificateType::RawPublicKey), + ServerExtension::ServerCertType(CertificateType::RawPublicKey) + ]), + Ok(()) + ); + } + + fn client_requiring_rpk_receives_server_ee( + encrypted_extensions: Vec, + ) -> 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 { + typ: HandshakeType::ServerHello, + payload: 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: vec![ServerExtension::KeyShare(KeyShareEntry { + group: NamedGroup::X25519, + payload: PayloadU16::new(vec![0xaa; 32]), + })], + }), + }), + }; + 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 { + typ: HandshakeType::EncryptedExtensions, + payload: HandshakePayload::EncryptedExtensions(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) -> 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); @@ -214,6 +367,98 @@ mod tests { 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 { + todo!() + } + + #[cfg_attr(coverage_nightly, coverage(off))] + fn verify_tls12_signature( + &self, + _message: &[u8], + _cert: &CertificateDer<'_>, + _dss: &DigitallySignedStruct, + ) -> Result { + todo!() + } + + #[cfg_attr(coverage_nightly, coverage(off))] + fn verify_tls13_signature( + &self, + _message: &[u8], + _cert: &CertificateDer<'_>, + _dss: &DigitallySignedStruct, + ) -> Result { + todo!() + } + + fn supported_verify_schemes(&self) -> Vec { + vec![SignatureScheme::RSA_PKCS1_SHA1] + } + + fn requires_raw_public_keys(&self) -> bool { + true + } + } + + #[derive(Debug)] + struct FakeServerCrypto { + server_handshake_secret: OnceLock>, + } + + impl FakeServerCrypto { + fn new() -> Self { + Self { + server_handshake_secret: OnceLock::new(), + } + } + + fn server_handshake_encrypter(&self) -> Box { + 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 diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index be861afd62d..37fa6561e72 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -15,7 +15,7 @@ use rustls::crypto::{ActiveKeyExchange, CryptoProvider, SharedSecret, SupportedK use rustls::internal::msgs::base::Payload; use rustls::internal::msgs::codec::Codec; use rustls::internal::msgs::enums::{AlertLevel, CertificateType, ExtensionType}; -use rustls::internal::msgs::handshake::{HandshakePayload, ServerExtension}; +use rustls::internal::msgs::handshake::HandshakePayload; use rustls::internal::msgs::message::{Message, MessagePayload, PlainMessage}; use rustls::server::{ClientHello, ParsedCertificate, ResolvesServerCert}; use rustls::{ @@ -47,14 +47,6 @@ use provider::sign::RsaSigningKey; use rustls::ProtocolVersion::TLSv1_2; mod test_raw_keys { - use rustls::crypto::cipher::{ - InboundOpaqueMessage, MessageDecrypter, MessageEncrypter, OutboundChunks, - OutboundPlainMessage, - }; - use rustls::crypto::tls13::OkmBlock; - use rustls::internal::{derive_traffic_iv, derive_traffic_key}; - use rustls::{Connection, Tls13CipherSuite}; - use super::*; #[test] @@ -165,210 +157,6 @@ mod test_raw_keys { } } } - - #[test] - fn incorrectly_alter_server_hello() { - let provider = provider::default_provider(); - for kt in KeyType::all_for_provider(&provider) { - let supported_suite = cipher_suite::TLS13_AES_256_GCM_SHA384; - - // Alter Server Hello server certificate extension and expect IncorrectCertificateTypeExtension error - let client_config_rpk = make_client_config_with_raw_key_support(*kt, &provider); - let server_config_rpk = make_server_config_with_raw_key_support(*kt, &provider); - add_keylog_and_do_altered_handshake( - client_config_rpk, - server_config_rpk, - supported_suite, - Some(&CertificateType::X509), - None, - Error::PeerIncompatible(PeerIncompatible::IncorrectCertificateTypeExtension), - ); - - // Alter Server Hello client certificate extension and expect IncorrectCertificateTypeExtension error - let client_config_rpk = make_client_config_with_raw_key_support(*kt, &provider); - let server_config_rpk = make_server_config_with_raw_key_support(*kt, &provider); - add_keylog_and_do_altered_handshake( - client_config_rpk, - server_config_rpk, - supported_suite, - None, - Some(&CertificateType::X509), - Error::PeerIncompatible(PeerIncompatible::IncorrectCertificateTypeExtension), - ); - - // Alter Server Hello server certificate extension and expect UnexpectedCertificateTypeExtension error - let client_config = make_client_config(*kt, &provider); - let server_config_rpk = make_server_config(*kt, &provider); - add_keylog_and_do_altered_handshake( - client_config, - server_config_rpk, - supported_suite, - Some(&CertificateType::X509), - None, - Error::PeerMisbehaved(PeerMisbehaved::UnsolicitedEncryptedExtension), - ); - - // Alter Server Hello client certificate extension and expect UnexpectedCertificateTypeExtension error - let client_config = make_client_config(*kt, &provider); - let server_config_rpk = make_server_config(*kt, &provider); - add_keylog_and_do_altered_handshake( - client_config, - server_config_rpk, - supported_suite, - None, - Some(&CertificateType::X509), - Error::PeerMisbehaved(PeerMisbehaved::UnsolicitedEncryptedExtension), - ); - } - } - - fn add_keylog_and_do_altered_handshake( - client_config: ClientConfig, - mut server_config: ServerConfig, - supported_suite: SupportedCipherSuite, - server_cert_type: Option<&CertificateType>, - client_cert_type: Option<&CertificateType>, - expected_error: Error, - ) { - let keylog_to_vec = Arc::new(KeyLogToVec::new("server")); - server_config.key_log = keylog_to_vec.clone(); - - let (mut client, mut server) = make_pair_for_configs(client_config, server_config); - - // Client -> Server (Client Hello) - transfer(&mut client, &mut server); - server - .process_new_packets() - .map_err(ErrorFromPeer::Server) - .unwrap(); - - // Server -> Client (Server Hello, Server Change Cipher Spec, Server Encrypted Extensions, etc) - let mut server = Connection::Server(server); - let mut client = Connection::Client(client); - transfer_altered( - &mut server, - |msg| { - alter_server_hello_message( - msg, - server_cert_type, - client_cert_type, - supported_suite, - &keylog_to_vec, - ) - }, - &mut client, - ); - - match client.process_new_packets() { - Ok(_) => unreachable!("Expected error because server cert is altered"), - Err(err) => assert_eq!(err, expected_error), - } - } - - fn alter_server_hello_message( - msg: &mut Message, - server_cert_type: Option<&CertificateType>, - client_cert_type: Option<&CertificateType>, - cipher_suite: SupportedCipherSuite, - keylog_to_vec: &Arc, - ) -> Altered { - if msg.payload.content_type() != ContentType::ApplicationData { - // transfer_altered will forward multiple messages, but we are only interested in - // application data, which contains the server's encrypted extensions - return Altered::InPlace; - } - - // Derive Encrypter and Decrypter from the keylog and cipher suite - let (mut encrypter, mut decrypter) = - derive_message_encrypter_and_decrypter(cipher_suite.tls13().unwrap(), keylog_to_vec); - - // Decrypt raw payload - let mut raw_payload = Vec::new(); - msg.payload.encode(&mut raw_payload); - let mut bytes = raw_payload.clone(); - let incoming = InboundOpaqueMessage::new( - ContentType::ApplicationData, - ProtocolVersion::TLSv1_3, - &mut bytes, - ); - let decrypted_msg = decrypter.decrypt(incoming, 0).unwrap(); - - // Manipulate Message - let mut msg = Message::try_from(decrypted_msg).unwrap(); - - let encoded = if let MessagePayload::Handshake { parsed, .. } = &mut msg.payload { - if let HandshakePayload::EncryptedExtensions(enc_ext) = &mut parsed.payload { - let mut sct_present = false; - let mut cct_present = false; - for extension in enc_ext.iter_mut() { - if let ServerExtension::ClientCertType(cert_type) = extension { - if let Some(cct) = client_cert_type { - *cert_type = *cct; - } - cct_present = true; - }; - if let ServerExtension::ServerCertType(cert_type) = extension { - if let Some(sct) = server_cert_type { - *cert_type = *sct; - } - sct_present = true; - }; - } - if !sct_present { - if let Some(sct) = server_cert_type { - enc_ext.push(ServerExtension::ServerCertType(*sct)); - } - } - if !cct_present { - if let Some(cct) = client_cert_type { - enc_ext.push(ServerExtension::ClientCertType(*cct)); - } - } - } - Payload::new(parsed.get_encoding()) - } else { - panic!("Expected to successfully encode handshake message"); - }; - - // // Re-encrypt - let outgoing = OutboundPlainMessage { - typ: ContentType::Handshake, - version: ProtocolVersion::TLSv1_3, - payload: OutboundChunks::Single(encoded.bytes()), - }; - Altered::Raw( - encrypter - .encrypt(outgoing, 0) - .unwrap() - .encode(), - ) - } - - fn derive_message_encrypter_and_decrypter( - cipher_suite: &Tls13CipherSuite, - keylog_to_vec: &Arc, - ) -> (Box, Box) { - let keylog_vec = keylog_to_vec.take(); - let keylog_item = keylog_vec - .iter() - .find(|item| item.label == "SERVER_HANDSHAKE_TRAFFIC_SECRET") - .unwrap(); - let expander = cipher_suite - .hkdf_provider - .expander_for_okm(&OkmBlock::new(&keylog_item.secret)); - - // Derive Encrypter - let key = derive_traffic_key(expander.as_ref(), cipher_suite.aead_alg); - let iv = derive_traffic_iv(expander.as_ref()); - let encrypter = cipher_suite.aead_alg.encrypter(key, iv); - - // Derive Decrypter - let key = derive_traffic_key(expander.as_ref(), cipher_suite.aead_alg); - let iv = derive_traffic_iv(expander.as_ref()); - let decrypter = cipher_suite.aead_alg.decrypter(key, iv); - - (encrypter, decrypter) - } } fn alpn_test_error( From 91cf9a74c33647a4a09e07e791cf955fa4ace696 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 29 May 2025 11:14:34 +0100 Subject: [PATCH 260/403] Convert `test_client_with_custom_verifier_can_accept_ecdsa_sha1_signatures` to unit test --- rustls/src/client/test.rs | 145 +++++++++++++++++++++++++++++++++++++- rustls/tests/api.rs | 55 --------------- 2 files changed, 143 insertions(+), 57 deletions(-) diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs index faedaed364e..71d0407e6ef 100644 --- a/rustls/src/client/test.rs +++ b/rustls/src/client/test.rs @@ -1,4 +1,5 @@ #![cfg(any(feature = "ring", feature = "aws_lc_rs"))] +use core::sync::atomic::{AtomicBool, Ordering}; use std::prelude::v1::*; use std::vec; @@ -26,8 +27,12 @@ mod tests { use crate::client::AlwaysResolvesClientRawPublicKeys; use crate::crypto::cipher::MessageEncrypter; use crate::crypto::tls13::OkmBlock; - use crate::msgs::enums::CertificateType; - use crate::msgs::handshake::{ClientExtension, KeyShareEntry, ServerExtension}; + use crate::msgs::base::PayloadU8; + use crate::msgs::enums::{CertificateType, ECCurveType}; + use crate::msgs::handshake::{ + CertificateChain, ClientExtension, EcParameters, KeyShareEntry, ServerEcdhParams, + ServerExtension, ServerKeyExchange, ServerKeyExchangeParams, ServerKeyExchangePayload, + }; use crate::msgs::message::PlainMessage; use crate::pki_types::pem::PemObject; use crate::pki_types::{PrivateKeyDer, UnixTime}; @@ -180,6 +185,142 @@ mod tests { } } + /// Regression test for + #[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 { + typ: HandshakeType::ServerHello, + payload: 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: vec![ServerExtension::ExtendedMasterSecretAck], + }), + }), + }; + 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 { + typ: HandshakeType::Certificate, + payload: 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 { + typ: HandshakeType::ServerKeyExchange, + payload: 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 { + typ: HandshakeType::ServerHelloDone, + payload: 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 { + Ok(ServerCertVerified::assertion()) + } + + fn verify_tls12_signature( + &self, + _message: &[u8], + _cert: &CertificateDer<'_>, + dss: &DigitallySignedStruct, + ) -> Result { + 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 { + todo!() + } + + fn supported_verify_schemes(&self) -> Vec { + vec![SignatureScheme::ECDSA_SHA1_Legacy] + } + } + #[test] fn test_client_requiring_rpk_rejects_server_that_only_offers_x509_id_by_omission() { assert_eq!( diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 37fa6561e72..f3122e5a856 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -15,7 +15,6 @@ use rustls::crypto::{ActiveKeyExchange, CryptoProvider, SharedSecret, SupportedK use rustls::internal::msgs::base::Payload; use rustls::internal::msgs::codec::Codec; use rustls::internal::msgs::enums::{AlertLevel, CertificateType, ExtensionType}; -use rustls::internal::msgs::handshake::HandshakePayload; use rustls::internal::msgs::message::{Message, MessagePayload, PlainMessage}; use rustls::server::{ClientHello, ParsedCertificate, ResolvesServerCert}; use rustls::{ @@ -6204,60 +6203,6 @@ fn test_client_tls12_no_resume_after_server_downgrade() { ); } -#[cfg(feature = "tls12")] -#[test] -fn test_client_with_custom_verifier_can_accept_ecdsa_sha1_signatures() { - fn alter_server_signature_to_ecdsa_sha1(msg: &mut Message) -> Altered { - if let MessagePayload::Handshake { parsed, encoded } = &mut msg.payload { - if let HandshakePayload::ServerKeyExchange(_) = &mut parsed.payload { - // nb. we don't care that this corrupts the signature, key exchange, etc. - let original = encoded.bytes(); - let offset = 40; // of signature scheme - assert_eq!( - &original[offset..offset + 2], - &SignatureScheme::ECDSA_NISTP256_SHA256.to_array(), - "expected ecdsa-sha256" - ); - let mut altered = original.to_vec(); - altered[offset..offset + 2] - .copy_from_slice(&SignatureScheme::ECDSA_SHA1_Legacy.to_array()); - - *encoded = Payload::new(altered); - } - } - Altered::InPlace - } - - let kx_groups = provider::ALL_KX_GROUPS; - let client_config = ClientConfig::builder_with_provider( - CryptoProvider { - kx_groups: kx_groups.to_vec(), - ..provider::default_provider() - } - .into(), - ) - .with_protocol_versions(&[&rustls::version::TLS12]) - .unwrap() - .dangerous() - .with_custom_certificate_verifier(Arc::new(MockServerVerifier::accepts_anything())) - .with_no_client_auth(); - let server_config = make_server_config_with_kx_groups( - KeyType::EcdsaP256, - kx_groups.to_vec(), - &provider::default_provider(), - ); - let (mut client, mut server) = make_pair_for_configs(client_config, server_config); - transfer(&mut client, &mut server); - server.process_new_packets().unwrap(); - let (mut client, mut server) = (client.into(), server.into()); - transfer_altered( - &mut server, - alter_server_signature_to_ecdsa_sha1, - &mut client, - ); - client.process_new_packets().unwrap(); -} - #[test] fn test_acceptor() { use rustls::server::Acceptor; From f9335b58b4ed8872e85b1af57cde8629cc7dea64 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 29 May 2025 11:14:55 +0100 Subject: [PATCH 261/403] tests/api: minor clean-up of ProtocolVersion enum use --- rustls/tests/api.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index f3122e5a856..f3559d97afb 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -43,7 +43,6 @@ mod common; use common::*; use provider::cipher_suite; use provider::sign::RsaSigningKey; -use rustls::ProtocolVersion::TLSv1_2; mod test_raw_keys { use super::*; @@ -783,7 +782,7 @@ fn resumption_combinations() { assert_eq!(client.handshake_kind(), Some(HandshakeKind::Resumed)); assert_eq!(server.handshake_kind(), Some(HandshakeKind::Resumed)); - if version.version == TLSv1_2 { + if version.version == ProtocolVersion::TLSv1_2 { assert!( client .negotiated_key_exchange_group() From 598f6319cb626fd903e4ad1771b9fe2e5e8a5aed Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 29 May 2025 11:40:13 +0100 Subject: [PATCH 262/403] Withdraw unnecessary types from `rustls::internals` --- rustls/src/lib.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 451036b0016..248ec9719ec 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -477,8 +477,7 @@ pub mod internal { } pub mod enums { pub use crate::msgs::enums::{ - AlertLevel, CertificateType, Compression, EchVersion, ExtensionType, HpkeAead, - HpkeKdf, HpkeKem, NamedGroup, + AlertLevel, CertificateType, EchVersion, ExtensionType, HpkeAead, HpkeKdf, HpkeKem, }; } pub mod fragmenter { @@ -486,10 +485,7 @@ pub mod internal { } pub mod handshake { pub use crate::msgs::handshake::{ - CertificateChain, ClientExtension, ClientHelloPayload, DistinguishedName, - EchConfigContents, EchConfigPayload, HandshakeMessagePayload, HandshakePayload, - HpkeKeyConfig, HpkeSymmetricCipherSuite, KeyShareEntry, Random, ServerExtension, - SessionId, + EchConfigContents, EchConfigPayload, HpkeKeyConfig, HpkeSymmetricCipherSuite, }; } pub mod message { From 2e7f326742ceae60bcacf58c1f631fa1535c4be2 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 29 May 2025 11:42:39 +0100 Subject: [PATCH 263/403] Promote `CertificateType` enum to public API Since 99447957 this has appeared in the public API, in the return types of `server::ClientHello::server_cert_types()` and `server::ClientHello::client_cert_types()`. Move its definition into `crate::enums`. --- rustls/src/client/hs.rs | 8 ++++---- rustls/src/client/test.rs | 3 ++- rustls/src/enums.rs | 14 ++++++++++++++ rustls/src/lib.rs | 3 ++- rustls/src/msgs/enums.rs | 14 -------------- rustls/src/msgs/handshake.rs | 10 +++++----- rustls/src/msgs/handshake_test.rs | 5 +++-- rustls/src/server/hs.rs | 6 +++--- rustls/src/server/server_conn.rs | 3 +-- rustls/src/server/test.rs | 2 +- rustls/tests/api.rs | 4 ++-- 11 files changed, 37 insertions(+), 35 deletions(-) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index ca6e5efecd0..92e7c5defba 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -20,14 +20,14 @@ 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, CipherSuite, ContentType, HandshakeType, ProtocolVersion}; +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::{ - CertificateType, Compression, ECPointFormat, ExtensionType, PskKeyExchangeMode, -}; +use crate::msgs::enums::{Compression, ECPointFormat, ExtensionType, PskKeyExchangeMode}; use crate::msgs::handshake::{ CertificateStatusRequest, ClientExtension, ClientHelloPayload, ClientSessionTicket, HandshakeMessagePayload, HandshakePayload, HasServerExtensions, HelloRetryRequest, diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs index 71d0407e6ef..6f353a81cdb 100644 --- a/rustls/src/client/test.rs +++ b/rustls/src/client/test.rs @@ -27,8 +27,9 @@ mod tests { 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::{CertificateType, ECCurveType}; + use crate::msgs::enums::ECCurveType; use crate::msgs::handshake::{ CertificateChain, ClientExtension, EcParameters, KeyShareEntry, ServerEcdhParams, ServerExtension, ServerKeyExchange, ServerKeyExchangeParams, ServerKeyExchangePayload, diff --git a/rustls/src/enums.rs b/rustls/src/enums.rs index a2997ec56e3..2290b73b107 100644 --- a/rustls/src/enums.rs +++ b/rustls/src/enums.rs @@ -604,6 +604,19 @@ enum_builder! { } } +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]: + /// [RFC 7250 Section 7]: + #[repr(u8)] + pub enum CertificateType { + X509 => 0x00, + RawPublicKey => 0x02, + } +} + enum_builder! { /// The type of Encrypted Client Hello (`EchClientHelloType`). /// @@ -635,6 +648,7 @@ mod tests { CertificateCompressionAlgorithm::Zlib, CertificateCompressionAlgorithm::Zstd, ); + test_enum8::(CertificateType::X509, CertificateType::RawPublicKey); } #[test] diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 248ec9719ec..845f4e94de0 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -477,7 +477,7 @@ pub mod internal { } pub mod enums { pub use crate::msgs::enums::{ - AlertLevel, CertificateType, EchVersion, ExtensionType, HpkeAead, HpkeKdf, HpkeKem, + AlertLevel, EchVersion, ExtensionType, HpkeAead, HpkeKdf, HpkeKem, }; } pub mod fragmenter { @@ -647,6 +647,7 @@ pub mod server { #[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, diff --git a/rustls/src/msgs/enums.rs b/rustls/src/msgs/enums.rs index 6bf255781c5..0be5c7f6abb 100644 --- a/rustls/src/msgs/enums.rs +++ b/rustls/src/msgs/enums.rs @@ -312,19 +312,6 @@ enum_builder! { } } -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]: - /// [RFC 7250 Section 7]: - #[repr(u8)] - pub enum CertificateType { - X509 => 0x00, - RawPublicKey => 0x02, - } -} - enum_builder! { /// The Key Encapsulation Mechanism (`Kem`) type for HPKE operations. /// Listed by IANA, as specified in [RFC 9180 Section 7.1] @@ -457,7 +444,6 @@ pub(crate) mod tests { CertificateStatusType::OCSP, CertificateStatusType::OCSP, ); - test_enum8::(CertificateType::X509, CertificateType::RawPublicKey); } pub(crate) fn test_enum8 Codec<'a>>(first: T, last: T) { diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index aefcc0c2845..ff32eaf8ecb 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -12,8 +12,8 @@ use pki_types::{CertificateDer, DnsName}; use crate::crypto::ActiveKeyExchange; use crate::crypto::SecureRandom; use crate::enums::{ - CertificateCompressionAlgorithm, CipherSuite, EchClientHelloType, HandshakeType, - ProtocolVersion, SignatureScheme, + CertificateCompressionAlgorithm, CertificateType, CipherSuite, EchClientHelloType, + HandshakeType, ProtocolVersion, SignatureScheme, }; use crate::error::InvalidMessage; #[cfg(feature = "tls12")] @@ -22,9 +22,9 @@ use crate::log::warn; use crate::msgs::base::{MaybeEmpty, NonEmpty, Payload, PayloadU8, PayloadU16, PayloadU24}; use crate::msgs::codec::{self, Codec, LengthPrefixedBuffer, ListLength, Reader, TlsListElement}; use crate::msgs::enums::{ - CertificateStatusType, CertificateType, ClientCertificateType, Compression, ECCurveType, - ECPointFormat, EchVersion, ExtensionType, HpkeAead, HpkeKdf, HpkeKem, KeyUpdateRequest, - NamedGroup, PskKeyExchangeMode, ServerNameType, + CertificateStatusType, ClientCertificateType, Compression, ECCurveType, ECPointFormat, + EchVersion, ExtensionType, HpkeAead, HpkeKdf, HpkeKem, KeyUpdateRequest, NamedGroup, + PskKeyExchangeMode, ServerNameType, }; use crate::rand; use crate::sync::Arc; diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index e90546bde27..46bc9132153 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -6,7 +6,7 @@ use pki_types::{CertificateDer, DnsName}; use super::base::{Payload, PayloadU8, PayloadU16, PayloadU24}; use super::codec::{Codec, Reader, put_u16}; use super::enums::{ - CertificateType, ClientCertificateType, Compression, ECCurveType, ECPointFormat, ExtensionType, + ClientCertificateType, Compression, ECCurveType, ECPointFormat, ExtensionType, KeyUpdateRequest, NamedGroup, PskKeyExchangeMode, }; use super::handshake::{ @@ -22,7 +22,8 @@ use super::handshake::{ SingleProtocolName, SupportedProtocolVersions, UnknownExtension, }; use crate::enums::{ - CertificateCompressionAlgorithm, CipherSuite, HandshakeType, ProtocolVersion, SignatureScheme, + CertificateCompressionAlgorithm, CertificateType, CipherSuite, HandshakeType, ProtocolVersion, + SignatureScheme, }; use crate::error::InvalidMessage; use crate::msgs::handshake::ServerNamePayload; diff --git a/rustls/src/server/hs.rs b/rustls/src/server/hs.rs index b3c0e9a1b27..e3939a05540 100644 --- a/rustls/src/server/hs.rs +++ b/rustls/src/server/hs.rs @@ -11,13 +11,13 @@ use crate::common_state::{KxState, Protocol, State}; use crate::conn::ConnectionRandoms; use crate::crypto::SupportedKxGroup; use crate::enums::{ - AlertDescription, CipherSuite, HandshakeType, ProtocolVersion, SignatureAlgorithm, - SignatureScheme, + 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::{CertificateType, Compression, ExtensionType, NamedGroup}; +use crate::msgs::enums::{Compression, ExtensionType, NamedGroup}; #[cfg(feature = "tls12")] use crate::msgs::handshake::SessionId; use crate::msgs::handshake::{ diff --git a/rustls/src/server/server_conn.rs b/rustls/src/server/server_conn.rs index ee6830ab188..669baa565ea 100644 --- a/rustls/src/server/server_conn.rs +++ b/rustls/src/server/server_conn.rs @@ -20,12 +20,11 @@ use crate::conn::{ConnectionCommon, ConnectionCore, UnbufferedConnectionCommon}; #[cfg(doc)] use crate::crypto; use crate::crypto::CryptoProvider; -use crate::enums::{CipherSuite, ProtocolVersion, SignatureScheme}; +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::enums::CertificateType; use crate::msgs::handshake::{ClientHelloPayload, ProtocolName, ServerExtension}; use crate::msgs::message::Message; use crate::suites::ExtractedSecrets; diff --git a/rustls/src/server/test.rs b/rustls/src/server/test.rs index 6beebd995fa..d50d19ff11d 100644 --- a/rustls/src/server/test.rs +++ b/rustls/src/server/test.rs @@ -75,7 +75,7 @@ mod tests { use crate::crypto::{ ActiveKeyExchange, CryptoProvider, KeyExchangeAlgorithm, SupportedKxGroup, }; - use crate::msgs::enums::CertificateType; + use crate::enums::CertificateType; use crate::pki_types::pem::PemObject; use crate::pki_types::{CertificateDer, PrivateKeyDer}; use crate::server::{AlwaysResolvesServerRawPublicKeys, ServerConfig, ServerConnection}; diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index f3559d97afb..d6fa8bda19e 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -14,9 +14,9 @@ use rustls::client::{ResolvesClientCert, Resumption, verify_server_cert_signed_b use rustls::crypto::{ActiveKeyExchange, CryptoProvider, SharedSecret, SupportedKxGroup}; use rustls::internal::msgs::base::Payload; use rustls::internal::msgs::codec::Codec; -use rustls::internal::msgs::enums::{AlertLevel, CertificateType, ExtensionType}; +use rustls::internal::msgs::enums::{AlertLevel, ExtensionType}; use rustls::internal::msgs::message::{Message, MessagePayload, PlainMessage}; -use rustls::server::{ClientHello, ParsedCertificate, ResolvesServerCert}; +use rustls::server::{CertificateType, ClientHello, ParsedCertificate, ResolvesServerCert}; use rustls::{ AlertDescription, CertificateError, CipherSuite, ClientConfig, ClientConnection, ConnectionCommon, ConnectionTrafficSecrets, ContentType, DistinguishedName, Error, From 24957ce1a799aca7febd95978fdee745a492dd1e Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 2 Jun 2025 15:38:10 +0100 Subject: [PATCH 264/403] Eliminate redundant `HandshakeMessagePayload::typ` field We encode the handshake type in the `HandshakePayload` variant, so repeating it is duplicative. `HandshakeMessagePayload` itself is retained as a privacy barrier for `HandshakePayload`. --- rustls/src/check.rs | 19 +-- rustls/src/client/ech.rs | 32 ++-- rustls/src/client/hs.rs | 17 +- rustls/src/client/test.rs | 68 +++----- rustls/src/client/tls12.rs | 51 ++---- rustls/src/client/tls13.rs | 98 +++-------- rustls/src/hash_hs.rs | 9 +- rustls/src/msgs/handshake.rs | 76 ++++++--- rustls/src/msgs/handshake_test.rs | 274 +++++++++++------------------- rustls/src/msgs/message/mod.rs | 16 +- rustls/src/server/server_conn.rs | 3 +- rustls/src/server/test.rs | 39 ++--- rustls/src/server/tls12.rs | 64 +++---- rustls/src/server/tls13.rs | 87 +++------- 14 files changed, 323 insertions(+), 530 deletions(-) diff --git a/rustls/src/check.rs b/rustls/src/check.rs index aae5ff6c202..beb70aa2805 100644 --- a/rustls/src/check.rs +++ b/rustls/src/check.rs @@ -10,10 +10,9 @@ use crate::msgs::message::MessagePayload; macro_rules! require_handshake_msg( ( $m:expr, $handshake_type:path, $payload_type:path ) => ( match &$m.payload { - MessagePayload::Handshake { parsed: $crate::msgs::handshake::HandshakeMessagePayload { - payload: $payload_type(hm), - .. - }, .. } => Ok(hm), + MessagePayload::Handshake { parsed: $crate::msgs::handshake::HandshakeMessagePayload( + $payload_type(hm), + ), .. } => Ok(hm), payload => Err($crate::check::inappropriate_handshake_message( payload, &[$crate::ContentType::Handshake], @@ -26,10 +25,9 @@ macro_rules! require_handshake_msg( 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: $payload_type(hm), - .. - }, .. } => Ok(hm), + MessagePayload::Handshake { parsed: $crate::msgs::handshake::HandshakeMessagePayload( + $payload_type(hm), + ), .. } => Ok(hm), payload => Err($crate::check::inappropriate_handshake_message( &payload, @@ -61,13 +59,14 @@ pub(crate) fn inappropriate_handshake_message( ) -> Error { match payload { MessagePayload::Handshake { parsed, .. } => { + let got_type = parsed.0.handshake_type(); warn!( "Received a {:?} handshake message while expecting {:?}", - parsed.typ, handshake_types + got_type, handshake_types ); Error::InappropriateHandshakeMessage { expect_types: handshake_types.to_vec(), - got_type: parsed.typ, + got_type, } } payload => inappropriate_message(payload, content_types), diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index 80acff93941..5df50ccdb3c 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -28,8 +28,8 @@ use crate::tls13::key_schedule::{ KeyScheduleEarly, KeyScheduleHandshakeStart, server_ech_hrr_confirmation_secret, }; use crate::{ - AlertDescription, CommonState, EncryptedClientHelloError, Error, HandshakeType, - PeerIncompatible, PeerMisbehaved, ProtocolVersion, Tls13CipherSuite, + AlertDescription, CommonState, EncryptedClientHelloError, Error, PeerIncompatible, + PeerMisbehaved, ProtocolVersion, Tls13CipherSuite, }; /// Controls how Encrypted Client Hello (ECH) is used in a client handshake. @@ -664,10 +664,7 @@ impl EchState { // 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 { - typ: HandshakeType::ClientHello, - payload: HandshakePayload::ClientHello(inner_hello), - }; + 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( @@ -678,7 +675,7 @@ impl EchState { // 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.payload { + inner_hello = match chp.0 { HandshakePayload::ClientHello(chp) => chp, // Safety: we construct the HMP above and know its type unconditionally. _ => unreachable!(), @@ -733,10 +730,9 @@ impl EchState { // (retryreq == None means we're in the "initial ClientHello" case) None => ProtocolVersion::TLSv1_0, }, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::ClientHello, - payload: HandshakePayload::ClientHello(inner_hello), - }), + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::ClientHello(inner_hello), + )), }; // Update the inner transcript buffer with the inner hello message. @@ -779,17 +775,15 @@ impl EchState { } fn server_hello_conf(server_hello: &ServerHelloPayload) -> Message<'_> { - Self::ech_conf_message(HandshakeMessagePayload { - typ: HandshakeType::ServerHello, - payload: HandshakePayload::ServerHello(server_hello.clone()), - }) + Self::ech_conf_message(HandshakeMessagePayload(HandshakePayload::ServerHello( + server_hello.clone(), + ))) } fn hello_retry_request_conf(retry_req: &HelloRetryRequest) -> Message<'_> { - Self::ech_conf_message(HandshakeMessagePayload { - typ: HandshakeType::HelloRetryRequest, - payload: HandshakePayload::HelloRetryRequest(retry_req.clone()), - }) + Self::ech_conf_message(HandshakeMessagePayload( + HandshakePayload::HelloRetryRequest(retry_req.clone()), + )) } fn ech_conf_message(hmp: HandshakeMessagePayload<'_>) -> Message<'_> { diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 92e7c5defba..842355d7b7b 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -504,10 +504,7 @@ fn emit_client_hello_for_retry( .map(ClientExtension::ext_type) .collect(); - let mut chp = HandshakeMessagePayload { - typ: HandshakeType::ClientHello, - payload: HandshakePayload::ClientHello(chp_payload), - }; + 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 @@ -1187,21 +1184,13 @@ impl State for ExpectServerHelloOrHelloRetryRequest { { match m.payload { MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - payload: HandshakePayload::ServerHello(..), - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::ServerHello(..)), .. } => self .into_expect_server_hello() .handle(cx, m), MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - payload: HandshakePayload::HelloRetryRequest(..), - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::HelloRetryRequest(..)), .. } => self.handle_hello_retry_request(cx, m), payload => Err(inappropriate_handshake_message( diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs index 6f353a81cdb..dc52311280a 100644 --- a/rustls/src/client/test.rs +++ b/rustls/src/client/test.rs @@ -7,7 +7,7 @@ use pki_types::{CertificateDer, ServerName}; use crate::client::{ClientConfig, ClientConnection, Resumption, Tls12Resumption}; use crate::crypto::CryptoProvider; -use crate::enums::{CipherSuite, HandshakeType, ProtocolVersion, SignatureScheme}; +use crate::enums::{CipherSuite, ProtocolVersion, SignatureScheme}; use crate::msgs::base::PayloadU16; use crate::msgs::codec::Reader; use crate::msgs::enums::{Compression, NamedGroup}; @@ -93,9 +93,8 @@ mod tests { // server replies with HRR, but does not echo `session_id` as required. let hrr = Message { version: ProtocolVersion::TLSv1_3, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::HelloRetryRequest, - payload: HandshakePayload::HelloRetryRequest(HelloRetryRequest { + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::HelloRetryRequest(HelloRetryRequest { cipher_suite: CipherSuite::TLS13_AES_128_GCM_SHA256, legacy_version: ProtocolVersion::TLSv1_2, session_id: SessionId::empty(), @@ -103,7 +102,7 @@ mod tests { 1, 2, 3, 4, ]))], }), - }), + )), }; conn.read_tls(&mut hrr.into_wire_bytes().as_slice()) @@ -138,9 +137,8 @@ mod tests { let sh = Message { version: ProtocolVersion::TLSv1_3, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::ServerHello, - payload: HandshakePayload::ServerHello(ServerHelloPayload { + 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, @@ -148,7 +146,7 @@ mod tests { session_id: SessionId::empty(), extensions: vec![], }), - }), + )), }; conn.read_tls(&mut sh.into_wire_bytes().as_slice()) .unwrap(); @@ -206,9 +204,8 @@ mod tests { let sh = Message { version: ProtocolVersion::TLSv1_2, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::ServerHello, - payload: HandshakePayload::ServerHello(ServerHelloPayload { + 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, @@ -216,7 +213,7 @@ mod tests { session_id: SessionId::empty(), extensions: vec![ServerExtension::ExtendedMasterSecretAck], }), - }), + )), }; conn.read_tls(&mut sh.into_wire_bytes().as_slice()) .unwrap(); @@ -224,12 +221,11 @@ mod tests { let cert = Message { version: ProtocolVersion::TLSv1_2, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::Certificate, - payload: HandshakePayload::Certificate(CertificateChain(vec![ - CertificateDer::from(&b"does not matter"[..]), - ])), - }), + 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(); @@ -237,9 +233,8 @@ mod tests { let server_kx = Message { version: ProtocolVersion::TLSv1_2, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::ServerKeyExchange, - payload: HandshakePayload::ServerKeyExchange(ServerKeyExchangePayload::Known( + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::ServerKeyExchange(ServerKeyExchangePayload::Known( ServerKeyExchange { dss: DigitallySignedStruct::new( SignatureScheme::ECDSA_SHA1_Legacy, @@ -254,7 +249,7 @@ mod tests { }), }, )), - }), + )), }; conn.read_tls(&mut server_kx.into_wire_bytes().as_slice()) .unwrap(); @@ -262,10 +257,9 @@ mod tests { let server_done = Message { version: ProtocolVersion::TLSv1_2, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::ServerHelloDone, - payload: HandshakePayload::ServerHelloDone, - }), + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::ServerHelloDone, + )), }; conn.read_tls(&mut server_done.into_wire_bytes().as_slice()) .unwrap(); @@ -386,9 +380,8 @@ mod tests { let sh = Message { version: ProtocolVersion::TLSv1_3, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::ServerHello, - payload: HandshakePayload::ServerHello(ServerHelloPayload { + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::ServerHello(ServerHelloPayload { random: Random([0; 32]), compression_method: Compression::Null, cipher_suite: CipherSuite::TLS13_AES_128_GCM_SHA256, @@ -399,7 +392,7 @@ mod tests { payload: PayloadU16::new(vec![0xaa; 32]), })], }), - }), + )), }; conn.read_tls(&mut sh.into_wire_bytes().as_slice()) .unwrap(); @@ -407,10 +400,9 @@ mod tests { let ee = Message { version: ProtocolVersion::TLSv1_3, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::EncryptedExtensions, - payload: HandshakePayload::EncryptedExtensions(encrypted_extensions), - }), + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::EncryptedExtensions(encrypted_extensions), + )), }; let mut encrypter = fake_server_crypto.server_handshake_encrypter(); @@ -662,11 +654,7 @@ fn client_hello_sent_for_config(config: ClientConfig) -> Result for ExpectCertificateStatusOrServerKx<'_> { { match m.payload { MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - payload: HandshakePayload::ServerKeyExchange(..), - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::ServerKeyExchange(..)), .. } => Box::new(ExpectServerKx { config: self.config, @@ -300,11 +296,7 @@ impl State for ExpectCertificateStatusOrServerKx<'_> { }) .handle(cx, m), MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - payload: HandshakePayload::CertificateStatus(..), - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::CertificateStatus(..)), .. } => Box::new(ExpectCertificateStatus { config: self.config, @@ -506,10 +498,9 @@ fn emit_certificate( ) { let cert = Message { version: ProtocolVersion::TLSv1_2, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::Certificate, - payload: HandshakePayload::Certificate(cert_chain), - }), + payload: MessagePayload::handshake(HandshakeMessagePayload(HandshakePayload::Certificate( + cert_chain, + ))), }; transcript.add_message(&cert); @@ -536,10 +527,9 @@ fn emit_client_kx( let ckx = Message { version: ProtocolVersion::TLSv1_2, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::ClientKeyExchange, - payload: HandshakePayload::ClientKeyExchange(pubkey), - }), + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::ClientKeyExchange(pubkey), + )), }; transcript.add_message(&ckx); @@ -561,10 +551,9 @@ fn emit_certverify( let m = Message { version: ProtocolVersion::TLSv1_2, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::CertificateVerify, - payload: HandshakePayload::CertificateVerify(body), - }), + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::CertificateVerify(body), + )), }; transcript.add_message(&m); @@ -592,10 +581,9 @@ fn emit_finished( let f = Message { version: ProtocolVersion::TLSv1_2, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::Finished, - payload: HandshakePayload::Finished(verify_data_payload), - }), + payload: MessagePayload::handshake(HandshakeMessagePayload(HandshakePayload::Finished( + verify_data_payload, + ))), }; transcript.add_message(&f); @@ -645,10 +633,7 @@ impl State for ExpectServerDoneOrCertReq<'_> { if matches!( m.payload, MessagePayload::Handshake { - parsed: HandshakeMessagePayload { - payload: HandshakePayload::CertificateRequest(_), - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::CertificateRequest(_)), .. } ) { @@ -812,11 +797,7 @@ impl State for ExpectServerDone<'_> { { match m.payload { MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - payload: HandshakePayload::ServerHelloDone, - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::ServerHelloDone), .. } => {} payload => { diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index 148505b3e26..cb50c1a557c 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -326,7 +326,7 @@ pub(super) fn fill_in_psk_binder( 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.payload { + if let HandshakePayload::ClientHello(ch) = &mut hmp.0 { ch.set_psk_binder(real_binder.as_ref()); }; @@ -607,11 +607,7 @@ impl State for ExpectCertificateOrCompressedCertificateOrC { match m.payload { MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - payload: HandshakePayload::CertificateTls13(..), - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::CertificateTls13(..)), .. } => Box::new(ExpectCertificate { config: self.config, @@ -626,11 +622,7 @@ impl State for ExpectCertificateOrCompressedCertificateOrC }) .handle(cx, m), MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - payload: HandshakePayload::CompressedCertificate(..), - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::CompressedCertificate(..)), .. } => Box::new(ExpectCompressedCertificate { config: self.config, @@ -644,11 +636,7 @@ impl State for ExpectCertificateOrCompressedCertificateOrC }) .handle(cx, m), MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - payload: HandshakePayload::CertificateRequestTls13(..), - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::CertificateRequestTls13(..)), .. } => Box::new(ExpectCertificateRequest { config: self.config, @@ -700,11 +688,7 @@ impl State for ExpectCertificateOrCompressedCertificate { { match m.payload { MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - payload: HandshakePayload::CertificateTls13(..), - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::CertificateTls13(..)), .. } => Box::new(ExpectCertificate { config: self.config, @@ -719,11 +703,7 @@ impl State for ExpectCertificateOrCompressedCertificate { }) .handle(cx, m), MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - payload: HandshakePayload::CompressedCertificate(..), - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::CompressedCertificate(..)), .. } => Box::new(ExpectCompressedCertificate { config: self.config, @@ -773,11 +753,7 @@ impl State for ExpectCertificateOrCertReq { { match m.payload { MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - payload: HandshakePayload::CertificateTls13(..), - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::CertificateTls13(..)), .. } => Box::new(ExpectCertificate { config: self.config, @@ -792,11 +768,7 @@ impl State for ExpectCertificateOrCertReq { }) .handle(cx, m), MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - payload: HandshakePayload::CertificateRequestTls13(..), - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::CertificateRequestTls13(..)), .. } => Box::new(ExpectCertificateRequest { config: self.config, @@ -1014,10 +986,9 @@ impl State for ExpectCompressedCertificate { let m = Message { version: ProtocolVersion::TLSv1_3, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::Certificate, - payload: HandshakePayload::CertificateTls13(cert_payload.into_owned()), - }), + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::CertificateTls13(cert_payload.into_owned()), + )), }; Box::new(ExpectCertificate { @@ -1229,10 +1200,9 @@ fn emit_compressed_certificate_tls13( return emit_certificate_tls13(flight, Some(certkey), auth_context); }; - flight.add(HandshakeMessagePayload { - typ: HandshakeType::CompressedCertificate, - payload: HandshakePayload::CompressedCertificate(compressed.compressed_cert_payload()), - }); + flight.add(HandshakeMessagePayload( + HandshakePayload::CompressedCertificate(compressed.compressed_cert_payload()), + )); } fn emit_certificate_tls13( @@ -1246,10 +1216,9 @@ fn emit_certificate_tls13( let mut cert_payload = CertificatePayloadTls13::new(certs.iter(), None); cert_payload.context = PayloadU8::new(auth_context.unwrap_or_default()); - flight.add(HandshakeMessagePayload { - typ: HandshakeType::Certificate, - payload: HandshakePayload::CertificateTls13(cert_payload), - }); + flight.add(HandshakeMessagePayload(HandshakePayload::CertificateTls13( + cert_payload, + ))); } fn emit_certverify_tls13( @@ -1262,20 +1231,18 @@ fn emit_certverify_tls13( let sig = signer.sign(message.as_ref())?; let dss = DigitallySignedStruct::new(scheme, sig); - flight.add(HandshakeMessagePayload { - typ: HandshakeType::CertificateVerify, - payload: HandshakePayload::CertificateVerify(dss), - }); + 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 { - typ: HandshakeType::Finished, - payload: HandshakePayload::Finished(verify_data_payload), - }); + flight.add(HandshakeMessagePayload(HandshakePayload::Finished( + verify_data_payload, + ))); } fn emit_end_of_early_data_tls13(transcript: &mut HandshakeHash, common: &mut CommonState) { @@ -1285,10 +1252,9 @@ fn emit_end_of_early_data_tls13(transcript: &mut HandshakeHash, common: &mut Com let m = Message { version: ProtocolVersion::TLSv1_3, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::EndOfEarlyData, - payload: HandshakePayload::EndOfEarlyData, - }), + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::EndOfEarlyData, + )), }; transcript.add_message(&m); @@ -1575,19 +1541,11 @@ impl State for ExpectTraffic { .common .take_received_plaintext(payload), MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - payload: HandshakePayload::NewSessionTicketTls13(new_ticket), - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::NewSessionTicketTls13(new_ticket)), .. } => self.handle_new_ticket_tls13(cx, &new_ticket)?, MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - payload: HandshakePayload::KeyUpdate(key_update), - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::KeyUpdate(key_update)), .. } => self.handle_key_update(cx.common, &key_update)?, payload => { diff --git a/rustls/src/hash_hs.rs b/rustls/src/hash_hs.rs index 4f664002d7b..8b4edc68fb2 100644 --- a/rustls/src/hash_hs.rs +++ b/rustls/src/hash_hs.rs @@ -189,7 +189,7 @@ mod tests { use super::provider::hash::SHA256; use super::*; use crate::crypto::hash::Hash; - use crate::enums::{HandshakeType, ProtocolVersion}; + use crate::enums::ProtocolVersion; use crate::msgs::base::Payload; use crate::msgs::handshake::{HandshakeMessagePayload, HandshakePayload}; @@ -214,10 +214,9 @@ mod tests { // handshake protocol encoding of 0x0e 00 00 00 let server_hello_done_message = Message { version: ProtocolVersion::TLSv1_2, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::ServerHelloDone, - payload: HandshakePayload::ServerHelloDone, - }), + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::ServerHelloDone, + )), }; let app_data_ignored = Message { diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index ff32eaf8ecb..97c99fc3b89 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -2739,7 +2739,7 @@ pub enum HandshakePayload<'a> { Finished(Payload<'a>), CertificateStatus(CertificateStatus<'a>), MessageHash(Payload<'a>), - Unknown(Payload<'a>), + Unknown((HandshakeType, Payload<'a>)), } impl HandshakePayload<'_> { @@ -2765,7 +2765,40 @@ impl HandshakePayload<'_> { Finished(x) => x.encode(bytes), CertificateStatus(x) => x.encode(bytes), MessageHash(x) => x.encode(bytes), - Unknown(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, } } @@ -2794,16 +2827,13 @@ impl HandshakePayload<'_> { Finished(x) => Finished(x.into_owned()), CertificateStatus(x) => CertificateStatus(x.into_owned()), MessageHash(x) => MessageHash(x.into_owned()), - Unknown(x) => Unknown(x.into_owned()), + Unknown((t, x)) => Unknown((t, x.into_owned())), } } } #[derive(Debug)] -pub struct HandshakeMessagePayload<'a> { - pub typ: HandshakeType, - pub payload: HandshakePayload<'a>, -} +pub struct HandshakeMessagePayload<'a>(pub HandshakePayload<'a>); impl<'a> Codec<'a> for HandshakeMessagePayload<'a> { fn encode(&self, bytes: &mut Vec) { @@ -2820,7 +2850,7 @@ impl<'a> HandshakeMessagePayload<'a> { r: &mut Reader<'a>, vers: ProtocolVersion, ) -> Result { - let mut typ = HandshakeType::read(r)?; + let typ = HandshakeType::read(r)?; let len = codec::u24::read(r)?.0 as usize; let mut sub = r.sub(len)?; @@ -2836,7 +2866,6 @@ impl<'a> HandshakeMessagePayload<'a> { if random == HELLO_RETRY_REQUEST_RANDOM { let mut hrr = HelloRetryRequest::read(&mut sub)?; hrr.legacy_version = version; - typ = HandshakeType::HelloRetryRequest; HandshakePayload::HelloRetryRequest(hrr) } else { let mut shp = ServerHelloPayload::read(&mut sub)?; @@ -2907,11 +2936,11 @@ impl<'a> HandshakeMessagePayload<'a> { // not legal on wire return Err(InvalidMessage::UnexpectedMessage("HelloRetryRequest")); } - _ => HandshakePayload::Unknown(Payload::read(&mut sub)), + _ => HandshakePayload::Unknown((typ, Payload::read(&mut sub))), }; sub.expect_empty("HandshakeMessagePayload") - .map(|_| Self { typ, payload }) + .map(|_| Self(payload)) } pub(crate) fn encoding_for_binder_signing(&self) -> Vec { @@ -2922,7 +2951,7 @@ impl<'a> HandshakeMessagePayload<'a> { } pub(crate) fn total_binder_length(&self) -> usize { - match &self.payload { + match &self.0 { HandshakePayload::ClientHello(ch) => match ch.extensions.last() { Some(ClientExtension::PresharedKey(offer)) => { let mut binders_encoding = Vec::new(); @@ -2939,11 +2968,9 @@ impl<'a> HandshakeMessagePayload<'a> { pub(crate) fn payload_encode(&self, bytes: &mut Vec, encoding: Encoding) { // output type, length, and encoded payload - match self.typ { - HandshakeType::HelloRetryRequest => HandshakeType::ServerHello, - _ => self.typ, - } - .encode(bytes); + self.0 + .wire_handshake_type() + .encode(bytes); let nested = LengthPrefixedBuffer::new( ListLength::U24 { @@ -2953,7 +2980,7 @@ impl<'a> HandshakeMessagePayload<'a> { bytes, ); - match &self.payload { + 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), @@ -2962,23 +2989,16 @@ impl<'a> HandshakeMessagePayload<'a> { } // All other payload types are encoded the same regardless of purpose. - _ => self.payload.encode(nested.buf), + _ => self.0.encode(nested.buf), } } pub(crate) fn build_handshake_hash(hash: &[u8]) -> Self { - Self { - typ: HandshakeType::MessageHash, - payload: HandshakePayload::MessageHash(Payload::new(hash.to_vec())), - } + Self(HandshakePayload::MessageHash(Payload::new(hash.to_vec()))) } pub(crate) fn into_owned(self) -> HandshakeMessagePayload<'static> { - let Self { typ, payload } = self; - HandshakeMessagePayload { - typ, - payload: payload.into_owned(), - } + HandshakeMessagePayload(self.0.into_owned()) } } diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index 46bc9132153..cb2c6d639df 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -739,7 +739,7 @@ fn can_clone_all_server_extensions() { #[test] fn can_round_trip_all_tls12_handshake_payloads() { for hm in all_tls12_handshake_payloads().iter() { - println!("{:?}", hm.typ); + println!("{:?}", hm.0.handshake_type()); let bytes = hm.get_encoding(); let mut rd = Reader::init(&bytes); let other = HandshakeMessagePayload::read(&mut rd).unwrap(); @@ -778,7 +778,7 @@ fn can_detect_truncation_of_all_tls12_handshake_payloads() { put_u24(l as u32, &mut enc[1..]); println!(" check len {l:?} enc {enc:?}"); - match (hm.typ, l) { + match (hm.0.handshake_type(), l) { (HandshakeType::ClientHello, 41) | (HandshakeType::ServerHello, 38) | (HandshakeType::ServerKeyExchange, _) @@ -803,7 +803,7 @@ fn can_detect_truncation_of_all_tls12_handshake_payloads() { #[test] fn can_round_trip_all_tls13_handshake_payloads() { for hm in all_tls13_handshake_payloads().iter() { - println!("{:?}", hm.typ); + println!("{:?}", hm.0.handshake_type()); let bytes = hm.get_encoding(); let mut rd = Reader::init(&bytes); @@ -844,7 +844,7 @@ fn can_detect_truncation_of_all_tls13_handshake_payloads() { put_u24(l as u32, &mut enc[1..]); println!(" check len {l:?} enc {enc:?}"); - match (hm.typ, l) { + match (hm.0.handshake_type(), l) { (HandshakeType::ClientHello, 41) | (HandshakeType::ServerHello, 38) | (HandshakeType::ServerKeyExchange, _) @@ -873,10 +873,7 @@ fn put_u24(u: u32, b: &mut [u8]) { #[test] fn cannot_read_message_hash_from_network() { - let mh = HandshakeMessagePayload { - typ: HandshakeType::MessageHash, - payload: HandshakePayload::MessageHash(Payload::new(vec![1, 2, 3])), - }; + 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()); @@ -1028,176 +1025,107 @@ fn sample_server_hello_payload() -> ServerHelloPayload { fn all_tls12_handshake_payloads() -> Vec> { vec![ - HandshakeMessagePayload { - typ: HandshakeType::HelloRequest, - payload: HandshakePayload::HelloRequest, - }, - HandshakeMessagePayload { - typ: HandshakeType::ClientHello, - payload: HandshakePayload::ClientHello(sample_client_hello_payload()), - }, - HandshakeMessagePayload { - typ: HandshakeType::ServerHello, - payload: HandshakePayload::ServerHello(sample_server_hello_payload()), - }, - HandshakeMessagePayload { - typ: HandshakeType::HelloRetryRequest, - payload: HandshakePayload::HelloRetryRequest(sample_hello_retry_request()), - }, - HandshakeMessagePayload { - typ: HandshakeType::Certificate, - payload: HandshakePayload::Certificate(CertificateChain(vec![CertificateDer::from( - vec![1, 2, 3], - )])), - }, - HandshakeMessagePayload { - typ: HandshakeType::ServerKeyExchange, - payload: HandshakePayload::ServerKeyExchange(sample_ecdhe_server_key_exchange_payload()), - }, - HandshakeMessagePayload { - typ: HandshakeType::ServerKeyExchange, - payload: HandshakePayload::ServerKeyExchange(sample_dhe_server_key_exchange_payload()), - }, - HandshakeMessagePayload { - typ: HandshakeType::ServerKeyExchange, - payload: HandshakePayload::ServerKeyExchange( - sample_unknown_server_key_exchange_payload(), - ), - }, - HandshakeMessagePayload { - typ: HandshakeType::CertificateRequest, - payload: HandshakePayload::CertificateRequest(sample_certificate_request_payload()), - }, - HandshakeMessagePayload { - typ: HandshakeType::ServerHelloDone, - payload: HandshakePayload::ServerHelloDone, - }, - HandshakeMessagePayload { - typ: HandshakeType::ClientKeyExchange, - payload: HandshakePayload::ClientKeyExchange(Payload::Borrowed(&[1, 2, 3])), - }, - HandshakeMessagePayload { - typ: HandshakeType::NewSessionTicket, - payload: HandshakePayload::NewSessionTicket(sample_new_session_ticket_payload()), - }, - HandshakeMessagePayload { - typ: HandshakeType::EncryptedExtensions, - payload: HandshakePayload::EncryptedExtensions(sample_encrypted_extensions()), - }, - HandshakeMessagePayload { - typ: HandshakeType::KeyUpdate, - payload: HandshakePayload::KeyUpdate(KeyUpdateRequest::UpdateRequested), - }, - HandshakeMessagePayload { - typ: HandshakeType::KeyUpdate, - payload: HandshakePayload::KeyUpdate(KeyUpdateRequest::UpdateNotRequested), - }, - HandshakeMessagePayload { - typ: HandshakeType::Finished, - payload: HandshakePayload::Finished(Payload::Borrowed(&[1, 2, 3])), - }, - HandshakeMessagePayload { - typ: HandshakeType::CertificateStatus, - payload: HandshakePayload::CertificateStatus(sample_certificate_status()), - }, - HandshakeMessagePayload { - typ: HandshakeType::Unknown(99), - payload: HandshakePayload::Unknown(Payload::Borrowed(&[1, 2, 3])), - }, + 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> { vec![ - HandshakeMessagePayload { - typ: HandshakeType::HelloRequest, - payload: HandshakePayload::HelloRequest, - }, - HandshakeMessagePayload { - typ: HandshakeType::ClientHello, - payload: HandshakePayload::ClientHello(sample_client_hello_payload()), - }, - HandshakeMessagePayload { - typ: HandshakeType::ServerHello, - payload: HandshakePayload::ServerHello(sample_server_hello_payload()), - }, - HandshakeMessagePayload { - typ: HandshakeType::HelloRetryRequest, - payload: HandshakePayload::HelloRetryRequest(sample_hello_retry_request()), - }, - HandshakeMessagePayload { - typ: HandshakeType::Certificate, - payload: HandshakePayload::CertificateTls13(sample_certificate_payload_tls13()), - }, - HandshakeMessagePayload { - typ: HandshakeType::CompressedCertificate, - payload: HandshakePayload::CompressedCertificate(sample_compressed_certificate()), - }, - HandshakeMessagePayload { - typ: HandshakeType::ServerKeyExchange, - payload: HandshakePayload::ServerKeyExchange(sample_ecdhe_server_key_exchange_payload()), - }, - HandshakeMessagePayload { - typ: HandshakeType::ServerKeyExchange, - payload: HandshakePayload::ServerKeyExchange(sample_dhe_server_key_exchange_payload()), - }, - HandshakeMessagePayload { - typ: HandshakeType::ServerKeyExchange, - payload: HandshakePayload::ServerKeyExchange( - sample_unknown_server_key_exchange_payload(), - ), - }, - HandshakeMessagePayload { - typ: HandshakeType::CertificateRequest, - payload: HandshakePayload::CertificateRequestTls13( - sample_certificate_request_payload_tls13(), - ), - }, - HandshakeMessagePayload { - typ: HandshakeType::CertificateVerify, - payload: HandshakePayload::CertificateVerify(DigitallySignedStruct::new( - SignatureScheme::ECDSA_NISTP256_SHA256, - vec![1, 2, 3], - )), - }, - HandshakeMessagePayload { - typ: HandshakeType::ServerHelloDone, - payload: HandshakePayload::ServerHelloDone, - }, - HandshakeMessagePayload { - typ: HandshakeType::ClientKeyExchange, - payload: HandshakePayload::ClientKeyExchange(Payload::Borrowed(&[1, 2, 3])), - }, - HandshakeMessagePayload { - typ: HandshakeType::NewSessionTicket, - payload: HandshakePayload::NewSessionTicketTls13( - sample_new_session_ticket_payload_tls13(), - ), - }, - HandshakeMessagePayload { - typ: HandshakeType::EncryptedExtensions, - payload: HandshakePayload::EncryptedExtensions(sample_encrypted_extensions()), - }, - HandshakeMessagePayload { - typ: HandshakeType::KeyUpdate, - payload: HandshakePayload::KeyUpdate(KeyUpdateRequest::UpdateRequested), - }, - HandshakeMessagePayload { - typ: HandshakeType::KeyUpdate, - payload: HandshakePayload::KeyUpdate(KeyUpdateRequest::UpdateNotRequested), - }, - HandshakeMessagePayload { - typ: HandshakeType::Finished, - payload: HandshakePayload::Finished(Payload::Borrowed(&[1, 2, 3])), - }, - HandshakeMessagePayload { - typ: HandshakeType::CertificateStatus, - payload: HandshakePayload::CertificateStatus(sample_certificate_status()), - }, - HandshakeMessagePayload { - typ: HandshakeType::Unknown(99), - payload: HandshakePayload::Unknown(Payload::Borrowed(&[1, 2, 3])), - }, + 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]), + ))), ] } diff --git a/rustls/src/msgs/message/mod.rs b/rustls/src/msgs/message/mod.rs index 2a8e1112c22..0b9e4fd87c4 100644 --- a/rustls/src/msgs/message/mod.rs +++ b/rustls/src/msgs/message/mod.rs @@ -162,7 +162,7 @@ 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.typ == hstyp + parsed.0.handshake_type() == hstyp } else { false } @@ -181,20 +181,18 @@ impl Message<'_> { pub fn build_key_update_notify() -> Self { Self { version: ProtocolVersion::TLSv1_3, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::KeyUpdate, - payload: HandshakePayload::KeyUpdate(KeyUpdateRequest::UpdateNotRequested), - }), + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::KeyUpdate(KeyUpdateRequest::UpdateNotRequested), + )), } } pub fn build_key_update_request() -> Self { Self { version: ProtocolVersion::TLSv1_3, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::KeyUpdate, - payload: HandshakePayload::KeyUpdate(KeyUpdateRequest::UpdateRequested), - }), + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::KeyUpdate(KeyUpdateRequest::UpdateRequested), + )), } } diff --git a/rustls/src/server/server_conn.rs b/rustls/src/server/server_conn.rs index 669baa565ea..c21464b059c 100644 --- a/rustls/src/server/server_conn.rs +++ b/rustls/src/server/server_conn.rs @@ -1039,8 +1039,7 @@ impl Accepted { fn client_hello_payload<'a>(message: &'a Message<'_>) -> &'a ClientHelloPayload { match &message.payload { - crate::msgs::message::MessagePayload::Handshake { parsed, .. } => match &parsed.payload - { + crate::msgs::message::MessagePayload::Handshake { parsed, .. } => match &parsed.0 { crate::msgs::handshake::HandshakePayload::ClientHello(ch) => ch, _ => unreachable!(), }, diff --git a/rustls/src/server/test.rs b/rustls/src/server/test.rs index d50d19ff11d..0587e39af52 100644 --- a/rustls/src/server/test.rs +++ b/rustls/src/server/test.rs @@ -12,9 +12,7 @@ use crate::msgs::handshake::{ Random, SessionId, SupportedProtocolVersions, }; use crate::msgs::message::{Message, MessagePayload}; -use crate::{ - CommonState, Error, HandshakeType, PeerIncompatible, PeerMisbehaved, ProtocolVersion, Side, -}; +use crate::{CommonState, Error, PeerIncompatible, PeerMisbehaved, ProtocolVersion, Side}; #[test] fn null_compression_required() { @@ -51,10 +49,9 @@ fn server_rejects_sni_with_illegal_dns_name() { fn test_process_client_hello(hello: ClientHelloPayload) -> Result<(), Error> { let m = Message { version: ProtocolVersion::TLSv1_2, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::ClientHello, - payload: HandshakePayload::ClientHello(hello), - }), + payload: MessagePayload::handshake(HandshakeMessagePayload(HandshakePayload::ClientHello( + hello, + ))), }; super::hs::process_client_hello( &m, @@ -106,10 +103,9 @@ mod tests { .retain(|ext| ext.ext_type() != ExtensionType::ExtendedMasterSecret); let ch = Message { version: ProtocolVersion::TLSv1_3, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::ClientHello, - payload: HandshakePayload::ClientHello(ch), - }), + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::ClientHello(ch), + )), }; conn.read_tls(&mut ch.into_wire_bytes().as_slice()) .unwrap(); @@ -192,10 +188,9 @@ mod tests { ) { let ch = Message { version: ProtocolVersion::TLSv1_3, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::ClientHello, - payload: HandshakePayload::ClientHello(client_hello), - }), + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::ClientHello(client_hello), + )), }; conn.read_tls(&mut ch.into_wire_bytes().as_slice()) .unwrap(); @@ -216,10 +211,9 @@ mod tests { ])); let ch = Message { version: ProtocolVersion::TLSv1_3, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::ClientHello, - payload: HandshakePayload::ClientHello(ch), - }), + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::ClientHello(ch), + )), }; let mut conn = ServerConnection::new(server_config_for_rpk().into()).unwrap(); @@ -240,10 +234,9 @@ mod tests { ])); let ch = Message { version: ProtocolVersion::TLSv1_3, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::ClientHello, - payload: HandshakePayload::ClientHello(ch), - }), + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::ClientHello(ch), + )), }; let mut conn = ServerConnection::new(server_config_for_rpk().into()).unwrap(); diff --git a/rustls/src/server/tls12.rs b/rustls/src/server/tls12.rs index 48935600d9d..2eb1fd8dcc9 100644 --- a/rustls/src/server/tls12.rs +++ b/rustls/src/server/tls12.rs @@ -347,17 +347,14 @@ mod client_hello { ep.process_common(config, cx, ocsp_response, hello, resumedata, extra_exts)?; ep.process_tls12(config, hello, using_ems); - let sh = HandshakeMessagePayload { - typ: HandshakeType::ServerHello, - payload: 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.exts, - }), - }; + 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.exts, + })); trace!("sending server hello {sh:?}"); flight.add(sh); @@ -368,17 +365,15 @@ mod client_hello { flight: &mut HandshakeFlightTls12<'_>, cert_chain: &[CertificateDer<'static>], ) { - flight.add(HandshakeMessagePayload { - typ: HandshakeType::Certificate, - payload: HandshakePayload::Certificate(CertificateChain(cert_chain.to_vec())), - }); + flight.add(HandshakeMessagePayload(HandshakePayload::Certificate( + CertificateChain(cert_chain.to_vec()), + ))); } fn emit_cert_status(flight: &mut HandshakeFlightTls12<'_>, ocsp: &[u8]) { - flight.add(HandshakeMessagePayload { - typ: HandshakeType::CertificateStatus, - payload: HandshakePayload::CertificateStatus(CertificateStatus::new(ocsp)), - }); + flight.add(HandshakeMessagePayload( + HandshakePayload::CertificateStatus(CertificateStatus::new(ocsp)), + )); } fn emit_server_kx( @@ -407,10 +402,9 @@ mod client_hello { dss: DigitallySignedStruct::new(sigscheme, sig), }); - flight.add(HandshakeMessagePayload { - typ: HandshakeType::ServerKeyExchange, - payload: HandshakePayload::ServerKeyExchange(skx), - }); + flight.add(HandshakeMessagePayload( + HandshakePayload::ServerKeyExchange(skx), + )); Ok(kx) } @@ -440,10 +434,7 @@ mod client_hello { canames: names, }; - let creq = HandshakeMessagePayload { - typ: HandshakeType::CertificateRequest, - payload: HandshakePayload::CertificateRequest(cr), - }; + let creq = HandshakeMessagePayload(HandshakePayload::CertificateRequest(cr)); trace!("Sending CertificateRequest {creq:?}"); flight.add(creq); @@ -451,10 +442,7 @@ mod client_hello { } fn emit_server_hello_done(flight: &mut HandshakeFlightTls12<'_>) { - flight.add(HandshakeMessagePayload { - typ: HandshakeType::ServerHelloDone, - payload: HandshakePayload::ServerHelloDone, - }); + flight.add(HandshakeMessagePayload(HandshakePayload::ServerHelloDone)); } } @@ -820,13 +808,12 @@ fn emit_ticket( let m = Message { version: ProtocolVersion::TLSv1_2, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::NewSessionTicket, - payload: HandshakePayload::NewSessionTicket(NewSessionTicketPayload::new( + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::NewSessionTicket(NewSessionTicketPayload::new( ticket_lifetime, ticket, )), - }), + )), }; transcript.add_message(&m); @@ -854,10 +841,9 @@ fn emit_finished( let f = Message { version: ProtocolVersion::TLSv1_2, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::Finished, - payload: HandshakePayload::Finished(verify_data_payload), - }), + payload: MessagePayload::handshake(HandshakeMessagePayload(HandshakePayload::Finished( + verify_data_payload, + ))), }; transcript.add_message(&f); diff --git a/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index 5e55dff9e09..8780eb83916 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -515,9 +515,8 @@ mod client_hello { let sh = Message { version: ProtocolVersion::TLSv1_2, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::ServerHello, - payload: HandshakePayload::ServerHello(ServerHelloPayload { + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::ServerHello(ServerHelloPayload { legacy_version: ProtocolVersion::TLSv1_2, random: Random::from(randoms.server), session_id: *session_id, @@ -525,7 +524,7 @@ mod client_hello { compression_method: Compression::Null, extensions, }), - }), + )), }; cx.common.check_aligned_handshake()?; @@ -599,10 +598,9 @@ mod client_hello { let m = Message { version: ProtocolVersion::TLSv1_2, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::HelloRetryRequest, - payload: HandshakePayload::HelloRetryRequest(req), - }), + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::HelloRetryRequest(req), + )), }; trace!("Requesting retry {m:?}"); @@ -686,10 +684,7 @@ mod client_hello { ep.exts.push(ServerExtension::EarlyData); } - let ee = HandshakeMessagePayload { - typ: HandshakeType::EncryptedExtensions, - payload: HandshakePayload::EncryptedExtensions(ep.exts), - }; + let ee = HandshakeMessagePayload(HandshakePayload::EncryptedExtensions(ep.exts)); trace!("sending encrypted extensions {ee:?}"); flight.add(ee); @@ -732,10 +727,7 @@ mod client_hello { .push(CertReqExtension::AuthorityNames(authorities.to_vec())); } - let creq = HandshakeMessagePayload { - typ: HandshakeType::CertificateRequest, - payload: HandshakePayload::CertificateRequestTls13(cr), - }; + let creq = HandshakeMessagePayload(HandshakePayload::CertificateRequestTls13(cr)); trace!("Sending CertificateRequest {creq:?}"); flight.add(creq); @@ -747,13 +739,9 @@ mod client_hello { cert_chain: &[CertificateDer<'static>], ocsp_response: Option<&[u8]>, ) { - let cert = HandshakeMessagePayload { - typ: HandshakeType::Certificate, - payload: HandshakePayload::CertificateTls13(CertificatePayloadTls13::new( - cert_chain.iter(), - ocsp_response, - )), - }; + let cert = HandshakeMessagePayload(HandshakePayload::CertificateTls13( + CertificatePayloadTls13::new(cert_chain.iter(), ocsp_response), + )); trace!("sending certificate {cert:?}"); flight.add(cert); @@ -775,10 +763,9 @@ mod client_hello { return emit_certificate_tls13(flight, cert_chain, ocsp_response); }; - let c = HandshakeMessagePayload { - typ: HandshakeType::CompressedCertificate, - payload: HandshakePayload::CompressedCertificate(entry.compressed_cert_payload()), - }; + let c = HandshakeMessagePayload(HandshakePayload::CompressedCertificate( + entry.compressed_cert_payload(), + )); trace!("sending compressed certificate {c:?}"); flight.add(c); @@ -806,10 +793,7 @@ mod client_hello { let cv = DigitallySignedStruct::new(scheme, sig); - let cv = HandshakeMessagePayload { - typ: HandshakeType::CertificateVerify, - payload: HandshakePayload::CertificateVerify(cv), - }; + let cv = HandshakeMessagePayload(HandshakePayload::CertificateVerify(cv)); trace!("sending certificate-verify {cv:?}"); flight.add(cv); @@ -827,10 +811,7 @@ mod client_hello { let verify_data = key_schedule.sign_server_finish(&handshake_hash); let verify_data_payload = Payload::new(verify_data.as_ref()); - let fin = HandshakeMessagePayload { - typ: HandshakeType::Finished, - payload: HandshakePayload::Finished(verify_data_payload), - }; + let fin = HandshakeMessagePayload(HandshakePayload::Finished(verify_data_payload)); trace!("sending finished {fin:?}"); flight.add(fin); @@ -900,11 +881,7 @@ impl State for ExpectCertificateOrCompressedCertificate { { match m.payload { MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - payload: HandshakePayload::CertificateTls13(..), - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::CertificateTls13(..)), .. } => Box::new(ExpectCertificate { config: self.config, @@ -917,11 +894,7 @@ impl State for ExpectCertificateOrCompressedCertificate { .handle(cx, m), MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - payload: HandshakePayload::CompressedCertificate(..), - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::CompressedCertificate(..)), .. } => Box::new(ExpectCompressedCertificate { config: self.config, @@ -1024,10 +997,9 @@ impl State for ExpectCompressedCertificate { let m = Message { version: ProtocolVersion::TLSv1_3, - payload: MessagePayload::handshake(HandshakeMessagePayload { - typ: HandshakeType::Certificate, - payload: HandshakePayload::CertificateTls13(cert_payload.into_owned()), - }), + payload: MessagePayload::handshake(HandshakeMessagePayload( + HandshakePayload::CertificateTls13(cert_payload.into_owned()), + )), }; Box::new(ExpectCertificate { @@ -1223,11 +1195,7 @@ impl State for ExpectEarlyData { } } MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - typ: HandshakeType::EndOfEarlyData, - payload: HandshakePayload::EndOfEarlyData, - }, + parsed: HandshakeMessagePayload(HandshakePayload::EndOfEarlyData), .. } => { self.key_schedule @@ -1340,10 +1308,7 @@ impl ExpectFinished { } } - let t = HandshakeMessagePayload { - typ: HandshakeType::NewSessionTicket, - payload: HandshakePayload::NewSessionTicketTls13(payload), - }; + let t = HandshakeMessagePayload(HandshakePayload::NewSessionTicketTls13(payload)); trace!("sending new ticket {t:?} (stateless: {stateless})"); flight.add(t); @@ -1461,11 +1426,7 @@ impl State for ExpectTraffic { .common .take_received_plaintext(payload), MessagePayload::Handshake { - parsed: - HandshakeMessagePayload { - payload: HandshakePayload::KeyUpdate(key_update), - .. - }, + parsed: HandshakeMessagePayload(HandshakePayload::KeyUpdate(key_update)), .. } => self.handle_key_update(cx.common, &key_update)?, payload => { From f1a27027afa5dfbdfd984fd38868c81734f85ddd Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 2 Jun 2025 16:35:30 +0100 Subject: [PATCH 265/403] Privatise `HandshakePayload` --- rustls/src/msgs/base.rs | 2 +- rustls/src/msgs/handshake.rs | 90 ++++++++++++++++++------------------ 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/rustls/src/msgs/base.rs b/rustls/src/msgs/base.rs index 38eb3ede32e..4204714d891 100644 --- a/rustls/src/msgs/base.rs +++ b/rustls/src/msgs/base.rs @@ -158,7 +158,7 @@ impl fmt::Debug for PayloadU16 { /// /// `C` controls the minimum length accepted when decoding. #[derive(Clone, Eq, PartialEq)] -pub struct PayloadU8(pub(crate) Vec, PhantomData); +pub(crate) struct PayloadU8(pub(crate) Vec, PhantomData); impl PayloadU8 { pub(crate) fn encode_slice(slice: &[u8], bytes: &mut Vec) { diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 97c99fc3b89..483b7edeb59 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -67,7 +67,7 @@ macro_rules! wrapped_payload( ); #[derive(Clone, Copy, Eq, PartialEq)] -pub struct Random(pub(crate) [u8; 32]); +pub(crate) struct Random(pub(crate) [u8; 32]); impl fmt::Debug for Random { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -114,7 +114,7 @@ impl From<[u8; 32]> for Random { } #[derive(Copy, Clone)] -pub struct SessionId { +pub(crate) struct SessionId { len: usize, data: [u8; 32], } @@ -164,7 +164,7 @@ impl Codec<'_> for SessionId { } impl SessionId { - pub fn random(secure_random: &dyn SecureRandom) -> Result { + pub(crate) fn random(secure_random: &dyn SecureRandom) -> Result { let mut data = [0u8; 32]; secure_random.fill(&mut data)?; Ok(Self { data, len: 32 }) @@ -228,7 +228,7 @@ impl TlsListElement for SignatureScheme { } #[derive(Clone, Debug)] -pub enum ServerNamePayload<'a> { +pub(crate) enum ServerNamePayload<'a> { /// A successfully decoded value: SingleDnsName(DnsName<'a>), @@ -357,7 +357,7 @@ impl HostNamePayload { wrapped_payload!( /// RFC7301: `opaque ProtocolName<1..2^8-1>;` - pub struct ProtocolName, PayloadU8, + pub(crate) struct ProtocolName, PayloadU8, ); /// RFC7301: `ProtocolName protocol_name_list<2..2^16-1>` @@ -369,7 +369,7 @@ impl TlsListElement for ProtocolName { /// RFC7301 encodes a single protocol name as `Vec` #[derive(Clone, Debug)] -pub struct SingleProtocolName(ProtocolName); +pub(crate) struct SingleProtocolName(ProtocolName); impl SingleProtocolName { pub(crate) fn new(bytes: Vec) -> Self { @@ -409,14 +409,14 @@ impl AsRef<[u8]> for SingleProtocolName { // --- TLS 1.3 Key shares --- #[derive(Clone, Debug)] -pub struct KeyShareEntry { +pub(crate) struct KeyShareEntry { pub(crate) group: NamedGroup, /// RFC8446: `opaque key_exchange<1..2^16-1>;` pub(crate) payload: PayloadU16, } impl KeyShareEntry { - pub fn new(group: NamedGroup, payload: impl Into>) -> Self { + pub(crate) fn new(group: NamedGroup, payload: impl Into>) -> Self { Self { group, payload: PayloadU16::new(payload.into()), @@ -489,7 +489,7 @@ impl TlsListElement for PresharedKeyBinder { } #[derive(Clone, Debug)] -pub struct PresharedKeyOffer { +pub(crate) struct PresharedKeyOffer { pub(crate) identities: Vec, pub(crate) binders: Vec, } @@ -527,7 +527,7 @@ impl TlsListElement for ResponderId { } #[derive(Clone, Debug)] -pub struct OcspCertificateStatusRequest { +pub(crate) struct OcspCertificateStatusRequest { pub(crate) responder_ids: Vec, pub(crate) extensions: PayloadU16, } @@ -548,7 +548,7 @@ impl Codec<'_> for OcspCertificateStatusRequest { } #[derive(Clone, Debug)] -pub enum CertificateStatusRequest { +pub(crate) enum CertificateStatusRequest { Ocsp(OcspCertificateStatusRequest), Unknown((CertificateStatusType, Payload<'static>)), } @@ -612,7 +612,7 @@ impl TlsListElement for KeyShareEntry { /// /// RFC8446: `ProtocolVersion versions<2..254>;` #[derive(Clone, Copy, Debug, Default)] -pub struct SupportedProtocolVersions { +pub(crate) struct SupportedProtocolVersions { pub(crate) tls13: bool, pub(crate) tls12: bool, } @@ -687,7 +687,7 @@ impl TlsListElement for CertificateCompressionAlgorithm { } #[derive(Clone, Debug)] -pub enum ClientExtension { +pub(crate) enum ClientExtension { EcPointFormats(Vec), NamedGroups(Vec), SignatureAlgorithms(Vec), @@ -858,13 +858,13 @@ fn trim_hostname_trailing_dot_for_sni(dns_name: &DnsName<'_>) -> DnsName<'static } #[derive(Clone, Debug)] -pub enum ClientSessionTicket { +pub(crate) enum ClientSessionTicket { Request, Offer(Payload<'static>), } #[derive(Clone, Debug)] -pub enum ServerExtension { +pub(crate) enum ServerExtension { EcPointFormats(Vec), ServerNameAck, SessionTicketAck, @@ -986,13 +986,13 @@ impl ServerExtension { } #[derive(Clone, Debug)] -pub struct ClientHelloPayload { - pub client_version: ProtocolVersion, - pub random: Random, - pub session_id: SessionId, - pub cipher_suites: Vec, - pub compression_methods: Vec, - pub extensions: Vec, +pub(crate) struct ClientHelloPayload { + pub(crate) client_version: ProtocolVersion, + pub(crate) random: Random, + pub(crate) session_id: SessionId, + pub(crate) cipher_suites: Vec, + pub(crate) compression_methods: Vec, + pub(crate) extensions: Vec, } impl ClientHelloPayload { @@ -1082,7 +1082,7 @@ impl ClientHelloPayload { } } - pub fn sigalgs_extension(&self) -> Option<&[SignatureScheme]> { + pub(crate) fn sigalgs_extension(&self) -> Option<&[SignatureScheme]> { let ext = self.find_extension(ExtensionType::SignatureAlgorithms)?; match ext { ClientExtension::SignatureAlgorithms(req) => Some(req), @@ -1155,7 +1155,7 @@ impl ClientHelloPayload { } } - pub fn keyshare_extension(&self) -> Option<&[KeyShareEntry]> { + pub(crate) fn keyshare_extension(&self) -> Option<&[KeyShareEntry]> { let ext = self.find_extension(ExtensionType::KeyShare)?; match ext { ClientExtension::KeyShare(shares) => Some(shares), @@ -1361,9 +1361,9 @@ impl TlsListElement for HelloRetryExtension { } #[derive(Clone, Debug)] -pub struct HelloRetryRequest { +pub(crate) struct HelloRetryRequest { pub(crate) legacy_version: ProtocolVersion, - pub session_id: SessionId, + pub(crate) session_id: SessionId, pub(crate) cipher_suite: CipherSuite, pub(crate) extensions: Vec, } @@ -1417,7 +1417,7 @@ impl HelloRetryRequest { .find(|x| x.ext_type() == ext) } - pub fn requested_key_share_group(&self) -> Option { + pub(crate) fn requested_key_share_group(&self) -> Option { let ext = self.find_extension(ExtensionType::KeyShare)?; match ext { HelloRetryExtension::KeyShare(grp) => Some(*grp), @@ -1484,13 +1484,13 @@ impl HelloRetryRequest { } #[derive(Clone, Debug)] -pub struct ServerHelloPayload { - pub extensions: Vec, +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: Vec, } impl Codec<'_> for ServerHelloPayload { @@ -1595,7 +1595,7 @@ impl ServerHelloPayload { } #[derive(Clone, Default, Debug)] -pub struct CertificateChain<'a>(pub Vec>); +pub(crate) struct CertificateChain<'a>(pub(crate) Vec>); impl CertificateChain<'_> { pub(crate) fn into_owned(self) -> CertificateChain<'static> { @@ -1771,7 +1771,7 @@ impl TlsListElement for CertificateEntry<'_> { } #[derive(Debug)] -pub struct CertificatePayloadTls13<'a> { +pub(crate) struct CertificatePayloadTls13<'a> { pub(crate) context: PayloadU8, pub(crate) entries: Vec>, } @@ -2131,20 +2131,20 @@ impl KxDecode<'_> for ServerKeyExchangeParams { } #[derive(Debug)] -pub struct ServerKeyExchange { +pub(crate) struct ServerKeyExchange { pub(crate) params: ServerKeyExchangeParams, pub(crate) dss: DigitallySignedStruct, } impl ServerKeyExchange { - pub fn encode(&self, buf: &mut Vec) { + pub(crate) fn encode(&self, buf: &mut Vec) { self.params.encode(buf); self.dss.encode(buf); } } #[derive(Debug)] -pub enum ServerKeyExchangePayload { +pub(crate) enum ServerKeyExchangePayload { Known(ServerKeyExchange), Unknown(Payload<'static>), } @@ -2317,7 +2317,7 @@ impl TlsListElement for DistinguishedName { } #[derive(Debug)] -pub struct CertificateRequestPayload { +pub(crate) struct CertificateRequestPayload { pub(crate) certtypes: Vec, pub(crate) sigschemes: Vec, pub(crate) canames: Vec, @@ -2416,7 +2416,7 @@ impl TlsListElement for CertReqExtension { } #[derive(Debug)] -pub struct CertificateRequestPayloadTls13 { +pub(crate) struct CertificateRequestPayloadTls13 { pub(crate) context: PayloadU8, pub(crate) extensions: Vec, } @@ -2474,7 +2474,7 @@ impl CertificateRequestPayloadTls13 { // -- NewSessionTicket -- #[derive(Debug)] -pub struct NewSessionTicketPayload { +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 @@ -2556,7 +2556,7 @@ impl TlsListElement for NewSessionTicketExtension { } #[derive(Debug)] -pub struct NewSessionTicketPayloadTls13 { +pub(crate) struct NewSessionTicketPayloadTls13 { pub(crate) lifetime: u32, pub(crate) age_add: u32, pub(crate) nonce: PayloadU8, @@ -2633,7 +2633,7 @@ impl Codec<'_> for NewSessionTicketPayloadTls13 { /// Only supports OCSP #[derive(Debug)] -pub struct CertificateStatus<'a> { +pub(crate) struct CertificateStatus<'a> { pub(crate) ocsp_response: PayloadU24<'a>, } @@ -2677,7 +2677,7 @@ impl<'a> CertificateStatus<'a> { // -- RFC8879 compressed certificates #[derive(Debug)] -pub struct CompressedCertificatePayload<'a> { +pub(crate) struct CompressedCertificatePayload<'a> { pub(crate) alg: CertificateCompressionAlgorithm, pub(crate) uncompressed_len: u32, pub(crate) compressed: PayloadU24<'a>, @@ -2717,7 +2717,7 @@ impl CompressedCertificatePayload<'_> { } #[derive(Debug)] -pub enum HandshakePayload<'a> { +pub(crate) enum HandshakePayload<'a> { HelloRequest, ClientHello(ClientHelloPayload), ServerHello(ServerHelloPayload), @@ -2833,7 +2833,7 @@ impl HandshakePayload<'_> { } #[derive(Debug)] -pub struct HandshakeMessagePayload<'a>(pub HandshakePayload<'a>); +pub struct HandshakeMessagePayload<'a>(pub(crate) HandshakePayload<'a>); impl<'a> Codec<'a> for HandshakeMessagePayload<'a> { fn encode(&self, bytes: &mut Vec) { @@ -3214,7 +3214,7 @@ impl TlsListElement for EchConfigExtension { /// /// [draft-ietf-tls-esni Section 5]: #[derive(Clone, Debug)] -pub enum EncryptedClientHello { +pub(crate) enum EncryptedClientHello { /// A `ECHClientHello` with type [EchClientHelloType::ClientHelloOuter]. Outer(EncryptedClientHelloOuter), /// An empty `ECHClientHello` with type [EchClientHelloType::ClientHelloInner]. @@ -3253,7 +3253,7 @@ impl Codec<'_> for EncryptedClientHello { /// /// [draft-ietf-tls-esni Section 5]: #[derive(Clone, Debug)] -pub struct EncryptedClientHelloOuter { +pub(crate) struct EncryptedClientHelloOuter { /// The cipher suite used to encrypt ClientHelloInner. Must match a value from /// ECHConfigContents.cipher_suites list. pub cipher_suite: HpkeSymmetricCipherSuite, @@ -3289,7 +3289,7 @@ impl Codec<'_> for EncryptedClientHelloOuter { /// /// [draft-ietf-tls-esni Section 5]: #[derive(Clone, Debug)] -pub struct ServerEncryptedClientHello { +pub(crate) struct ServerEncryptedClientHello { pub(crate) retry_configs: Vec, } From 19133f2f0baf13fea8ec4e646d29cfe84da7fd44 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 2 Jun 2025 18:37:19 +0100 Subject: [PATCH 266/403] Introduce specific error for unsupported signatures `BadSignature` convolves two cases with different causes: a genuinely bad signature, where we positively identified that a signature was incorrect; and where we don't support a signature algorithm and can't say whether it was valid or not. --- bogo/config.json.in | 4 ---- bogo/src/main.rs | 3 +++ rustls/src/error.rs | 14 ++++++++++++-- rustls/src/webpki/mod.rs | 35 ++++++++++++++++++++--------------- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index 0b1d4092d28..3f7f836a7dc 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -200,9 +200,6 @@ "ALPNClient-EmptyProtocolName-TLS-TLS13": ":ILLEGAL_EMPTY_VALUE:", "ALPNServer-EmptyProtocolName-TLS-TLS12": ":ILLEGAL_EMPTY_VALUE:", "ALPNServer-EmptyProtocolName-TLS-TLS13": ":ILLEGAL_EMPTY_VALUE:", - "Verify-ClientAuth-SignatureType": ":BAD_SIGNATURE:", - "Verify-ServerAuth-SignatureType-TLS13": ":BAD_SIGNATURE:", - "Verify-ClientAuth-SignatureType-TLS13": ":BAD_SIGNATURE:", "UnofferedExtension-Client": ":PEER_MISBEHAVIOUR:", "UnknownExtension-Client": ":PEER_MISBEHAVIOUR:", "KeyUpdate-InvalidRequestMode": ":BAD_HANDSHAKE_MSG:", @@ -365,7 +362,6 @@ "Downgrade-TLS12-Client-TLS": ":PEER_MISBEHAVIOUR:", "Downgrade-TLS10-Client": ":HANDSHAKE_FAILURE:", "Downgrade-TLS10-Server": ":INCOMPATIBLE:", - "ECDSACurveMismatch-Verify-TLS13": ":BAD_SIGNATURE:", "SecondServerHelloNoVersion-TLS13": ":PEER_MISBEHAVIOUR:", "SecondServerHelloWrongVersion-TLS13": ":INCOMPATIBLE:", "TooManyChangeCipherSpec-Client-TLS13": ":PEER_MISBEHAVIOUR:", diff --git a/bogo/src/main.rs b/bogo/src/main.rs index a305eac143d..31a9511d1f1 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -1003,6 +1003,9 @@ fn handle_err(opts: &Options, err: Error) -> ! { quit(":CANNOT_PARSE_LEAF_CERT:") } Error::InvalidCertificate(CertificateError::BadSignature) => quit(":BAD_SIGNATURE:"), + Error::InvalidCertificate(CertificateError::UnsupportedSignatureAlgorithm) => { + quit(":WRONG_SIGNATURE_TYPE:") + } Error::InvalidCertificate(e) => quit(&format!(":BAD_CERT: ({e:?})")), Error::PeerSentOversizedRecord => quit(":DATA_LENGTH_TOO_LONG:"), _ => { diff --git a/rustls/src/error.rs b/rustls/src/error.rs index 264f4025fbd..50d989c530b 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -413,6 +413,9 @@ pub enum CertificateError { /// issuer. BadSignature, + /// A signature inside a certificate or on a handshake was made with an unsupported algorithm. + UnsupportedSignatureAlgorithm, + /// The subject names in an end-entity certificate do not include /// the expected name. NotValidForName, @@ -496,6 +499,7 @@ impl PartialEq for CertificateError { (UnhandledCriticalExtension, UnhandledCriticalExtension) => true, (UnknownIssuer, UnknownIssuer) => true, (BadSignature, BadSignature) => true, + (UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm) => true, (NotValidForName, NotValidForName) => true, ( NotValidForNameContext { @@ -560,7 +564,7 @@ impl From for AlertDescription { | UnknownRevocationStatus | ExpiredRevocationList | ExpiredRevocationListContext { .. } => Self::UnknownCA, - BadSignature => Self::DecryptError, + BadSignature | UnsupportedSignatureAlgorithm => Self::DecryptError, InvalidPurpose | InvalidPurposeContext { .. } => Self::UnsupportedCertificate, ApplicationVerificationFailure => Self::AccessDenied, // RFC 5246/RFC 8446 @@ -723,9 +727,12 @@ impl fmt::Display for ExtendedKeyPurpose { #[derive(Debug, Clone)] /// The ways in which a certificate revocation list (CRL) can be invalid. pub enum CertRevocationListError { - /// The CRL had a bad, or unsupported signature from its issuer. + /// The CRL had a bad signature from its issuer. BadSignature, + /// The CRL had an unsupported signature from its issuer. + UnsupportedSignatureAlgorithm, + /// The CRL contained an invalid CRL number. InvalidCrlNumber, @@ -769,6 +776,7 @@ impl PartialEq for CertRevocationListError { #[allow(clippy::match_like_matches_macro)] match (self, other) { (BadSignature, BadSignature) => true, + (UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm) => true, (InvalidCrlNumber, InvalidCrlNumber) => true, (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true, (IssuerInvalidForCrl, IssuerInvalidForCrl) => true, @@ -1027,6 +1035,7 @@ mod tests { } ); assert_eq!(BadSignature, BadSignature); + assert_eq!(UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm); assert_eq!(NotValidForName, NotValidForName); let context = NotValidForNameContext { expected: ServerName::try_from("example.com") @@ -1070,6 +1079,7 @@ mod tests { fn crl_error_equality() { use super::CertRevocationListError::*; assert_eq!(BadSignature, BadSignature); + assert_eq!(UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm); assert_eq!(InvalidCrlNumber, InvalidCrlNumber); assert_eq!( InvalidRevokedCertSerialNumber, diff --git a/rustls/src/webpki/mod.rs b/rustls/src/webpki/mod.rs index 2c7e5a17171..bc8ee009507 100644 --- a/rustls/src/webpki/mod.rs +++ b/rustls/src/webpki/mod.rs @@ -83,14 +83,14 @@ fn pki_error(error: webpki::Error) -> Error { } IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl.into(), - InvalidSignatureForPublicKey - | UnsupportedSignatureAlgorithm - | UnsupportedSignatureAlgorithmForPublicKey => CertificateError::BadSignature.into(), - - InvalidCrlSignatureForPublicKey - | UnsupportedCrlSignatureAlgorithm - | UnsupportedCrlSignatureAlgorithmForPublicKey => { - CertRevocationListError::BadSignature.into() + InvalidSignatureForPublicKey => CertificateError::BadSignature.into(), + UnsupportedSignatureAlgorithm | UnsupportedSignatureAlgorithmForPublicKey => { + CertificateError::UnsupportedSignatureAlgorithm.into() + } + + InvalidCrlSignatureForPublicKey => CertRevocationListError::BadSignature.into(), + UnsupportedCrlSignatureAlgorithm | UnsupportedCrlSignatureAlgorithmForPublicKey => { + CertRevocationListError::UnsupportedSignatureAlgorithm.into() } #[allow(deprecated)] @@ -117,9 +117,10 @@ fn pki_error(error: webpki::Error) -> Error { fn crl_error(e: webpki::Error) -> CertRevocationListError { use webpki::Error::*; match e { - InvalidCrlSignatureForPublicKey - | UnsupportedCrlSignatureAlgorithm - | UnsupportedCrlSignatureAlgorithmForPublicKey => CertRevocationListError::BadSignature, + InvalidCrlSignatureForPublicKey => CertRevocationListError::BadSignature, + UnsupportedCrlSignatureAlgorithm | UnsupportedCrlSignatureAlgorithmForPublicKey => { + CertRevocationListError::UnsupportedSignatureAlgorithm + } InvalidCrlNumber => CertRevocationListError::InvalidCrlNumber, InvalidSerialNumber => CertRevocationListError::InvalidRevokedCertSerialNumber, IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl, @@ -158,11 +159,15 @@ mod tests { ); assert_eq!( pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithm), - Error::InvalidCertRevocationList(CertRevocationListError::BadSignature), + Error::InvalidCertRevocationList( + CertRevocationListError::UnsupportedSignatureAlgorithm + ), ); assert_eq!( pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey), - Error::InvalidCertRevocationList(CertRevocationListError::BadSignature), + Error::InvalidCertRevocationList( + CertRevocationListError::UnsupportedSignatureAlgorithm + ), ); // Revoked cert errors should be turned into Revoked. @@ -187,11 +192,11 @@ mod tests { (webpki::Error::InvalidCrlSignatureForPublicKey, BadSignature), ( webpki::Error::UnsupportedCrlSignatureAlgorithm, - BadSignature, + UnsupportedSignatureAlgorithm, ), ( webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey, - BadSignature, + UnsupportedSignatureAlgorithm, ), (webpki::Error::InvalidCrlNumber, InvalidCrlNumber), ( From 3cdc0b05310cf72a7310fb00459287136e1e3ca8 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 6 Jun 2025 17:20:29 +0100 Subject: [PATCH 267/403] Take semver-compatible updates --- Cargo.lock | 514 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 316 insertions(+), 198 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c89c67280a5..22e71da68a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -84,9 +84,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" dependencies = [ "anstyle", "anstyle-parse", @@ -99,36 +99,36 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" dependencies = [ "anstyle", - "once_cell", + "once_cell_polyfill", "windows-sys 0.59.0", ] @@ -140,9 +140,9 @@ checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "asn1" -version = "0.21.1" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33fb74ca1da7780ced4ef36df6ea620b4e1debeff2b1ccde057583771e405e78" +checksum = "2d9c3502a6f1b50a2c69b97b71638a81ad3b21b9874604880401b9b2b0bf758f" dependencies = [ "asn1_derive", "itoa", @@ -189,9 +189,9 @@ dependencies = [ [[package]] name = "asn1_derive" -version = "0.21.1" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa21886d7595227bbe0a5d53598aa295ef5f0d093936e2e76d4239d6d14ef22" +checksum = "1766ebcb519d8dd186d60dfa912571edcaa2c1f995e2e56643a261a87df69a61" dependencies = [ "proc-macro2", "quote", @@ -262,9 +262,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" +checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3" dependencies = [ "async-lock", "cfg-if", @@ -273,7 +273,7 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix", + "rustix 1.0.7", "slab", "tracing", "windows-sys 0.59.0", @@ -362,9 +362,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b756939cb2f8dc900aa6dcd505e6e2428e9cae7ff7b028c49e3946efa70878" +checksum = "93fcc8f365936c834db5514fc45aee5b1202d677e6b40e48468aaaa8183ca8c7" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", @@ -373,9 +373,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.28.2" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa9b6986f250236c27e5a204062434a773a13243d2ffc2955f37bdba4c5c6a1" +checksum = "61b1d86e7705efe1be1b569bab41d4fa1e14e220b60a160f78de2db687add079" dependencies = [ "bindgen", "cc", @@ -413,9 +413,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.7.3" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" [[package]] name = "bencher" @@ -448,9 +448,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "block-buffer" @@ -508,9 +508,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" [[package]] name = "byteorder" @@ -532,9 +532,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.21" +version = "1.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8691782945451c1c383942c4874dbe63814f61cb57ef773cda2972682b7bb3c0" +checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" dependencies = [ "jobserver", "libc", @@ -637,9 +637,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.37" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" +checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" dependencies = [ "clap_builder", "clap_derive", @@ -647,9 +647,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.37" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" +checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" dependencies = [ "anstream", "anstyle", @@ -686,9 +686,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "concurrent-queue" @@ -1010,9 +1010,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", "windows-sys 0.59.0", @@ -1179,10 +1179,11 @@ dependencies = [ [[package]] name = "generator" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6bd114ceda131d3b1d665eba35788690ad37f5916457286b32ab6fd3c438dd" +checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" dependencies = [ + "cc", "cfg-if", "libc", "log", @@ -1214,9 +1215,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", @@ -1265,7 +1266,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00678994ed89e22df4c4d99e3105b0ae69206d4b9aaeaeec3a52c2bec55c1f01" dependencies = [ "cfg-if", - "getrandom 0.3.2", + "getrandom 0.3.3", ] [[package]] @@ -1325,9 +1326,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.4.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" [[package]] name = "hex" @@ -1468,21 +1469,22 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", + "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", "litemap", @@ -1491,31 +1493,11 @@ dependencies = [ "zerovec", ] -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" - [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", @@ -1523,67 +1505,54 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "potential_utf", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", + "icu_locale_core", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", + "zerotrie", "zerovec", ] -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - [[package]] name = "idna" version = "1.0.3" @@ -1597,9 +1566,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -1692,9 +1661,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f02000660d30638906021176af16b17498bd0d12813dbfe7b276d8bc7f3c0806" +checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93" dependencies = [ "jiff-static", "log", @@ -1705,9 +1674,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c30758ddd7188629c6713fc45d1188af4f44c90582311d0c8d8c9907f60c48" +checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442" dependencies = [ "proc-macro2", "quote", @@ -1720,7 +1689,7 @@ version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", "libc", ] @@ -1766,12 +1735,12 @@ checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libloading" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.53.0", ] [[package]] @@ -1786,17 +1755,23 @@ version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + [[package]] name = "litemap" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", @@ -1826,9 +1801,9 @@ dependencies = [ [[package]] name = "macro_rules_attribute" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a82271f7bc033d84bbca59a3ce3e4159938cb08a9c3aebbe54d215131518a13" +checksum = "65049d7923698040cd0b1ddcced9b0eb14dd22c5f86ae59c3740eab64a676520" dependencies = [ "macro_rules_attribute-proc_macro", "paste", @@ -1836,9 +1811,9 @@ dependencies = [ [[package]] name = "macro_rules_attribute-proc_macro" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dd856d451cc0da70e2ef2ce95a18e39a93b7558bedf10201ad28503f918568" +checksum = "670fdfda89751bc4a84ac13eaa63e205cf0fd22b4c9a5fbfa085b63c1f1d3a30" [[package]] name = "matchers" @@ -1872,14 +1847,14 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2024,6 +1999,12 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + [[package]] name = "oorandom" version = "11.1.5" @@ -2038,9 +2019,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.72" +version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ "bitflags", "cfg-if", @@ -2064,9 +2045,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.108" +version = "0.9.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", @@ -2110,9 +2091,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", @@ -2120,9 +2101,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", @@ -2233,15 +2214,15 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.4" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" +checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix", + "rustix 1.0.7", "tracing", "windows-sys 0.59.0", ] @@ -2271,9 +2252,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "portable-atomic-util" @@ -2284,6 +2265,15 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -2301,9 +2291,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" +checksum = "9dee91521343f4c5c6a63edd65e54f31f5c92fe8978c40a4282f8372194c6a7d" dependencies = [ "proc-macro2", "syn 2.0.101", @@ -2397,7 +2387,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", ] [[package]] @@ -2488,9 +2478,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "resolv-conf" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7c8f7f733062b66dc1c63f9db168ac0b97a9210e247fa90fdc9ad08f51b302" +checksum = "95325155c684b1c89f7765e30bc1c42e4a6da51ca513615660cb8a62ef9a88e3" [[package]] name = "rfc6979" @@ -2576,7 +2566,20 @@ dependencies = [ "bitflags", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.9.4", "windows-sys 0.59.0", ] @@ -2701,9 +2704,12 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] [[package]] name = "rustls-post-quantum" @@ -2759,9 +2765,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.2" +version = "0.103.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7149975849f1abb3832b246010ef62ccc80d3a76169517ada7188252b9cfb437" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" dependencies = [ "aws-lc-rs", "ring", @@ -2771,9 +2777,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "ryu" @@ -2907,9 +2913,9 @@ checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" [[package]] name = "socket2" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3091,9 +3097,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", "zerovec", @@ -3126,9 +3132,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.45.0" +version = "1.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" +checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" dependencies = [ "backtrace", "bytes", @@ -3186,9 +3192,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", "valuable", @@ -3262,12 +3268,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -3282,11 +3282,13 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", + "js-sys", + "wasm-bindgen", ] [[package]] @@ -3446,7 +3448,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix", + "rustix 0.38.44", ] [[package]] @@ -3488,32 +3490,55 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.58.0" +version = "0.61.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-link", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" dependencies = [ "windows-core", - "windows-targets 0.52.6", ] [[package]] name = "windows-core" -version = "0.58.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", + "windows-link", "windows-result", "windows-strings", - "windows-targets 0.52.6", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", ] [[package]] name = "windows-implement" -version = "0.58.0" +version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", @@ -3522,9 +3547,9 @@ dependencies = [ [[package]] name = "windows-interface" -version = "0.58.0" +version = "0.59.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", @@ -3532,22 +3557,37 @@ dependencies = [ ] [[package]] -name = "windows-result" +name = "windows-link" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + +[[package]] +name = "windows-numerics" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ - "windows-targets 0.52.6", + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link", ] [[package]] name = "windows-strings" -version = "0.1.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-result", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -3601,13 +3641,38 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -3620,6 +3685,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -3632,6 +3703,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -3644,12 +3721,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[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_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -3662,6 +3751,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -3674,6 +3769,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -3686,6 +3787,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -3698,6 +3805,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winreg" version = "0.50.0" @@ -3717,17 +3830,11 @@ dependencies = [ "bitflags", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - [[package]] name = "writeable" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "x25519-dalek" @@ -3769,9 +3876,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", @@ -3781,9 +3888,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", @@ -3852,11 +3959,22 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + [[package]] name = "zerovec" -version = "0.10.4" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" dependencies = [ "yoke", "zerofrom", @@ -3865,9 +3983,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", @@ -3876,6 +3994,6 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "868b928d7949e09af2f6086dfc1e01936064cc7a819253bce650d4e2a2d63ba8" +checksum = "626bd9fa9734751fc50d6060752170984d7053f5a39061f524cda68023d4db8a" From b4aca496d3d3703593bfa432114e05b8d2f2061a Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 9 Jun 2025 09:01:33 +0100 Subject: [PATCH 268/403] Extract `ClientSessionTicket` codec steps --- rustls/src/msgs/handshake.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 483b7edeb59..8593d20a914 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -755,10 +755,8 @@ impl Codec<'_> for ClientExtension { Self::NamedGroups(r) => r.encode(nested.buf), Self::SignatureAlgorithms(r) => r.encode(nested.buf), Self::ServerName(r) => r.encode(nested.buf), - Self::SessionTicket(ClientSessionTicket::Request) - | Self::ExtendedMasterSecretRequest - | Self::EarlyData => {} - Self::SessionTicket(ClientSessionTicket::Offer(r)) => r.encode(nested.buf), + Self::SessionTicket(r) => r.encode(nested.buf), + Self::ExtendedMasterSecretRequest | Self::EarlyData => {} Self::Protocols(r) => r.encode(nested.buf), Self::SupportedVersions(r) => r.encode(nested.buf), Self::KeyShare(r) => r.encode(nested.buf), @@ -792,12 +790,7 @@ impl Codec<'_> for ClientExtension { Self::ServerName(ServerNamePayload::read(&mut sub)?.into_owned()) } ExtensionType::SessionTicket => { - if sub.any_left() { - let contents = Payload::read(&mut sub).into_owned(); - Self::SessionTicket(ClientSessionTicket::Offer(contents)) - } else { - Self::SessionTicket(ClientSessionTicket::Request) - } + Self::SessionTicket(ClientSessionTicket::read(&mut sub)?) } ExtensionType::ALProtocolNegotiation => Self::Protocols(Vec::read(&mut sub)?), ExtensionType::SupportedVersions => { @@ -863,6 +856,22 @@ pub(crate) enum ClientSessionTicket { Offer(Payload<'static>), } +impl<'a> Codec<'a> for ClientSessionTicket { + fn encode(&self, bytes: &mut Vec) { + match self { + Self::Request => (), + Self::Offer(p) => p.encode(bytes), + } + } + + fn read(r: &mut Reader<'a>) -> Result { + Ok(match r.left() { + 0 => Self::Request, + _ => Self::Offer(Payload::read(r).into_owned()), + }) + } +} + #[derive(Clone, Debug)] pub(crate) enum ServerExtension { EcPointFormats(Vec), From 34cdce3d8c81378480bd71c7c64b6ae2925891ae Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 9 Jun 2025 09:08:32 +0100 Subject: [PATCH 269/403] Return more specific type from `grease_ext()` --- rustls/src/client/ech.rs | 16 +++++++--------- rustls/src/client/hs.rs | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index 5df50ccdb3c..3fa07fe7467 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -202,7 +202,7 @@ impl EchGreaseConfig { secure_random: &'static dyn SecureRandom, inner_name: ServerName<'static>, outer_hello: &ClientHelloPayload, - ) -> Result { + ) -> Result { trace!("Preparing GREASE ECH extension"); // Pick a random config id. @@ -251,14 +251,12 @@ impl EchGreaseConfig { secure_random.fill(&mut payload)?; // Return the GREASE extension. - Ok(ClientExtension::EncryptedClientHello( - EncryptedClientHello::Outer(EncryptedClientHelloOuter { - cipher_suite: suite.sym, - config_id: config_id[0], - enc: PayloadU16::new(grease_state.enc.0), - payload: PayloadU16::new(payload), - }), - )) + Ok(EncryptedClientHello::Outer(EncryptedClientHelloOuter { + cipher_suite: suite.sym, + config_id: config_id[0], + enc: PayloadU16::new(grease_state.enc.0), + payload: PayloadU16::new(payload), + })) } } diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 842355d7b7b..8de0d141be0 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -484,7 +484,7 @@ fn emit_client_hello_for_retry( (EchStatus::NotOffered, None) => { if let Some(grease_ext) = ech_grease_ext { // Add the GREASE ECH extension. - let grease_ext = grease_ext?; + let grease_ext = ClientExtension::EncryptedClientHello(grease_ext?); chp_payload .extensions .push(grease_ext.clone()); From d8828602c5d28ebefba59178d39cbdb38ed29429 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 9 Jun 2025 09:23:06 +0100 Subject: [PATCH 270/403] Return more specific type from `outer_hello_ext()` --- rustls/src/client/ech.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index 3fa07fe7467..c79b30f9adf 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -396,15 +396,13 @@ impl EchState { false => self.enc.0.clone(), }; - fn outer_hello_ext(ctx: &EchState, enc: Vec, payload: Vec) -> ClientExtension { - ClientExtension::EncryptedClientHello(EncryptedClientHello::Outer( - EncryptedClientHelloOuter { - cipher_suite: ctx.cipher_suite, - config_id: ctx.config_id, - enc: PayloadU16::new(enc), - payload: PayloadU16::new(payload), - }, - )) + fn outer_hello_ext(ctx: &EchState, enc: Vec, payload: Vec) -> 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 @@ -418,7 +416,11 @@ impl EchState { // To compute the encoded AAD we add a placeholder extension with an empty payload. outer_hello .extensions - .push(outer_hello_ext(self, enc.clone(), vec![0; payload_len])); + .push(ClientExtension::EncryptedClientHello(outer_hello_ext( + self, + enc.clone(), + vec![0; payload_len], + ))); // Next we compute the proper extension payload. let payload = self @@ -429,7 +431,9 @@ impl EchState { outer_hello.extensions.pop(); outer_hello .extensions - .push(outer_hello_ext(self, enc, payload)); + .push(ClientExtension::EncryptedClientHello(outer_hello_ext( + self, enc, payload, + ))); Ok(outer_hello) } From 229dfe250d03fcdd5c38fda5faf3a1ac5da81868 Mon Sep 17 00:00:00 2001 From: Joseph Birr-Pixton Date: Thu, 14 Sep 2023 16:21:17 +0100 Subject: [PATCH 271/403] Allow future customisation of alert sent for `InvalidMessage` --- rustls/src/conn.rs | 2 +- rustls/src/error.rs | 6 ++++++ rustls/src/msgs/message/mod.rs | 6 +++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/rustls/src/conn.rs b/rustls/src/conn.rs index 1d601b04bcf..1a95079fada 100644 --- a/rustls/src/conn.rs +++ b/rustls/src/conn.rs @@ -1147,7 +1147,7 @@ impl ConnectionCore { Err(err) => { return Err(self .common_state - .send_fatal_alert(AlertDescription::DecodeError, err)); + .send_fatal_alert(AlertDescription::from(err), err)); } }; diff --git a/rustls/src/error.rs b/rustls/src/error.rs index 50d989c530b..ebc857ffd1b 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -203,6 +203,12 @@ impl From for Error { } } +impl From for AlertDescription { + fn from(_: InvalidMessage) -> Self { + Self::DecodeError + } +} + #[non_exhaustive] #[allow(missing_docs)] #[derive(Debug, PartialEq, Clone)] diff --git a/rustls/src/msgs/message/mod.rs b/rustls/src/msgs/message/mod.rs index 0b9e4fd87c4..d5cecc94892 100644 --- a/rustls/src/msgs/message/mod.rs +++ b/rustls/src/msgs/message/mod.rs @@ -1,5 +1,5 @@ use crate::enums::{AlertDescription, ContentType, HandshakeType, ProtocolVersion}; -use crate::error::{Error, InvalidMessage}; +use crate::error::InvalidMessage; use crate::msgs::alert::AlertMessagePayload; use crate::msgs::base::Payload; use crate::msgs::ccs::ChangeCipherSpecPayload; @@ -214,7 +214,7 @@ impl Message<'_> { } impl TryFrom for Message<'static> { - type Error = Error; + type Error = InvalidMessage; fn try_from(plain: PlainMessage) -> Result { Ok(Self { @@ -230,7 +230,7 @@ impl TryFrom for Message<'static> { /// 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> for Message<'a> { - type Error = Error; + type Error = InvalidMessage; fn try_from(plain: InboundPlainMessage<'a>) -> Result { Ok(Self { From 568b2c650014301af70deedc26cd8032cbda6dc1 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 9 Jun 2025 10:05:23 +0100 Subject: [PATCH 272/403] Use `ProtocolName` for ALPN protocol pervasively --- rustls/src/client/client_conn.rs | 6 +++++- rustls/src/client/common.rs | 6 +++--- rustls/src/client/hs.rs | 15 +++++---------- rustls/src/common_state.rs | 4 ++-- rustls/src/msgs/handshake.rs | 22 ++++++++++++++++++---- rustls/src/msgs/handshake_test.rs | 2 +- rustls/src/msgs/persist.rs | 6 +++--- rustls/src/server/hs.rs | 6 +++--- rustls/src/server/tls13.rs | 2 +- 9 files changed, 41 insertions(+), 28 deletions(-) diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index d66664cd9c2..f0c7dae4744 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -19,7 +19,7 @@ use crate::error::Error; use crate::kernel::KernelConnection; use crate::log::trace; use crate::msgs::enums::NamedGroup; -use crate::msgs::handshake::ClientExtension; +use crate::msgs::handshake::{ClientExtension, ProtocolName}; use crate::msgs::persist; use crate::suites::{ExtractedSecrets, SupportedCipherSuite}; use crate::sync::Arc; @@ -851,6 +851,10 @@ impl ConnectionCore { common_state.enable_secret_extraction = config.enable_secret_extraction; common_state.fips = config.fips(); let mut data = ClientConnectionData::new(); + let alpn_protocols = alpn_protocols + .into_iter() + .map(ProtocolName::from) + .collect(); let mut cx = hs::ClientContext { common: &mut common_state, diff --git a/rustls/src/client/common.rs b/rustls/src/client/common.rs index 214fe07a2ec..fb6a013b424 100644 --- a/rustls/src/client/common.rs +++ b/rustls/src/client/common.rs @@ -4,7 +4,7 @@ use alloc::vec::Vec; use super::ResolvesClientCert; use crate::log::{debug, trace}; use crate::msgs::enums::ExtensionType; -use crate::msgs::handshake::{CertificateChain, DistinguishedName, ServerExtension}; +use crate::msgs::handshake::{CertificateChain, DistinguishedName, ProtocolName, ServerExtension}; use crate::sync::Arc; use crate::{SignatureScheme, compress, sign}; @@ -35,14 +35,14 @@ impl<'a> ServerCertDetails<'a> { } pub(super) struct ClientHelloDetails { - pub(super) alpn_protocols: Vec>, + pub(super) alpn_protocols: Vec, pub(super) sent_extensions: Vec, pub(super) extension_order_seed: u16, pub(super) offered_cert_compression: bool, } impl ClientHelloDetails { - pub(super) fn new(alpn_protocols: Vec>, extension_order_seed: u16) -> Self { + pub(super) fn new(alpn_protocols: Vec, extension_order_seed: u16) -> Self { Self { alpn_protocols, sent_extensions: Vec::new(), diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 8de0d141be0..d0983b21f7f 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -99,7 +99,7 @@ fn find_session( pub(super) fn start_handshake( server_name: ServerName<'static>, - alpn_protocols: Vec>, + alpn_protocols: Vec, extra_exts: Vec, config: Arc, cx: &mut ClientContext<'_>, @@ -359,12 +359,7 @@ fn emit_client_hello_for_retry( // Add ALPN extension if we have any protocols if !input.hello.alpn_protocols.is_empty() { exts.push(ClientExtension::Protocols( - input - .hello - .alpn_protocols - .iter() - .map(|proto| ProtocolName::from(proto.clone())) - .collect::>(), + input.hello.alpn_protocols.clone(), )); } @@ -668,10 +663,10 @@ fn prepare_resumption<'a>( pub(super) fn process_alpn_protocol( common: &mut CommonState, - offered_protocols: &[Vec], - proto: Option<&[u8]>, + offered_protocols: &[ProtocolName], + selected: Option<&ProtocolName>, ) -> Result<(), Error> { - common.alpn_protocol = proto.map(ToOwned::to_owned); + common.alpn_protocol = selected.map(ToOwned::to_owned); if let Some(alpn_protocol) = &common.alpn_protocol { if !offered_protocols.contains(alpn_protocol) { diff --git a/rustls/src/common_state.rs b/rustls/src/common_state.rs index 07c8dd3492f..4d47cf15076 100644 --- a/rustls/src/common_state.rs +++ b/rustls/src/common_state.rs @@ -14,7 +14,7 @@ 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}; +use crate::msgs::handshake::{CertificateChain, HandshakeMessagePayload, ProtocolName}; use crate::msgs::message::{ Message, MessagePayload, OutboundChunks, OutboundOpaqueMessage, OutboundPlainMessage, PlainMessage, @@ -35,7 +35,7 @@ pub struct CommonState { pub(crate) record_layer: record_layer::RecordLayer, pub(crate) suite: Option, pub(crate) kx_state: KxState, - pub(crate) alpn_protocol: Option>, + pub(crate) alpn_protocol: Option, pub(crate) aligned_handshake: bool, pub(crate) may_send_application_data: bool, pub(crate) may_receive_application_data: bool, diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 8593d20a914..d849425566c 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -360,6 +360,20 @@ wrapped_payload!( pub(crate) struct ProtocolName, PayloadU8, ); +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 { @@ -372,8 +386,8 @@ impl TlsListElement for ProtocolName { pub(crate) struct SingleProtocolName(ProtocolName); impl SingleProtocolName { - pub(crate) fn new(bytes: Vec) -> Self { - Self(ProtocolName::from(bytes)) + pub(crate) fn new(single: ProtocolName) -> Self { + Self(single) } const SIZE_LEN: ListLength = ListLength::NonZeroU16 { @@ -2224,10 +2238,10 @@ pub(crate) trait HasServerExtensions { .find(|x| x.ext_type() == ext) } - fn alpn_protocol(&self) -> Option<&[u8]> { + fn alpn_protocol(&self) -> Option<&ProtocolName> { let ext = self.find_extension(ExtensionType::ALProtocolNegotiation)?; match ext { - ServerExtension::Protocols(protos) => Some(protos.as_ref()), + ServerExtension::Protocols(protos) => Some(&protos.0), _ => None, } } diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index cb2c6d639df..ab1c742981d 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -1006,7 +1006,7 @@ fn sample_server_hello_payload() -> ServerHelloPayload { ServerExtension::ServerNameAck, ServerExtension::SessionTicketAck, ServerExtension::RenegotiationInfo(PayloadU8::new(vec![0])), - ServerExtension::Protocols(SingleProtocolName::new(vec![0])), + ServerExtension::Protocols(SingleProtocolName::new(ProtocolName::from(vec![0]))), ServerExtension::KeyShare(KeyShareEntry::new(NamedGroup::X25519, &[1, 2, 3][..])), ServerExtension::PresharedKey(3), ServerExtension::ExtendedMasterSecretAck, diff --git a/rustls/src/msgs/persist.rs b/rustls/src/msgs/persist.rs index 88960daf99f..8231c8ff61c 100644 --- a/rustls/src/msgs/persist.rs +++ b/rustls/src/msgs/persist.rs @@ -9,9 +9,9 @@ use crate::enums::{CipherSuite, ProtocolVersion}; use crate::error::InvalidMessage; use crate::msgs::base::{MaybeEmpty, PayloadU8, PayloadU16}; use crate::msgs::codec::{Codec, Reader}; -use crate::msgs::handshake::CertificateChain; #[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; @@ -399,7 +399,7 @@ impl ServerSessionValue { cs: CipherSuite, ms: &[u8], client_cert_chain: Option>, - alpn: Option>, + alpn: Option, application_data: Vec, creation_time: UnixTime, age_obfuscation_offset: u32, @@ -411,7 +411,7 @@ impl ServerSessionValue { master_secret: Zeroizing::new(PayloadU8::new(ms.to_vec())), extended_ms: false, client_cert_chain, - alpn: alpn.map(PayloadU8::new), + 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, diff --git a/rustls/src/server/hs.rs b/rustls/src/server/hs.rs index e3939a05540..2bf8659b637 100644 --- a/rustls/src/server/hs.rs +++ b/rustls/src/server/hs.rs @@ -21,8 +21,8 @@ use crate::msgs::enums::{Compression, ExtensionType, NamedGroup}; #[cfg(feature = "tls12")] use crate::msgs::handshake::SessionId; use crate::msgs::handshake::{ - ClientHelloPayload, HandshakePayload, KeyExchangeAlgorithm, Random, ServerExtension, - ServerNamePayload, SingleProtocolName, + ClientHelloPayload, HandshakePayload, KeyExchangeAlgorithm, ProtocolName, Random, + ServerExtension, ServerNamePayload, SingleProtocolName, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; @@ -89,7 +89,7 @@ impl ExtensionProcessing { .iter() .any(|theirs| theirs.as_ref() == ours.as_slice()) }) - .cloned(); + .map(|bytes| ProtocolName::from(bytes.clone())); if let Some(selected_protocol) = &cx.common.alpn_protocol { debug!("Chosen ALPN protocol {selected_protocol:?}"); self.exts diff --git a/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index 8780eb83916..8e7a389a349 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -652,7 +652,7 @@ mod client_hello { && resume.is_fresh() && Some(resume.version) == cx.common.negotiated_version && resume.cipher_suite == suite.common.suite - && resume.alpn.as_ref().map(|x| &x.0) == cx.common.alpn_protocol.as_ref(); + && 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 From 96d66569c9c9fe3d7343eb12b51ea42226eef2c8 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 11 Jun 2025 14:25:37 +0100 Subject: [PATCH 273/403] Only include renegotiation SCSV for TLS1.2 attempts --- rustls/src/client/hs.rs | 7 +++++-- rustls/src/client/test.rs | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index d0983b21f7f..f16117c564b 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -440,8 +440,11 @@ fn emit_client_hello_for_retry( false => None, }) .collect(); - // We don't do renegotiation at all, in fact. - cipher_suites.push(CipherSuite::TLS_EMPTY_RENEGOTIATION_INFO_SCSV); + + 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, diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs index dc52311280a..89d6493bab1 100644 --- a/rustls/src/client/test.rs +++ b/rustls/src/client/test.rs @@ -58,6 +58,22 @@ mod tests { assert!(ch.ticket_extension().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 { From 136e857c77b6ab126dd0da41c128ef1274915efd Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 10 Jun 2025 09:48:39 +0100 Subject: [PATCH 274/403] fuzzing-provider: make ciphersuites public --- rustls-fuzzing-provider/src/lib.rs | 46 ++++++++++++++++-------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/rustls-fuzzing-provider/src/lib.rs b/rustls-fuzzing-provider/src/lib.rs index b30c418aca2..28fb88ae7ed 100644 --- a/rustls-fuzzing-provider/src/lib.rs +++ b/rustls-fuzzing-provider/src/lib.rs @@ -101,28 +101,30 @@ impl crypto::KeyProvider for Provider { } } -static TLS13_FUZZING_SUITE: SupportedCipherSuite = SupportedCipherSuite::Tls13(&Tls13CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::Unknown(0xff13), - hash_provider: &Hash, - confidentiality_limit: u64::MAX, - }, - hkdf_provider: &tls13::HkdfUsingHmac(&Hmac), - aead_alg: &Aead, - quic: None, -}); - -static TLS_FUZZING_SUITE: SupportedCipherSuite = SupportedCipherSuite::Tls12(&Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::Unknown(0xff12), - hash_provider: &Hash, - confidentiality_limit: u64::MAX, - }, - kx: KeyExchangeAlgorithm::ECDHE, - sign: &[SIGNATURE_SCHEME], - prf_provider: &tls12::PrfUsingHmac(&Hmac), - aead_alg: &Aead, -}); +pub static TLS13_FUZZING_SUITE: SupportedCipherSuite = + SupportedCipherSuite::Tls13(&Tls13CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::Unknown(0xff13), + hash_provider: &Hash, + confidentiality_limit: u64::MAX, + }, + hkdf_provider: &tls13::HkdfUsingHmac(&Hmac), + aead_alg: &Aead, + quic: None, + }); + +pub static TLS_FUZZING_SUITE: SupportedCipherSuite = + SupportedCipherSuite::Tls12(&Tls12CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::Unknown(0xff12), + hash_provider: &Hash, + confidentiality_limit: u64::MAX, + }, + kx: KeyExchangeAlgorithm::ECDHE, + sign: &[SIGNATURE_SCHEME], + prf_provider: &tls12::PrfUsingHmac(&Hmac), + aead_alg: &Aead, + }); struct Hash; From 9b452d26a4b28bf209bd9e052cea87e6e13b216a Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 10 Jun 2025 09:49:22 +0100 Subject: [PATCH 275/403] fuzzing-provider: support no-op ticketer --- rustls-fuzzing-provider/src/lib.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/rustls-fuzzing-provider/src/lib.rs b/rustls-fuzzing-provider/src/lib.rs index 28fb88ae7ed..4a217465c3c 100644 --- a/rustls-fuzzing-provider/src/lib.rs +++ b/rustls-fuzzing-provider/src/lib.rs @@ -31,6 +31,7 @@ use rustls::pki_types::{ AlgorithmIdentifier, CertificateDer, InvalidSignature, PrivateKeyDer, SignatureVerificationAlgorithm, alg_id, }; +use rustls::server::ProducesTickets; use rustls::{ CipherSuite, ConnectionTrafficSecrets, ContentType, Error, NamedGroup, PeerMisbehaved, ProtocolVersion, RootCertStore, SignatureAlgorithm, SignatureScheme, SupportedCipherSuite, @@ -126,6 +127,27 @@ pub static TLS_FUZZING_SUITE: SupportedCipherSuite = aead_alg: &Aead, }); +#[derive(Debug, Default)] +pub struct Ticketer; + +impl ProducesTickets for Ticketer { + fn enabled(&self) -> bool { + true + } + + fn lifetime(&self) -> u32 { + 60 * 60 * 6 + } + + fn encrypt(&self, plain: &[u8]) -> Option> { + Some(plain.to_vec()) + } + + fn decrypt(&self, cipher: &[u8]) -> Option> { + Some(cipher.to_vec()) + } +} + struct Hash; impl hash::Hash for Hash { From b9a530a746d7a5db759a3ef8dc34b95973af8f19 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 10 Jun 2025 09:49:39 +0100 Subject: [PATCH 276/403] ci-bench: low-noise benchmarks with rustls-fuzzing-provider --- Cargo.lock | 1 + Cargo.toml | 1 + ci-bench/Cargo.toml | 1 + ci-bench/src/benchmark.rs | 14 +++++--- ci-bench/src/main.rs | 73 ++++++++++++++++++++++++++++++--------- 5 files changed, 70 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 22e71da68a4..3e43514d306 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2640,6 +2640,7 @@ dependencies = [ "itertools 0.14.0", "rayon", "rustls", + "rustls-fuzzing-provider", "rustls-test", "tikv-jemallocator", ] diff --git a/Cargo.toml b/Cargo.toml index 6248d09d964..de345902795 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -83,6 +83,7 @@ ring = "0.17" rsa = { version = "0.9", features = ["sha2"], default-features = false } rustls-graviola = { version = "0.2" } rustls-test = { path = "rustls-test/" } +rustls-fuzzing-provider = { path = "rustls-fuzzing-provider/" } serde = { version = "1", features = ["derive"] } serde_json = "1" sha2 = { version = "0.10", default-features = false } diff --git a/ci-bench/Cargo.toml b/ci-bench/Cargo.toml index ff92bfb507d..ef3b5566121 100644 --- a/ci-bench/Cargo.toml +++ b/ci-bench/Cargo.toml @@ -16,6 +16,7 @@ itertools = { workspace = true } rayon = { workspace = true } rustls = { path = "../rustls", features = ["ring", "aws_lc_rs"] } rustls-test = { workspace = true } +rustls-fuzzing-provider = { workspace = true } [target.'cfg(not(target_env = "msvc"))'.dependencies] tikv-jemallocator = { workspace = true } diff --git a/ci-bench/src/benchmark.rs b/ci-bench/src/benchmark.rs index 1ecea0a7b9e..4e4a9446e1a 100644 --- a/ci-bench/src/benchmark.rs +++ b/ci-bench/src/benchmark.rs @@ -87,8 +87,8 @@ pub struct BenchmarkParams { pub provider: rustls::crypto::CryptoProvider, /// How to make a suitable [`rustls::server::ProducesTickets`]. pub ticketer: &'static fn() -> Arc, - /// The type of key used to sign the TLS certificate - pub key_type: KeyType, + /// Where to get keys for server auth + pub auth_key: AuthKeySource, /// Cipher suite pub ciphersuite: rustls::SupportedCipherSuite, /// TLS version @@ -102,7 +102,7 @@ impl BenchmarkParams { pub const fn new( provider: rustls::crypto::CryptoProvider, ticketer: &'static fn() -> Arc, - key_type: KeyType, + auth_key: AuthKeySource, ciphersuite: rustls::SupportedCipherSuite, version: &'static rustls::SupportedProtocolVersion, label: String, @@ -110,7 +110,7 @@ impl BenchmarkParams { Self { provider, ticketer, - key_type, + auth_key, ciphersuite, version, label, @@ -118,6 +118,12 @@ impl BenchmarkParams { } } +#[derive(Clone, Debug)] +pub enum AuthKeySource { + KeyType(KeyType), + FuzzingProvider, +} + /// A benchmark specification pub struct Benchmark { /// The name of the benchmark, as shown in the benchmark results diff --git a/ci-bench/src/main.rs b/ci-bench/src/main.rs index de6772fbef8..6fa165c9fb1 100644 --- a/ci-bench/src/main.rs +++ b/ci-bench/src/main.rs @@ -40,8 +40,8 @@ use rustls::{ use rustls_test::KeyType; use crate::benchmark::{ - Benchmark, BenchmarkKind, BenchmarkParams, ResumptionKind, get_reported_instr_count, - validate_benchmarks, + AuthKeySource, Benchmark, BenchmarkKind, BenchmarkParams, ResumptionKind, + get_reported_instr_count, validate_benchmarks, }; use crate::callgrind::{CallgrindRunner, CountInstructions}; use crate::util::async_io::{self, AsyncRead, AsyncWrite}; @@ -373,7 +373,7 @@ fn all_benchmarks_params() -> Vec { all.push(BenchmarkParams::new( provider.clone(), ticketer, - key_type, + AuthKeySource::KeyType(key_type), find_suite(suites, suite_name), version, format!("{provider_name}_{name}"), @@ -381,6 +381,28 @@ fn all_benchmarks_params() -> Vec { } } + #[allow(trivial_casts)] // false positive + let make_ticketer = &((|| Arc::new(rustls_fuzzing_provider::Ticketer)) + as fn() -> Arc); + + all.push(BenchmarkParams::new( + rustls_fuzzing_provider::provider(), + make_ticketer, + AuthKeySource::FuzzingProvider, + rustls_fuzzing_provider::TLS13_FUZZING_SUITE, + &rustls::version::TLS13, + "1.3_no_crypto".to_string(), + )); + + all.push(BenchmarkParams::new( + rustls_fuzzing_provider::provider(), + make_ticketer, + AuthKeySource::FuzzingProvider, + rustls_fuzzing_provider::TLS_FUZZING_SUITE, + &rustls::version::TLS12, + "1.2_no_crypto".to_string(), + )); + all } @@ -518,12 +540,8 @@ struct ClientSideStepper<'a> { impl ClientSideStepper<'_> { fn make_config(params: &BenchmarkParams, resume: ResumptionKind) -> Arc { assert_eq!(params.ciphersuite.version(), params.version); - let mut root_store = RootCertStore::empty(); - root_store - .add(params.key_type.ca_cert()) - .unwrap(); - let mut cfg = ClientConfig::builder_with_provider( + let cfg = ClientConfig::builder_with_provider( CryptoProvider { cipher_suites: vec![params.ciphersuite], ..params.provider.clone() @@ -531,9 +549,24 @@ impl ClientSideStepper<'_> { .into(), ) .with_protocol_versions(&[params.version]) - .unwrap() - .with_root_certificates(root_store) - .with_no_client_auth(); + .unwrap(); + + let mut cfg = match params.auth_key { + AuthKeySource::KeyType(key_type) => { + let mut root_store = RootCertStore::empty(); + root_store + .add(key_type.ca_cert()) + .unwrap(); + + cfg.with_root_certificates(root_store) + .with_no_client_auth() + } + + AuthKeySource::FuzzingProvider => cfg + .dangerous() + .with_custom_certificate_verifier(rustls_fuzzing_provider::server_verifier()) + .with_no_client_auth(), + }; if resume != ResumptionKind::No { cfg.resumption = Resumption::in_memory_sessions(128); @@ -603,12 +636,20 @@ impl ServerSideStepper<'_> { fn make_config(params: &BenchmarkParams, resume: ResumptionKind) -> Arc { assert_eq!(params.ciphersuite.version(), params.version); - let mut cfg = ServerConfig::builder_with_provider(params.provider.clone().into()) + let cfg = ServerConfig::builder_with_provider(params.provider.clone().into()) .with_protocol_versions(&[params.version]) - .unwrap() - .with_client_cert_verifier(WebPkiClientVerifier::no_client_auth()) - .with_single_cert(params.key_type.get_chain(), params.key_type.get_key()) - .expect("bad certs/private key?"); + .unwrap(); + + let mut cfg = match params.auth_key { + AuthKeySource::KeyType(key_type) => cfg + .with_client_cert_verifier(WebPkiClientVerifier::no_client_auth()) + .with_single_cert(key_type.get_chain(), key_type.get_key()) + .expect("bad certs/private key?"), + + AuthKeySource::FuzzingProvider => cfg + .with_client_cert_verifier(WebPkiClientVerifier::no_client_auth()) + .with_cert_resolver(rustls_fuzzing_provider::server_cert_resolver()), + }; if resume == ResumptionKind::SessionId { cfg.session_storage = ServerSessionMemoryCache::new(128); From 46ba039ba02fae323cc8145552982107cf498db5 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 12 Jun 2025 14:12:28 +0100 Subject: [PATCH 277/403] Expose `named_groups` extension in `ClientHello` --- rustls/src/server/handy.rs | 2 ++ rustls/src/server/hs.rs | 1 + rustls/src/server/server_conn.rs | 27 +++++++++++++++++++- rustls/tests/api.rs | 42 ++++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/rustls/src/server/handy.rs b/rustls/src/server/handy.rs index f11ca373803..ea3ec5d9db0 100644 --- a/rustls/src/server/handy.rs +++ b/rustls/src/server/handy.rs @@ -282,6 +282,7 @@ mod sni_resolver { client_cert_types: None, cipher_suites: &[], certificate_authorities: None, + named_groups: None, }) .is_none() ); @@ -303,6 +304,7 @@ mod sni_resolver { client_cert_types: None, cipher_suites: &[], certificate_authorities: None, + named_groups: None, }) .is_none() ); diff --git a/rustls/src/server/hs.rs b/rustls/src/server/hs.rs index 2bf8659b637..3c6ac479c49 100644 --- a/rustls/src/server/hs.rs +++ b/rustls/src/server/hs.rs @@ -417,6 +417,7 @@ impl ExpectClientHello { server_cert_types: client_hello.client_certificate_extension(), cipher_suites: &client_hello.cipher_suites, certificate_authorities, + named_groups: client_hello.namedgroups_extension(), }; trace!("Resolving server certificate: {client_hello:#?}"); diff --git a/rustls/src/server/server_conn.rs b/rustls/src/server/server_conn.rs index c21464b059c..35b5705474b 100644 --- a/rustls/src/server/server_conn.rs +++ b/rustls/src/server/server_conn.rs @@ -33,7 +33,9 @@ use crate::sync::Arc; use crate::time_provider::DefaultTimeProvider; use crate::time_provider::TimeProvider; use crate::vecbuf::ChunkVecBuffer; -use crate::{DistinguishedName, KeyLog, WantsVersions, compress, sign, verify, versions}; +use crate::{ + DistinguishedName, KeyLog, NamedGroup, WantsVersions, compress, sign, verify, versions, +}; /// A trait for the ability to store server session data. /// @@ -145,6 +147,7 @@ pub struct ClientHello<'a> { /// /// [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> { @@ -216,6 +219,27 @@ impl<'a> ClientHello<'a> { 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. @@ -995,6 +1019,7 @@ impl Accepted { client_cert_types: payload.client_certificate_extension(), cipher_suites: &payload.cipher_suites, certificate_authorities: payload.certificate_authorities_extension(), + named_groups: payload.namedgroups_extension(), }; trace!("Accepted::client_hello(): {ch:#?}"); diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index d6fa8bda19e..c6def2d2121 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -1157,6 +1157,7 @@ struct ServerCheckCertResolve { expected_cipher_suites: Option>, expected_server_cert_types: Option>, expected_client_cert_types: Option>, + expected_named_groups: Option>, } impl ResolvesServerCert for ServerCheckCertResolve { @@ -1227,6 +1228,15 @@ impl ResolvesServerCert for ServerCheckCertResolve { ); } + if let Some(expected_named_groups) = &self.expected_named_groups { + assert_eq!( + expected_named_groups, + client_hello + .named_groups() + .expect("Named groups not present"), + ) + } + None } } @@ -1275,6 +1285,30 @@ fn server_cert_resolve_with_alpn() { } } +#[test] +fn server_cert_resolve_with_named_groups() { + let provider = provider::default_provider(); + for kt in KeyType::all_for_provider(&provider) { + let client_config = make_client_config(*kt, &provider); + + let mut server_config = make_server_config(*kt, &provider); + server_config.cert_resolver = Arc::new(ServerCheckCertResolve { + expected_named_groups: Some( + provider + .kx_groups + .iter() + .map(|kx| kx.name()) + .collect(), + ), + ..Default::default() + }); + + let (mut client, mut server) = make_pair_for_configs(client_config, server_config); + let err = do_handshake_until_error(&mut client, &mut server); + assert!(err.is_err()); + } +} + #[test] fn client_trims_terminating_dot() { let provider = provider::default_provider(); @@ -6220,6 +6254,14 @@ fn test_acceptor() { let accepted = acceptor.accept().unwrap().unwrap(); let ch = accepted.client_hello(); assert_eq!(ch.server_name(), Some("localhost")); + assert_eq!( + ch.named_groups().unwrap(), + provider::default_provider() + .kx_groups + .iter() + .map(|kx| kx.name()) + .collect::>() + ); let server = accepted .into_connection(server_config) From 12fe0c123fa7dd0d2ed46cc815d3629d9f07c335 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 16 Jun 2025 11:54:17 +0100 Subject: [PATCH 278/403] Prepare 0.23.28 --- Cargo.lock | 83 +++-------------------------------------------- fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 80 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3e43514d306..a09b7b9b853 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -432,7 +432,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools 0.10.5", "lazy_static", "lazycell", "log", @@ -1626,15 +1626,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -1740,7 +1731,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.53.0", + "windows-targets 0.48.5", ] [[package]] @@ -2585,7 +2576,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.27" +version = "0.23.28" dependencies = [ "aws-lc-rs", "base64", @@ -3480,7 +3471,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] @@ -3642,29 +3633,13 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", + "windows_i686_gnullvm", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" -dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", -] - [[package]] name = "windows-threading" version = "0.1.0" @@ -3686,12 +3661,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -3704,12 +3673,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -3722,24 +3685,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - [[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_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -3752,12 +3703,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -3770,12 +3715,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -3788,12 +3727,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -3806,12 +3739,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - [[package]] name = "winreg" version = "0.50.0" diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index dfa8f3f50e1..abfd8c0f5d5 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.27" +version = "0.23.28" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index b0ab257849a..134d4c7c975 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.27" +version = "0.23.28" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From 6584005e8c22979548daac188d78abf57aa2a71b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 16 Jun 2025 13:27:28 +0100 Subject: [PATCH 279/403] Remove no-std ticketer code that didn't compile This was feature gated under `hashbrown` and `not(feature = std)` but didn't actually compile for that combination of features. That means we can a) conclude nobody ever used this, and b) withdraw this code in a non-breaking change. --- rustls/src/crypto/aws_lc_rs/mod.rs | 4 ++-- rustls/src/crypto/aws_lc_rs/ticketer.rs | 18 ------------------ rustls/src/crypto/ring/mod.rs | 4 ++-- rustls/src/crypto/ring/ticketer.rs | 15 --------------- 4 files changed, 4 insertions(+), 37 deletions(-) diff --git a/rustls/src/crypto/aws_lc_rs/mod.rs b/rustls/src/crypto/aws_lc_rs/mod.rs index 6795db5d558..6b9c0f7b6cd 100644 --- a/rustls/src/crypto/aws_lc_rs/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/mod.rs @@ -32,7 +32,7 @@ pub(crate) mod hmac; pub(crate) mod kx; #[path = "../ring/quic.rs"] pub(crate) mod quic; -#[cfg(any(feature = "std", feature = "hashbrown"))] +#[cfg(feature = "std")] pub(crate) mod ticketer; #[cfg(feature = "tls12")] pub(crate) mod tls12; @@ -262,7 +262,7 @@ pub static ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[ kx_group::MLKEM768, ]; -#[cfg(any(feature = "std", feature = "hashbrown"))] +#[cfg(feature = "std")] pub use ticketer::Ticketer; /// Compatibility shims between ring 0.16.x and 0.17.x API diff --git a/rustls/src/crypto/aws_lc_rs/ticketer.rs b/rustls/src/crypto/aws_lc_rs/ticketer.rs index b1b245495a2..44c7c21b473 100644 --- a/rustls/src/crypto/aws_lc_rs/ticketer.rs +++ b/rustls/src/crypto/aws_lc_rs/ticketer.rs @@ -38,24 +38,6 @@ impl Ticketer { make_ticket_generator, )?)) } - - /// 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(not(feature = "std"))] - pub fn new( - time_provider: &'static dyn TimeProvider, - ) -> Result, Error> { - Ok(Arc::new(crate::ticketer::TicketSwitcher::new::( - 6 * 60 * 60, - make_ticket_generator, - time_provider, - )?)) - } } fn make_ticket_generator() -> Result, GetRandomFailed> { diff --git a/rustls/src/crypto/ring/mod.rs b/rustls/src/crypto/ring/mod.rs index 79c2307ea18..2cd90e29732 100644 --- a/rustls/src/crypto/ring/mod.rs +++ b/rustls/src/crypto/ring/mod.rs @@ -19,7 +19,7 @@ pub(crate) mod hash; pub(crate) mod hmac; pub(crate) mod kx; pub(crate) mod quic; -#[cfg(any(feature = "std", feature = "hashbrown"))] +#[cfg(feature = "std")] pub(crate) mod ticketer; #[cfg(feature = "tls12")] pub(crate) mod tls12; @@ -177,7 +177,7 @@ pub static DEFAULT_KX_GROUPS: &[&dyn SupportedKxGroup] = ALL_KX_GROUPS; pub static ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[kx_group::X25519, kx_group::SECP256R1, kx_group::SECP384R1]; -#[cfg(any(feature = "std", feature = "hashbrown"))] +#[cfg(feature = "std")] pub use ticketer::Ticketer; /// Compatibility shims between ring 0.16.x and 0.17.x API diff --git a/rustls/src/crypto/ring/ticketer.rs b/rustls/src/crypto/ring/ticketer.rs index 45fe5db8a53..45dcc27a873 100644 --- a/rustls/src/crypto/ring/ticketer.rs +++ b/rustls/src/crypto/ring/ticketer.rs @@ -31,21 +31,6 @@ impl Ticketer { make_ticket_generator, )?)) } - - /// Make the recommended `Ticketer`. This produces tickets - /// with a 12 hour life and randomly generated keys. - /// - /// The encryption mechanism used is Chacha20Poly1305. - #[cfg(not(feature = "std"))] - pub fn new( - time_provider: &'static dyn TimeProvider, - ) -> Result, Error> { - Ok(Arc::new(crate::ticketer::TicketSwitcher::new::( - 6 * 60 * 60, - make_ticket_generator, - time_provider, - )?)) - } } fn make_ticket_generator() -> Result, GetRandomFailed> { From 834cb119699e4ff4bc04ce96e363e979a340c90b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 16 Jun 2025 13:24:41 +0100 Subject: [PATCH 280/403] ci: extend to check no-std-specific code compiles --- .github/workflows/build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f5fba4a5e6c..567427dd2b2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -98,6 +98,9 @@ jobs: env: RUST_BACKTRACE: 1 + - name: cargo build (debug; no-std) + run: cargo build --locked --lib -p rustls $(admin/all-features-except std,brotli,read_buf rustls) + - name: cargo build (debug; rustls-provider-example) run: cargo build --locked -p rustls-provider-example From 7c1859c140a0b94cb6ba3ced62975470835cbdbe Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 19 Jun 2025 06:15:32 +0100 Subject: [PATCH 281/403] Omit `RSA_PKCS1_3072_8192_SHA384` in calls to webpki This is a more-restricted version of `RSA_PKCS1_2048_8192_SHA384`, so supplying it alongside that doesn't make sense. --- rustls/src/crypto/aws_lc_rs/mod.rs | 1 - rustls/src/crypto/ring/mod.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/rustls/src/crypto/aws_lc_rs/mod.rs b/rustls/src/crypto/aws_lc_rs/mod.rs index 6b9c0f7b6cd..4d3aaafcf4e 100644 --- a/rustls/src/crypto/aws_lc_rs/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/mod.rs @@ -171,7 +171,6 @@ static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms 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_3072_8192_SHA384, ], mapping: &[ // Note: for TLS1.2 the curve is not fixed by SignatureScheme. For TLS1.3 it is. diff --git a/rustls/src/crypto/ring/mod.rs b/rustls/src/crypto/ring/mod.rs index 2cd90e29732..b9cac775159 100644 --- a/rustls/src/crypto/ring/mod.rs +++ b/rustls/src/crypto/ring/mod.rs @@ -116,7 +116,6 @@ static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms 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_3072_8192_SHA384, ], mapping: &[ // Note: for TLS1.2 the curve is not fixed by SignatureScheme. For TLS1.3 it is. From 6509aa1cc69727ba4273699feb1537597b4d6232 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 19 Jun 2025 06:17:12 +0100 Subject: [PATCH 282/403] Add PKCS#1 `_ABSENT_PARAMS` algorithms to webpki calls Requires rustls-webpki 0.103.3 --- Cargo.toml | 2 +- fuzz/Cargo.lock | 4 ++-- rustls/src/crypto/aws_lc_rs/mod.rs | 3 +++ rustls/src/crypto/ring/mod.rs | 3 +++ 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index de345902795..36c5dca486a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,7 +92,7 @@ subtle = { version = "2.5.0", default-features = false } time = { version = "0.3.6", default-features = false } tikv-jemallocator = "0.6" tokio = { version = "1.34", features = ["io-util", "macros", "net", "rt"] } -webpki = { package = "rustls-webpki", version = "0.103.2", features = ["alloc"], default-features = false } +webpki = { package = "rustls-webpki", version = "0.103.3", features = ["alloc"], default-features = false } webpki-roots = "1" x25519-dalek = "2" x509-parser = "0.17" diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index abfd8c0f5d5..d4b0bb07642 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -310,9 +310,9 @@ checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" [[package]] name = "rustls-webpki" -version = "0.103.2" +version = "0.103.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7149975849f1abb3832b246010ef62ccc80d3a76169517ada7188252b9cfb437" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" dependencies = [ "ring", "rustls-pki-types", diff --git a/rustls/src/crypto/aws_lc_rs/mod.rs b/rustls/src/crypto/aws_lc_rs/mod.rs index 4d3aaafcf4e..1a7d226387c 100644 --- a/rustls/src/crypto/aws_lc_rs/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/mod.rs @@ -171,6 +171,9 @@ static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms 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. diff --git a/rustls/src/crypto/ring/mod.rs b/rustls/src/crypto/ring/mod.rs index b9cac775159..3ce99b15297 100644 --- a/rustls/src/crypto/ring/mod.rs +++ b/rustls/src/crypto/ring/mod.rs @@ -116,6 +116,9 @@ static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms 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. From c82b2cfdf1b20e7d12b4bd6608af1b5eaed4aec5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 21 Jun 2025 00:15:07 +0000 Subject: [PATCH 283/403] chore(deps): update rust crate asn1 to 0.22 --- Cargo.lock | 12 ++++++------ Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a09b7b9b853..3528e45b41e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,9 +140,9 @@ checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "asn1" -version = "0.21.3" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d9c3502a6f1b50a2c69b97b71638a81ad3b21b9874604880401b9b2b0bf758f" +checksum = "df42c2b01c5e1060b8281f67b4e5fb858260694916a667345a7305cd11e5dbfa" dependencies = [ "asn1_derive", "itoa", @@ -189,9 +189,9 @@ dependencies = [ [[package]] name = "asn1_derive" -version = "0.21.3" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1766ebcb519d8dd186d60dfa912571edcaa2c1f995e2e56643a261a87df69a61" +checksum = "cdccf849b54365e3693e9a90ad36e4482b79937e6373ac8e2cf229c985187b21" dependencies = [ "proc-macro2", "quote", @@ -1731,7 +1731,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -3471,7 +3471,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 36c5dca486a..1b438463be5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ resolver = "2" [workspace.dependencies] anyhow = "1.0.73" -asn1 = "0.21" +asn1 = "0.22" async-std = { version = "1.12.0", features = ["attributes"] } async-trait = "0.1.74" aws-lc-rs = { version = "1.12", default-features = false } From ecc68efe93a02233a6dc3181d62277d3cda5d6ee Mon Sep 17 00:00:00 2001 From: Joseph Birr-Pixton Date: Thu, 14 Sep 2023 09:18:45 +0100 Subject: [PATCH 284/403] impl Codec for unit type Shortly extension bodies will be required to `impl Codec`, so this type will be used for extensions without a body. --- rustls/src/msgs/codec.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rustls/src/msgs/codec.rs b/rustls/src/msgs/codec.rs index 17cf35c65c2..567fb520e4f 100644 --- a/rustls/src/msgs/codec.rs +++ b/rustls/src/msgs/codec.rs @@ -236,6 +236,14 @@ impl<'a, T: Codec<'a> + TlsListElement + Debug> Codec<'a> for Vec { } } +impl Codec<'_> for () { + fn encode(&self, _: &mut Vec) {} + + fn read(r: &mut Reader<'_>) -> Result { + 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`. Lists in the TLS wire format are From 4513c69e0ce0c315c2d2c85ab6e716c3be258f86 Mon Sep 17 00:00:00 2001 From: Joseph Birr-Pixton Date: Thu, 14 Sep 2023 16:49:21 +0100 Subject: [PATCH 285/403] Introduce `ClientExtensions` type Instead of `Vec`, store the extension data as a struct. This is possible because past commits have removed the need for this us to losslessly round-trip extension data. This involves fewer allocations to construct the extensions for clients. It eliminates repeated iteration of the vector to find specific extensions when processing a `ClientHello` for servers. It also reduces the cost of detecting duplicate extensions, which is moved into the decoding process -- a new `InvalidMessage::DuplicateExtension` error is introduced for this purpose. The struct is produced by a macro, which externalises the overall encoding and decoding operations. This allows specialisation for order of encoding (for ClientHello extension order randomisation) and whether an empty input is allowed (for ClientHello extensions in TLS1.2). During decoding a ClientHello, validate that any PSK offer appears last. This replaces `ClientHelloPayload::check_psk_ext_is_last`. Now that we have a specific error for this we can produce the error bogo expects for this case. --- bogo/config.json.in | 2 - bogo/src/main.rs | 6 + rustls/src/client/client_conn.rs | 10 +- rustls/src/client/ech.rs | 78 +--- rustls/src/client/hs.rs | 170 +++----- rustls/src/client/test.rs | 29 +- rustls/src/client/tls13.rs | 28 +- rustls/src/error.rs | 11 +- rustls/src/msgs/handshake.rs | 684 +++++++++++++++--------------- rustls/src/msgs/handshake_test.rs | 507 ++++++++++------------ rustls/src/msgs/macros.rs | 175 ++++++++ rustls/src/quic.rs | 20 +- rustls/src/server/hs.rs | 75 ++-- rustls/src/server/server_conn.rs | 16 +- rustls/src/server/test.rs | 63 +-- rustls/src/server/tls12.rs | 21 +- rustls/src/server/tls13.rs | 35 +- 17 files changed, 986 insertions(+), 944 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index 3f7f836a7dc..ebddbfd63a4 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -254,12 +254,10 @@ "Resume-Server-ExtraPSKBinder-SecondBinder": ":PEER_MISBEHAVIOUR:", "Resume-Server-ExtraIdentityNoBinder-SecondBinder": ":PEER_MISBEHAVIOUR:", "Resume-Server-InvalidPSKBinder-SecondBinder": ":PEER_MISBEHAVIOUR:", - "Resume-Server-PSKBinderFirstExtension-SecondBinder": ":PEER_MISBEHAVIOUR:", "Resume-Server-BinderWrongLength": ":PEER_MISBEHAVIOUR:", "Resume-Server-ExtraPSKBinder": ":PEER_MISBEHAVIOUR:", "Resume-Server-ExtraIdentityNoBinder": ":PEER_MISBEHAVIOUR:", "Resume-Server-InvalidPSKBinder": ":PEER_MISBEHAVIOUR:", - "Resume-Server-PSKBinderFirstExtension": ":PEER_MISBEHAVIOUR:", "Resume-Client-PRFMismatch-TLS13": ":PEER_MISBEHAVIOUR:", "Resume-Client-Mismatch-TLS12-TLS13-TLS": ":PEER_MISBEHAVIOUR:", "Resume-Client-Mismatch-TLS13-TLS12-TLS": ":WRONG_CIPHER_RETURNED:", diff --git a/bogo/src/main.rs b/bogo/src/main.rs index 31a9511d1f1..a1fd3407f3d 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -924,7 +924,13 @@ fn handle_err(opts: &Options, err: Error) -> ! { { quit(":ERROR_PARSING_EXTENSION:") } + Error::InvalidMessage(InvalidMessage::DuplicateExtension(_)) => { + quit(":DUPLICATE_EXTENSION:") + } Error::InvalidMessage(InvalidMessage::UnexpectedMessage(_)) => quit(":GARBAGE:"), + Error::InvalidMessage(InvalidMessage::PreSharedKeyIsNotFinalExtension) => { + quit(":PRE_SHARED_KEY_MUST_BE_LAST:") + } Error::DecryptError if opts.ech_config_list.is_some() => { quit(":INCONSISTENT_ECH_NEGOTIATION:") } diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index f0c7dae4744..68ecaebfb75 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -19,7 +19,7 @@ use crate::error::Error; use crate::kernel::KernelConnection; use crate::log::trace; use crate::msgs::enums::NamedGroup; -use crate::msgs::handshake::{ClientExtension, ProtocolName}; +use crate::msgs::handshake::{ClientExtensionsInput, ProtocolName}; use crate::msgs::persist; use crate::suites::{ExtractedSecrets, SupportedCipherSuite}; use crate::sync::Arc; @@ -634,7 +634,7 @@ mod connection { use pki_types::ServerName; - use super::ClientConnectionData; + use super::{ClientConnectionData, ClientExtensionsInput}; use crate::ClientConfig; use crate::client::EchStatus; use crate::common_state::Protocol; @@ -717,7 +717,7 @@ mod connection { config, name, alpn_protocols, - Vec::new(), + ClientExtensionsInput::default(), Protocol::Tcp, )?), }) @@ -842,7 +842,7 @@ impl ConnectionCore { config: Arc, name: ServerName<'static>, alpn_protocols: Vec>, - extra_exts: Vec, + extra_exts: ClientExtensionsInput<'_>, proto: Protocol, ) -> Result { let mut common_state = CommonState::new(Side::Client); @@ -898,7 +898,7 @@ impl UnbufferedClientConnection { config, name, alpn_protocols, - Vec::new(), + ClientExtensionsInput::default(), Protocol::Tcp, )?), }) diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index c79b30f9adf..ef2b895b77c 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -16,7 +16,7 @@ use crate::msgs::base::{Payload, PayloadU16}; use crate::msgs::codec::{Codec, Reader}; use crate::msgs::enums::{ExtensionType, HpkeKem}; use crate::msgs::handshake::{ - ClientExtension, ClientHelloPayload, EchConfigContents, EchConfigPayload, Encoding, + ClientExtensions, ClientHelloPayload, EchConfigContents, EchConfigPayload, Encoding, EncryptedClientHello, EncryptedClientHelloOuter, HandshakeMessagePayload, HandshakePayload, HelloRetryRequest, HpkeKeyConfig, HpkeSymmetricCipherSuite, PresharedKeyBinder, PresharedKeyOffer, Random, ServerHelloPayload, ServerNamePayload, @@ -409,18 +409,13 @@ impl EchState { // 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(ClientExtension::PresharedKey(psk_offer)) = outer_hello.extensions.last_mut() { + 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 - .extensions - .push(ClientExtension::EncryptedClientHello(outer_hello_ext( - self, - enc.clone(), - vec![0; payload_len], - ))); + 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 @@ -428,12 +423,7 @@ impl EchState { .seal(&outer_hello.get_encoding(), &encoded_inner_hello)?; // And then we replace the placeholder extension with the real one. - outer_hello.extensions.pop(); - outer_hello - .extensions - .push(ClientExtension::EncryptedClientHello(outer_hello_ext( - self, enc, payload, - ))); + outer_hello.encrypted_client_hello = Some(outer_hello_ext(self, enc, payload)); Ok(outer_hello) } @@ -564,7 +554,7 @@ impl EchState { compression_methods: outer_hello.compression_methods.clone(), // We will build up the included extensions ourselves. - extensions: vec![], + 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 @@ -582,13 +572,11 @@ impl EchState { .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 - .extensions - .push(ClientExtension::EncryptedClientHello( - EncryptedClientHello::Inner, - )); + 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 @@ -602,14 +590,14 @@ impl EchState { // 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 mut compressed_exts = Vec::with_capacity(outer_hello.extensions.len()); - let mut compressed_ext_types = Vec::with_capacity(outer_hello.extensions.len()); - for ext in &outer_hello.extensions { + 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.ext_type(), + ext, ExtensionType::ExtendedMasterSecret | ExtensionType::SessionTicket | ExtensionType::ECPointFormats @@ -617,14 +605,10 @@ impl EchState { continue; } - if ext.ext_type() == ExtensionType::ServerName { + 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 - .extensions - .push(ClientExtension::ServerName(ServerNamePayload::from( - sni_value, - ))); + inner_hello.server_name = Some(ServerNamePayload::from(sni_value)); } // We don't want to add, or compress, the SNI from the outer hello. continue; @@ -632,37 +616,21 @@ impl EchState { // Compressed extensions need to be put aside to include in one contiguous block. // Uncompressed extensions get added directly to the inner hello. - if ext.ext_type().ech_compress() { - compressed_exts.push(ext.clone()); - compressed_ext_types.push(ext.ext_type()); - } else { - inner_hello.extensions.push(ext.clone()); + 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. Where we do this depends on whether the - // last uncompressed extension is a PSK for resumption. In this case we must - // add the to-be-compressed extensions _before_ the PSK. - let compressed_exts_index = - if let Some(ClientExtension::PresharedKey(_)) = inner_hello.extensions.last() { - inner_hello.extensions.len() - 1 - } else { - inner_hello.extensions.len() - }; - inner_hello.extensions.splice( - compressed_exts_index..compressed_exts_index, - compressed_exts, - ); + // 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 - .extensions - .iter() - .map(|ext| ext.ext_type()) - .collect(); + 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() { @@ -689,7 +657,7 @@ impl EchState { // 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_ext_types); + let mut encoded_hello = inner_hello.ech_inner_encoding(compressed_exts); // Calculate padding // max_name_len = L diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index f16117c564b..b4c7156b606 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -29,9 +29,10 @@ use crate::log::{debug, trace}; use crate::msgs::base::Payload; use crate::msgs::enums::{Compression, ECPointFormat, ExtensionType, PskKeyExchangeMode}; use crate::msgs::handshake::{ - CertificateStatusRequest, ClientExtension, ClientHelloPayload, ClientSessionTicket, - HandshakeMessagePayload, HandshakePayload, HasServerExtensions, HelloRetryRequest, - KeyShareEntry, ProtocolName, Random, SessionId, SupportedProtocolVersions, + CertificateStatusRequest, ClientExtensions, ClientExtensionsInput, ClientHelloPayload, + ClientSessionTicket, EncryptedClientHello, HandshakeMessagePayload, HandshakePayload, + HasServerExtensions, HelloRetryRequest, KeyShareEntry, ProtocolName, Random, ServerNamePayload, + SessionId, SupportedProtocolVersions, TransportParameters, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; @@ -100,7 +101,7 @@ fn find_session( pub(super) fn start_handshake( server_name: ServerName<'static>, alpn_protocols: Vec, - extra_exts: Vec, + extra_exts: ClientExtensionsInput<'_>, config: Arc, cx: &mut ClientContext<'_>, ) -> NextStateOrError<'static> { @@ -213,7 +214,7 @@ struct ExpectServerHello { struct ExpectServerHelloOrHelloRetryRequest { next: ExpectServerHello, - extra_exts: Vec, + extra_exts: ClientExtensionsInput<'static>, } struct ClientHelloInput { @@ -226,7 +227,7 @@ struct ClientHelloInput { hello: ClientHelloDetails, session_id: SessionId, server_name: ServerName<'static>, - prev_ech_ext: Option, + prev_ech_ext: Option, } /// Emits the initial ClientHello or a ClientHello in response to @@ -238,7 +239,7 @@ fn emit_client_hello_for_retry( mut transcript_buffer: HandshakeHashBuffer, retryreq: Option<&HelloRetryRequest>, key_share: Option>, - extra_exts: Vec, + extra_exts: ClientExtensionsInput<'_>, suite: Option, mut input: ClientHelloInput, cx: &mut ClientContext<'_>, @@ -257,30 +258,41 @@ fn emit_client_hello_for_retry( // should be unreachable thanks to config builder assert!(supported_versions.any(|_| true)); - // offer groups which are usable for any offered version - let offered_groups = config - .provider - .kx_groups - .iter() - .filter(|skxg| supported_versions.any(|v| skxg.usable_for_version(v))) - .map(|skxg| skxg.name()) - .collect(); + let ClientExtensionsInput { + transport_parameters, + } = extra_exts.clone().into_owned(); - let mut exts = vec![ - ClientExtension::SupportedVersions(supported_versions), - ClientExtension::NamedGroups(offered_groups), - ClientExtension::SignatureAlgorithms( + 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(), ), - ClientExtension::ExtendedMasterSecretRequest, - ClientExtension::CertificateStatusRequest(CertificateStatusRequest::build_ocsp()), - ]; + extended_master_secret_request: Some(()), + certificate_status_request: Some(CertificateStatusRequest::build_ocsp()), + ..Default::default() + }); + + match transport_parameters { + 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.push(ClientExtension::AuthorityNames(cas_extension.to_owned())); + exts.certificate_authority_names = Some(cas_extension.to_owned()); } } @@ -291,30 +303,25 @@ fn emit_client_hello_for_retry( .iter() .any(|skxg| skxg.name().key_exchange_algorithm() == KeyExchangeAlgorithm::ECDHE) { - exts.push(ClientExtension::EcPointFormats( - ECPointFormat::SUPPORTED.to_vec(), - )); + exts.ec_point_formats = Some(ECPointFormat::SUPPORTED.to_vec()); } - match (ech_state.as_ref(), config.enable_sni) { + 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), _) => { - exts.push(ClientExtension::ServerName((&ech_state.outer_name).into())) - } + (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) => { - if let ServerName::DnsName(dns_name) = &input.server_name { - exts.push(ClientExtension::ServerName(dns_name.into())); - } - } + (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, false) => None, }; if let Some(key_share) = &key_share { @@ -342,36 +349,34 @@ fn emit_client_hello_for_retry( } } - exts.push(ClientExtension::KeyShare(shares)); + exts.key_shares = Some(shares); } if let Some(cookie) = retryreq.and_then(HelloRetryRequest::cookie) { - exts.push(ClientExtension::Cookie(cookie.clone())); + 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. let psk_modes = vec![PskKeyExchangeMode::PSK_DHE_KE]; - exts.push(ClientExtension::PresharedKeyModes(psk_modes)); + exts.preshared_key_modes = Some(psk_modes); } // Add ALPN extension if we have any protocols if !input.hello.alpn_protocols.is_empty() { - exts.push(ClientExtension::Protocols( - input.hello.alpn_protocols.clone(), - )); + exts.protocols = Some(input.hello.alpn_protocols.clone()); } input.hello.offered_cert_compression = if supported_versions.tls13 && !config.cert_decompressors.is_empty() { - exts.push(ClientExtension::CertificateCompressionAlgorithms( + exts.certificate_compression_algorithms = Some( config .cert_decompressors .iter() .map(|dec| dec.algorithm()) .collect(), - )); + ); true } else { false @@ -381,29 +386,22 @@ fn emit_client_hello_for_retry( .client_auth_cert_resolver .only_raw_public_keys() { - exts.push(ClientExtension::ClientCertTypes(vec![ - CertificateType::RawPublicKey, - ])); + exts.client_certificate_types = Some(vec![CertificateType::RawPublicKey]); } if config .verifier .requires_raw_public_keys() { - exts.push(ClientExtension::ServerCertTypes(vec![ - CertificateType::RawPublicKey, - ])); + exts.server_certificate_types = Some(vec![CertificateType::RawPublicKey]); } - // Extra extensions must be placed before the PSK extension - exts.extend(extra_exts.iter().cloned()); - // 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.push(prev_ech_ext); + exts.encrypted_client_hello = Some(prev_ech_ext); } } @@ -412,24 +410,7 @@ fn emit_client_hello_for_retry( // Extensions MAY be randomized // but they also need to keep the same order as the previous ClientHello - exts.sort_by_cached_key(|new_ext| { - match (&cx.data.ech_status, new_ext) { - // When not offering ECH/GREASE, the PSK extension is always last. - (EchStatus::NotOffered, ClientExtension::PresharedKey(..)) => return u32::MAX, - // When ECH or GREASE are in-play, the ECH extension is always last. - (_, ClientExtension::EncryptedClientHello(_)) => return u32::MAX, - // ... and the PSK extension should be second-to-last. - (_, ClientExtension::PresharedKey(..)) => return u32::MAX - 1, - _ => {} - }; - - let seed = ((input.hello.extension_order_seed as u32) << 16) - | (u16::from(new_ext.ext_type()) as u32); - match low_quality_integer_hash(seed) { - u32::MAX => 0, - key => key, - } - }); + exts.order_seed = input.hello.extension_order_seed; let mut cipher_suites: Vec<_> = config .provider @@ -475,17 +456,17 @@ fn emit_client_hello_for_retry( 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.extensions.last().cloned(); + 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 = ClientExtension::EncryptedClientHello(grease_ext?); - chp_payload - .extensions - .push(grease_ext.clone()); + 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. @@ -496,11 +477,7 @@ fn emit_client_hello_for_retry( } // Note what extensions we sent. - input.hello.sent_extensions = chp_payload - .extensions - .iter() - .map(ClientExtension::ext_type) - .collect(); + input.hello.sent_extensions = chp_payload.collect_used(); let mut chp = HandshakeMessagePayload(HandshakePayload::ClientHello(chp_payload)); @@ -589,7 +566,10 @@ fn emit_client_hello_for_retry( }; Ok(if supported_versions.tls13 && retryreq.is_none() { - Box::new(ExpectServerHelloOrHelloRetryRequest { next, extra_exts }) + Box::new(ExpectServerHelloOrHelloRetryRequest { + next, + extra_exts: extra_exts.into_owned(), + }) } else { Box::new(next) }) @@ -612,7 +592,7 @@ fn emit_client_hello_for_retry( /// It returns the TLS 1.3 PSKs, if any, for further processing. fn prepare_resumption<'a>( resuming: &'a Option>, - exts: &mut Vec, + exts: &mut ClientExtensions<'_>, suite: Option, cx: &mut ClientContext<'_>, config: &ClientConfig, @@ -625,7 +605,7 @@ fn prepare_resumption<'a>( && config.resumption.tls12_resumption == Tls12Resumption::SessionIdOrTickets { // If we don't have a ticket, request one. - exts.push(ClientExtension::SessionTicket(ClientSessionTicket::Request)); + exts.session_ticket = Some(ClientSessionTicket::Request); } return None; } @@ -636,9 +616,7 @@ fn prepare_resumption<'a>( if config.supports_version(ProtocolVersion::TLSv1_2) && config.resumption.tls12_resumption == Tls12Resumption::SessionIdOrTickets { - exts.push(ClientExtension::SessionTicket(ClientSessionTicket::Offer( - Payload::new(resuming.ticket()), - ))); + exts.session_ticket = Some(ClientSessionTicket::Offer(Payload::new(resuming.ticket()))); } return None; // TLS 1.2, so nothing to return here }; @@ -1272,19 +1250,3 @@ impl Deref for ClientSessionValue { self.common() } } - -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 -} diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs index 89d6493bab1..b7a4f0a3061 100644 --- a/rustls/src/client/test.rs +++ b/rustls/src/client/test.rs @@ -31,8 +31,8 @@ mod tests { use crate::msgs::base::PayloadU8; use crate::msgs::enums::ECCurveType; use crate::msgs::handshake::{ - CertificateChain, ClientExtension, EcParameters, KeyShareEntry, ServerEcdhParams, - ServerExtension, ServerKeyExchange, ServerKeyExchangeParams, ServerKeyExchangePayload, + CertificateChain, EcParameters, KeyShareEntry, ServerEcdhParams, ServerExtension, + ServerKeyExchange, ServerKeyExchangeParams, ServerKeyExchangePayload, }; use crate::msgs::message::PlainMessage; use crate::pki_types::pem::PemObject; @@ -55,7 +55,7 @@ mod tests { config.resumption = Resumption::in_memory_sessions(128) .tls12_resumption(Tls12Resumption::SessionIdOrTickets); let ch = client_hello_sent_for_config(config).unwrap(); - assert!(ch.ticket_extension().is_none()); + assert!(ch.extensions.session_ticket.is_none()); } #[test] @@ -84,9 +84,12 @@ mod tests { .with_root_certificates(roots()) .with_no_client_auth(); let ch = client_hello_sent_for_config(config).unwrap(); - let sigalgs = ch.sigalgs_extension().unwrap(); assert!( - !sigalgs.contains(&SignatureScheme::RSA_PKCS1_SHA1), + !ch.extensions + .signature_schemes + .as_ref() + .unwrap() + .contains(&SignatureScheme::RSA_PKCS1_SHA1), "sha1 unexpectedly offered" ); } @@ -193,8 +196,8 @@ mod tests { assert_eq!( client_hello .extensions - .iter() - .any(|ext| matches!(ext, ClientExtension::AuthorityNames(_))), + .certificate_authority_names + .is_some(), cas_extension_expected ); } @@ -628,7 +631,11 @@ fn hybrid_kx_component_share_offered_if_supported_separately() { ) .unwrap(); - let key_shares = ch.keyshare_extension().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); @@ -651,7 +658,11 @@ fn hybrid_kx_component_share_not_offered_unless_supported_separately() { ) .unwrap(); - let key_shares = ch.keyshare_extension().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); } diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index cb50c1a557c..f7a49a03ef6 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -28,10 +28,10 @@ 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, ClientExtension, EchConfigPayload, + CERTIFICATE_MAX_SIZE_LIMIT, CertificatePayloadTls13, ClientExtensions, EchConfigPayload, HandshakeMessagePayload, HandshakePayload, HasServerExtensions, KeyShareEntry, - NewSessionTicketPayloadTls13, PresharedKeyIdentity, PresharedKeyOffer, ServerExtension, - ServerHelloPayload, + NewSessionTicketPayloadTls13, PresharedKeyBinder, PresharedKeyIdentity, PresharedKeyOffer, + ServerExtension, ServerHelloPayload, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; @@ -327,7 +327,19 @@ pub(super) fn fill_in_psk_binder( let real_binder = key_schedule.resumption_psk_binder_key_and_sign_verify_data(&handshake_hash); if let HandshakePayload::ClientHello(ch) = &mut hmp.0 { - ch.set_psk_binder(real_binder.as_ref()); + 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 @@ -337,7 +349,7 @@ pub(super) fn prepare_resumption( config: &ClientConfig, cx: &mut ClientContext<'_>, resuming_session: &persist::Retrieved<&persist::Tls13ClientSessionValue>, - exts: &mut Vec, + exts: &mut ClientExtensions<'_>, doing_retry: bool, ) { let resuming_suite = resuming_session.suite(); @@ -349,7 +361,7 @@ pub(super) fn prepare_resumption( cx.data .early_data .enable(max_early_data_size as usize); - exts.push(ClientExtension::EarlyData); + exts.early_data_request = Some(()); } // Finally, and only for TLS1.3 with a ticket resumption, include a binder @@ -367,8 +379,8 @@ pub(super) fn prepare_resumption( let psk_identity = PresharedKeyIdentity::new(resuming_session.ticket().to_vec(), obfuscated_ticket_age); - let psk_ext = PresharedKeyOffer::new(psk_identity, binder); - exts.push(ClientExtension::PresharedKey(psk_ext)); + let psk_offer = PresharedKeyOffer::new(psk_identity, binder); + exts.preshared_key_offer = Some(psk_offer); } pub(super) fn derive_early_traffic_secret( diff --git a/rustls/src/error.rs b/rustls/src/error.rs index ebc857ffd1b..f0edcb4c4b0 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -194,6 +194,10 @@ pub enum InvalidMessage { 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, } impl From for Error { @@ -204,8 +208,11 @@ impl From for Error { } impl From for AlertDescription { - fn from(_: InvalidMessage) -> Self { - Self::DecodeError + fn from(e: InvalidMessage) -> Self { + match e { + InvalidMessage::PreSharedKeyIsNotFinalExtension => Self::IllegalParameter, + _ => Self::DecodeError, + } } } diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index d849425566c..18efe099893 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -1,9 +1,10 @@ +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; +use core::ops::{Deref, DerefMut}; use core::{fmt, iter}; use pki_types::{CertificateDer, DnsName}; @@ -700,152 +701,309 @@ impl TlsListElement for CertificateCompressionAlgorithm { }; } -#[derive(Clone, Debug)] -pub(crate) enum ClientExtension { - EcPointFormats(Vec), - NamedGroups(Vec), - SignatureAlgorithms(Vec), - ServerName(ServerNamePayload<'static>), - SessionTicket(ClientSessionTicket), - Protocols(Vec), - SupportedVersions(SupportedProtocolVersions), - KeyShare(Vec), - PresharedKeyModes(Vec), - PresharedKey(PresharedKeyOffer), - Cookie(PayloadU16), - ExtendedMasterSecretRequest, - CertificateStatusRequest(CertificateStatusRequest), - ServerCertTypes(Vec), - ClientCertTypes(Vec), - TransportParameters(Vec), - TransportParametersDraft(Vec), - EarlyData, - CertificateCompressionAlgorithms(Vec), - EncryptedClientHello(EncryptedClientHello), - EncryptedClientHelloOuterExtensions(Vec), - AuthorityNames(Vec), - Unknown(UnknownExtension), +/// 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>, } -impl ClientExtension { - pub(crate) fn ext_type(&self) -> ExtensionType { +impl ClientExtensionsInput<'_> { + pub(crate) fn into_owned(self) -> ClientExtensionsInput<'static> { + let Self { + transport_parameters, + } = self; + ClientExtensionsInput { + transport_parameters: transport_parameters.map(|x| x.into_owned()), + } + } +} + +#[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::EcPointFormats(_) => ExtensionType::ECPointFormats, - Self::NamedGroups(_) => ExtensionType::EllipticCurves, - Self::SignatureAlgorithms(_) => ExtensionType::SignatureAlgorithms, - Self::ServerName(_) => ExtensionType::ServerName, - Self::SessionTicket(_) => ExtensionType::SessionTicket, - Self::Protocols(_) => ExtensionType::ALProtocolNegotiation, - Self::SupportedVersions(_) => ExtensionType::SupportedVersions, - Self::KeyShare(_) => ExtensionType::KeyShare, - Self::PresharedKeyModes(_) => ExtensionType::PSKKeyExchangeModes, - Self::PresharedKey(_) => ExtensionType::PreSharedKey, - Self::Cookie(_) => ExtensionType::Cookie, - Self::ExtendedMasterSecretRequest => ExtensionType::ExtendedMasterSecret, - Self::CertificateStatusRequest(_) => ExtensionType::StatusRequest, - Self::ClientCertTypes(_) => ExtensionType::ClientCertificateType, - Self::ServerCertTypes(_) => ExtensionType::ServerCertificateType, - Self::TransportParameters(_) => ExtensionType::TransportParameters, - Self::TransportParametersDraft(_) => ExtensionType::TransportParametersDraft, - Self::EarlyData => ExtensionType::EarlyData, - Self::CertificateCompressionAlgorithms(_) => ExtensionType::CompressCertificate, - Self::EncryptedClientHello(_) => ExtensionType::EncryptedClientHello, - Self::EncryptedClientHelloOuterExtensions(_) => { - ExtensionType::EncryptedClientHelloOuterExtensions - } - Self::AuthorityNames(_) => ExtensionType::CertificateAuthorities, - Self::Unknown(r) => r.typ, + 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`. + /// + /// 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>, + + /// Certificate status is requested (RFC6066) + ExtensionType::StatusRequest => + pub(crate) certificate_status_request: Option, + + /// Supported groups (RFC4492/RFC8446) + ExtensionType::EllipticCurves => + pub(crate) named_groups: Option>, + + /// Supported EC point formats (RFC4492) + ExtensionType::ECPointFormats => + pub(crate) ec_point_formats: Option>, + + /// Supported signature schemes (RFC5246/RFC8446) + ExtensionType::SignatureAlgorithms => + pub(crate) signature_schemes: Option>, + + /// Offered ALPN protocols (RFC6066) + ExtensionType::ALProtocolNegotiation => + pub(crate) protocols: Option>, + + /// Available client certificate types (RFC7250) + ExtensionType::ClientCertificateType => + pub(crate) client_certificate_types: Option>, + + /// Acceptable server certificate types (RFC7250) + ExtensionType::ServerCertificateType => + pub(crate) server_certificate_types: Option>, + + /// 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>, + + /// Session ticket offer or request (RFC5077/RFC8446) + ExtensionType::SessionTicket => + pub(crate) session_ticket: Option, + + /// Offered preshared keys (RFC8446) + ExtensionType::PreSharedKey => + pub(crate) preshared_key_offer: Option, + + /// Early data is requested (RFC8446) + ExtensionType::EarlyData => + pub(crate) early_data_request: Option<()>, + + /// Supported TLS versions (RFC8446) + ExtensionType::SupportedVersions => + pub(crate) supported_versions: Option, + + /// Stateless HelloRetryRequest cookie (RFC8446) + ExtensionType::Cookie => + pub(crate) cookie: Option>, + + /// Offered preshared key modes (RFC8446) + ExtensionType::PSKKeyExchangeModes => + pub(crate) preshared_key_modes: Option>, + + /// Certificate authority names (RFC8446) + ExtensionType::CertificateAuthorities => + pub(crate) certificate_authority_names: Option>, + + /// Offered key exchange shares (RFC8446) + ExtensionType::KeyShare => + pub(crate) key_shares: Option>, + + /// QUIC transport parameters (RFC9001) + ExtensionType::TransportParameters => + pub(crate) transport_parameters: Option>, + + /// Secure renegotiation (RFC5746) + ExtensionType::RenegotiationInfo => + pub(crate) renegotiation_info: Option, + + /// QUIC transport parameters (RFC9001 prior to draft 33) + ExtensionType::TransportParametersDraft => + pub(crate) transport_parameters_draft: Option>, + + /// Encrypted inner client hello (draft-ietf-tls-esni) + ExtensionType::EncryptedClientHello => + pub(crate) encrypted_client_hello: Option, + + /// Encrypted client hello outer extensions (draft-ietf-tls-esni) + ExtensionType::EncryptedClientHelloOuterExtensions => + pub(crate) encrypted_client_hello_outer: Option>, + } + { + /// Order randomization seed. + pub(crate) order_seed: u16, + + /// Extensions that must appear contiguously. + pub(crate) contiguous_extensions: Vec, + } +} + +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 { + 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 { + 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 Codec<'_> for ClientExtension { +impl<'a> Codec<'a> for ClientExtensions<'a> { fn encode(&self, bytes: &mut Vec) { - self.ext_type().encode(bytes); + let order = self.used_extensions_in_encoding_order(); - let nested = LengthPrefixedBuffer::new(ListLength::U16, bytes); - match self { - Self::EcPointFormats(r) => r.encode(nested.buf), - Self::NamedGroups(r) => r.encode(nested.buf), - Self::SignatureAlgorithms(r) => r.encode(nested.buf), - Self::ServerName(r) => r.encode(nested.buf), - Self::SessionTicket(r) => r.encode(nested.buf), - Self::ExtendedMasterSecretRequest | Self::EarlyData => {} - Self::Protocols(r) => r.encode(nested.buf), - Self::SupportedVersions(r) => r.encode(nested.buf), - Self::KeyShare(r) => r.encode(nested.buf), - Self::PresharedKeyModes(r) => r.encode(nested.buf), - Self::PresharedKey(r) => r.encode(nested.buf), - Self::Cookie(r) => r.encode(nested.buf), - Self::CertificateStatusRequest(r) => r.encode(nested.buf), - Self::ClientCertTypes(r) => r.encode(nested.buf), - Self::ServerCertTypes(r) => r.encode(nested.buf), - Self::TransportParameters(r) | Self::TransportParametersDraft(r) => { - nested.buf.extend_from_slice(r); - } - Self::CertificateCompressionAlgorithms(r) => r.encode(nested.buf), - Self::EncryptedClientHello(r) => r.encode(nested.buf), - Self::EncryptedClientHelloOuterExtensions(r) => r.encode(nested.buf), - Self::AuthorityNames(r) => r.encode(nested.buf), - Self::Unknown(r) => r.encode(nested.buf), + 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<'_>) -> Result { - let typ = ExtensionType::read(r)?; - let len = u16::read(r)? as usize; + fn read(r: &mut Reader<'a>) -> Result { + let mut out = Self::default(); + + // extensions length can be absent if no extensions + if !r.any_left() { + return Ok(out); + } + + let mut unknown_extensions = BTreeSet::new(); + + let len = usize::from(u16::read(r)?); let mut sub = r.sub(len)?; - let ext = match typ { - ExtensionType::ECPointFormats => Self::EcPointFormats(Vec::read(&mut sub)?), - ExtensionType::EllipticCurves => Self::NamedGroups(Vec::read(&mut sub)?), - ExtensionType::SignatureAlgorithms => Self::SignatureAlgorithms(Vec::read(&mut sub)?), - ExtensionType::ServerName => { - Self::ServerName(ServerNamePayload::read(&mut sub)?.into_owned()) - } - ExtensionType::SessionTicket => { - Self::SessionTicket(ClientSessionTicket::read(&mut sub)?) - } - ExtensionType::ALProtocolNegotiation => Self::Protocols(Vec::read(&mut sub)?), - ExtensionType::SupportedVersions => { - Self::SupportedVersions(SupportedProtocolVersions::read(&mut sub)?) - } - ExtensionType::KeyShare => Self::KeyShare(Vec::read(&mut sub)?), - ExtensionType::PSKKeyExchangeModes => Self::PresharedKeyModes(Vec::read(&mut sub)?), - ExtensionType::PreSharedKey => Self::PresharedKey(PresharedKeyOffer::read(&mut sub)?), - ExtensionType::Cookie => Self::Cookie(PayloadU16::read(&mut sub)?), - ExtensionType::ExtendedMasterSecret if !sub.any_left() => { - Self::ExtendedMasterSecretRequest - } - ExtensionType::ClientCertificateType => Self::ClientCertTypes(Vec::read(&mut sub)?), - ExtensionType::ServerCertificateType => Self::ServerCertTypes(Vec::read(&mut sub)?), - ExtensionType::StatusRequest => { - let csr = CertificateStatusRequest::read(&mut sub)?; - Self::CertificateStatusRequest(csr) - } - ExtensionType::TransportParameters => Self::TransportParameters(sub.rest().to_vec()), - ExtensionType::TransportParametersDraft => { - Self::TransportParametersDraft(sub.rest().to_vec()) - } - ExtensionType::EarlyData if !sub.any_left() => Self::EarlyData, - ExtensionType::CompressCertificate => { - Self::CertificateCompressionAlgorithms(Vec::read(&mut sub)?) - } - ExtensionType::EncryptedClientHelloOuterExtensions => { - Self::EncryptedClientHelloOuterExtensions(Vec::read(&mut sub)?) - } - ExtensionType::CertificateAuthorities => Self::AuthorityNames({ - let items = Vec::read(&mut sub)?; - if items.is_empty() { - return Err(InvalidMessage::IllegalEmptyList("DistinguishedNames")); + while sub.any_left() { + let typ = out.read_one(&mut sub, |unknown| { + let u = u16::from(unknown); + match unknown_extensions.insert(u) { + true => Ok(()), + false => Err(InvalidMessage::DuplicateExtension(u)), } - items - }), - _ => Self::Unknown(UnknownExtension::read(typ, &mut sub)), - }; + })?; - sub.expect_empty("ClientExtension") - .map(|_| ext) + // PreSharedKey offer must come last + if typ == ExtensionType::PreSharedKey && sub.any_left() { + return Err(InvalidMessage::PreSharedKeyIsNotFinalExtension); + } + } + + Ok(out) } } @@ -1015,7 +1173,7 @@ pub(crate) struct ClientHelloPayload { pub(crate) session_id: SessionId, pub(crate) cipher_suites: Vec, pub(crate) compression_methods: Vec, - pub(crate) extensions: Vec, + pub(crate) extensions: Box>, } impl ClientHelloPayload { @@ -1039,155 +1197,30 @@ impl ClientHelloPayload { self.compression_methods.encode(bytes); let to_compress = match purpose { - // Compressed extensions must be replaced in the encoded inner client hello. Encoding::EchInnerHello { to_compress } if !to_compress.is_empty() => to_compress, _ => { - if !self.extensions.is_empty() { - self.extensions.encode(bytes); - } + self.extensions.encode(bytes); return; } }; - // Safety: not empty check in match guard. - let first_compressed_type = *to_compress.first().unwrap(); - - // Compressed extensions are in a contiguous range and must be replaced - // with a marker extension. - let compressed_start_idx = self - .extensions - .iter() - .position(|ext| ext.ext_type() == first_compressed_type); - let compressed_end_idx = compressed_start_idx.map(|start| start + to_compress.len()); - let marker_ext = ClientExtension::EncryptedClientHelloOuterExtensions(to_compress); - - let exts = self - .extensions - .iter() - .enumerate() - .filter_map(|(i, ext)| { - if Some(i) == compressed_start_idx { - Some(&marker_ext) - } else if Some(i) > compressed_start_idx && Some(i) < compressed_end_idx { - None - } else { - Some(ext) - } - }); - - let nested = LengthPrefixedBuffer::new(ListLength::U16, bytes); - for ext in exts { - ext.encode(nested.buf); - } - } - - /// 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()), - ) - } - - pub(crate) fn find_extension(&self, ext: ExtensionType) -> Option<&ClientExtension> { - self.extensions - .iter() - .find(|x| x.ext_type() == ext) - } - - pub(crate) fn sni_extension(&self) -> Option<&ServerNamePayload<'_>> { - let ext = self.find_extension(ExtensionType::ServerName)?; - match ext { - ClientExtension::ServerName(req) => Some(req), - _ => None, - } - } - - pub(crate) fn sigalgs_extension(&self) -> Option<&[SignatureScheme]> { - let ext = self.find_extension(ExtensionType::SignatureAlgorithms)?; - match ext { - ClientExtension::SignatureAlgorithms(req) => Some(req), - _ => None, - } - } - - pub(crate) fn namedgroups_extension(&self) -> Option<&[NamedGroup]> { - let ext = self.find_extension(ExtensionType::EllipticCurves)?; - match ext { - ClientExtension::NamedGroups(req) => Some(req), - _ => None, - } - } - - #[cfg(feature = "tls12")] - pub(crate) fn ecpoints_extension(&self) -> Option<&[ECPointFormat]> { - let ext = self.find_extension(ExtensionType::ECPointFormats)?; - match ext { - ClientExtension::EcPointFormats(req) => Some(req), - _ => None, - } - } - - pub(crate) fn server_certificate_extension(&self) -> Option<&[CertificateType]> { - let ext = self.find_extension(ExtensionType::ServerCertificateType)?; - match ext { - ClientExtension::ServerCertTypes(req) => Some(req), - _ => None, - } - } - - pub(crate) fn client_certificate_extension(&self) -> Option<&[CertificateType]> { - let ext = self.find_extension(ExtensionType::ClientCertificateType)?; - match ext { - ClientExtension::ClientCertTypes(req) => Some(req), - _ => None, - } - } + let mut compressed = self.extensions.clone(); - pub(crate) fn alpn_extension(&self) -> Option<&Vec> { - let ext = self.find_extension(ExtensionType::ALProtocolNegotiation)?; - match ext { - ClientExtension::Protocols(req) => Some(req), - _ => None, + // First, eliminate the full-fat versions of the extensions + for e in &to_compress { + compressed.clear(*e); } - } - pub(crate) fn quic_params_extension(&self) -> Option> { - let ext = self - .find_extension(ExtensionType::TransportParameters) - .or_else(|| self.find_extension(ExtensionType::TransportParametersDraft))?; - match ext { - ClientExtension::TransportParameters(bytes) - | ClientExtension::TransportParametersDraft(bytes) => Some(bytes.to_vec()), - _ => None, - } - } + // Replace with the marker noting which extensions were elided. + compressed.encrypted_client_hello_outer = Some(to_compress); - #[cfg(feature = "tls12")] - pub(crate) fn ticket_extension(&self) -> Option<&ClientExtension> { - self.find_extension(ExtensionType::SessionTicket) - } - - pub(crate) fn versions_extension(&self) -> Option { - let ext = self.find_extension(ExtensionType::SupportedVersions)?; - match ext { - ClientExtension::SupportedVersions(vers) => Some(*vers), - _ => None, - } - } - - pub(crate) fn keyshare_extension(&self) -> Option<&[KeyShareEntry]> { - let ext = self.find_extension(ExtensionType::KeyShare)?; - match ext { - ClientExtension::KeyShare(shares) => Some(shares), - _ => None, - } + // And encode as normal. + compressed.encode(bytes); } pub(crate) fn has_keyshare_extension_with_duplicates(&self) -> bool { - self.keyshare_extension() + self.key_shares + .as_ref() .map(|entries| { has_duplicates::<_, _, u16>( entries @@ -1198,76 +1231,13 @@ impl ClientHelloPayload { .unwrap_or_default() } - pub(crate) fn psk(&self) -> Option<&PresharedKeyOffer> { - let ext = self.find_extension(ExtensionType::PreSharedKey)?; - match ext { - ClientExtension::PresharedKey(psk) => Some(psk), - _ => None, - } - } - - pub(crate) fn check_psk_ext_is_last(&self) -> bool { - self.extensions - .last() - .is_some_and(|ext| ext.ext_type() == ExtensionType::PreSharedKey) - } - - pub(crate) fn psk_modes(&self) -> Option<&[PskKeyExchangeMode]> { - let ext = self.find_extension(ExtensionType::PSKKeyExchangeModes)?; - match ext { - ClientExtension::PresharedKeyModes(psk_modes) => Some(psk_modes), - _ => None, - } - } - - pub(crate) fn psk_mode_offered(&self, mode: PskKeyExchangeMode) -> bool { - self.psk_modes() - .map(|modes| modes.contains(&mode)) - .unwrap_or(false) - } - - pub(crate) fn set_psk_binder(&mut self, binder: impl Into>) { - let last_extension = self.extensions.last_mut(); - if let Some(ClientExtension::PresharedKey(offer)) = last_extension { - offer.binders[0] = PresharedKeyBinder::from(binder.into()); - } - } - - #[cfg(feature = "tls12")] - pub(crate) fn ems_support_offered(&self) -> bool { - self.find_extension(ExtensionType::ExtendedMasterSecret) - .is_some() - } - - pub(crate) fn early_data_extension_offered(&self) -> bool { - self.find_extension(ExtensionType::EarlyData) - .is_some() - } - - pub(crate) fn certificate_compression_extension( - &self, - ) -> Option<&[CertificateCompressionAlgorithm]> { - let ext = self.find_extension(ExtensionType::CompressCertificate)?; - match ext { - ClientExtension::CertificateCompressionAlgorithms(algs) => Some(algs), - _ => None, - } - } - pub(crate) fn has_certificate_compression_extension_with_duplicates(&self) -> bool { - if let Some(algs) = self.certificate_compression_extension() { + if let Some(algs) = &self.certificate_compression_algorithms { has_duplicates::<_, _, u16>(algs.iter().cloned()) } else { false } } - - pub(crate) fn certificate_authorities_extension(&self) -> Option<&[DistinguishedName]> { - match self.find_extension(ExtensionType::CertificateAuthorities)? { - ClientExtension::AuthorityNames(ext) => Some(ext), - _ => unreachable!("extension type checked"), - } - } } impl Codec<'_> for ClientHelloPayload { @@ -1276,24 +1246,32 @@ impl Codec<'_> for ClientHelloPayload { } fn read(r: &mut Reader<'_>) -> Result { - let mut ret = Self { + 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: Vec::new(), + extensions: Box::new(ClientExtensions::read(r)?.into_owned()), }; - if r.any_left() { - ret.extensions = Vec::read(r)?; + match r.any_left() { + true => Err(InvalidMessage::TrailingData("ClientHelloPayload")), + false => Ok(ret), } + } +} - match (r.any_left(), ret.extensions.is_empty()) { - (true, _) => Err(InvalidMessage::TrailingData("ClientHelloPayload")), - (_, true) => Err(InvalidMessage::MissingData("ClientHelloPayload")), - _ => 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 } } @@ -1311,10 +1289,6 @@ impl TlsListElement for Compression { }; } -impl TlsListElement for ClientExtension { - const SIZE_LEN: ListLength = ListLength::U16; -} - /// draft-ietf-tls-esni-17: `ExtensionType OuterExtensions<2..254>;` impl TlsListElement for ExtensionType { const SIZE_LEN: ListLength = ListLength::NonZeroU8 { @@ -2975,8 +2949,8 @@ impl<'a> HandshakeMessagePayload<'a> { pub(crate) fn total_binder_length(&self) -> usize { match &self.0 { - HandshakePayload::ClientHello(ch) => match ch.extensions.last() { - Some(ClientExtension::PresharedKey(offer)) => { + HandshakePayload::ClientHello(ch) => match &ch.preshared_key_offer { + Some(offer) => { let mut binders_encoding = Vec::new(); offer .binders @@ -3354,6 +3328,22 @@ fn has_duplicates, E: Into, T: Eq + Ord>(iter: I) - false } +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::*; diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index ab1c742981d..519388f9a0e 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -12,13 +12,14 @@ use super::enums::{ use super::handshake::{ CertReqExtension, CertificateChain, CertificateEntry, CertificateExtension, CertificatePayloadTls13, CertificateRequestPayload, CertificateRequestPayloadTls13, - CertificateStatus, CertificateStatusRequest, ClientExtension, ClientHelloPayload, + CertificateStatus, CertificateStatusRequest, ClientExtensions, ClientHelloPayload, ClientSessionTicket, CompressedCertificatePayload, DistinguishedName, EcParameters, - HandshakeMessagePayload, HandshakePayload, HasServerExtensions, HelloRetryExtension, - HelloRetryRequest, KeyShareEntry, NewSessionTicketExtension, NewSessionTicketPayload, - NewSessionTicketPayloadTls13, PresharedKeyBinder, PresharedKeyIdentity, PresharedKeyOffer, - ProtocolName, Random, ServerDhParams, ServerEcdhParams, ServerExtension, ServerHelloPayload, - ServerKeyExchange, ServerKeyExchangeParams, ServerKeyExchangePayload, SessionId, + EncryptedClientHello, HandshakeMessagePayload, HandshakePayload, HasServerExtensions, + HelloRetryExtension, HelloRetryRequest, KeyShareEntry, NewSessionTicketExtension, + NewSessionTicketPayload, NewSessionTicketPayloadTls13, PresharedKeyBinder, + PresharedKeyIdentity, PresharedKeyOffer, ProtocolName, Random, ServerDhParams, + ServerEcdhParams, ServerExtension, ServerHelloPayload, ServerKeyExchange, + ServerKeyExchangeParams, ServerKeyExchangePayload, ServerNamePayload, SessionId, SingleProtocolName, SupportedProtocolVersions, UnknownExtension, }; use crate::enums::{ @@ -26,7 +27,6 @@ use crate::enums::{ SignatureScheme, }; use crate::error::InvalidMessage; -use crate::msgs::handshake::ServerNamePayload; use crate::sync::Arc; use crate::verify::DigitallySignedStruct; @@ -117,21 +117,12 @@ fn debug_session_id() { } #[test] -fn can_round_trip_unknown_client_ext() { - let bytes = [0x12u8, 0x34u8, 0, 3, 1, 2, 3]; - let mut rd = Reader::init(&bytes); - let ext = ClientExtension::read(&mut rd).unwrap(); - - println!("{ext:?}"); - assert_eq!(ext.ext_type(), ExtensionType::Unknown(0x1234)); - assert_eq!(bytes.to_vec(), ext.get_encoding()); -} - -#[test] -fn refuses_client_ext_with_unparsed_bytes() { - let bytes = [0x00u8, 0x0b, 0x00, 0x04, 0x02, 0xf8, 0x01, 0x02]; - let mut rd = Reader::init(&bytes); - assert!(ClientExtension::read(&mut rd).is_err()); +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] @@ -169,70 +160,34 @@ fn refuses_new_session_ticket_ext_with_unparsed_bytes() { assert!(NewSessionTicketExtension::read(&mut rd).is_err()); } -#[test] -fn can_round_trip_single_sni() { - let bytes = [0, 0, 0, 7, 0, 5, 0, 0, 2, 0x6c, 0x6f]; - let mut rd = Reader::init(&bytes); - let ext = ClientExtension::read(&mut rd).unwrap(); - println!("{ext:?}"); - - assert_eq!(ext.ext_type(), ExtensionType::ServerName); - assert_eq!(bytes.to_vec(), ext.get_encoding()); -} - -#[test] -fn can_round_trip_mixed_case_sni() { - let bytes = [0, 0, 0, 7, 0, 5, 0, 0, 2, 0x4c, 0x6f]; - let mut rd = Reader::init(&bytes); - let ext = ClientExtension::read(&mut rd).unwrap(); - println!("{ext:?}"); - - assert_eq!(ext.ext_type(), ExtensionType::ServerName); - assert_eq!(bytes.to_vec(), ext.get_encoding()); -} - -#[test] -fn single_hostname_returns_none_for_other_sni_name_types() { - let bytes = [0, 0, 0, 7, 0, 5, 1, 0, 2, 0x6c, 0x6f]; - let mut rd = Reader::init(&bytes); - let ext = ClientExtension::read(&mut rd).unwrap(); - println!("{ext:?}"); - - assert_eq!(ext.ext_type(), ExtensionType::ServerName); - assert!(matches!( - ext, - ClientExtension::ServerName(ServerNamePayload::Invalid) - )); -} - #[test] fn rejects_truncated_sni() { - let bytes = [0, 0, 0, 1, 0]; - assert!(ClientExtension::read(&mut Reader::init(&bytes)).is_err()); + let bytes = [0, 1, 0]; + assert!(ServerNamePayload::read(&mut Reader::init(&bytes)).is_err()); - let bytes = [0, 0, 0, 2, 0, 1]; - assert!(ClientExtension::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, 0, 0, 3, 0, 1, 0]; - assert!(ClientExtension::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, 0, 0, 4, 0, 2, 0, 0]; - assert!(ClientExtension::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, 0, 0, 5, 0, 3, 0, 0, 0]; - assert!(ClientExtension::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, 0, 0, 5, 0, 3, 0, 0, 1]; - assert!(ClientExtension::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, 0, 0, 6, 0, 4, 0, 0, 2, 0x68]; - assert!(ClientExtension::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!( - ClientExtension::read_bytes(&[0, 0, 0, 2, 0, 0]).unwrap_err(), + ClientExtensions::read_bytes(&[0, 6, 0, 0, 0, 2, 0, 0]).unwrap_err(), InvalidMessage::IllegalEmptyList("ServerNames") ); } @@ -240,7 +195,7 @@ fn rejects_empty_sni_extension() { #[test] fn rejects_duplicate_names_in_sni_extension() { assert_eq!( - ClientExtension::read_bytes(&[0, 0, 0, 10, 0, 8, 0, 0, 1, b'a', 0, 0, 1, b'b',]) + 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 ); @@ -280,79 +235,31 @@ fn can_round_trip_psk_offer() { #[test] fn can_round_trip_cert_status_req_for_ocsp() { - let ext = ClientExtension::CertificateStatusRequest(CertificateStatusRequest::build_ocsp()); - println!("{ext:?}"); + let ext = CertificateStatusRequest::build_ocsp(); + println!("{:?}", ext); let bytes = [ - 0, 5, // CertificateStatusRequest 0, 11, 1, // OCSP 0, 5, 0, 3, 0, 1, 1, 0, 1, 2, ]; - let csr = ClientExtension::read(&mut Reader::init(&bytes)).unwrap(); - println!("{csr:?}"); + 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, // CertificateStatusRequest 0, 5, 2, // !OCSP 1, 2, 3, 4, ]; - let csr = ClientExtension::read(&mut Reader::init(&bytes)).unwrap(); - println!("{csr:?}"); + let csr = CertificateStatusRequest::read(&mut Reader::init(&bytes)).unwrap(); + println!("{:?}", csr); assert_eq!(csr.get_encoding(), bytes.to_vec()); } -#[test] -fn can_round_trip_multi_proto() { - let bytes = [0, 16, 0, 8, 0, 6, 2, 0x68, 0x69, 2, 0x6c, 0x6f]; - let mut rd = Reader::init(&bytes); - let ext = ClientExtension::read(&mut rd).unwrap(); - println!("{ext:?}"); - - assert_eq!(ext.ext_type(), ExtensionType::ALProtocolNegotiation); - assert_eq!(ext.get_encoding(), bytes.to_vec()); - match ext { - ClientExtension::Protocols(prot) => { - assert_eq!(2, prot.len()); - assert_eq!( - vec![b"hi", b"lo"], - prot.iter() - .map(|p| p.as_ref()) - .collect::>() - ); - } - _ => unreachable!(), - } -} - -#[test] -fn can_round_trip_single_proto() { - let bytes = [0, 16, 0, 5, 0, 3, 2, 0x68, 0x69]; - let mut rd = Reader::init(&bytes); - let ext = ClientExtension::read(&mut rd).unwrap(); - println!("{ext:?}"); - - assert_eq!(ext.ext_type(), ExtensionType::ALProtocolNegotiation); - assert_eq!(bytes.to_vec(), ext.get_encoding()); - match ext { - ClientExtension::Protocols(prot) => { - assert_eq!(1, prot.len()); - assert_eq!( - vec![b"hi"], - prot.iter() - .map(|p| p.as_ref()) - .collect::>() - ); - } - _ => unreachable!(), - } -} - #[test] fn can_print_all_client_extensions() { println!("client hello {:?}", sample_client_hello_payload()); @@ -366,23 +273,162 @@ fn can_clone_all_client_extensions() { } #[test] -fn client_has_duplicate_extensions_works() { - let mut chp = sample_client_hello_payload(); - assert!(chp.has_duplicate_extension()); // due to SessionTicketRequest/SessionTicketOffer +fn client_extensions_basics() { + let src = ClientExtensions { + early_data_request: Some(()), + ..Default::default() + }; + let mut target = ClientExtensions::default(); - chp.extensions.drain(1..); - assert!(!chp.has_duplicate_extension()); + assert_eq!(src.collect_used(), vec![ExtensionType::EarlyData]); + assert_eq!(target.collect_used(), vec![]); - chp.extensions = vec![]; - assert!(!chp.has_duplicate_extension()); + 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::::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 { + 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 = ClientExtension::PresharedKey(PresharedKeyOffer { + 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:?}"); @@ -390,8 +436,8 @@ fn test_truncated_psk_offer() { if l == 9 { continue; } - put_u16(l as u16, &mut enc[4..]); - let rc = ClientExtension::read_bytes(&enc); + put_u16(l as u16, &mut enc); + let rc = PresharedKeyOffer::read_bytes(&enc); assert!(rc.is_err()); } } @@ -415,136 +461,16 @@ fn test_truncated_client_hello_is_detected() { fn test_truncated_client_extension_is_detected() { let chp = sample_client_hello_payload(); - for ext in &chp.extensions { - let mut enc = ext.get_encoding(); - println!("testing {ext:?} enc {enc:?}"); - - // "outer" truncation, i.e., where the extension-level length is longer than - // the input - for l in 0..enc.len() { - assert!(ClientExtension::read_bytes(&enc[..l]).is_err()); - } - - // these extension types don't have any internal encoding that rustls validates: - match ext.ext_type() { - ExtensionType::TransportParameters | ExtensionType::Unknown(_) => { - continue; - } - _ => {} - }; + let enc = chp.extensions.get_encoding(); + println!("testing enc {:?}", enc); - // "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!(ClientExtension::read_bytes(&enc).is_err()); - } + // "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 client_sni_extension() { - test_client_extension_getter(ExtensionType::ServerName, |chp| { - chp.sni_extension().is_some() - }); -} - -#[test] -fn client_sigalgs_extension() { - test_client_extension_getter(ExtensionType::SignatureAlgorithms, |chp| { - chp.sigalgs_extension().is_some() - }); -} - -#[test] -fn client_namedgroups_extension() { - test_client_extension_getter(ExtensionType::EllipticCurves, |chp| { - chp.namedgroups_extension().is_some() - }); -} - -#[cfg(feature = "tls12")] -#[test] -fn client_ecpoints_extension() { - test_client_extension_getter(ExtensionType::ECPointFormats, |chp| { - chp.ecpoints_extension().is_some() - }); -} - -#[test] -fn client_alpn_extension() { - test_client_extension_getter(ExtensionType::ALProtocolNegotiation, |chp| { - chp.alpn_extension().is_some() - }); -} - -#[test] -fn client_client_certificate_extension() { - test_client_extension_getter(ExtensionType::ClientCertificateType, |chp| { - chp.client_certificate_extension() - .is_some() - }); -} - -#[test] -fn client_server_certificate_extension() { - test_client_extension_getter(ExtensionType::ServerCertificateType, |chp| { - chp.server_certificate_extension() - .is_some() - }); -} - -#[test] -fn client_quic_params_extension() { - test_client_extension_getter(ExtensionType::TransportParameters, |chp| { - chp.quic_params_extension().is_some() - }); -} - -#[test] -fn client_versions_extension() { - test_client_extension_getter(ExtensionType::SupportedVersions, |chp| { - chp.versions_extension().is_some() - }); -} - -#[test] -fn client_keyshare_extension() { - test_client_extension_getter(ExtensionType::KeyShare, |chp| { - chp.keyshare_extension().is_some() - }); -} - -#[test] -fn client_psk() { - test_client_extension_getter(ExtensionType::PreSharedKey, |chp| chp.psk().is_some()); -} - -#[test] -fn client_psk_modes() { - test_client_extension_getter(ExtensionType::PSKKeyExchangeModes, |chp| { - chp.psk_modes().is_some() - }); -} - -fn test_client_extension_getter(typ: ExtensionType, getter: fn(&ClientHelloPayload) -> bool) { - let mut chp = sample_client_hello_payload(); - let ext = chp.find_extension(typ).unwrap().clone(); - - chp.extensions = vec![]; - assert!(!getter(&chp)); - - chp.extensions = vec![ext]; - assert!(getter(&chp)); - - chp.extensions = vec![ClientExtension::Unknown(UnknownExtension { - typ, - payload: Payload::Borrowed(&[]), - })]; - assert!(!getter(&chp)); -} - #[test] fn test_truncated_hello_retry_extension_is_detected() { let hrr = sample_hello_retry_request(); @@ -949,23 +875,23 @@ fn sample_client_hello_payload() -> ClientHelloPayload { session_id: SessionId::empty(), cipher_suites: vec![CipherSuite::TLS_NULL_WITH_NULL_NULL], compression_methods: vec![Compression::Null], - extensions: vec![ - ClientExtension::EcPointFormats(ECPointFormat::SUPPORTED.to_vec()), - ClientExtension::NamedGroups(vec![NamedGroup::X25519]), - ClientExtension::SignatureAlgorithms(vec![SignatureScheme::ECDSA_NISTP256_SHA256]), - ClientExtension::ServerName(ServerNamePayload::from( + extensions: Box::new(ClientExtensions { + server_name: Some(ServerNamePayload::from( &DnsName::try_from("hello").unwrap(), )), - ClientExtension::SessionTicket(ClientSessionTicket::Request), - ClientExtension::SessionTicket(ClientSessionTicket::Offer(Payload::Borrowed(&[]))), - ClientExtension::Protocols(vec![ProtocolName::from(vec![0])]), - ClientExtension::SupportedVersions(SupportedProtocolVersions { + 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(ECPointFormat::SUPPORTED.to_vec()), + named_groups: Some(vec![NamedGroup::X25519]), + protocols: Some(vec![ProtocolName::from(vec![0])]), + supported_versions: Some(SupportedProtocolVersions { tls13: true, ..Default::default() }), - ClientExtension::KeyShare(vec![KeyShareEntry::new(NamedGroup::X25519, &[1, 2, 3][..])]), - ClientExtension::PresharedKeyModes(vec![PskKeyExchangeMode::PSK_DHE_KE]), - ClientExtension::PresharedKey(PresharedKeyOffer { + key_shares: Some(vec![KeyShareEntry::new(NamedGroup::X25519, &[1, 2, 3][..])]), + preshared_key_modes: Some(vec![PskKeyExchangeMode::PSK_DHE_KE]), + preshared_key_offer: Some(PresharedKeyOffer { identities: vec![ PresharedKeyIdentity::new(vec![3, 4, 5], 123456), PresharedKeyIdentity::new(vec![6, 7, 8], 7891011), @@ -975,22 +901,17 @@ fn sample_client_hello_payload() -> ClientHelloPayload { PresharedKeyBinder::from(vec![3, 4, 5]), ], }), - ClientExtension::Cookie(PayloadU16::new(vec![1, 2, 3])), - ClientExtension::ExtendedMasterSecretRequest, - ClientExtension::CertificateStatusRequest(CertificateStatusRequest::build_ocsp()), - ClientExtension::ServerCertTypes(vec![CertificateType::RawPublicKey]), - ClientExtension::ClientCertTypes(vec![CertificateType::RawPublicKey]), - ClientExtension::TransportParameters(vec![1, 2, 3]), - ClientExtension::EarlyData, - ClientExtension::CertificateCompressionAlgorithms(vec![ - CertificateCompressionAlgorithm::Brotli, - CertificateCompressionAlgorithm::Zlib, - ]), - ClientExtension::Unknown(UnknownExtension { - typ: ExtensionType::Unknown(12345), - payload: Payload::Borrowed(&[1, 2, 3]), - }), - ], + 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() + }), } } diff --git a/rustls/src/msgs/macros.rs b/rustls/src/msgs/macros.rs index 5fe49ae58eb..602f92f1be0 100644 --- a/rustls/src/msgs/macros.rs +++ b/rustls/src/msgs/macros.rs @@ -83,3 +83,178 @@ macro_rules! enum_builder { } }; } + +/// 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, Debug, 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 { + 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 { + 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(r: &mut Reader<'a>, id: ExtensionType, out: &mut Option) -> 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, + ) { + 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` + pub(crate) fn collect_used(&self) -> Vec { + 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. + 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`. + pub(crate) fn clear(&mut self, typ: ExtensionType) { + match typ { + $( + $item_id => self.$item_slot = None, + )* + _ => {}, + } + } + + /// Every `ExtensionType` this structure may encode/decode. + const ALL_EXTENSIONS: &'static [ExtensionType] = &[ + $($item_id,)* + ]; + } + } +} diff --git a/rustls/src/quic.rs b/rustls/src/quic.rs index d1d4e8b2d66..26a63542720 100644 --- a/rustls/src/quic.rs +++ b/rustls/src/quic.rs @@ -30,8 +30,9 @@ mod connection { 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::{ClientExtension, ServerExtension}; + use crate::msgs::handshake::{ClientExtensionsInput, ServerExtension, TransportParameters}; use crate::msgs::message::InboundPlainMessage; use crate::server::{ServerConfig, ServerConnectionData}; use crate::sync::Arc; @@ -193,18 +194,15 @@ mod connection { )); } - let ext = match quic_version { - Version::V1Draft => ClientExtension::TransportParametersDraft(params), - Version::V1 | Version::V2 => ClientExtension::TransportParameters(params), + 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)), + }), }; - let mut inner = ConnectionCore::for_client( - config, - name, - alpn_protocols, - vec![ext], - Protocol::Quic, - )?; + let mut inner = + ConnectionCore::for_client(config, name, alpn_protocols, exts, Protocol::Quic)?; inner.common_state.quic.version = quic_version; Ok(Self { inner: inner.into(), diff --git a/rustls/src/server/hs.rs b/rustls/src/server/hs.rs index 3c6ac479c49..4a50871e3b0 100644 --- a/rustls/src/server/hs.rs +++ b/rustls/src/server/hs.rs @@ -80,8 +80,7 @@ impl ExtensionProcessing { ) -> Result<(), Error> { // ALPN let our_protocols = &config.alpn_protocols; - let maybe_their_protocols = hello.alpn_extension(); - if let Some(their_protocols) = maybe_their_protocols { + if let Some(their_protocols) = &hello.protocols { cx.common.alpn_protocol = our_protocols .iter() .find(|ours| { @@ -113,7 +112,7 @@ impl ExtensionProcessing { // successful establishment of connections between peers that can't understand // each other. if cx.common.alpn_protocol.is_none() - && (!our_protocols.is_empty() || maybe_their_protocols.is_some()) + && (!our_protocols.is_empty() || hello.protocols.is_some()) { return Err(cx.common.send_fatal_alert( AlertDescription::NoApplicationProtocol, @@ -121,8 +120,14 @@ impl ExtensionProcessing { )); } - match hello.quic_params_extension() { - Some(params) => cx.common.quic.params = Some(params), + 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 @@ -133,7 +138,8 @@ impl ExtensionProcessing { let for_resume = resumedata.is_some(); // SNI - if !for_resume && hello.sni_extension().is_some() { + if let (false, Some(ServerNamePayload::SingleDnsName(_))) = (for_resume, &hello.server_name) + { self.exts .push(ServerExtension::ServerNameAck); } @@ -143,7 +149,7 @@ impl ExtensionProcessing { // to send. if !for_resume && hello - .find_extension(ExtensionType::StatusRequest) + .certificate_status_request .is_some() { if ocsp_response.is_some() && !cx.common.is_tls13() { @@ -174,7 +180,8 @@ impl ExtensionProcessing { // Renegotiation. // (We don't do reneg at all, but would support the secure version if we did.) let secure_reneg_offered = hello - .find_extension(ExtensionType::RenegotiationInfo) + .extensions + .renegotiation_info .is_some() || hello .cipher_suites @@ -188,11 +195,7 @@ impl ExtensionProcessing { // Tickets: // If we get any SessionTicket extension and have tickets enabled, // we send an ack. - if hello - .find_extension(ExtensionType::SessionTicket) - .is_some() - && config.ticketer.enabled() - { + if hello.session_ticket.is_some() && config.ticketer.enabled() { self.send_ticket = true; self.exts .push(ServerExtension::SessionTicketAck); @@ -212,8 +215,8 @@ impl ExtensionProcessing { cx: &mut ServerContext<'_>, ) -> Result<(), Error> { let client_supports = hello - .server_certificate_extension() - .map(|certificate_types| certificate_types.to_vec()) + .server_certificate_types + .as_deref() .unwrap_or_default(); self.process_cert_type_extension( @@ -233,8 +236,8 @@ impl ExtensionProcessing { cx: &mut ServerContext<'_>, ) -> Result<(), Error> { let client_supports = hello - .client_certificate_extension() - .map(|certificate_types| certificate_types.to_vec()) + .client_certificate_types + .as_deref() .unwrap_or_default(); self.process_cert_type_extension( @@ -249,7 +252,7 @@ impl ExtensionProcessing { fn process_cert_type_extension( &mut self, - client_supports: Vec, + client_supports: &[CertificateType], requires_raw_keys: bool, extension_type: ExtensionType, cx: &mut ServerContext<'_>, @@ -343,8 +346,7 @@ impl ExpectClientHello { .supports_version(ProtocolVersion::TLSv1_2); // Are we doing TLS1.3? - let maybe_versions_ext = client_hello.versions_extension(); - let version = if let Some(versions) = maybe_versions_ext { + let version = if let Some(versions) = &client_hello.supported_versions { if versions.tls13 && tls13_enabled { ProtocolVersion::TLSv1_3 } else if !versions.tls12 || !tls12_enabled { @@ -405,19 +407,25 @@ impl ExpectClientHello { // 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_authorities_extension(), + _ => 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.alpn_extension(), - client_cert_types: client_hello.server_certificate_extension(), - server_cert_types: client_hello.client_certificate_extension(), + 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.namedgroups_extension(), + named_groups: client_hello.named_groups.as_deref(), }; trace!("Resolving server certificate: {client_hello:#?}"); @@ -441,8 +449,9 @@ impl ExpectClientHello { certkey.get_key().algorithm(), cx.common.protocol, client_hello - .namedgroups_extension() - .unwrap_or(&[]), + .named_groups + .as_deref() + .unwrap_or_default(), &client_hello.cipher_suites, ) .map_err(|incompat| { @@ -685,13 +694,6 @@ pub(super) fn process_client_hello<'m>( )); } - if client_hello.has_duplicate_extension() { - return Err(cx.common.send_fatal_alert( - AlertDescription::DecodeError, - PeerMisbehaved::DuplicateClientHelloExtensions, - )); - } - // No handshake messages should follow this one in this flight. cx.common.check_aligned_handshake()?; @@ -709,7 +711,7 @@ pub(super) fn process_client_hello<'m>( // but then act like the client sent no `server_name` extension. // // [RFC6066]: https://datatracker.ietf.org/doc/html/rfc6066#section-3 - let sni: Option> = match client_hello.sni_extension() { + 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) => { @@ -732,7 +734,8 @@ pub(super) fn process_client_hello<'m>( } let sig_schemes = client_hello - .sigalgs_extension() + .signature_schemes + .as_ref() .ok_or_else(|| { cx.common.send_fatal_alert( AlertDescription::HandshakeFailure, diff --git a/rustls/src/server/server_conn.rs b/rustls/src/server/server_conn.rs index 35b5705474b..75adf90b6be 100644 --- a/rustls/src/server/server_conn.rs +++ b/rustls/src/server/server_conn.rs @@ -1014,12 +1014,18 @@ impl Accepted { let ch = ClientHello { server_name: &self.connection.core.data.sni, signature_schemes: &self.sig_schemes, - alpn: payload.alpn_extension(), - server_cert_types: payload.server_certificate_extension(), - client_cert_types: payload.client_certificate_extension(), + 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_authorities_extension(), - named_groups: payload.namedgroups_extension(), + certificate_authorities: payload + .certificate_authority_names + .as_deref(), + named_groups: payload.named_groups.as_deref(), }; trace!("Accepted::client_hello(): {ch:#?}"); diff --git a/rustls/src/server/test.rs b/rustls/src/server/test.rs index 0587e39af52..9254dbc64be 100644 --- a/rustls/src/server/test.rs +++ b/rustls/src/server/test.rs @@ -5,11 +5,10 @@ use super::ServerConnectionData; use crate::common_state::Context; use crate::enums::{CipherSuite, SignatureScheme}; use crate::msgs::base::PayloadU16; -use crate::msgs::codec::{Codec, LengthPrefixedBuffer, ListLength}; -use crate::msgs::enums::{Compression, ExtensionType, NamedGroup}; +use crate::msgs::enums::{Compression, NamedGroup}; use crate::msgs::handshake::{ - ClientExtension, ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, KeyShareEntry, - Random, SessionId, SupportedProtocolVersions, + ClientExtensions, ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, KeyShareEntry, + Random, ServerNamePayload, SessionId, SupportedProtocolVersions, }; use crate::msgs::message::{Message, MessagePayload}; use crate::{CommonState, Error, PeerIncompatible, PeerMisbehaved, ProtocolVersion, Side}; @@ -28,8 +27,7 @@ fn null_compression_required() { #[test] fn server_ignores_sni_with_ip_address() { let mut ch = minimal_client_hello(); - ch.extensions - .push(ClientExtension::read_bytes(&sni_extension(&[b"1.1.1.1"])).unwrap()); + ch.extensions.server_name = Some(ServerNamePayload::IpAddress); std::println!("{:?}", ch.extensions); assert_eq!(test_process_client_hello(ch), Ok(())); } @@ -37,8 +35,7 @@ fn server_ignores_sni_with_ip_address() { #[test] fn server_rejects_sni_with_illegal_dns_name() { let mut ch = minimal_client_hello(); - ch.extensions - .push(ClientExtension::read_bytes(&sni_extension(&[b"ab@cd.com"])).unwrap()); + ch.extensions.server_name = Some(ServerNamePayload::Invalid); std::println!("{:?}", ch.extensions); assert_eq!( test_process_client_hello(ch), @@ -100,7 +97,8 @@ mod tests { let mut ch = minimal_client_hello(); ch.extensions - .retain(|ext| ext.ext_type() != ExtensionType::ExtendedMasterSecret); + .extended_master_secret_request + .take(); let ch = Message { version: ProtocolVersion::TLSv1_3, payload: MessagePayload::handshake(HandshakeMessagePayload( @@ -151,8 +149,7 @@ mod tests { let mut ch = minimal_client_hello(); ch.cipher_suites .push(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256.suite()); - ch.extensions - .retain(|ext| ext.ext_type() != ExtensionType::EllipticCurves); + ch.extensions.named_groups.take(); server_chooses_ffdhe_group_for_client_hello( ServerConnection::new(config.into()).unwrap(), @@ -173,8 +170,7 @@ mod tests { let mut ch = minimal_client_hello(); ch.cipher_suites .push(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256.suite()); - ch.extensions - .retain(|ext| ext.ext_type() != ExtensionType::ECPointFormats); + ch.extensions.ec_point_formats.take(); server_chooses_ffdhe_group_for_client_hello( ServerConnection::new(config.into()).unwrap(), @@ -205,10 +201,7 @@ mod tests { #[test] fn test_server_requiring_rpk_client_rejects_x509_client() { let mut ch = minimal_client_hello(); - ch.extensions - .push(ClientExtension::ClientCertTypes(vec![ - CertificateType::X509, - ])); + ch.extensions.client_certificate_types = Some(vec![CertificateType::X509]); let ch = Message { version: ProtocolVersion::TLSv1_3, payload: MessagePayload::handshake(HandshakeMessagePayload( @@ -228,10 +221,7 @@ mod tests { #[test] fn test_rpk_only_server_rejects_x509_only_client() { let mut ch = minimal_client_hello(); - ch.extensions - .push(ClientExtension::ServerCertTypes(vec![ - CertificateType::X509, - ])); + ch.extensions.server_certificate_types = Some(vec![CertificateType::X509]); let ch = Message { version: ProtocolVersion::TLSv1_3, payload: MessagePayload::handshake(HandshakeMessagePayload( @@ -361,34 +351,19 @@ fn minimal_client_hello() -> ClientHelloPayload { CipherSuite::TLS13_AES_128_GCM_SHA256, ], compression_methods: vec![Compression::Null], - extensions: vec![ - ClientExtension::SignatureAlgorithms(vec![SignatureScheme::RSA_PSS_SHA256]), - ClientExtension::NamedGroups(vec![NamedGroup::X25519, NamedGroup::secp256r1]), - ClientExtension::SupportedVersions(SupportedProtocolVersions { + 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, }), - ClientExtension::KeyShare(vec![KeyShareEntry { + key_shares: Some(vec![KeyShareEntry { group: NamedGroup::X25519, payload: PayloadU16::new(vec![0xab; 32]), }]), - ClientExtension::ExtendedMasterSecretRequest, - ], - } -} - -fn sni_extension(names: &[&[u8]]) -> Vec { - let mut r = Vec::new(); - ExtensionType::ServerName.encode(&mut r); - let outer = LengthPrefixedBuffer::new(ListLength::U16, &mut r); - let name_items = LengthPrefixedBuffer::new(ListLength::U16, outer.buf); - for name in names { - name_items.buf.push(0); - let host_name = LengthPrefixedBuffer::new(ListLength::U16, name_items.buf); - host_name.buf.extend_from_slice(name); - drop(host_name); + extended_master_secret_request: Some(()), + ..ClientExtensions::default() + }), } - drop(name_items); - drop(outer); - r } diff --git a/rustls/src/server/tls12.rs b/rustls/src/server/tls12.rs index 2eb1fd8dcc9..7c4e4f1ce6a 100644 --- a/rustls/src/server/tls12.rs +++ b/rustls/src/server/tls12.rs @@ -42,9 +42,9 @@ mod client_hello { use crate::enums::SignatureScheme; use crate::msgs::enums::{ClientCertificateType, Compression, ECPointFormat}; use crate::msgs::handshake::{ - CertificateRequestPayload, CertificateStatus, ClientExtension, ClientHelloPayload, - ClientSessionTicket, Random, ServerExtension, ServerHelloPayload, ServerKeyExchange, - ServerKeyExchangeParams, ServerKeyExchangePayload, + CertificateRequestPayload, CertificateStatus, ClientHelloPayload, ClientSessionTicket, + Random, ServerExtension, ServerHelloPayload, ServerKeyExchange, ServerKeyExchangeParams, + ServerKeyExchangePayload, }; use crate::sign; use crate::verify::DigitallySignedStruct; @@ -74,7 +74,10 @@ mod client_hello { // -- TLS1.2 only from hereon in -- self.transcript.add_message(chm); - if client_hello.ems_support_offered() { + 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( @@ -88,7 +91,8 @@ mod client_hello { // supported" // - let ecpoints_ext = client_hello - .ecpoints_extension() + .ec_point_formats + .as_deref() .unwrap_or(&[ECPointFormat::Uncompressed]); trace!("ecpoints {ecpoints_ext:?}"); @@ -119,11 +123,10 @@ mod client_hello { // let mut ticket_received = false; let resume_data = client_hello - .ticket_extension() + .session_ticket + .as_ref() .and_then(|ticket_ext| match ticket_ext { - ClientExtension::SessionTicket(ClientSessionTicket::Offer(ticket)) => { - Some(ticket) - } + ClientSessionTicket::Offer(ticket) => Some(ticket), _ => None, }) .and_then(|ticket| { diff --git a/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index 8e7a389a349..343745b16ca 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -151,7 +151,8 @@ mod client_hello { sigschemes_ext.retain(SignatureScheme::supported_in_tls13); let shares_ext = client_hello - .keyshare_extension() + .key_shares + .as_ref() .ok_or_else(|| { cx.common.send_fatal_alert( AlertDescription::HandshakeFailure, @@ -174,7 +175,8 @@ mod client_hello { } let cert_compressor = client_hello - .certificate_compression_extension() + .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. @@ -184,7 +186,9 @@ mod client_hello { .find(|compressor| offered.contains(&compressor.algorithm())) .cloned()); - let early_data_requested = client_hello.early_data_extension_offered(); + 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 { @@ -249,19 +253,15 @@ mod client_hello { let mut chosen_psk_index = None; let mut resumedata = None; - if let Some(psk_offer) = client_hello.psk() { - if !client_hello.check_psk_ext_is_last() { - return Err(cx.common.send_fatal_alert( - AlertDescription::IllegalParameter, - PeerMisbehaved::PskExtensionMustBeLast, - )); - } - + 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.psk_modes().is_none() { + if client_hello + .preshared_key_modes + .is_none() + { return Err(cx.common.send_fatal_alert( AlertDescription::MissingExtension, PeerMisbehaved::MissingPskModesExtension, @@ -316,7 +316,12 @@ mod client_hello { } } - if !client_hello.psk_mode_offered(PskKeyExchangeMode::PSK_DHE_KE) { + if !client_hello + .preshared_key_modes + .as_ref() + .map(|offer| offer.contains(&PskKeyExchangeMode::PSK_DHE_KE)) + .unwrap_or_default() + { debug!("Client unwilling to resume, DHE_KE not offered"); self.send_tickets = 0; chosen_psk_index = None; @@ -617,7 +622,9 @@ mod client_hello { suite: &'static Tls13CipherSuite, config: &ServerConfig, ) -> EarlyDataDecision { - let early_data_requested = client_hello.early_data_extension_offered(); + 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, From 54100be9258abf66be408899155334e19f70c11f Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 3 Jun 2025 15:23:18 +0100 Subject: [PATCH 286/403] Move desired client ALPN into `ClientExtensionInput` --- rustls/src/client/client_conn.rs | 33 ++++++++++++++++++++------------ rustls/src/client/hs.rs | 15 ++++++++------- rustls/src/msgs/handshake.rs | 22 +++++++++++++++++++++ rustls/src/quic.rs | 5 +++-- 4 files changed, 54 insertions(+), 21 deletions(-) diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index 68ecaebfb75..caf0529ab34 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -19,7 +19,7 @@ use crate::error::Error; use crate::kernel::KernelConnection; use crate::log::trace; use crate::msgs::enums::NamedGroup; -use crate::msgs::handshake::{ClientExtensionsInput, ProtocolName}; +use crate::msgs::handshake::ClientExtensionsInput; use crate::msgs::persist; use crate::suites::{ExtractedSecrets, SupportedCipherSuite}; use crate::sync::Arc; @@ -716,8 +716,7 @@ mod connection { inner: ConnectionCommon::from(ConnectionCore::for_client( config, name, - alpn_protocols, - ClientExtensionsInput::default(), + ClientExtensionsInput::from_alpn(alpn_protocols), Protocol::Tcp, )?), }) @@ -841,7 +840,6 @@ impl ConnectionCore { pub(crate) fn for_client( config: Arc, name: ServerName<'static>, - alpn_protocols: Vec>, extra_exts: ClientExtensionsInput<'_>, proto: Protocol, ) -> Result { @@ -851,10 +849,6 @@ impl ConnectionCore { common_state.enable_secret_extraction = config.enable_secret_extraction; common_state.fips = config.fips(); let mut data = ClientConnectionData::new(); - let alpn_protocols = alpn_protocols - .into_iter() - .map(ProtocolName::from) - .collect(); let mut cx = hs::ClientContext { common: &mut common_state, @@ -863,7 +857,7 @@ impl ConnectionCore { sendable_plaintext: None, }; - let state = hs::start_handshake(name, alpn_protocols, extra_exts, config, &mut cx)?; + let state = hs::start_handshake(name, extra_exts, config, &mut cx)?; Ok(Self::new(state, data, common_state)) } @@ -884,7 +878,11 @@ 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, name: ServerName<'static>) -> Result { - Self::new_with_alpn(config.clone(), name, config.alpn_protocols.clone()) + Self::new_with_extensions( + config.clone(), + name, + ClientExtensionsInput::from_alpn(config.alpn_protocols.clone()), + ) } /// Make a new UnbufferedClientConnection with custom ALPN protocols. @@ -892,13 +890,24 @@ impl UnbufferedClientConnection { config: Arc, name: ServerName<'static>, alpn_protocols: Vec>, + ) -> Result { + Self::new_with_extensions( + config, + name, + ClientExtensionsInput::from_alpn(alpn_protocols), + ) + } + + fn new_with_extensions( + config: Arc, + name: ServerName<'static>, + extensions: ClientExtensionsInput<'static>, ) -> Result { Ok(Self { inner: UnbufferedConnectionCommon::from(ConnectionCore::for_client( config, name, - alpn_protocols, - ClientExtensionsInput::default(), + extensions, Protocol::Tcp, )?), }) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index b4c7156b606..98f54079b1d 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -100,7 +100,6 @@ fn find_session( pub(super) fn start_handshake( server_name: ServerName<'static>, - alpn_protocols: Vec, extra_exts: ClientExtensionsInput<'_>, config: Arc, cx: &mut ClientContext<'_>, @@ -173,6 +172,11 @@ pub(super) fn start_handshake( _ => None, }; + let alpn_protocols = extra_exts + .protocols + .clone() + .unwrap_or_default(); + emit_client_hello_for_retry( transcript_buffer, None, @@ -260,6 +264,7 @@ fn emit_client_hello_for_retry( let ClientExtensionsInput { transport_parameters, + protocols, } = extra_exts.clone().into_owned(); let mut exts = Box::new(ClientExtensions { @@ -281,6 +286,7 @@ fn emit_client_hello_for_retry( ), extended_master_secret_request: Some(()), certificate_status_request: Some(CertificateStatusRequest::build_ocsp()), + protocols, ..Default::default() }); @@ -363,11 +369,6 @@ fn emit_client_hello_for_retry( exts.preshared_key_modes = Some(psk_modes); } - // Add ALPN extension if we have any protocols - if !input.hello.alpn_protocols.is_empty() { - exts.protocols = Some(input.hello.alpn_protocols.clone()); - } - input.hello.offered_cert_compression = if supported_versions.tls13 && !config.cert_decompressors.is_empty() { exts.certificate_compression_algorithms = Some( @@ -676,7 +677,7 @@ pub(super) fn process_alpn_protocol( common .alpn_protocol .as_ref() - .map(|v| bs_debug::BsDebug(v)) + .map(|v| bs_debug::BsDebug(v.as_ref())) ); Ok(()) } diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 18efe099893..7cf0fbb5ede 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -709,15 +709,37 @@ impl TlsListElement for CertificateCompressionAlgorithm { pub(crate) struct ClientExtensionsInput<'a> { /// QUIC transport parameters pub(crate) transport_parameters: Option>, + + /// ALPN protocols + pub(crate) protocols: Option>, } impl ClientExtensionsInput<'_> { + pub(crate) fn from_alpn(alpn_protocols: Vec>) -> ClientExtensionsInput<'static> { + let protocols = match alpn_protocols.is_empty() { + true => None, + false => Some( + alpn_protocols + .into_iter() + .map(ProtocolName::from) + .collect::>(), + ), + }; + + 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, } } } diff --git a/rustls/src/quic.rs b/rustls/src/quic.rs index 26a63542720..e900d12bca4 100644 --- a/rustls/src/quic.rs +++ b/rustls/src/quic.rs @@ -199,10 +199,11 @@ mod connection { 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, alpn_protocols, exts, Protocol::Quic)?; + let mut inner = ConnectionCore::for_client(config, name, exts, Protocol::Quic)?; inner.common_state.quic.version = quic_version; Ok(Self { inner: inner.into(), From 467c85c2522bff89c5b4497d0af1e5be74bff155 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 3 Apr 2025 14:36:41 +0100 Subject: [PATCH 287/403] Move to new extensions repr for HRR Annoyingly, ECH server confirmation requires that this can be round tripped. Record the decoded order and prefer to encode in that order. --- bogo/config.json.in | 6 +- bogo/src/main.rs | 3 + rustls/src/client/ech.rs | 6 +- rustls/src/client/hs.rs | 37 ++---- rustls/src/client/test.rs | 16 +-- rustls/src/error.rs | 5 +- rustls/src/msgs/handshake.rs | 203 +++++++++++++----------------- rustls/src/msgs/handshake_test.rs | 95 ++++---------- rustls/src/msgs/macros.rs | 3 + rustls/src/server/tls13.rs | 17 ++- 10 files changed, 146 insertions(+), 245 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index ebddbfd63a4..c9b121a9bfd 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -270,8 +270,6 @@ "TrailingKeyShareData-TLS13": ":BAD_HANDSHAKE_MSG:", "HelloRetryRequestCurveMismatch-TLS13": ":PEER_MISBEHAVIOUR:", "HelloRetryRequestVersionMismatch-TLS13": ":INCOMPATIBLE:", - "HelloRetryRequest-DuplicateCookie-TLS13": ":PEER_MISBEHAVIOUR:", - "HelloRetryRequest-DuplicateCurve-TLS13": ":PEER_MISBEHAVIOUR:", "UnknownUnencryptedExtension-Client-TLS13": ":PEER_MISBEHAVIOUR:", "UnexpectedUnencryptedExtension-Client-TLS13": ":PEER_MISBEHAVIOUR:", "UnofferedExtension-Client-TLS13": ":PEER_MISBEHAVIOUR:", @@ -386,7 +384,9 @@ "Downgrade-TLS10-Server": "remote error: protocol version not supported", "TrailingDataWithFinished-Client-TLS13": "local error: bad record MAC", "TrailingDataWithFinished-Resume-Client-TLS13": "local error: bad record MAC", - "SkipEarlyData-SecondClientHelloEarlyData-TLS13": "remote error: illegal parameter" + "SkipEarlyData-SecondClientHelloEarlyData-TLS13": "remote error: illegal parameter", + "DuplicateExtensionServer-TLS-TLS12": "remote error: illegal parameter", + "DuplicateExtensionServer-TLS-TLS13": "remote error: illegal parameter" }, "HalfRTTTickets": 0 } diff --git a/bogo/src/main.rs b/bogo/src/main.rs index a1fd3407f3d..89a3644350e 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -927,6 +927,9 @@ fn handle_err(opts: &Options, err: Error) -> ! { Error::InvalidMessage(InvalidMessage::DuplicateExtension(_)) => { quit(":DUPLICATE_EXTENSION:") } + Error::InvalidMessage(InvalidMessage::UnknownHelloRetryRequestExtension) => { + quit(":UNEXPECTED_EXTENSION:") + } Error::InvalidMessage(InvalidMessage::UnexpectedMessage(_)) => quit(":GARBAGE:"), Error::InvalidMessage(InvalidMessage::PreSharedKeyIsNotFinalExtension) => { quit(":PRE_SHARED_KEY_MUST_BE_LAST:") diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index ef2b895b77c..132b3d11636 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -480,12 +480,12 @@ impl EchState { common: &mut CommonState, ) -> Result { // The client checks for the "encrypted_client_hello" extension. - let ech_conf = match hrr.ech() { + 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.len() != 8 => { + Some(ech_conf) if ech_conf.bytes().len() != 8 => { return Err({ common.send_fatal_alert( AlertDescription::DecodeError, @@ -510,7 +510,7 @@ impl EchState { confirmation_transcript.current_hash(), ); - match ConstantTimeEq::ct_eq(derived.as_ref(), ech_conf).into() { + match ConstantTimeEq::ct_eq(derived.as_ref(), ech_conf.bytes()).into() { true => { trace!("ECH accepted by server in hello retry request"); Ok(true) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 98f54079b1d..afbfcb4ddfb 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -335,7 +335,7 @@ fn emit_client_hello_for_retry( let mut shares = vec![KeyShareEntry::new(key_share.group(), key_share.pub_key())]; if !retryreq - .map(|rr| rr.requested_key_share_group().is_some()) + .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, @@ -358,7 +358,7 @@ fn emit_client_hello_for_retry( exts.key_shares = Some(shares); } - if let Some(cookie) = retryreq.and_then(HelloRetryRequest::cookie) { + if let Some(cookie) = retryreq.and_then(|hrr| hrr.cookie.as_ref()) { exts.cookie = Some(cookie.clone()); } @@ -958,9 +958,6 @@ impl ExpectServerHelloOrHelloRetryRequest { cx.common.check_aligned_handshake()?; - let cookie = hrr.cookie(); - let req_group = hrr.requested_key_share_group(); - // We always send a key share when TLS 1.3 is enabled. let offered_key_share = self.next.offered_key_share.unwrap(); @@ -968,7 +965,7 @@ impl ExpectServerHelloOrHelloRetryRequest { // retry of a group we already sent. let config = &self.next.input.config; - if let (None, Some(req_group)) = (cookie, req_group) { + if let (None, Some(req_group)) = (&hrr.cookie, hrr.key_share) { let offered_hybrid = offered_key_share .hybrid_component() .and_then(|(group_name, _)| { @@ -987,7 +984,7 @@ impl ExpectServerHelloOrHelloRetryRequest { } // Or has an empty cookie. - if let Some(cookie) = cookie { + if let Some(cookie) = &hrr.cookie { if cookie.0.is_empty() { return Err({ cx.common.send_fatal_alert( @@ -998,26 +995,8 @@ impl ExpectServerHelloOrHelloRetryRequest { } } - // Or has something unrecognised - if hrr.has_unknown_extension() { - return Err(cx.common.send_fatal_alert( - AlertDescription::UnsupportedExtension, - PeerIncompatible::ServerSentHelloRetryRequestWithUnknownExtension, - )); - } - - // Or has the same extensions more than once - if hrr.has_duplicate_extension() { - return Err({ - cx.common.send_fatal_alert( - AlertDescription::IllegalParameter, - PeerMisbehaved::DuplicateHelloRetryRequestExtensions, - ) - }); - } - // Or asks us to change nothing. - if cookie.is_none() && req_group.is_none() { + if hrr.cookie.is_none() && hrr.key_share.is_none() { return Err({ cx.common.send_fatal_alert( AlertDescription::IllegalParameter, @@ -1049,7 +1028,7 @@ impl ExpectServerHelloOrHelloRetryRequest { } // Or asks us to talk a protocol we didn't offer, or doesn't support HRR at all. - match hrr.supported_versions() { + match hrr.supported_versions { Some(ProtocolVersion::TLSv1_3) => { cx.common.negotiated_version = Some(ProtocolVersion::TLSv1_3); } @@ -1074,7 +1053,7 @@ impl ExpectServerHelloOrHelloRetryRequest { }; // Or offers ECH related extensions when we didn't offer ECH. - if cx.data.ech_status == EchStatus::NotOffered && hrr.ech().is_some() { + if cx.data.ech_status == EchStatus::NotOffered && hrr.encrypted_client_hello.is_some() { return Err({ cx.common.send_fatal_alert( AlertDescription::UnsupportedExtension, @@ -1122,7 +1101,7 @@ impl ExpectServerHelloOrHelloRetryRequest { cx.data.early_data.rejected(); } - let key_share = match req_group { + 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( diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs index b7a4f0a3061..d07e1f45219 100644 --- a/rustls/src/client/test.rs +++ b/rustls/src/client/test.rs @@ -12,8 +12,8 @@ use crate::msgs::base::PayloadU16; use crate::msgs::codec::Reader; use crate::msgs::enums::{Compression, NamedGroup}; use crate::msgs::handshake::{ - ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, HelloRetryExtension, - HelloRetryRequest, Random, ServerHelloPayload, SessionId, + ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, HelloRetryRequest, Random, + ServerHelloPayload, SessionId, }; use crate::msgs::message::{Message, MessagePayload, OutboundOpaqueMessage}; use crate::sync::Arc; @@ -31,8 +31,9 @@ mod tests { use crate::msgs::base::PayloadU8; use crate::msgs::enums::ECCurveType; use crate::msgs::handshake::{ - CertificateChain, EcParameters, KeyShareEntry, ServerEcdhParams, ServerExtension, - ServerKeyExchange, ServerKeyExchangeParams, ServerKeyExchangePayload, + CertificateChain, EcParameters, HelloRetryRequestExtensions, KeyShareEntry, + ServerEcdhParams, ServerExtension, ServerKeyExchange, ServerKeyExchangeParams, + ServerKeyExchangePayload, }; use crate::msgs::message::PlainMessage; use crate::pki_types::pem::PemObject; @@ -117,9 +118,10 @@ mod tests { cipher_suite: CipherSuite::TLS13_AES_128_GCM_SHA256, legacy_version: ProtocolVersion::TLSv1_2, session_id: SessionId::empty(), - extensions: vec![HelloRetryExtension::Cookie(PayloadU16::new(vec![ - 1, 2, 3, 4, - ]))], + extensions: HelloRetryRequestExtensions { + cookie: Some(PayloadU16::new(vec![1, 2, 3, 4])), + ..HelloRetryRequestExtensions::default() + }, }), )), }; diff --git a/rustls/src/error.rs b/rustls/src/error.rs index f0edcb4c4b0..1cb54e24b09 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -142,7 +142,6 @@ impl From for Error { /// 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, @@ -198,6 +197,8 @@ pub enum InvalidMessage { 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, } impl From for Error { @@ -211,6 +212,8 @@ impl From for AlertDescription { fn from(e: InvalidMessage) -> Self { match e { InvalidMessage::PreSharedKeyIsNotFinalExtension => Self::IllegalParameter, + InvalidMessage::DuplicateExtension(_) => Self::IllegalParameter, + InvalidMessage::UnknownHelloRetryRequestExtension => Self::UnsupportedExtension, _ => Self::DecodeError, } } diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 7cf0fbb5ede..52549f9c7c9 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -1318,65 +1318,79 @@ impl TlsListElement for ExtensionType { }; } -#[derive(Clone, Debug)] -pub(crate) enum HelloRetryExtension { - KeyShare(NamedGroup), - Cookie(PayloadU16), - SupportedVersions(ProtocolVersion), - EchHelloRetryRequest(Vec), - Unknown(UnknownExtension), +extension_struct! { + /// A representation of extensions present in a `HelloRetryRequest` message + pub(crate) struct HelloRetryRequestExtensions<'a> { + ExtensionType::KeyShare => + pub(crate) key_share: Option, + + ExtensionType::Cookie => + pub(crate) cookie: Option>, + + ExtensionType::SupportedVersions => + pub(crate) supported_versions: Option, + + ExtensionType::EncryptedClientHello => + pub(crate) encrypted_client_hello: Option>, + } + { + /// Records decoding order of records, and controls encoding order. + pub(crate) order: Option>, + } } -impl HelloRetryExtension { - pub(crate) fn ext_type(&self) -> ExtensionType { - match self { - Self::KeyShare(_) => ExtensionType::KeyShare, - Self::Cookie(_) => ExtensionType::Cookie, - Self::SupportedVersions(_) => ExtensionType::SupportedVersions, - Self::EchHelloRetryRequest(_) => ExtensionType::EncryptedClientHello, - Self::Unknown(r) => r.typ, +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 Codec<'_> for HelloRetryExtension { +impl<'a> Codec<'a> for HelloRetryRequestExtensions<'a> { fn encode(&self, bytes: &mut Vec) { - self.ext_type().encode(bytes); + let extensions = LengthPrefixedBuffer::new(ListLength::U16, bytes); - let nested = LengthPrefixedBuffer::new(ListLength::U16, bytes); - match self { - Self::KeyShare(r) => r.encode(nested.buf), - Self::Cookie(r) => r.encode(nested.buf), - Self::SupportedVersions(r) => r.encode(nested.buf), - Self::EchHelloRetryRequest(r) => { - nested.buf.extend_from_slice(r); - } - Self::Unknown(r) => r.encode(nested.buf), + for ext in self + .order + .as_deref() + .unwrap_or(Self::ALL_EXTENSIONS) + { + self.encode_one(*ext, extensions.buf); } } - fn read(r: &mut Reader<'_>) -> Result { - let typ = ExtensionType::read(r)?; - let len = u16::read(r)? as usize; + fn read(r: &mut Reader<'a>) -> Result { + 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)?; - let ext = match typ { - ExtensionType::KeyShare => Self::KeyShare(NamedGroup::read(&mut sub)?), - ExtensionType::Cookie => Self::Cookie(PayloadU16::read(&mut sub)?), - ExtensionType::SupportedVersions => { - Self::SupportedVersions(ProtocolVersion::read(&mut sub)?) - } - ExtensionType::EncryptedClientHello => Self::EchHelloRetryRequest(sub.rest().to_vec()), - _ => Self::Unknown(UnknownExtension::read(typ, &mut sub)), - }; + while sub.any_left() { + let typ = out.read_one(&mut sub, |_unk| { + Err(InvalidMessage::UnknownHelloRetryRequestExtension) + })?; - sub.expect_empty("HelloRetryExtension") - .map(|_| ext) - } -} + order.push(typ); + } -impl TlsListElement for HelloRetryExtension { - const SIZE_LEN: ListLength = ListLength::U16; + out.order = Some(order); + Ok(out) + } } #[derive(Clone, Debug)] @@ -1384,7 +1398,7 @@ pub(crate) struct HelloRetryRequest { pub(crate) legacy_version: ProtocolVersion, pub(crate) session_id: SessionId, pub(crate) cipher_suite: CipherSuite, - pub(crate) extensions: Vec, + pub(crate) extensions: HelloRetryRequestExtensions<'static>, } impl Codec<'_> for HelloRetryRequest { @@ -1405,69 +1419,12 @@ impl Codec<'_> for HelloRetryRequest { legacy_version: ProtocolVersion::Unknown(0), session_id, cipher_suite, - extensions: Vec::read(r)?, + extensions: HelloRetryRequestExtensions::read(r)?.into_owned(), }) } } impl HelloRetryRequest { - /// 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()), - ) - } - - pub(crate) fn has_unknown_extension(&self) -> bool { - self.extensions.iter().any(|ext| { - ext.ext_type() != ExtensionType::KeyShare - && ext.ext_type() != ExtensionType::SupportedVersions - && ext.ext_type() != ExtensionType::Cookie - && ext.ext_type() != ExtensionType::EncryptedClientHello - }) - } - - fn find_extension(&self, ext: ExtensionType) -> Option<&HelloRetryExtension> { - self.extensions - .iter() - .find(|x| x.ext_type() == ext) - } - - pub(crate) fn requested_key_share_group(&self) -> Option { - let ext = self.find_extension(ExtensionType::KeyShare)?; - match ext { - HelloRetryExtension::KeyShare(grp) => Some(*grp), - _ => None, - } - } - - pub(crate) fn cookie(&self) -> Option<&PayloadU16> { - let ext = self.find_extension(ExtensionType::Cookie)?; - match ext { - HelloRetryExtension::Cookie(ck) => Some(ck), - _ => None, - } - } - - pub(crate) fn supported_versions(&self) -> Option { - let ext = self.find_extension(ExtensionType::SupportedVersions)?; - match ext { - HelloRetryExtension::SupportedVersions(ver) => Some(*ver), - _ => None, - } - } - - pub(crate) fn ech(&self) -> Option<&Vec> { - let ext = self.find_extension(ExtensionType::EncryptedClientHello)?; - match ext { - HelloRetryExtension::EchHelloRetryRequest(ech) => Some(ech), - _ => None, - } - } - fn payload_encode(&self, bytes: &mut Vec, purpose: Encoding) { self.legacy_version.encode(bytes); HELLO_RETRY_REQUEST_RANDOM.encode(bytes); @@ -1481,27 +1438,37 @@ impl HelloRetryRequest { // // See draft-ietf-tls-esni-18 7.2.1: // - Encoding::EchConfirmation => { - let extensions = LengthPrefixedBuffer::new(ListLength::U16, bytes); - for ext in &self.extensions { - match ext.ext_type() { - ExtensionType::EncryptedClientHello => { - HelloRetryExtension::EchHelloRetryRequest(vec![0u8; 8]) - .encode(extensions.buf); - } - _ => { - ext.encode(extensions.buf); - } - } + 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); - } + _ => 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, diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index 519388f9a0e..f7a118cf4ea 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -15,7 +15,7 @@ use super::handshake::{ CertificateStatus, CertificateStatusRequest, ClientExtensions, ClientHelloPayload, ClientSessionTicket, CompressedCertificatePayload, DistinguishedName, EcParameters, EncryptedClientHello, HandshakeMessagePayload, HandshakePayload, HasServerExtensions, - HelloRetryExtension, HelloRetryRequest, KeyShareEntry, NewSessionTicketExtension, + HelloRetryRequest, HelloRetryRequestExtensions, KeyShareEntry, NewSessionTicketExtension, NewSessionTicketPayload, NewSessionTicketPayloadTls13, PresharedKeyBinder, PresharedKeyIdentity, PresharedKeyOffer, ProtocolName, Random, ServerDhParams, ServerEcdhParams, ServerExtension, ServerHelloPayload, ServerKeyExchange, @@ -146,13 +146,6 @@ fn refuses_certificate_req_ext_with_unparsed_bytes() { assert!(CertReqExtension::read(&mut rd).is_err()); } -#[test] -fn refuses_helloreq_ext_with_unparsed_bytes() { - let bytes = [0x00u8, 0x2b, 0x00, 0x03, 0x00, 0x00, 0x01]; - let mut rd = Reader::init(&bytes); - assert!(HelloRetryExtension::read(&mut rd).is_err()); -} - #[test] fn refuses_new_session_ticket_ext_with_unparsed_bytes() { let bytes = [0x00u8, 0x2a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x01]; @@ -475,66 +468,22 @@ fn test_truncated_client_extension_is_detected() { fn test_truncated_hello_retry_extension_is_detected() { let hrr = sample_hello_retry_request(); - for ext in &hrr.extensions { - let mut enc = ext.get_encoding(); - println!("testing {ext:?} enc {enc:?}"); - - // "outer" truncation, i.e., where the extension-level length is longer than - // the input - for l in 0..enc.len() { - assert!(HelloRetryExtension::read_bytes(&enc[..l]).is_err()); - } - - // these extension types don't have any internal encoding that rustls validates: - if let ExtensionType::Unknown(_) = ext.ext_type() { - continue; - } + let mut enc = hrr.extensions.get_encoding(); + println!("testing enc {:?}", enc); - // "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!(HelloRetryExtension::read_bytes(&enc).is_err()); - } + // "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()); } -} -#[test] -fn hello_retry_requested_key_share_group() { - test_hello_retry_extension_getter(ExtensionType::KeyShare, |hrr| { - hrr.requested_key_share_group() - .is_some() - }); -} - -#[test] -fn hello_retry_cookie() { - test_hello_retry_extension_getter(ExtensionType::Cookie, |hrr| hrr.cookie().is_some()); -} - -#[test] -fn hello_retry_supported_versions() { - test_hello_retry_extension_getter(ExtensionType::SupportedVersions, |hrr| { - hrr.supported_versions().is_some() - }); -} - -fn test_hello_retry_extension_getter(typ: ExtensionType, getter: fn(&HelloRetryRequest) -> bool) { - let mut hrr = sample_hello_retry_request(); - let mut exts = core::mem::take(&mut hrr.extensions); - exts.retain(|ext| ext.ext_type() == typ); - - assert!(!getter(&hrr)); - - hrr.extensions = exts; - assert!(getter(&hrr)); - - hrr.extensions = vec![HelloRetryExtension::Unknown(UnknownExtension { - typ, - payload: Payload::Borrowed(&[]), - })]; - assert!(!getter(&hrr)); + // "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 {:?} len {:?}", enc, l); + assert!(HelloRetryRequestExtensions::read_bytes(&enc).is_err()); + } } #[test] @@ -856,15 +805,13 @@ fn sample_hello_retry_request() -> HelloRetryRequest { legacy_version: ProtocolVersion::TLSv1_2, session_id: SessionId::empty(), cipher_suite: CipherSuite::TLS_NULL_WITH_NULL_NULL, - extensions: vec![ - HelloRetryExtension::KeyShare(NamedGroup::X25519), - HelloRetryExtension::Cookie(PayloadU16::new(vec![0])), - HelloRetryExtension::SupportedVersions(ProtocolVersion::TLSv1_2), - HelloRetryExtension::Unknown(UnknownExtension { - typ: ExtensionType::Unknown(12345), - payload: Payload::Borrowed(&[1, 2, 3]), - }), - ], + 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, + }, } } diff --git a/rustls/src/msgs/macros.rs b/rustls/src/msgs/macros.rs index 602f92f1be0..d1a67b7e106 100644 --- a/rustls/src/msgs/macros.rs +++ b/rustls/src/msgs/macros.rs @@ -213,6 +213,7 @@ macro_rules! extension_struct { } /// Return a list of extensions whose items are `Some` + #[allow(dead_code)] pub(crate) fn collect_used(&self) -> Vec { let mut r = Vec::with_capacity(Self::ALL_EXTENSIONS.len()); @@ -228,6 +229,7 @@ macro_rules! extension_struct { /// 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, @@ -242,6 +244,7 @@ macro_rules! extension_struct { } /// Remove the extension identified by `typ` from `self`. + #[allow(dead_code)] pub(crate) fn clear(&mut self, typ: ExtensionType) { match typ { $( diff --git a/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index 343745b16ca..711e4a1a86a 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -47,7 +47,7 @@ mod client_hello { use crate::msgs::enums::{Compression, NamedGroup, PskKeyExchangeMode}; use crate::msgs::handshake::{ CertReqExtension, CertificatePayloadTls13, CertificateRequestPayloadTls13, - ClientHelloPayload, HelloRetryExtension, HelloRetryRequest, KeyShareEntry, Random, + ClientHelloPayload, HelloRetryRequest, HelloRetryRequestExtensions, KeyShareEntry, Random, ServerExtension, ServerHelloPayload, SessionId, }; use crate::server::common::ActiveCertifiedKey; @@ -587,20 +587,17 @@ mod client_hello { common: &mut CommonState, group: NamedGroup, ) { - let mut req = HelloRetryRequest { + let req = HelloRetryRequest { legacy_version: ProtocolVersion::TLSv1_2, session_id, cipher_suite: suite.common.suite, - extensions: Vec::new(), + extensions: HelloRetryRequestExtensions { + key_share: Some(group), + supported_versions: Some(ProtocolVersion::TLSv1_3), + ..Default::default() + }, }; - req.extensions - .push(HelloRetryExtension::KeyShare(group)); - req.extensions - .push(HelloRetryExtension::SupportedVersions( - ProtocolVersion::TLSv1_3, - )); - let m = Message { version: ProtocolVersion::TLSv1_2, payload: MessagePayload::handshake(HandshakeMessagePayload( From 2eb271f0feeb1fae830d4868fd0b0ae7c2622352 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 4 Apr 2025 11:05:36 +0100 Subject: [PATCH 288/403] Move to new extensions repr for TLS1.3 certs --- bogo/config.json.in | 2 - bogo/src/main.rs | 3 +- rustls/src/client/tls13.rs | 8 -- rustls/src/error.rs | 2 + rustls/src/msgs/handshake.rs | 157 +++++++++--------------------- rustls/src/msgs/handshake_test.rs | 57 ++++------- rustls/src/msgs/macros.rs | 14 +++ rustls/src/server/tls13.rs | 6 +- 8 files changed, 87 insertions(+), 162 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index c9b121a9bfd..22edf2e5899 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -325,8 +325,6 @@ "Server-TooLongSessionID-TLS13": ":BAD_HANDSHAKE_MSG:", "Server-TooLongSessionID-TLS12": ":BAD_HANDSHAKE_MSG:", "Client-TooLongSessionID": ":BAD_HANDSHAKE_MSG:", - "SendUnknownExtensionOnCertificate-TLS13": ":PEER_MISBEHAVIOUR:", - "SendDuplicateExtensionsOnCerts-TLS13": ":PEER_MISBEHAVIOUR:", "EMS-Forbidden-TLS13": ":PEER_MISBEHAVIOUR:", "Unclean-Shutdown": ":CLOSE_WITHOUT_CLOSE_NOTIFY:", "SendExtensionOnClientCertificate-TLS13": ":PEER_MISBEHAVIOUR:", diff --git a/bogo/src/main.rs b/bogo/src/main.rs index 89a3644350e..df6bcca4982 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -927,7 +927,8 @@ fn handle_err(opts: &Options, err: Error) -> ! { Error::InvalidMessage(InvalidMessage::DuplicateExtension(_)) => { quit(":DUPLICATE_EXTENSION:") } - Error::InvalidMessage(InvalidMessage::UnknownHelloRetryRequestExtension) => { + Error::InvalidMessage(InvalidMessage::UnknownHelloRetryRequestExtension) + | Error::InvalidMessage(InvalidMessage::UnknownCertificateExtension) => { quit(":UNEXPECTED_EXTENSION:") } Error::InvalidMessage(InvalidMessage::UnexpectedMessage(_)) => quit(":GARBAGE:"), diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index f7a49a03ef6..69d1502e4c1 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -1060,14 +1060,6 @@ impl State for ExpectCertificate { )); } - if cert_chain.any_entry_has_duplicate_extension() - || cert_chain.any_entry_has_unknown_extension() - { - return Err(cx.common.send_fatal_alert( - AlertDescription::UnsupportedExtension, - PeerMisbehaved::BadCertChainExtensions, - )); - } let end_entity_ocsp = cert_chain.end_entity_ocsp().to_vec(); let server_cert = ServerCertDetails::new( cert_chain diff --git a/rustls/src/error.rs b/rustls/src/error.rs index 1cb54e24b09..d616769eecd 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -199,6 +199,8 @@ pub enum InvalidMessage { 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 for Error { diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 52549f9c7c9..fc4bead308c 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -1626,84 +1626,62 @@ impl TlsListElement for CertificateDer<'_> { /// that is directly controllable by the peer. pub(crate) const CERTIFICATE_MAX_SIZE_LIMIT: usize = 0x1_0000; -#[derive(Debug)] -pub(crate) enum CertificateExtension<'a> { - CertificateStatus(CertificateStatus<'a>), - Unknown(UnknownExtension), -} - -impl CertificateExtension<'_> { - pub(crate) fn ext_type(&self) -> ExtensionType { - match self { - Self::CertificateStatus(_) => ExtensionType::StatusRequest, - Self::Unknown(r) => r.typ, - } - } - - pub(crate) fn cert_status(&self) -> Option<&[u8]> { - match self { - Self::CertificateStatus(cs) => Some(cs.ocsp_response.0.bytes()), - _ => None, - } +extension_struct! { + pub(crate) struct CertificateExtensions<'a> { + ExtensionType::StatusRequest => + pub(crate) status: Option>, } +} - pub(crate) fn into_owned(self) -> CertificateExtension<'static> { - match self { - Self::CertificateStatus(st) => CertificateExtension::CertificateStatus(st.into_owned()), - Self::Unknown(unk) => CertificateExtension::Unknown(unk), +impl CertificateExtensions<'_> { + fn into_owned(self) -> CertificateExtensions<'static> { + CertificateExtensions { + status: self.status.map(|s| s.into_owned()), } } } -impl<'a> Codec<'a> for CertificateExtension<'a> { +impl<'a> Codec<'a> for CertificateExtensions<'a> { fn encode(&self, bytes: &mut Vec) { - self.ext_type().encode(bytes); + let extensions = LengthPrefixedBuffer::new(ListLength::U16, bytes); - let nested = LengthPrefixedBuffer::new(ListLength::U16, bytes); - match self { - Self::CertificateStatus(r) => r.encode(nested.buf), - Self::Unknown(r) => r.encode(nested.buf), + for ext in Self::ALL_EXTENSIONS { + self.encode_one(*ext, extensions.buf); } } fn read(r: &mut Reader<'a>) -> Result { - let typ = ExtensionType::read(r)?; - let len = u16::read(r)? as usize; + let mut out = Self::default(); + + let len = usize::from(u16::read(r)?); let mut sub = r.sub(len)?; - let ext = match typ { - ExtensionType::StatusRequest => { - let st = CertificateStatus::read(&mut sub)?; - Self::CertificateStatus(st) - } - _ => Self::Unknown(UnknownExtension::read(typ, &mut sub)), - }; + while sub.any_left() { + out.read_one(&mut sub, |_unk| { + Err(InvalidMessage::UnknownCertificateExtension) + })?; + } - sub.expect_empty("CertificateExtension") - .map(|_| ext) + Ok(out) } } -impl TlsListElement for CertificateExtension<'_> { - const SIZE_LEN: ListLength = ListLength::U16; -} - #[derive(Debug)] pub(crate) struct CertificateEntry<'a> { pub(crate) cert: CertificateDer<'a>, - pub(crate) exts: Vec>, + pub(crate) extensions: CertificateExtensions<'a>, } impl<'a> Codec<'a> for CertificateEntry<'a> { fn encode(&self, bytes: &mut Vec) { self.cert.encode(bytes); - self.exts.encode(bytes); + self.extensions.encode(bytes); } fn read(r: &mut Reader<'a>) -> Result { Ok(Self { cert: CertificateDer::read(r)?, - exts: Vec::read(r)?, + extensions: CertificateExtensions::read(r)?.into_owned(), }) } } @@ -1712,41 +1690,16 @@ impl<'a> CertificateEntry<'a> { pub(crate) fn new(cert: CertificateDer<'a>) -> Self { Self { cert, - exts: Vec::new(), + extensions: CertificateExtensions::default(), } } pub(crate) fn into_owned(self) -> CertificateEntry<'static> { CertificateEntry { cert: self.cert.into_owned(), - exts: self - .exts - .into_iter() - .map(CertificateExtension::into_owned) - .collect(), + extensions: self.extensions.into_owned(), } } - - pub(crate) fn has_duplicate_extension(&self) -> bool { - has_duplicates::<_, _, u16>( - self.exts - .iter() - .map(|ext| ext.ext_type()), - ) - } - - pub(crate) fn has_unknown_extension(&self) -> bool { - self.exts - .iter() - .any(|ext| ext.ext_type() != ExtensionType::StatusRequest) - } - - pub(crate) fn ocsp_response(&self) -> Option<&[u8]> { - self.exts - .iter() - .find(|ext| ext.ext_type() == ExtensionType::StatusRequest) - .and_then(CertificateExtension::cert_status) - } } impl TlsListElement for CertificateEntry<'_> { @@ -1795,10 +1748,7 @@ impl<'a> CertificatePayloadTls13<'a> { .map(|(cert, ocsp)| { let mut e = CertificateEntry::new(cert.clone()); if let Some(ocsp) = ocsp { - e.exts - .push(CertificateExtension::CertificateStatus( - CertificateStatus::new(ocsp), - )); + e.extensions.status = Some(CertificateStatus::new(ocsp)); } e }) @@ -1817,40 +1767,21 @@ impl<'a> CertificatePayloadTls13<'a> { } } - pub(crate) fn any_entry_has_duplicate_extension(&self) -> bool { - for entry in &self.entries { - if entry.has_duplicate_extension() { - return true; - } - } - - false - } - - pub(crate) fn any_entry_has_unknown_extension(&self) -> bool { - for entry in &self.entries { - if entry.has_unknown_extension() { - return true; - } - } - - false - } - - pub(crate) fn any_entry_has_extension(&self) -> bool { - for entry in &self.entries { - if !entry.exts.is_empty() { - return true; - } - } - - false - } - - pub(crate) fn end_entity_ocsp(&self) -> &[u8] { - self.entries - .first() - .and_then(CertificateEntry::ocsp_response) + pub(crate) fn end_entity_ocsp(&self) -> Vec { + 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() } @@ -2618,7 +2549,7 @@ impl Codec<'_> for NewSessionTicketPayloadTls13 { // -- RFC6066 certificate status types /// Only supports OCSP -#[derive(Debug)] +#[derive(Clone, Debug)] pub(crate) struct CertificateStatus<'a> { pub(crate) ocsp_response: PayloadU24<'a>, } diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index f7a118cf4ea..0666722bdea 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -10,7 +10,7 @@ use super::enums::{ KeyUpdateRequest, NamedGroup, PskKeyExchangeMode, }; use super::handshake::{ - CertReqExtension, CertificateChain, CertificateEntry, CertificateExtension, + CertReqExtension, CertificateChain, CertificateEntry, CertificateExtensions, CertificatePayloadTls13, CertificateRequestPayload, CertificateRequestPayloadTls13, CertificateStatus, CertificateStatusRequest, ClientExtensions, ClientHelloPayload, ClientSessionTicket, CompressedCertificatePayload, DistinguishedName, EcParameters, @@ -134,9 +134,22 @@ fn refuses_server_ext_with_unparsed_bytes() { #[test] fn refuses_certificate_ext_with_unparsed_bytes() { - let bytes = [0x00u8, 0x05, 0x00, 0x03, 0x00, 0x00, 0x01]; - let mut rd = Reader::init(&bytes); - assert!(CertificateExtension::read(&mut rd).is_err()); + 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] @@ -573,32 +586,6 @@ fn server_server_certificate_type_extension() { }); } -#[test] -fn cert_entry_ocsp_response() { - test_cert_extension_getter(ExtensionType::StatusRequest, |ce| { - ce.ocsp_response().is_some() - }); -} - -fn test_cert_extension_getter(typ: ExtensionType, getter: fn(&CertificateEntry<'_>) -> bool) { - let mut ce = sample_certificate_payload_tls13() - .entries - .remove(0); - let mut exts = core::mem::take(&mut ce.exts); - exts.retain(|ext| ext.ext_type() == typ); - - assert!(!getter(&ce)); - - ce.exts = exts; - assert!(getter(&ce)); - - ce.exts = vec![CertificateExtension::Unknown(UnknownExtension { - typ, - payload: Payload::Borrowed(&[]), - })]; - assert!(!getter(&ce)); -} - #[test] fn can_print_all_server_extensions() { println!("server hello {:?}", sample_server_hello_payload()); @@ -1002,15 +989,11 @@ fn sample_certificate_payload_tls13() -> CertificatePayloadTls13<'static> { context: PayloadU8::new(vec![1, 2, 3]), entries: vec![CertificateEntry { cert: CertificateDer::from(vec![3, 4, 5]), - exts: vec![ - CertificateExtension::CertificateStatus(CertificateStatus { + extensions: CertificateExtensions { + status: Some(CertificateStatus { ocsp_response: PayloadU24(Payload::new(vec![1, 2, 3])), }), - CertificateExtension::Unknown(UnknownExtension { - typ: ExtensionType::Unknown(12345), - payload: Payload::Borrowed(&[1, 2, 3]), - }), - ], + }, }], } } diff --git a/rustls/src/msgs/macros.rs b/rustls/src/msgs/macros.rs index d1a67b7e106..c6d564dc150 100644 --- a/rustls/src/msgs/macros.rs +++ b/rustls/src/msgs/macros.rs @@ -254,6 +254,20 @@ macro_rules! extension_struct { } } + /// 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 + } + /// Every `ExtensionType` this structure may encode/decode. const ALL_EXTENSIONS: &'static [ExtensionType] = &[ $($item_id,)* diff --git a/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index 711e4a1a86a..c776547158e 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -1051,7 +1051,11 @@ impl State for ExpectCertificate { // We don't send any CertificateRequest extensions, so any extensions // here are illegal. - if certp.any_entry_has_extension() { + if certp + .entries + .iter() + .any(|e| !e.extensions.only_contains(&[])) + { return Err(PeerMisbehaved::UnsolicitedCertExtension.into()); } From 01ca121d4f9a64f4ac343d70f5175e53daa98cdd Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 23 Jun 2025 15:21:57 +0100 Subject: [PATCH 289/403] Extract `DuplicateExtensionChecker` helper --- rustls/src/msgs/handshake.rs | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index fc4bead308c..e0e2738d1e9 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -1005,19 +1005,13 @@ impl<'a> Codec<'a> for ClientExtensions<'a> { return Ok(out); } - let mut unknown_extensions = BTreeSet::new(); + 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| { - let u = u16::from(unknown); - match unknown_extensions.insert(u) { - true => Ok(()), - false => Err(InvalidMessage::DuplicateExtension(u)), - } - })?; + let typ = out.read_one(&mut sub, |unknown| checker.check(unknown))?; // PreSharedKey offer must come last if typ == ExtensionType::PreSharedKey && sub.any_left() { @@ -3248,6 +3242,22 @@ fn has_duplicates, E: Into, T: Eq + Ord>(iter: I) - false } +struct DuplicateExtensionChecker(BTreeSet); + +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) From b5f22b5d1c4b3886e402cfa1f6646700f78d633f Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 4 Apr 2025 11:51:43 +0100 Subject: [PATCH 290/403] Move to new extensions repr for cert requests --- rustls/src/client/tls13.rs | 16 ++-- rustls/src/msgs/handshake.rs | 120 ++++++++---------------------- rustls/src/msgs/handshake_test.rs | 36 +++++---- rustls/src/server/tls13.rs | 48 ++++++------ 4 files changed, 89 insertions(+), 131 deletions(-) diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index 69d1502e4c1..b28fbc32bf0 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -852,10 +852,11 @@ impl State for ExpectCertificateRequest { )); } - let no_sigschemes = Vec::new(); let compat_sigschemes = certreq - .sigalgs_extension() - .unwrap_or(&no_sigschemes) + .extensions + .signature_algorithms + .as_deref() + .unwrap_or_default() .iter() .cloned() .filter(SignatureScheme::supported_in_tls13) @@ -869,7 +870,9 @@ impl State for ExpectCertificateRequest { } let compat_compressor = certreq - .certificate_compression_extension() + .extensions + .certificate_compression_algorithms + .as_deref() .and_then(|offered| { self.config .cert_compressors @@ -882,7 +885,10 @@ impl State for ExpectCertificateRequest { self.config .client_auth_cert_resolver .as_ref(), - certreq.authorities_extension(), + certreq + .extensions + .authority_names + .as_deref(), &compat_sigschemes, Some(certreq.context.0.clone()), compat_compressor, diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index e0e2738d1e9..7d0f59bbb70 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -2259,77 +2259,57 @@ impl Codec<'_> for CertificateRequestPayload { } } -#[derive(Debug)] -pub(crate) enum CertReqExtension { - SignatureAlgorithms(Vec), - AuthorityNames(Vec), - CertificateCompressionAlgorithms(Vec), - Unknown(UnknownExtension), -} +extension_struct! { + pub(crate) struct CertificateRequestExtensions { + ExtensionType::SignatureAlgorithms => + pub(crate) signature_algorithms: Option>, -impl CertReqExtension { - pub(crate) fn ext_type(&self) -> ExtensionType { - match self { - Self::SignatureAlgorithms(_) => ExtensionType::SignatureAlgorithms, - Self::AuthorityNames(_) => ExtensionType::CertificateAuthorities, - Self::CertificateCompressionAlgorithms(_) => ExtensionType::CompressCertificate, - Self::Unknown(r) => r.typ, - } + ExtensionType::CertificateAuthorities => + pub(crate) authority_names: Option>, + + ExtensionType::CompressCertificate => + pub(crate) certificate_compression_algorithms: Option>, } } -impl Codec<'_> for CertReqExtension { +impl Codec<'_> for CertificateRequestExtensions { fn encode(&self, bytes: &mut Vec) { - self.ext_type().encode(bytes); + let extensions = LengthPrefixedBuffer::new(ListLength::U16, bytes); - let nested = LengthPrefixedBuffer::new(ListLength::U16, bytes); - match self { - Self::SignatureAlgorithms(r) => r.encode(nested.buf), - Self::AuthorityNames(r) => r.encode(nested.buf), - Self::CertificateCompressionAlgorithms(r) => r.encode(nested.buf), - Self::Unknown(r) => r.encode(nested.buf), + for ext in Self::ALL_EXTENSIONS { + self.encode_one(*ext, extensions.buf); } } fn read(r: &mut Reader<'_>) -> Result { - let typ = ExtensionType::read(r)?; - let len = u16::read(r)? as usize; + let mut out = Self::default(); + + let mut checker = DuplicateExtensionChecker::new(); + + let len = usize::from(u16::read(r)?); let mut sub = r.sub(len)?; - let ext = match typ { - ExtensionType::SignatureAlgorithms => { - let schemes = Vec::read(&mut sub)?; - if schemes.is_empty() { - return Err(InvalidMessage::NoSignatureSchemes); - } - Self::SignatureAlgorithms(schemes) - } - ExtensionType::CertificateAuthorities => { - let cas = Vec::read(&mut sub)?; - if cas.is_empty() { - return Err(InvalidMessage::IllegalEmptyList("DistinguishedNames")); - } - Self::AuthorityNames(cas) - } - ExtensionType::CompressCertificate => { - Self::CertificateCompressionAlgorithms(Vec::read(&mut sub)?) - } - _ => Self::Unknown(UnknownExtension::read(typ, &mut sub)), - }; + while sub.any_left() { + out.read_one(&mut sub, |unknown| checker.check(unknown))?; + } - sub.expect_empty("CertReqExtension") - .map(|_| ext) - } -} + if out + .signature_algorithms + .as_ref() + .map(|algs| algs.is_empty()) + .unwrap_or_default() + { + return Err(InvalidMessage::NoSignatureSchemes); + } -impl TlsListElement for CertReqExtension { - const SIZE_LEN: ListLength = ListLength::U16; + Ok(out) + } } #[derive(Debug)] pub(crate) struct CertificateRequestPayloadTls13 { pub(crate) context: PayloadU8, - pub(crate) extensions: Vec, + pub(crate) extensions: CertificateRequestExtensions, } impl Codec<'_> for CertificateRequestPayloadTls13 { @@ -2340,7 +2320,7 @@ impl Codec<'_> for CertificateRequestPayloadTls13 { fn read(r: &mut Reader<'_>) -> Result { let context = PayloadU8::read(r)?; - let extensions = Vec::read(r)?; + let extensions = CertificateRequestExtensions::read(r)?; Ok(Self { context, @@ -2349,40 +2329,6 @@ impl Codec<'_> for CertificateRequestPayloadTls13 { } } -impl CertificateRequestPayloadTls13 { - pub(crate) fn find_extension(&self, ext: ExtensionType) -> Option<&CertReqExtension> { - self.extensions - .iter() - .find(|x| x.ext_type() == ext) - } - - pub(crate) fn sigalgs_extension(&self) -> Option<&[SignatureScheme]> { - let ext = self.find_extension(ExtensionType::SignatureAlgorithms)?; - match ext { - CertReqExtension::SignatureAlgorithms(sa) => Some(sa), - _ => None, - } - } - - pub(crate) fn authorities_extension(&self) -> Option<&[DistinguishedName]> { - let ext = self.find_extension(ExtensionType::CertificateAuthorities)?; - match ext { - CertReqExtension::AuthorityNames(an) => Some(an), - _ => None, - } - } - - pub(crate) fn certificate_compression_extension( - &self, - ) -> Option<&[CertificateCompressionAlgorithm]> { - let ext = self.find_extension(ExtensionType::CompressCertificate)?; - match ext { - CertReqExtension::CertificateCompressionAlgorithms(comps) => Some(comps), - _ => None, - } - } -} - // -- NewSessionTicket -- #[derive(Debug)] pub(crate) struct NewSessionTicketPayload { diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index 0666722bdea..e31be00c232 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -10,8 +10,8 @@ use super::enums::{ KeyUpdateRequest, NamedGroup, PskKeyExchangeMode, }; use super::handshake::{ - CertReqExtension, CertificateChain, CertificateEntry, CertificateExtensions, - CertificatePayloadTls13, CertificateRequestPayload, CertificateRequestPayloadTls13, + CertificateChain, CertificateEntry, CertificateExtensions, CertificatePayloadTls13, + CertificateRequestExtensions, CertificateRequestPayload, CertificateRequestPayloadTls13, CertificateStatus, CertificateStatusRequest, ClientExtensions, ClientHelloPayload, ClientSessionTicket, CompressedCertificatePayload, DistinguishedName, EcParameters, EncryptedClientHello, HandshakeMessagePayload, HandshakePayload, HasServerExtensions, @@ -154,9 +154,22 @@ fn refuses_certificate_ext_with_unknown_type() { #[test] fn refuses_certificate_req_ext_with_unparsed_bytes() { - let bytes = [0x00u8, 0x0d, 0x00, 0x05, 0x00, 0x02, 0x01, 0x02, 0xff]; - let mut rd = Reader::init(&bytes); - assert!(CertReqExtension::read(&mut rd).is_err()); + 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] @@ -1045,14 +1058,11 @@ fn sample_certificate_request_payload() -> CertificateRequestPayload { fn sample_certificate_request_payload_tls13() -> CertificateRequestPayloadTls13 { CertificateRequestPayloadTls13 { context: PayloadU8::new(vec![1, 2, 3]), - extensions: vec![ - CertReqExtension::SignatureAlgorithms(vec![SignatureScheme::ECDSA_NISTP256_SHA256]), - CertReqExtension::AuthorityNames(vec![DistinguishedName::from(vec![1, 2, 3])]), - CertReqExtension::Unknown(UnknownExtension { - typ: ExtensionType::Unknown(12345), - payload: Payload::Borrowed(&[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]), + }, } } diff --git a/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index c776547158e..b6d96ba7c87 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -46,7 +46,7 @@ mod client_hello { use crate::msgs::ccs::ChangeCipherSpecPayload; use crate::msgs::enums::{Compression, NamedGroup, PskKeyExchangeMode}; use crate::msgs::handshake::{ - CertReqExtension, CertificatePayloadTls13, CertificateRequestPayloadTls13, + CertificatePayloadTls13, CertificateRequestExtensions, CertificateRequestPayloadTls13, ClientHelloPayload, HelloRetryRequest, HelloRetryRequestExtensions, KeyShareEntry, Random, ServerExtension, ServerHelloPayload, SessionId, }; @@ -703,33 +703,29 @@ mod client_hello { return Ok(false); } - let mut cr = CertificateRequestPayloadTls13 { + let cr = CertificateRequestPayloadTls13 { context: PayloadU8::empty(), - extensions: Vec::new(), - }; - - let schemes = config - .verifier - .supported_verify_schemes(); - cr.extensions - .push(CertReqExtension::SignatureAlgorithms(schemes.to_vec())); - - if !config.cert_decompressors.is_empty() { - cr.extensions - .push(CertReqExtension::CertificateCompressionAlgorithms( + extensions: CertificateRequestExtensions { + signature_algorithms: Some( config - .cert_decompressors - .iter() - .map(|decomp| decomp.algorithm()) - .collect(), - )); - } - - let authorities = config.verifier.root_hint_subjects(); - if !authorities.is_empty() { - cr.extensions - .push(CertReqExtension::AuthorityNames(authorities.to_vec())); - } + .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)); From cfaf2db67b170893949a81c6606cca54bcfd8185 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 7 Apr 2025 08:40:08 +0100 Subject: [PATCH 291/403] Move to new extensions repr for TLS1.3 tickets --- bogo/config.json.in | 1 - rustls/src/client/tls13.rs | 16 ++----- rustls/src/msgs/handshake.rs | 79 +++++++++---------------------- rustls/src/msgs/handshake_test.rs | 28 +++++++---- rustls/src/server/tls13.rs | 8 +--- 5 files changed, 47 insertions(+), 85 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index 22edf2e5899..2f93e5127d3 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -338,7 +338,6 @@ "ServerCipherFilter-Ed25519": ":INCOMPATIBLE:", "TLS13-OnlyPadding-TLS": ":PEER_MISBEHAVIOUR:", "TLS13-EmptyRecords-TLS": ":PEER_MISBEHAVIOUR:", - "TLS13-DuplicateTicketEarlyDataSupport": ":PEER_MISBEHAVIOUR:", "SupportedVersionSelection-TLS12": ":PEER_MISBEHAVIOUR:", "HelloRetryRequest-CipherChange-TLS13": ":PEER_MISBEHAVIOUR:", "CurveTest-Client-Compressed-P-256-TLS12": ":PEER_MISBEHAVIOUR:", diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index b28fbc32bf0..dfbe7733829 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -1442,10 +1442,6 @@ impl ExpectTraffic { cx: &mut KernelContext<'_>, nst: &NewSessionTicketPayloadTls13, ) -> Result<(), Error> { - if nst.has_duplicate_extension() { - return Err(PeerMisbehaved::DuplicateNewSessionTicketExtensions.into()); - } - let handshake_hash = self.transcript.current_hash(); let secret = ResumptionSecret::new(&self.key_schedule, &handshake_hash) .derive_ticket_psk(&nst.nonce.0); @@ -1465,12 +1461,13 @@ impl ExpectTraffic { now, nst.lifetime, nst.age_add, - nst.max_early_data_size() + nst.extensions + .max_early_data_size .unwrap_or_default(), ); if cx.is_quic() { - if let Some(sz) = nst.max_early_data_size() { + if let Some(sz) = nst.extensions.max_early_data_size { if sz != 0 && sz != 0xffff_ffff { return Err(PeerMisbehaved::InvalidMaxEarlyDataSize.into()); } @@ -1491,13 +1488,6 @@ impl ExpectTraffic { cx: &mut ClientContext<'_>, nst: &NewSessionTicketPayloadTls13, ) -> Result<(), Error> { - if nst.has_duplicate_extension() { - return Err(cx.common.send_fatal_alert( - AlertDescription::IllegalParameter, - PeerMisbehaved::DuplicateNewSessionTicketExtensions, - )); - } - let mut kcx = KernelContext { peer_certificates: cx.common.peer_certificates.as_ref(), protocol: cx.common.protocol, diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 7d0f59bbb70..61e598ca4a8 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -2367,58 +2367,45 @@ impl Codec<'_> for NewSessionTicketPayload { } // -- NewSessionTicket electric boogaloo -- -#[derive(Debug)] -pub(crate) enum NewSessionTicketExtension { - EarlyData(u32), - Unknown(UnknownExtension), -} - -impl NewSessionTicketExtension { - pub(crate) fn ext_type(&self) -> ExtensionType { - match self { - Self::EarlyData(_) => ExtensionType::EarlyData, - Self::Unknown(r) => r.typ, - } +extension_struct! { + pub(crate) struct NewSessionTicketExtensions { + ExtensionType::EarlyData => + pub(crate) max_early_data_size: Option, } } -impl Codec<'_> for NewSessionTicketExtension { +impl Codec<'_> for NewSessionTicketExtensions { fn encode(&self, bytes: &mut Vec) { - self.ext_type().encode(bytes); + let extensions = LengthPrefixedBuffer::new(ListLength::U16, bytes); - let nested = LengthPrefixedBuffer::new(ListLength::U16, bytes); - match self { - Self::EarlyData(r) => r.encode(nested.buf), - Self::Unknown(r) => r.encode(nested.buf), + for ext in Self::ALL_EXTENSIONS { + self.encode_one(*ext, extensions.buf); } } fn read(r: &mut Reader<'_>) -> Result { - let typ = ExtensionType::read(r)?; - let len = u16::read(r)? as usize; + let mut out = Self::default(); + + let mut checker = DuplicateExtensionChecker::new(); + + let len = usize::from(u16::read(r)?); let mut sub = r.sub(len)?; - let ext = match typ { - ExtensionType::EarlyData => Self::EarlyData(u32::read(&mut sub)?), - _ => Self::Unknown(UnknownExtension::read(typ, &mut sub)), - }; + while sub.any_left() { + out.read_one(&mut sub, |unknown| checker.check(unknown))?; + } - sub.expect_empty("NewSessionTicketExtension") - .map(|_| ext) + Ok(out) } } -impl TlsListElement for NewSessionTicketExtension { - const SIZE_LEN: ListLength = ListLength::U16; -} - #[derive(Debug)] pub(crate) struct NewSessionTicketPayloadTls13 { pub(crate) lifetime: u32, pub(crate) age_add: u32, pub(crate) nonce: PayloadU8, pub(crate) ticket: Arc, - pub(crate) exts: Vec, + pub(crate) extensions: NewSessionTicketExtensions, } impl NewSessionTicketPayloadTls13 { @@ -2428,29 +2415,7 @@ impl NewSessionTicketPayloadTls13 { age_add, nonce: PayloadU8::new(nonce), ticket: Arc::new(PayloadU16::new(ticket)), - exts: vec![], - } - } - - pub(crate) fn has_duplicate_extension(&self) -> bool { - has_duplicates::<_, _, u16>( - self.exts - .iter() - .map(|ext| ext.ext_type()), - ) - } - - pub(crate) fn find_extension(&self, ext: ExtensionType) -> Option<&NewSessionTicketExtension> { - self.exts - .iter() - .find(|x| x.ext_type() == ext) - } - - pub(crate) fn max_early_data_size(&self) -> Option { - let ext = self.find_extension(ExtensionType::EarlyData)?; - match ext { - NewSessionTicketExtension::EarlyData(sz) => Some(*sz), - _ => None, + extensions: NewSessionTicketExtensions::default(), } } } @@ -2461,7 +2426,7 @@ impl Codec<'_> for NewSessionTicketPayloadTls13 { self.age_add.encode(bytes); self.nonce.encode(bytes); self.ticket.encode(bytes); - self.exts.encode(bytes); + self.extensions.encode(bytes); } fn read(r: &mut Reader<'_>) -> Result { @@ -2474,14 +2439,14 @@ impl Codec<'_> for NewSessionTicketPayloadTls13 { Err(err) => Err(err), Ok(pl) => Ok(PayloadU16::new(pl.0)), }?); - let exts = Vec::read(r)?; + let extensions = NewSessionTicketExtensions::read(r)?; Ok(Self { lifetime, age_add, nonce, ticket, - exts, + extensions, }) } } diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index e31be00c232..8b41a8e0d46 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -15,7 +15,7 @@ use super::handshake::{ CertificateStatus, CertificateStatusRequest, ClientExtensions, ClientHelloPayload, ClientSessionTicket, CompressedCertificatePayload, DistinguishedName, EcParameters, EncryptedClientHello, HandshakeMessagePayload, HandshakePayload, HasServerExtensions, - HelloRetryRequest, HelloRetryRequestExtensions, KeyShareEntry, NewSessionTicketExtension, + HelloRetryRequest, HelloRetryRequestExtensions, KeyShareEntry, NewSessionTicketExtensions, NewSessionTicketPayload, NewSessionTicketPayloadTls13, PresharedKeyBinder, PresharedKeyIdentity, PresharedKeyOffer, ProtocolName, Random, ServerDhParams, ServerEcdhParams, ServerExtension, ServerHelloPayload, ServerKeyExchange, @@ -174,9 +174,22 @@ fn refuses_certificate_req_ext_with_duplicate() { #[test] fn refuses_new_session_ticket_ext_with_unparsed_bytes() { - let bytes = [0x00u8, 0x2a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x01]; - let mut rd = Reader::init(&bytes); - assert!(NewSessionTicketExtension::read(&mut rd).is_err()); + 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] @@ -1079,10 +1092,9 @@ fn sample_new_session_ticket_payload_tls13() -> NewSessionTicketPayloadTls13 { age_add: 1234, nonce: PayloadU8::new(vec![1, 2, 3]), ticket: Arc::new(PayloadU16::new(vec![4, 5, 6])), - exts: vec![NewSessionTicketExtension::Unknown(UnknownExtension { - typ: ExtensionType::Unknown(12345), - payload: Payload::Borrowed(&[1, 2, 3]), - })], + extensions: NewSessionTicketExtensions { + max_early_data_size: Some(1234), + }, } } diff --git a/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index b6d96ba7c87..22130a2e57b 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -22,7 +22,7 @@ use crate::msgs::codec::{Codec, Reader}; use crate::msgs::enums::KeyUpdateRequest; use crate::msgs::handshake::{ CERTIFICATE_MAX_SIZE_LIMIT, CertificateChain, CertificatePayloadTls13, HandshakeMessagePayload, - HandshakePayload, NewSessionTicketExtension, NewSessionTicketPayloadTls13, + HandshakePayload, NewSessionTicketPayloadTls13, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; @@ -1300,11 +1300,7 @@ impl ExpectFinished { if config.max_early_data_size > 0 { if !stateless { - payload - .exts - .push(NewSessionTicketExtension::EarlyData( - config.max_early_data_size, - )); + 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 From 692f981446646af38d69d0771a3daa06b27b7884 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 7 Apr 2025 11:06:18 +0100 Subject: [PATCH 292/403] Move to new extensions repr for ServerHello/EE --- bogo/config.json.in | 2 + rustls/src/client/common.rs | 14 +- rustls/src/client/hs.rs | 27 +- rustls/src/client/test.rs | 58 +++-- rustls/src/client/tls12.rs | 11 +- rustls/src/client/tls13.rs | 93 +++---- rustls/src/msgs/handshake.rs | 394 ++++++++++++------------------ rustls/src/msgs/handshake_test.rs | 149 ++++------- rustls/src/msgs/macros.rs | 21 ++ rustls/src/quic.rs | 15 +- rustls/src/server/hs.rs | 75 +++--- rustls/src/server/server_conn.rs | 19 +- rustls/src/server/tls12.rs | 14 +- rustls/src/server/tls13.rs | 31 +-- 14 files changed, 416 insertions(+), 507 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index 2f93e5127d3..e7373e349db 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -382,6 +382,8 @@ "TrailingDataWithFinished-Client-TLS13": "local error: bad record MAC", "TrailingDataWithFinished-Resume-Client-TLS13": "local error: bad record MAC", "SkipEarlyData-SecondClientHelloEarlyData-TLS13": "remote error: illegal parameter", + "DuplicateExtensionClient-TLS-TLS12": "remote error: illegal parameter", + "DuplicateExtensionClient-TLS-TLS13": "remote error: illegal parameter", "DuplicateExtensionServer-TLS-TLS12": "remote error: illegal parameter", "DuplicateExtensionServer-TLS-TLS13": "remote error: illegal parameter" }, diff --git a/rustls/src/client/common.rs b/rustls/src/client/common.rs index fb6a013b424..9afa0c3410f 100644 --- a/rustls/src/client/common.rs +++ b/rustls/src/client/common.rs @@ -4,7 +4,7 @@ use alloc::vec::Vec; use super::ResolvesClientCert; use crate::log::{debug, trace}; use crate::msgs::enums::ExtensionType; -use crate::msgs::handshake::{CertificateChain, DistinguishedName, ProtocolName, ServerExtension}; +use crate::msgs::handshake::{CertificateChain, DistinguishedName, ProtocolName, ServerExtensions}; use crate::sync::Arc; use crate::{SignatureScheme, compress, sign}; @@ -53,11 +53,17 @@ impl ClientHelloDetails { pub(super) fn server_sent_unsolicited_extensions( &self, - received_exts: &[ServerExtension], + received_exts: &ServerExtensions<'_>, allowed_unsolicited: &[ExtensionType], ) -> bool { - for ext in received_exts { - let ext_type = ext.ext_type(); + 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:?}"); diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index afbfcb4ddfb..6d2097f4263 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -31,8 +31,8 @@ use crate::msgs::enums::{Compression, ECPointFormat, ExtensionType, PskKeyExchan use crate::msgs::handshake::{ CertificateStatusRequest, ClientExtensions, ClientExtensionsInput, ClientHelloPayload, ClientSessionTicket, EncryptedClientHello, HandshakeMessagePayload, HandshakePayload, - HasServerExtensions, HelloRetryRequest, KeyShareEntry, ProtocolName, Random, ServerNamePayload, - SessionId, SupportedProtocolVersions, TransportParameters, + HelloRetryRequest, KeyShareEntry, ProtocolName, Random, ServerNamePayload, SessionId, + SupportedProtocolVersions, TransportParameters, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; @@ -731,7 +731,7 @@ impl State for ExpectServerHello { let server_version = if server_hello.legacy_version == TLSv1_2 { server_hello - .supported_versions() + .selected_version .unwrap_or(server_hello.legacy_version) } else { server_hello.legacy_version @@ -746,10 +746,7 @@ impl State for ExpectServerHello { return Err(PeerMisbehaved::OfferedEarlyDataWithOldProtocolVersion.into()); } - if server_hello - .supported_versions() - .is_some() - { + if server_hello.selected_version.is_some() { return Err({ cx.common.send_fatal_alert( AlertDescription::IllegalParameter, @@ -780,18 +777,11 @@ impl State for ExpectServerHello { }); } - if server_hello.has_duplicate_extension() { - return Err(cx.common.send_fatal_alert( - AlertDescription::DecodeError, - PeerMisbehaved::DuplicateServerHelloExtensions, - )); - } - let allowed_unsolicited = [ExtensionType::RenegotiationInfo]; if self .input .hello - .server_sent_unsolicited_extensions(&server_hello.extensions, &allowed_unsolicited) + .server_sent_unsolicited_extensions(server_hello, &allowed_unsolicited) { return Err(cx.common.send_fatal_alert( AlertDescription::UnsupportedExtension, @@ -806,13 +796,16 @@ impl State for ExpectServerHello { process_alpn_protocol( cx.common, &self.input.hello.alpn_protocols, - server_hello.alpn_protocol(), + 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.ecpoints_extension() { + if let Some(point_fmts) = &server_hello.ec_point_formats { if !point_fmts.contains(&ECPointFormat::Uncompressed) { return Err(cx.common.send_fatal_alert( AlertDescription::HandshakeFailure, diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs index d07e1f45219..f4ea9580ea5 100644 --- a/rustls/src/client/test.rs +++ b/rustls/src/client/test.rs @@ -32,7 +32,7 @@ mod tests { use crate::msgs::enums::ECCurveType; use crate::msgs::handshake::{ CertificateChain, EcParameters, HelloRetryRequestExtensions, KeyShareEntry, - ServerEcdhParams, ServerExtension, ServerKeyExchange, ServerKeyExchangeParams, + ServerEcdhParams, ServerExtensions, ServerKeyExchange, ServerKeyExchangeParams, ServerKeyExchangePayload, }; use crate::msgs::message::PlainMessage; @@ -165,7 +165,7 @@ mod tests { cipher_suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, legacy_version: ProtocolVersion::TLSv1_2, session_id: SessionId::empty(), - extensions: vec![], + extensions: Box::new(ServerExtensions::default()), }), )), }; @@ -232,7 +232,10 @@ mod tests { cipher_suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, legacy_version: ProtocolVersion::TLSv1_2, session_id: SessionId::empty(), - extensions: vec![ServerExtension::ExtendedMasterSecretAck], + extensions: Box::new(ServerExtensions { + extended_master_secret_ack: Some(()), + ..ServerExtensions::default() + }), }), )), }; @@ -340,7 +343,7 @@ mod tests { #[test] fn test_client_requiring_rpk_rejects_server_that_only_offers_x509_id_by_omission() { assert_eq!( - client_requiring_rpk_receives_server_ee(vec![]), + client_requiring_rpk_receives_server_ee(ServerExtensions::default()), Err(PeerIncompatible::IncorrectCertificateTypeExtension.into()) ); } @@ -348,9 +351,10 @@ mod tests { #[test] fn test_client_requiring_rpk_rejects_server_that_only_offers_x509_id() { assert_eq!( - client_requiring_rpk_receives_server_ee(vec![ServerExtension::ServerCertType( - CertificateType::X509 - )]), + client_requiring_rpk_receives_server_ee(ServerExtensions { + server_certificate_type: Some(CertificateType::X509), + ..ServerExtensions::default() + }), Err(PeerIncompatible::IncorrectCertificateTypeExtension.into()) ); } @@ -358,9 +362,10 @@ mod tests { #[test] fn test_client_requiring_rpk_rejects_server_that_only_demands_x509_by_omission() { assert_eq!( - client_requiring_rpk_receives_server_ee(vec![ServerExtension::ServerCertType( - CertificateType::RawPublicKey - )]), + client_requiring_rpk_receives_server_ee(ServerExtensions { + server_certificate_type: Some(CertificateType::RawPublicKey), + ..ServerExtensions::default() + }), Err(PeerIncompatible::IncorrectCertificateTypeExtension.into()) ); } @@ -368,10 +373,11 @@ mod tests { #[test] fn test_client_requiring_rpk_rejects_server_that_only_demands_x509() { assert_eq!( - client_requiring_rpk_receives_server_ee(vec![ - ServerExtension::ClientCertType(CertificateType::X509), - ServerExtension::ServerCertType(CertificateType::RawPublicKey) - ]), + 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()) ); } @@ -379,16 +385,17 @@ mod tests { #[test] fn test_client_requiring_rpk_accepts_rpk_server() { assert_eq!( - client_requiring_rpk_receives_server_ee(vec![ - ServerExtension::ClientCertType(CertificateType::RawPublicKey), - ServerExtension::ServerCertType(CertificateType::RawPublicKey) - ]), + 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: Vec, + encrypted_extensions: ServerExtensions<'_>, ) -> Result<(), Error> { let fake_server_crypto = Arc::new(FakeServerCrypto::new()); let mut conn = ClientConnection::new( @@ -408,10 +415,13 @@ mod tests { cipher_suite: CipherSuite::TLS13_AES_128_GCM_SHA256, legacy_version: ProtocolVersion::TLSv1_3, session_id: SessionId::empty(), - extensions: vec![ServerExtension::KeyShare(KeyShareEntry { - group: NamedGroup::X25519, - payload: PayloadU16::new(vec![0xaa; 32]), - })], + extensions: Box::new(ServerExtensions { + key_share: Some(KeyShareEntry { + group: NamedGroup::X25519, + payload: PayloadU16::new(vec![0xaa; 32]), + }), + ..ServerExtensions::default() + }), }), )), }; @@ -422,7 +432,7 @@ mod tests { let ee = Message { version: ProtocolVersion::TLSv1_3, payload: MessagePayload::handshake(HandshakeMessagePayload( - HandshakePayload::EncryptedExtensions(encrypted_extensions), + HandshakePayload::EncryptedExtensions(Box::new(encrypted_extensions)), )), }; diff --git a/rustls/src/client/tls12.rs b/rustls/src/client/tls12.rs index 25da31dbd39..cb903c9b043 100644 --- a/rustls/src/client/tls12.rs +++ b/rustls/src/client/tls12.rs @@ -38,8 +38,7 @@ use crate::verify::{self, DigitallySignedStruct}; mod server_hello { use super::*; - use crate::msgs::enums::ExtensionType; - use crate::msgs::handshake::{HasServerExtensions, ServerHelloPayload}; + use crate::msgs::handshake::ServerHelloPayload; pub(in crate::client) struct CompleteServerHelloHandling { pub(in crate::client) config: Arc, @@ -76,7 +75,9 @@ mod server_hello { } // Doing EMS? - self.using_ems = server_hello.ems_support_acked(); + self.using_ems = server_hello + .extended_master_secret_ack + .is_some(); if self.config.require_ems && !self.using_ems { return Err({ cx.common.send_fatal_alert( @@ -88,7 +89,7 @@ mod server_hello { // Might the server send a ticket? let must_issue_new_ticket = if server_hello - .find_extension(ExtensionType::SessionTicket) + .session_ticket_ack .is_some() { debug!("Server supports tickets"); @@ -100,7 +101,7 @@ mod server_hello { // Might the server send a CertificateStatus between Certificate and // ServerKeyExchange? let may_send_cert_status = server_hello - .find_extension(ExtensionType::StatusRequest) + .certificate_status_request_ack .is_some(); if may_send_cert_status { debug!("Server may staple OCSP response"); diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index dfbe7733829..4d7155e59bf 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -29,9 +29,9 @@ 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, HasServerExtensions, KeyShareEntry, - NewSessionTicketPayloadTls13, PresharedKeyBinder, PresharedKeyIdentity, PresharedKeyOffer, - ServerExtension, ServerHelloPayload, + HandshakeMessagePayload, HandshakePayload, KeyShareEntry, NewSessionTicketPayloadTls13, + PresharedKeyBinder, PresharedKeyIdentity, PresharedKeyOffer, ServerExtensions, + ServerHelloPayload, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; @@ -85,7 +85,8 @@ pub(super) fn handle_server_hello( validate_server_hello(cx.common, server_hello)?; let their_key_share = server_hello - .key_share() + .key_share + .as_ref() .ok_or_else(|| { cx.common.send_fatal_alert( AlertDescription::MissingExtension, @@ -101,7 +102,7 @@ pub(super) fn handle_server_hello( ) })?; - let key_schedule_pre_handshake = match (server_hello.psk_index(), early_data_key_schedule) { + 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) => { @@ -269,13 +270,11 @@ fn validate_server_hello( common: &mut CommonState, server_hello: &ServerHelloPayload, ) -> Result<(), Error> { - for ext in &server_hello.extensions { - if !ALLOWED_PLAINTEXT_EXTS.contains(&ext.ext_type()) { - return Err(common.send_fatal_alert( - AlertDescription::UnsupportedExtension, - PeerMisbehaved::UnexpectedCleartextExtension, - )); - } + if !server_hello.only_contains(ALLOWED_PLAINTEXT_EXTS) { + return Err(common.send_fatal_alert( + AlertDescription::UnsupportedExtension, + PeerMisbehaved::UnexpectedCleartextExtension, + )); } Ok(()) @@ -427,15 +426,8 @@ pub(super) fn emit_fake_ccs(sent_tls13_fake_ccs: &mut bool, common: &mut CommonS fn validate_encrypted_extensions( common: &mut CommonState, hello: &ClientHelloDetails, - exts: &Vec, + exts: &ServerExtensions<'_>, ) -> Result<(), Error> { - if exts.has_duplicate_extension() { - return Err(common.send_fatal_alert( - AlertDescription::DecodeError, - PeerMisbehaved::DuplicateEncryptedExtensions, - )); - } - if hello.server_sent_unsolicited_extensions(exts, &[]) { return Err(common.send_fatal_alert( AlertDescription::UnsupportedExtension, @@ -443,15 +435,11 @@ fn validate_encrypted_extensions( )); } - for ext in exts { - if ALLOWED_PLAINTEXT_EXTS.contains(&ext.ext_type()) - || DISALLOWED_TLS13_EXTS.contains(&ext.ext_type()) - { - return Err(common.send_fatal_alert( - AlertDescription::UnsupportedExtension, - PeerMisbehaved::DisallowedEncryptedExtension, - )); - } + if exts.contains_any(ALLOWED_PLAINTEXT_EXTS) || exts.contains_any(DISALLOWED_TLS13_EXTS) { + return Err(common.send_fatal_alert( + AlertDescription::UnsupportedExtension, + PeerMisbehaved::DisallowedEncryptedExtension, + )); } Ok(()) @@ -486,11 +474,25 @@ impl State for ExpectEncryptedExtensions { self.transcript.add_message(&m); validate_encrypted_extensions(cx.common, &self.hello, exts)?; - hs::process_alpn_protocol(cx.common, &self.hello.alpn_protocols, exts.alpn_protocol())?; - hs::process_client_cert_type_extension(cx.common, &self.config, exts.client_cert_type())?; - hs::process_server_cert_type_extension(cx.common, &self.config, exts.server_cert_type())?; + 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.server_ech_extension()) { + 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(_)) => { @@ -502,14 +504,20 @@ impl State for ExpectEncryptedExtensions { // 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.map(|ext| ext.retry_configs.to_vec()), + (EchStatus::Rejected, ext) => ext + .as_ref() + .map(|ext| ext.retry_configs.to_vec()), _ => None, }; // QUIC transport parameters if cx.common.is_quic() { - match exts.quic_params_extension() { - Some(params) => cx.common.quic.params = Some(params), + 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 @@ -522,11 +530,12 @@ impl State for ExpectEncryptedExtensions { Some(resuming_session) => { let was_early_traffic = cx.common.early_traffic; if was_early_traffic { - if exts.early_data_extension_offered() { - cx.data.early_data.accepted(); - } else { - cx.data.early_data.rejected(); - cx.common.early_traffic = false; + match exts.early_data_ack { + Some(()) => cx.data.early_data.accepted(), + None => { + cx.data.early_data.rejected(); + cx.common.early_traffic = false; + } } } @@ -561,7 +570,7 @@ impl State for ExpectEncryptedExtensions { })) } _ => { - if exts.early_data_extension_offered() { + if exts.early_data_ack.is_some() { return Err(PeerMisbehaved::EarlyDataExtensionWithoutResumption.into()); } cx.common diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 61e598ca4a8..5912e5897f7 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -416,9 +416,9 @@ impl Codec<'_> for SingleProtocolName { } } -impl AsRef<[u8]> for SingleProtocolName { - fn as_ref(&self) -> &[u8] { - self.0.as_ref() +impl AsRef for SingleProtocolName { + fn as_ref(&self) -> &ProtocolName { + &self.0 } } @@ -1060,125 +1060,146 @@ impl<'a> Codec<'a> for ClientSessionTicket { } } -#[derive(Clone, Debug)] -pub(crate) enum ServerExtension { - EcPointFormats(Vec), - ServerNameAck, - SessionTicketAck, - RenegotiationInfo(PayloadU8), - Protocols(SingleProtocolName), - KeyShare(KeyShareEntry), - PresharedKey(u16), - ExtendedMasterSecretAck, - CertificateStatusAck, - ServerCertType(CertificateType), - ClientCertType(CertificateType), - SupportedVersions(ProtocolVersion), - TransportParameters(Vec), - TransportParametersDraft(Vec), - EarlyData, - EncryptedClientHello(ServerEncryptedClientHello), - Unknown(UnknownExtension), +#[derive(Default)] +pub(crate) struct ServerExtensionsInput<'a> { + /// QUIC transport parameters + pub(crate) transport_parameters: Option>, } -impl ServerExtension { - pub(crate) fn ext_type(&self) -> ExtensionType { - match self { - Self::EcPointFormats(_) => ExtensionType::ECPointFormats, - Self::ServerNameAck => ExtensionType::ServerName, - Self::SessionTicketAck => ExtensionType::SessionTicket, - Self::RenegotiationInfo(_) => ExtensionType::RenegotiationInfo, - Self::Protocols(_) => ExtensionType::ALProtocolNegotiation, - Self::KeyShare(_) => ExtensionType::KeyShare, - Self::PresharedKey(_) => ExtensionType::PreSharedKey, - Self::ClientCertType(_) => ExtensionType::ClientCertificateType, - Self::ServerCertType(_) => ExtensionType::ServerCertificateType, - Self::ExtendedMasterSecretAck => ExtensionType::ExtendedMasterSecret, - Self::CertificateStatusAck => ExtensionType::StatusRequest, - Self::SupportedVersions(_) => ExtensionType::SupportedVersions, - Self::TransportParameters(_) => ExtensionType::TransportParameters, - Self::TransportParametersDraft(_) => ExtensionType::TransportParametersDraft, - Self::EarlyData => ExtensionType::EarlyData, - Self::EncryptedClientHello(_) => ExtensionType::EncryptedClientHello, - Self::Unknown(r) => r.typ, +extension_struct! { + pub(crate) struct ServerExtensions<'a> { + /// Supported EC point formats (RFC4492) + ExtensionType::ECPointFormats => + pub(crate) ec_point_formats: Option>, + + /// 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, + + /// Selected ALPN protocol (RFC7301) + ExtensionType::ALProtocolNegotiation => + pub(crate) selected_protocol: Option, + + /// Key exchange server share (RFC8446) + ExtensionType::KeyShare => + pub(crate) key_share: Option, + + /// Selected preshared key index (RFC8446) + ExtensionType::PreSharedKey => + pub(crate) preshared_key: Option, + + /// Required client certificate type (RFC7250) + ExtensionType::ClientCertificateType => + pub(crate) client_certificate_type: Option, + + /// Selected server certificate type (RFC7250) + ExtensionType::ServerCertificateType => + pub(crate) server_certificate_type: Option, + + /// 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, + + /// QUIC transport parameters (RFC9001) + ExtensionType::TransportParameters => + pub(crate) transport_parameters: Option>, + + /// QUIC transport parameters (RFC9001 prior to draft 33) + ExtensionType::TransportParametersDraft => + pub(crate) transport_parameters_draft: Option>, + + /// 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, + } + { + pub(crate) unknown_extensions: BTreeSet, + } +} + +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 Codec<'_> for ServerExtension { +impl<'a> Codec<'a> for ServerExtensions<'a> { fn encode(&self, bytes: &mut Vec) { - self.ext_type().encode(bytes); + let extensions = LengthPrefixedBuffer::new(ListLength::U16, bytes); - let nested = LengthPrefixedBuffer::new(ListLength::U16, bytes); - match self { - Self::EcPointFormats(r) => r.encode(nested.buf), - Self::ServerNameAck - | Self::SessionTicketAck - | Self::ExtendedMasterSecretAck - | Self::CertificateStatusAck - | Self::EarlyData => {} - Self::RenegotiationInfo(r) => r.encode(nested.buf), - Self::Protocols(r) => r.encode(nested.buf), - Self::KeyShare(r) => r.encode(nested.buf), - Self::PresharedKey(r) => r.encode(nested.buf), - Self::ClientCertType(r) => r.encode(nested.buf), - Self::ServerCertType(r) => r.encode(nested.buf), - Self::SupportedVersions(r) => r.encode(nested.buf), - Self::TransportParameters(r) | Self::TransportParametersDraft(r) => { - nested.buf.extend_from_slice(r); - } - Self::EncryptedClientHello(r) => r.encode(nested.buf), - Self::Unknown(r) => r.encode(nested.buf), + for ext in Self::ALL_EXTENSIONS { + self.encode_one(*ext, extensions.buf); } } - fn read(r: &mut Reader<'_>) -> Result { - let typ = ExtensionType::read(r)?; - let len = u16::read(r)? as usize; - let mut sub = r.sub(len)?; + fn read(r: &mut Reader<'a>) -> Result { + let mut out = Self::default(); + let mut checker = DuplicateExtensionChecker::new(); - let ext = match typ { - ExtensionType::ECPointFormats => Self::EcPointFormats(Vec::read(&mut sub)?), - ExtensionType::ServerName => Self::ServerNameAck, - ExtensionType::SessionTicket => Self::SessionTicketAck, - ExtensionType::StatusRequest => Self::CertificateStatusAck, - ExtensionType::RenegotiationInfo => Self::RenegotiationInfo(PayloadU8::read(&mut sub)?), - ExtensionType::ALProtocolNegotiation => { - Self::Protocols(SingleProtocolName::read(&mut sub)?) - } - ExtensionType::ClientCertificateType => { - Self::ClientCertType(CertificateType::read(&mut sub)?) - } - ExtensionType::ServerCertificateType => { - Self::ServerCertType(CertificateType::read(&mut sub)?) - } - ExtensionType::KeyShare => Self::KeyShare(KeyShareEntry::read(&mut sub)?), - ExtensionType::PreSharedKey => Self::PresharedKey(u16::read(&mut sub)?), - ExtensionType::ExtendedMasterSecret => Self::ExtendedMasterSecretAck, - ExtensionType::SupportedVersions => { - Self::SupportedVersions(ProtocolVersion::read(&mut sub)?) - } - ExtensionType::TransportParameters => Self::TransportParameters(sub.rest().to_vec()), - ExtensionType::TransportParametersDraft => { - Self::TransportParametersDraft(sub.rest().to_vec()) - } - ExtensionType::EarlyData => Self::EarlyData, - ExtensionType::EncryptedClientHello => { - Self::EncryptedClientHello(ServerEncryptedClientHello::read(&mut sub)?) - } - _ => Self::Unknown(UnknownExtension::read(typ, &mut sub)), - }; + let len = usize::from(u16::read(r)?); + let mut sub = r.sub(len)?; - sub.expect_empty("ServerExtension") - .map(|_| ext) - } -} + while sub.any_left() { + out.read_one(&mut sub, |unknown| checker.check(unknown))?; + } -impl ServerExtension { - #[cfg(feature = "tls12")] - pub(crate) fn make_empty_renegotiation_info() -> Self { - let empty = Vec::new(); - Self::RenegotiationInfo(PayloadU8::new(empty)) + out.unknown_extensions = checker.0; + Ok(out) } } @@ -1470,7 +1491,7 @@ pub(crate) struct ServerHelloPayload { pub(crate) session_id: SessionId, pub(crate) cipher_suite: CipherSuite, pub(crate) compression_method: Compression, - pub(crate) extensions: Vec, + pub(crate) extensions: Box>, } impl Codec<'_> for ServerHelloPayload { @@ -1488,7 +1509,14 @@ impl Codec<'_> for ServerHelloPayload { // "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 = if r.any_left() { Vec::read(r)? } else { vec![] }; + let extensions = Box::new( + if r.any_left() { + ServerExtensions::read(r)? + } else { + ServerExtensions::default() + } + .into_owned(), + ); let ret = Self { legacy_version: ProtocolVersion::Unknown(0), @@ -1504,51 +1532,7 @@ impl Codec<'_> for ServerHelloPayload { } } -impl HasServerExtensions for ServerHelloPayload { - fn extensions(&self) -> &[ServerExtension] { - &self.extensions - } -} - impl ServerHelloPayload { - pub(crate) fn key_share(&self) -> Option<&KeyShareEntry> { - let ext = self.find_extension(ExtensionType::KeyShare)?; - match ext { - ServerExtension::KeyShare(share) => Some(share), - _ => None, - } - } - - pub(crate) fn psk_index(&self) -> Option { - let ext = self.find_extension(ExtensionType::PreSharedKey)?; - match ext { - ServerExtension::PresharedKey(index) => Some(*index), - _ => None, - } - } - - pub(crate) fn ecpoints_extension(&self) -> Option<&[ECPointFormat]> { - let ext = self.find_extension(ExtensionType::ECPointFormats)?; - match ext { - ServerExtension::EcPointFormats(fmts) => Some(fmts), - _ => None, - } - } - - #[cfg(feature = "tls12")] - pub(crate) fn ems_support_acked(&self) -> bool { - self.find_extension(ExtensionType::ExtendedMasterSecret) - .is_some() - } - - pub(crate) fn supported_versions(&self) -> Option { - let ext = self.find_extension(ExtensionType::SupportedVersions)?; - match ext { - ServerExtension::SupportedVersions(vers) => Some(*vers), - _ => None, - } - } - fn payload_encode(&self, bytes: &mut Vec, encoding: Encoding) { self.legacy_version.encode(bytes); @@ -1567,10 +1551,20 @@ impl ServerHelloPayload { self.session_id.encode(bytes); self.cipher_suite.encode(bytes); self.compression_method.encode(bytes); + self.extensions.encode(bytes); + } +} - if !self.extensions.is_empty() { - 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 } } @@ -2101,86 +2095,6 @@ impl ServerKeyExchangePayload { } } -// -- EncryptedExtensions (TLS1.3 only) -- - -impl TlsListElement for ServerExtension { - const SIZE_LEN: ListLength = ListLength::U16; -} - -pub(crate) trait HasServerExtensions { - fn extensions(&self) -> &[ServerExtension]; - - /// Returns true if there is more than one extension of a given - /// type. - fn has_duplicate_extension(&self) -> bool { - has_duplicates::<_, _, u16>( - self.extensions() - .iter() - .map(|ext| ext.ext_type()), - ) - } - - fn find_extension(&self, ext: ExtensionType) -> Option<&ServerExtension> { - self.extensions() - .iter() - .find(|x| x.ext_type() == ext) - } - - fn alpn_protocol(&self) -> Option<&ProtocolName> { - let ext = self.find_extension(ExtensionType::ALProtocolNegotiation)?; - match ext { - ServerExtension::Protocols(protos) => Some(&protos.0), - _ => None, - } - } - - fn server_cert_type(&self) -> Option<&CertificateType> { - let ext = self.find_extension(ExtensionType::ServerCertificateType)?; - match ext { - ServerExtension::ServerCertType(req) => Some(req), - _ => None, - } - } - - fn client_cert_type(&self) -> Option<&CertificateType> { - let ext = self.find_extension(ExtensionType::ClientCertificateType)?; - match ext { - ServerExtension::ClientCertType(req) => Some(req), - _ => None, - } - } - - fn quic_params_extension(&self) -> Option> { - let ext = self - .find_extension(ExtensionType::TransportParameters) - .or_else(|| self.find_extension(ExtensionType::TransportParametersDraft))?; - match ext { - ServerExtension::TransportParameters(bytes) - | ServerExtension::TransportParametersDraft(bytes) => Some(bytes.to_vec()), - _ => None, - } - } - - fn server_ech_extension(&self) -> Option { - let ext = self.find_extension(ExtensionType::EncryptedClientHello)?; - match ext { - ServerExtension::EncryptedClientHello(ech) => Some(ech.clone()), - _ => None, - } - } - - fn early_data_extension_offered(&self) -> bool { - self.find_extension(ExtensionType::EarlyData) - .is_some() - } -} - -impl HasServerExtensions for Vec { - fn extensions(&self) -> &[ServerExtension] { - self - } -} - /// RFC5246: `ClientCertificateType certificate_types<1..2^8-1>;` impl TlsListElement for ClientCertificateType { const SIZE_LEN: ListLength = ListLength::NonZeroU8 { @@ -2556,7 +2470,7 @@ pub(crate) enum HandshakePayload<'a> { ClientKeyExchange(Payload<'a>), NewSessionTicket(NewSessionTicketPayload), NewSessionTicketTls13(NewSessionTicketPayloadTls13), - EncryptedExtensions(Vec), + EncryptedExtensions(Box>), KeyUpdate(KeyUpdateRequest), Finished(Payload<'a>), CertificateStatus(CertificateStatus<'a>), @@ -2644,7 +2558,7 @@ impl HandshakePayload<'_> { ClientKeyExchange(x) => ClientKeyExchange(x.into_owned()), NewSessionTicket(x) => NewSessionTicket(x), NewSessionTicketTls13(x) => NewSessionTicketTls13(x), - EncryptedExtensions(x) => EncryptedExtensions(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()), @@ -2737,7 +2651,7 @@ impl<'a> HandshakeMessagePayload<'a> { HandshakePayload::NewSessionTicket(p) } HandshakeType::EncryptedExtensions => { - HandshakePayload::EncryptedExtensions(Vec::read(&mut sub)?) + HandshakePayload::EncryptedExtensions(Box::new(ServerExtensions::read(&mut sub)?)) } HandshakeType::KeyUpdate => { HandshakePayload::KeyUpdate(KeyUpdateRequest::read(&mut sub)?) diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index 8b41a8e0d46..ed9430f725c 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -14,13 +14,13 @@ use super::handshake::{ CertificateRequestExtensions, CertificateRequestPayload, CertificateRequestPayloadTls13, CertificateStatus, CertificateStatusRequest, ClientExtensions, ClientHelloPayload, ClientSessionTicket, CompressedCertificatePayload, DistinguishedName, EcParameters, - EncryptedClientHello, HandshakeMessagePayload, HandshakePayload, HasServerExtensions, - HelloRetryRequest, HelloRetryRequestExtensions, KeyShareEntry, NewSessionTicketExtensions, + EncryptedClientHello, HandshakeMessagePayload, HandshakePayload, HelloRetryRequest, + HelloRetryRequestExtensions, KeyShareEntry, NewSessionTicketExtensions, NewSessionTicketPayload, NewSessionTicketPayloadTls13, PresharedKeyBinder, PresharedKeyIdentity, PresharedKeyOffer, ProtocolName, Random, ServerDhParams, - ServerEcdhParams, ServerExtension, ServerHelloPayload, ServerKeyExchange, - ServerKeyExchangeParams, ServerKeyExchangePayload, ServerNamePayload, SessionId, - SingleProtocolName, SupportedProtocolVersions, UnknownExtension, + ServerEcdhParams, ServerEncryptedClientHello, ServerExtensions, ServerHelloPayload, + ServerKeyExchange, ServerKeyExchangeParams, ServerKeyExchangePayload, ServerNamePayload, + SessionId, SingleProtocolName, SupportedProtocolVersions, }; use crate::enums::{ CertificateCompressionAlgorithm, CertificateType, CipherSuite, HandshakeType, ProtocolVersion, @@ -127,9 +127,11 @@ fn refuses_client_exts_with_unparsed_bytes() { #[test] fn refuses_server_ext_with_unparsed_bytes() { - let bytes = [0x00u8, 0x0b, 0x00, 0x04, 0x02, 0xf8, 0x01, 0x02]; - let mut rd = Reader::init(&bytes); - assert!(ServerExtension::read(&mut rd).is_err()); + let bytes = [0x00u8, 0x08, 0x00, 0x0b, 0x00, 0x04, 0x02, 0xf8, 0x01, 0x02]; + assert_eq!( + ServerExtensions::read_bytes(&bytes).unwrap_err(), + InvalidMessage::TrailingData("ServerExtensions") + ); } #[test] @@ -529,87 +531,22 @@ fn test_truncated_hello_retry_extension_is_detected() { fn test_truncated_server_extension_is_detected() { let shp = sample_server_hello_payload(); - for ext in &shp.extensions { - let mut enc = ext.get_encoding(); - println!("testing {ext:?} enc {enc:?}"); - - // "outer" truncation, i.e., where the extension-level length is longer than - // the input - for l in 0..enc.len() { - assert!(ServerExtension::read_bytes(&enc[..l]).is_err()); - } + let mut enc = shp.extensions.get_encoding(); + println!("testing enc {:?}", enc); - // these extension types don't have any internal encoding that rustls validates: - match ext.ext_type() { - ExtensionType::TransportParameters | ExtensionType::Unknown(_) => { - continue; - } - _ => {} - }; - - // "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!(ServerExtension::read_bytes(&enc).is_err()); - } + // "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()); } -} - -fn test_server_extension_getter(typ: ExtensionType, getter: fn(&ServerHelloPayload) -> bool) { - let mut shp = sample_server_hello_payload(); - let ext = shp.find_extension(typ).unwrap().clone(); - - shp.extensions = vec![]; - assert!(!getter(&shp)); - - shp.extensions = vec![ext]; - assert!(getter(&shp)); - - shp.extensions = vec![ServerExtension::Unknown(UnknownExtension { - typ, - payload: Payload::Borrowed(&[]), - })]; - assert!(!getter(&shp)); -} - -#[test] -fn server_key_share() { - test_server_extension_getter(ExtensionType::KeyShare, |shp| shp.key_share().is_some()); -} -#[test] -fn server_psk_index() { - test_server_extension_getter(ExtensionType::PreSharedKey, |shp| shp.psk_index().is_some()); -} - -#[test] -fn server_ecpoints_extension() { - test_server_extension_getter(ExtensionType::ECPointFormats, |shp| { - shp.ecpoints_extension().is_some() - }); -} - -#[test] -fn server_supported_versions() { - test_server_extension_getter(ExtensionType::SupportedVersions, |shp| { - shp.supported_versions().is_some() - }); -} - -#[test] -fn server_client_certificate_type_extension() { - test_server_extension_getter(ExtensionType::ClientCertificateType, |shp| { - shp.client_cert_type().is_some() - }); -} - -#[test] -fn server_server_certificate_type_extension() { - test_server_extension_getter(ExtensionType::ServerCertificateType, |shp| { - shp.server_cert_type().is_some() - }); + // "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 {:?} len {:?}", enc, l); + assert!(ServerExtensions::read_bytes(&enc).is_err()); + } } #[test] @@ -882,25 +819,27 @@ fn sample_server_hello_payload() -> ServerHelloPayload { session_id: SessionId::empty(), cipher_suite: CipherSuite::TLS_NULL_WITH_NULL_NULL, compression_method: Compression::Null, - extensions: vec![ - ServerExtension::EcPointFormats(ECPointFormat::SUPPORTED.to_vec()), - ServerExtension::ServerNameAck, - ServerExtension::SessionTicketAck, - ServerExtension::RenegotiationInfo(PayloadU8::new(vec![0])), - ServerExtension::Protocols(SingleProtocolName::new(ProtocolName::from(vec![0]))), - ServerExtension::KeyShare(KeyShareEntry::new(NamedGroup::X25519, &[1, 2, 3][..])), - ServerExtension::PresharedKey(3), - ServerExtension::ExtendedMasterSecretAck, - ServerExtension::CertificateStatusAck, - ServerExtension::SupportedVersions(ProtocolVersion::TLSv1_2), - ServerExtension::TransportParameters(vec![1, 2, 3]), - ServerExtension::Unknown(UnknownExtension { - typ: ExtensionType::Unknown(12345), - payload: Payload::Borrowed(&[1, 2, 3]), + extensions: Box::new(ServerExtensions { + ec_point_formats: Some(ECPointFormat::SUPPORTED.to_vec()), + 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![], }), - ServerExtension::ClientCertType(CertificateType::RawPublicKey), - ServerExtension::ServerCertType(CertificateType::RawPublicKey), - ], + 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(), + }), } } @@ -1098,7 +1037,7 @@ fn sample_new_session_ticket_payload_tls13() -> NewSessionTicketPayloadTls13 { } } -fn sample_encrypted_extensions() -> Vec { +fn sample_encrypted_extensions() -> Box> { sample_server_hello_payload().extensions } diff --git a/rustls/src/msgs/macros.rs b/rustls/src/msgs/macros.rs index c6d564dc150..480950a6d67 100644 --- a/rustls/src/msgs/macros.rs +++ b/rustls/src/msgs/macros.rs @@ -268,6 +268,27 @@ macro_rules! extension_struct { 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,)* diff --git a/rustls/src/quic.rs b/rustls/src/quic.rs index e900d12bca4..f00f3bba77f 100644 --- a/rustls/src/quic.rs +++ b/rustls/src/quic.rs @@ -17,7 +17,6 @@ use crate::tls13::key_schedule::{ #[cfg(feature = "std")] mod connection { - use alloc::vec; use alloc::vec::Vec; use core::fmt::{self, Debug}; use core::ops::{Deref, DerefMut}; @@ -32,7 +31,9 @@ mod connection { use crate::error::Error; use crate::msgs::base::Payload; use crate::msgs::deframer::buffers::{DeframerVecBuffer, Locator}; - use crate::msgs::handshake::{ClientExtensionsInput, ServerExtension, TransportParameters}; + use crate::msgs::handshake::{ + ClientExtensionsInput, ServerExtensionsInput, TransportParameters, + }; use crate::msgs::message::InboundPlainMessage; use crate::server::{ServerConfig, ServerConnectionData}; use crate::sync::Arc; @@ -285,12 +286,14 @@ mod connection { )); } - let ext = match quic_version { - Version::V1Draft => ServerExtension::TransportParametersDraft(params), - Version::V1 | Version::V2 => ServerExtension::TransportParameters(params), + 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, vec![ext])?; + 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() }) diff --git a/rustls/src/server/hs.rs b/rustls/src/server/hs.rs index 4a50871e3b0..d3a360a6843 100644 --- a/rustls/src/server/hs.rs +++ b/rustls/src/server/hs.rs @@ -22,7 +22,8 @@ use crate::msgs::enums::{Compression, ExtensionType, NamedGroup}; use crate::msgs::handshake::SessionId; use crate::msgs::handshake::{ ClientHelloPayload, HandshakePayload, KeyExchangeAlgorithm, ProtocolName, Random, - ServerExtension, ServerNamePayload, SingleProtocolName, + ServerExtensions, ServerExtensionsInput, ServerNamePayload, SingleProtocolName, + TransportParameters, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; @@ -59,14 +60,31 @@ pub(super) fn can_resume( #[derive(Default)] pub(super) struct ExtensionProcessing { // extensions to reply with - pub(super) exts: Vec, + pub(super) extensions: Box>, #[cfg(feature = "tls12")] pub(super) send_ticket: bool, } impl ExtensionProcessing { - pub(super) fn new() -> Self { - Default::default() + 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( @@ -76,7 +94,6 @@ impl ExtensionProcessing { ocsp_response: &mut Option<&[u8]>, hello: &ClientHelloPayload, resumedata: Option<&persist::ServerSessionValue>, - extra_exts: Vec, ) -> Result<(), Error> { // ALPN let our_protocols = &config.alpn_protocols; @@ -90,11 +107,10 @@ impl ExtensionProcessing { }) .map(|bytes| ProtocolName::from(bytes.clone())); if let Some(selected_protocol) = &cx.common.alpn_protocol { - debug!("Chosen ALPN protocol {selected_protocol:?}"); - self.exts - .push(ServerExtension::Protocols(SingleProtocolName::new( - selected_protocol.clone(), - ))); + 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, @@ -140,8 +156,7 @@ impl ExtensionProcessing { // SNI if let (false, Some(ServerNamePayload::SingleDnsName(_))) = (for_resume, &hello.server_name) { - self.exts - .push(ServerExtension::ServerNameAck); + self.extensions.server_name_ack = Some(()); } // Send status_request response if we have one. This is not allowed @@ -154,8 +169,8 @@ impl ExtensionProcessing { { if ocsp_response.is_some() && !cx.common.is_tls13() { // Only TLS1.2 sends confirmation in ServerHello - self.exts - .push(ServerExtension::CertificateStatusAck); + self.extensions + .certificate_status_request_ack = Some(()); } } else { // Throw away any OCSP response so we don't try to send it later. @@ -165,8 +180,6 @@ impl ExtensionProcessing { self.validate_server_cert_type_extension(hello, config, cx)?; self.validate_client_cert_type_extension(hello, config, cx)?; - self.exts.extend(extra_exts); - Ok(()) } @@ -179,17 +192,15 @@ impl ExtensionProcessing { ) { // Renegotiation. // (We don't do reneg at all, but would support the secure version if we did.) - let secure_reneg_offered = hello - .extensions - .renegotiation_info - .is_some() + + 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.exts - .push(ServerExtension::make_empty_renegotiation_info()); + self.extensions.renegotiation_info = Some(PayloadU8::new(Vec::new())); } // Tickets: @@ -197,14 +208,13 @@ impl ExtensionProcessing { // we send an ack. if hello.session_ticket.is_some() && config.ticketer.enabled() { self.send_ticket = true; - self.exts - .push(ServerExtension::SessionTicketAck); + self.extensions.session_ticket_ack = Some(()); } // Confirm use of EMS if offered. if using_ems { - self.exts - .push(ServerExtension::ExtendedMasterSecretAck); + self.extensions + .extended_master_secret_ack = Some(()); } } @@ -279,12 +289,10 @@ impl ExtensionProcessing { match raw_key_negotation_result { Ok((ExtensionType::ClientCertificateType, cert_type)) => { - self.exts - .push(ServerExtension::ClientCertType(cert_type)); + self.extensions.client_certificate_type = Some(cert_type); } Ok((ExtensionType::ServerCertificateType, cert_type)) => { - self.exts - .push(ServerExtension::ServerCertType(cert_type)); + self.extensions.server_certificate_type = Some(cert_type); } Err(err) => { return Err(cx @@ -299,7 +307,7 @@ impl ExtensionProcessing { pub(super) struct ExpectClientHello { pub(super) config: Arc, - pub(super) extra_exts: Vec, + pub(super) extra_exts: ServerExtensionsInput<'static>, pub(super) transcript: HandshakeHashOrBuffer, #[cfg(feature = "tls12")] pub(super) session_id: SessionId, @@ -310,7 +318,10 @@ pub(super) struct ExpectClientHello { } impl ExpectClientHello { - pub(super) fn new(config: Arc, extra_exts: Vec) -> Self { + pub(super) fn new( + config: Arc, + extra_exts: ServerExtensionsInput<'static>, + ) -> Self { let mut transcript_buffer = HandshakeHashBuffer::new(); if config.verifier.offer_client_auth() { diff --git a/rustls/src/server/server_conn.rs b/rustls/src/server/server_conn.rs index 75adf90b6be..d1024b14319 100644 --- a/rustls/src/server/server_conn.rs +++ b/rustls/src/server/server_conn.rs @@ -25,7 +25,7 @@ use crate::error::Error; use crate::kernel::KernelConnection; use crate::log::trace; use crate::msgs::base::Payload; -use crate::msgs::handshake::{ClientHelloPayload, ProtocolName, ServerExtension}; +use crate::msgs::handshake::{ClientHelloPayload, ProtocolName, ServerExtensionsInput}; use crate::msgs::message::Message; use crate::suites::ExtractedSecrets; use crate::sync::Arc; @@ -584,13 +584,15 @@ impl ServerConfig { #[cfg(feature = "std")] mod connection { use alloc::boxed::Box; - use alloc::vec::Vec; use core::fmt; use core::fmt::{Debug, Formatter}; use core::ops::{Deref, DerefMut}; use std::io; - use super::{Accepted, Accepting, EarlyDataState, ServerConfig, ServerConnectionData}; + use super::{ + Accepted, Accepting, EarlyDataState, ServerConfig, ServerConnectionData, + ServerExtensionsInput, + }; use crate::common_state::{CommonState, Context, Side}; use crate::conn::{ConnectionCommon, ConnectionCore}; use crate::error::Error; @@ -638,7 +640,10 @@ mod connection { /// we behave in the TLS protocol. pub fn new(config: Arc) -> Result { Ok(Self { - inner: ConnectionCommon::from(ConnectionCore::for_server(config, Vec::new())?), + inner: ConnectionCommon::from(ConnectionCore::for_server( + config, + ServerExtensionsInput::default(), + )?), }) } @@ -943,7 +948,7 @@ impl UnbufferedServerConnection { Ok(Self { inner: UnbufferedConnectionCommon::from(ConnectionCore::for_server( config, - Vec::new(), + ServerExtensionsInput::default(), )?), }) } @@ -1053,7 +1058,7 @@ impl Accepted { self.connection.enable_secret_extraction = config.enable_secret_extraction; - let state = hs::ExpectClientHello::new(config, Vec::new()); + 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); @@ -1206,7 +1211,7 @@ impl Debug for EarlyDataState { impl ConnectionCore { pub(crate) fn for_server( config: Arc, - extra_exts: Vec, + extra_exts: ServerExtensionsInput<'static>, ) -> Result { let mut common = CommonState::new(Side::Server); common.set_max_fragment_size(config.max_fragment_size)?; diff --git a/rustls/src/server/tls12.rs b/rustls/src/server/tls12.rs index 7c4e4f1ce6a..5b50d7d35dc 100644 --- a/rustls/src/server/tls12.rs +++ b/rustls/src/server/tls12.rs @@ -43,8 +43,8 @@ mod client_hello { use crate::msgs::enums::{ClientCertificateType, Compression, ECPointFormat}; use crate::msgs::handshake::{ CertificateRequestPayload, CertificateStatus, ClientHelloPayload, ClientSessionTicket, - Random, ServerExtension, ServerHelloPayload, ServerKeyExchange, ServerKeyExchangeParams, - ServerKeyExchangePayload, + Random, ServerExtensionsInput, ServerHelloPayload, ServerKeyExchange, + ServerKeyExchangeParams, ServerKeyExchangePayload, }; use crate::sign; use crate::verify::DigitallySignedStruct; @@ -57,7 +57,7 @@ mod client_hello { 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: Vec, + pub(in crate::server) extra_exts: ServerExtensionsInput<'static>, } impl CompleteClientHelloHandling { @@ -344,10 +344,10 @@ mod client_hello { hello: &ClientHelloPayload, resumedata: Option<&persist::ServerSessionValue>, randoms: &ConnectionRandoms, - extra_exts: Vec, + extra_exts: ServerExtensionsInput<'static>, ) -> Result { - let mut ep = hs::ExtensionProcessing::new(); - ep.process_common(config, cx, ocsp_response, hello, resumedata, extra_exts)?; + 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 { @@ -356,7 +356,7 @@ mod client_hello { session_id, cipher_suite: suite.common.suite, compression_method: Compression::Null, - extensions: ep.exts, + extensions: ep.extensions, })); trace!("sending server hello {sh:?}"); flight.add(sh); diff --git a/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index 22130a2e57b..7782fefb462 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -48,7 +48,7 @@ mod client_hello { use crate::msgs::handshake::{ CertificatePayloadTls13, CertificateRequestExtensions, CertificateRequestPayloadTls13, ClientHelloPayload, HelloRetryRequest, HelloRetryRequestExtensions, KeyShareEntry, Random, - ServerExtension, ServerHelloPayload, SessionId, + ServerExtensions, ServerExtensionsInput, ServerHelloPayload, SessionId, }; use crate::server::common::ActiveCertifiedKey; use crate::sign; @@ -71,7 +71,7 @@ mod client_hello { 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: Vec, + pub(in crate::server) extra_exts: ServerExtensionsInput<'static>, } fn max_early_data_size(configured: u32) -> usize { @@ -495,8 +495,6 @@ mod client_hello { resuming_psk: Option<&[u8]>, config: &ServerConfig, ) -> Result { - let mut extensions = Vec::new(); - // Prepare key exchange; the caller already found the matching SupportedKxGroup let (share, kxgroup) = share_and_kxgroup; debug_assert_eq!(kxgroup.name(), share.group); @@ -508,15 +506,12 @@ mod client_hello { })?; cx.common.kx_state.complete(); - extensions.push(ServerExtension::KeyShare(KeyShareEntry::new( - ckx.group, - ckx.pub_key, - ))); - extensions.push(ServerExtension::SupportedVersions(ProtocolVersion::TLSv1_3)); - - if let Some(psk_idx) = chosen_psk_idx { - extensions.push(ServerExtension::PresharedKey(psk_idx as u16)); - } + 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, @@ -677,18 +672,18 @@ mod client_hello { ocsp_response: &mut Option<&[u8]>, hello: &ClientHelloPayload, resumedata: Option<&persist::ServerSessionValue>, - extra_exts: Vec, + extra_exts: ServerExtensionsInput<'static>, config: &ServerConfig, ) -> Result { - let mut ep = hs::ExtensionProcessing::new(); - ep.process_common(config, cx, ocsp_response, hello, resumedata, extra_exts)?; + 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.exts.push(ServerExtension::EarlyData); + ep.extensions.early_data_ack = Some(()); } - let ee = HandshakeMessagePayload(HandshakePayload::EncryptedExtensions(ep.exts)); + let ee = HandshakeMessagePayload(HandshakePayload::EncryptedExtensions(ep.extensions)); trace!("sending encrypted extensions {ee:?}"); flight.add(ee); From 5d5d26e0edab723a500a1186a342d56bb269dcef Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 17 Jun 2025 13:51:35 +0100 Subject: [PATCH 293/403] Introduce iterator-based TlsList decoding --- rustls/src/msgs/codec.rs | 38 ++++++++++++++++++++++++++++++++---- rustls/src/msgs/handshake.rs | 11 +++++------ 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/rustls/src/msgs/codec.rs b/rustls/src/msgs/codec.rs index 567fb520e4f..bd62cd3a6de 100644 --- a/rustls/src/msgs/codec.rs +++ b/rustls/src/msgs/codec.rs @@ -1,5 +1,6 @@ use alloc::vec::Vec; use core::fmt::Debug; +use core::marker::PhantomData; use crate::error::InvalidMessage; @@ -225,17 +226,46 @@ impl<'a, T: Codec<'a> + TlsListElement + Debug> Codec<'a> for Vec { } fn read(r: &mut Reader<'a>) -> Result { - let len = T::SIZE_LEN.read(r)?; - let mut sub = r.sub(len)?; let mut ret = Self::new(); - while sub.any_left() { - ret.push(T::read(&mut sub)?); + for item in TlsListIter::::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, +} + +impl<'a, T: Codec<'a> + TlsListElement + Debug> TlsListIter<'a, T> { + pub(crate) fn new(r: &mut Reader<'a>) -> Result { + 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; + + fn next(&mut self) -> Option { + match self.sub.any_left() { + true => Some(T::read(&mut self.sub)), + false => None, + } + } +} + impl Codec<'_> for () { fn encode(&self, _: &mut Vec) {} diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 5912e5897f7..ee6e871a87d 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -21,7 +21,9 @@ use crate::error::InvalidMessage; 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}; +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, @@ -661,14 +663,11 @@ impl Codec<'_> for SupportedProtocolVersions { } fn read(reader: &mut Reader<'_>) -> Result { - let len = Self::LIST_LENGTH.read(reader)?; - let mut sub = reader.sub(len)?; - let mut tls12 = false; let mut tls13 = false; - while sub.any_left() { - match ProtocolVersion::read(&mut sub)? { + for pv in TlsListIter::::new(reader)? { + match pv? { ProtocolVersion::TLSv1_3 => tls13 = true, ProtocolVersion::TLSv1_2 => tls12 = true, _ => continue, From 7ab492e70d1f87eb68171ae82bfad295c268bc85 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 20 Jun 2025 12:44:16 +0100 Subject: [PATCH 294/403] Remove duplicate EC point format check This happens above, and yields the `PeerIncompatible::UncompressedEcPointsRequired` error. This second one is unreachable. --- rustls/src/server/tls12.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/rustls/src/server/tls12.rs b/rustls/src/server/tls12.rs index 5b50d7d35dc..f7bb1c69984 100644 --- a/rustls/src/server/tls12.rs +++ b/rustls/src/server/tls12.rs @@ -173,19 +173,6 @@ mod client_hello { )); } - let ecpoint = ECPointFormat::SUPPORTED - .iter() - .find(|format| ecpoints_ext.contains(format)) - .cloned() - .ok_or_else(|| { - cx.common.send_fatal_alert( - AlertDescription::HandshakeFailure, - PeerIncompatible::NoEcPointFormatsInCommon, - ) - })?; - - debug_assert_eq!(ecpoint, ECPointFormat::Uncompressed); - let mut ocsp_response = server_key.get_ocsp(); // If we're not offered a ticket or a potential session ID, allocate a session ID. From 311ddea7323648c5056609cd148fcea07e92dfee Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 17 Jun 2025 13:54:02 +0100 Subject: [PATCH 295/403] Improve representation of EC point formats extension --- rustls/src/client/hs.rs | 8 +++---- rustls/src/msgs/enums.rs | 4 ---- rustls/src/msgs/handshake.rs | 37 +++++++++++++++++++++++++++++-- rustls/src/msgs/handshake_test.rs | 10 ++++----- rustls/src/server/tls12.rs | 11 +++++---- 5 files changed, 49 insertions(+), 21 deletions(-) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 6d2097f4263..e1856e28f67 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -27,12 +27,12 @@ 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, ECPointFormat, ExtensionType, PskKeyExchangeMode}; +use crate::msgs::enums::{Compression, ExtensionType, PskKeyExchangeMode}; use crate::msgs::handshake::{ CertificateStatusRequest, ClientExtensions, ClientExtensionsInput, ClientHelloPayload, ClientSessionTicket, EncryptedClientHello, HandshakeMessagePayload, HandshakePayload, HelloRetryRequest, KeyShareEntry, ProtocolName, Random, ServerNamePayload, SessionId, - SupportedProtocolVersions, TransportParameters, + SupportedEcPointFormats, SupportedProtocolVersions, TransportParameters, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; @@ -309,7 +309,7 @@ fn emit_client_hello_for_retry( .iter() .any(|skxg| skxg.name().key_exchange_algorithm() == KeyExchangeAlgorithm::ECDHE) { - exts.ec_point_formats = Some(ECPointFormat::SUPPORTED.to_vec()); + exts.ec_point_formats = Some(SupportedEcPointFormats::default()); } exts.server_name = match (ech_state.as_ref(), config.enable_sni) { @@ -806,7 +806,7 @@ impl State for ExpectServerHello { // 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.contains(&ECPointFormat::Uncompressed) { + if !point_fmts.uncompressed { return Err(cx.common.send_fatal_alert( AlertDescription::HandshakeFailure, PeerMisbehaved::ServerHelloMustOfferUncompressedEcPoints, diff --git a/rustls/src/msgs/enums.rs b/rustls/src/msgs/enums.rs index 0be5c7f6abb..75b16326c40 100644 --- a/rustls/src/msgs/enums.rs +++ b/rustls/src/msgs/enums.rs @@ -253,10 +253,6 @@ enum_builder! { } } -impl ECPointFormat { - pub(crate) const SUPPORTED: [Self; 1] = [Self::Uncompressed]; -} - enum_builder! { /// The `HeartbeatMode` TLS protocol enum. Values in this enum are taken /// from the various RFCs covering TLS, and are listed by IANA. diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index ee6e871a87d..4334fee529b 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -209,6 +209,39 @@ impl UnknownExtension { } } +#[derive(Clone, Copy, Debug)] +pub(crate) struct SupportedEcPointFormats { + pub(crate) uncompressed: bool, +} + +impl Codec<'_> for SupportedEcPointFormats { + fn encode(&self, bytes: &mut Vec) { + let inner = LengthPrefixedBuffer::new(ECPointFormat::SIZE_LEN, bytes); + + if self.uncompressed { + ECPointFormat::Uncompressed.encode(inner.buf); + } + } + + fn read(r: &mut Reader<'_>) -> Result { + let mut uncompressed = false; + + for pf in TlsListIter::::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 { @@ -784,7 +817,7 @@ extension_struct! { /// Supported EC point formats (RFC4492) ExtensionType::ECPointFormats => - pub(crate) ec_point_formats: Option>, + pub(crate) ec_point_formats: Option, /// Supported signature schemes (RFC5246/RFC8446) ExtensionType::SignatureAlgorithms => @@ -1069,7 +1102,7 @@ extension_struct! { pub(crate) struct ServerExtensions<'a> { /// Supported EC point formats (RFC4492) ExtensionType::ECPointFormats => - pub(crate) ec_point_formats: Option>, + pub(crate) ec_point_formats: Option, /// Server name indication acknowledgement (RFC6066) ExtensionType::ServerName => diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index ed9430f725c..8c70b062ebd 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -6,8 +6,8 @@ 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, ECPointFormat, ExtensionType, - KeyUpdateRequest, NamedGroup, PskKeyExchangeMode, + ClientCertificateType, Compression, ECCurveType, ExtensionType, KeyUpdateRequest, NamedGroup, + PskKeyExchangeMode, }; use super::handshake::{ CertificateChain, CertificateEntry, CertificateExtensions, CertificatePayloadTls13, @@ -20,7 +20,7 @@ use super::handshake::{ PresharedKeyIdentity, PresharedKeyOffer, ProtocolName, Random, ServerDhParams, ServerEcdhParams, ServerEncryptedClientHello, ServerExtensions, ServerHelloPayload, ServerKeyExchange, ServerKeyExchangeParams, ServerKeyExchangePayload, ServerNamePayload, - SessionId, SingleProtocolName, SupportedProtocolVersions, + SessionId, SingleProtocolName, SupportedEcPointFormats, SupportedProtocolVersions, }; use crate::enums::{ CertificateCompressionAlgorithm, CertificateType, CipherSuite, HandshakeType, ProtocolVersion, @@ -779,7 +779,7 @@ fn sample_client_hello_payload() -> ClientHelloPayload { 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(ECPointFormat::SUPPORTED.to_vec()), + ec_point_formats: Some(SupportedEcPointFormats::default()), named_groups: Some(vec![NamedGroup::X25519]), protocols: Some(vec![ProtocolName::from(vec![0])]), supported_versions: Some(SupportedProtocolVersions { @@ -820,7 +820,7 @@ fn sample_server_hello_payload() -> ServerHelloPayload { cipher_suite: CipherSuite::TLS_NULL_WITH_NULL_NULL, compression_method: Compression::Null, extensions: Box::new(ServerExtensions { - ec_point_formats: Some(ECPointFormat::SUPPORTED.to_vec()), + ec_point_formats: Some(SupportedEcPointFormats::default()), server_name_ack: Some(()), session_ticket_ack: Some(()), renegotiation_info: Some(PayloadU8::new(vec![0])), diff --git a/rustls/src/server/tls12.rs b/rustls/src/server/tls12.rs index f7bb1c69984..d3dfa5c83dd 100644 --- a/rustls/src/server/tls12.rs +++ b/rustls/src/server/tls12.rs @@ -40,7 +40,7 @@ mod client_hello { use crate::common_state::KxState; use crate::crypto::SupportedKxGroup; use crate::enums::SignatureScheme; - use crate::msgs::enums::{ClientCertificateType, Compression, ECPointFormat}; + use crate::msgs::enums::{ClientCertificateType, Compression}; use crate::msgs::handshake::{ CertificateRequestPayload, CertificateStatus, ClientHelloPayload, ClientSessionTicket, Random, ServerExtensionsInput, ServerHelloPayload, ServerKeyExchange, @@ -90,14 +90,13 @@ mod client_hello { // it means that only the uncompressed point format is // supported" // - - let ecpoints_ext = client_hello + let supported_ec_point_formats = client_hello .ec_point_formats - .as_deref() - .unwrap_or(&[ECPointFormat::Uncompressed]); + .unwrap_or_default(); - trace!("ecpoints {ecpoints_ext:?}"); + trace!("ecpoints {supported_ec_point_formats:?}"); - if !ecpoints_ext.contains(&ECPointFormat::Uncompressed) { + if !supported_ec_point_formats.uncompressed { return Err(cx.common.send_fatal_alert( AlertDescription::IllegalParameter, PeerIncompatible::UncompressedEcPointsRequired, From 4f362ca6b306054dc3a99a3750ea3bfbbbd87b7c Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 17 Jun 2025 14:04:38 +0100 Subject: [PATCH 296/403] Improve representation of PSK_KE extension --- rustls/src/client/hs.rs | 12 ++++++----- rustls/src/msgs/handshake.rs | 35 ++++++++++++++++++++++++++++++- rustls/src/msgs/handshake_test.rs | 15 +++++++------ rustls/src/server/tls13.rs | 6 +++--- 4 files changed, 53 insertions(+), 15 deletions(-) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index e1856e28f67..9c4e392037a 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -27,12 +27,12 @@ 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, PskKeyExchangeMode}; +use crate::msgs::enums::{Compression, ExtensionType}; use crate::msgs::handshake::{ CertificateStatusRequest, ClientExtensions, ClientExtensionsInput, ClientHelloPayload, ClientSessionTicket, EncryptedClientHello, HandshakeMessagePayload, HandshakePayload, - HelloRetryRequest, KeyShareEntry, ProtocolName, Random, ServerNamePayload, SessionId, - SupportedEcPointFormats, SupportedProtocolVersions, TransportParameters, + HelloRetryRequest, KeyShareEntry, ProtocolName, PskKeyExchangeModes, Random, ServerNamePayload, + SessionId, SupportedEcPointFormats, SupportedProtocolVersions, TransportParameters, }; use crate::msgs::message::{Message, MessagePayload}; use crate::msgs::persist; @@ -365,8 +365,10 @@ fn emit_client_hello_for_retry( 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. - let psk_modes = vec![PskKeyExchangeMode::PSK_DHE_KE]; - exts.preshared_key_modes = Some(psk_modes); + exts.preshared_key_modes = Some(PskKeyExchangeModes { + psk: false, + psk_dhe: true, + }); } input.hello.offered_cert_compression = diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index 4334fee529b..fd28ba1e4a6 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -643,6 +643,39 @@ impl CertificateStatusRequest { // --- /// 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) { + 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 { + let mut psk_dhe = false; + let mut psk = false; + + for ke in TlsListIter::::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"), @@ -865,7 +898,7 @@ extension_struct! { /// Offered preshared key modes (RFC8446) ExtensionType::PSKKeyExchangeModes => - pub(crate) preshared_key_modes: Option>, + pub(crate) preshared_key_modes: Option, /// Certificate authority names (RFC8446) ExtensionType::CertificateAuthorities => diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index 8c70b062ebd..e29aefca331 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -7,7 +7,6 @@ use super::base::{Payload, PayloadU8, PayloadU16, PayloadU24}; use super::codec::{Codec, Reader, put_u16}; use super::enums::{ ClientCertificateType, Compression, ECCurveType, ExtensionType, KeyUpdateRequest, NamedGroup, - PskKeyExchangeMode, }; use super::handshake::{ CertificateChain, CertificateEntry, CertificateExtensions, CertificatePayloadTls13, @@ -17,10 +16,11 @@ use super::handshake::{ EncryptedClientHello, HandshakeMessagePayload, HandshakePayload, HelloRetryRequest, HelloRetryRequestExtensions, KeyShareEntry, NewSessionTicketExtensions, NewSessionTicketPayload, NewSessionTicketPayloadTls13, PresharedKeyBinder, - PresharedKeyIdentity, PresharedKeyOffer, ProtocolName, Random, ServerDhParams, - ServerEcdhParams, ServerEncryptedClientHello, ServerExtensions, ServerHelloPayload, - ServerKeyExchange, ServerKeyExchangeParams, ServerKeyExchangePayload, ServerNamePayload, - SessionId, SingleProtocolName, SupportedEcPointFormats, SupportedProtocolVersions, + 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, @@ -787,7 +787,10 @@ fn sample_client_hello_payload() -> ClientHelloPayload { ..Default::default() }), key_shares: Some(vec![KeyShareEntry::new(NamedGroup::X25519, &[1, 2, 3][..])]), - preshared_key_modes: Some(vec![PskKeyExchangeMode::PSK_DHE_KE]), + preshared_key_modes: Some(PskKeyExchangeModes { + psk_dhe: true, + psk: false, + }), preshared_key_offer: Some(PresharedKeyOffer { identities: vec![ PresharedKeyIdentity::new(vec![3, 4, 5], 123456), diff --git a/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index 7782fefb462..bc5d53870a7 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -44,7 +44,7 @@ mod client_hello { use crate::enums::SignatureScheme; use crate::msgs::base::{Payload, PayloadU8}; use crate::msgs::ccs::ChangeCipherSpecPayload; - use crate::msgs::enums::{Compression, NamedGroup, PskKeyExchangeMode}; + use crate::msgs::enums::{Compression, NamedGroup}; use crate::msgs::handshake::{ CertificatePayloadTls13, CertificateRequestExtensions, CertificateRequestPayloadTls13, ClientHelloPayload, HelloRetryRequest, HelloRetryRequestExtensions, KeyShareEntry, Random, @@ -319,10 +319,10 @@ mod client_hello { if !client_hello .preshared_key_modes .as_ref() - .map(|offer| offer.contains(&PskKeyExchangeMode::PSK_DHE_KE)) + .map(|offer| offer.psk_dhe) .unwrap_or_default() { - debug!("Client unwilling to resume, DHE_KE not offered"); + debug!("Client unwilling to resume, PSK_DHE_KE not offered"); self.send_tickets = 0; chosen_psk_index = None; resumedata = None; From 0af24bdba9725bcd26f6440c8abbf666b5f91e59 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Mon, 23 Jun 2025 14:43:59 +0200 Subject: [PATCH 297/403] client: abstract if key share is needed --- rustls/src/client/client_conn.rs | 4 ++++ rustls/src/client/hs.rs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index caf0529ab34..3d9e3c38c02 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -397,6 +397,10 @@ impl ClientConfig { 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. diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 9c4e392037a..cb47ee4d536 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -114,7 +114,7 @@ pub(super) fn start_handshake( let mut resuming = find_session(&server_name, &config, cx); - let key_share = if config.supports_version(ProtocolVersion::TLSv1_3) { + let key_share = if config.needs_key_share() { Some(tls13::initial_key_share( &config, &server_name, From 7766efdfe49a54c3821cd4f2a342a0105bb2be09 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Mon, 23 Jun 2025 14:54:58 +0200 Subject: [PATCH 298/403] client: generalize early traffic secret derivation --- rustls/src/client/hs.rs | 2 +- rustls/src/client/tls13.rs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index cb47ee4d536..253760b3730 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -550,7 +550,7 @@ fn emit_client_hello_for_retry( tls13::derive_early_traffic_secret( &*config.key_log, cx, - resuming_suite, + resuming_suite.common.hash_provider, &schedule, &mut input.sent_tls13_fake_ccs, transcript_buffer, diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index 4d7155e59bf..31c1c0e4621 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -16,6 +16,7 @@ use crate::common_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, @@ -385,7 +386,7 @@ pub(super) fn prepare_resumption( pub(super) fn derive_early_traffic_secret( key_log: &dyn KeyLog, cx: &mut ClientContext<'_>, - resuming_suite: &'static Tls13CipherSuite, + hash_alg: &'static dyn Hash, early_key_schedule: &KeyScheduleEarly, sent_tls13_fake_ccs: &mut bool, transcript_buffer: &HandshakeHashBuffer, @@ -394,7 +395,7 @@ pub(super) fn derive_early_traffic_secret( // For middlebox compatibility emit_fake_ccs(sent_tls13_fake_ccs, cx.common); - let client_hello_hash = transcript_buffer.hash_given(resuming_suite.common.hash_provider, &[]); + let client_hello_hash = transcript_buffer.hash_given(hash_alg, &[]); early_key_schedule.client_early_traffic_secret( &client_hello_hash, key_log, From 6cc7a45fae74717a1c9bb4733ecdf0f6a8b75cc2 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Mon, 23 Jun 2025 15:54:41 +0200 Subject: [PATCH 299/403] client: pass all of ClientHelloInput into handle_server_hello() --- rustls/src/client/hs.rs | 38 ++++++++++++-------------------------- rustls/src/client/tls13.rs | 29 +++++++++++++++++++++-------- 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 253760b3730..9497ee50086 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -221,17 +221,17 @@ struct ExpectServerHelloOrHelloRetryRequest { extra_exts: ClientExtensionsInput<'static>, } -struct ClientHelloInput { - config: Arc, - resuming: Option>, - random: Random, +pub(super) struct ClientHelloInput { + pub(super) config: Arc, + pub(super) resuming: Option>, + pub(super) random: Random, #[cfg(feature = "tls12")] - using_ems: bool, - sent_tls13_fake_ccs: bool, - hello: ClientHelloDetails, - session_id: SessionId, - server_name: ServerName<'static>, - prev_ech_ext: Option, + pub(super) using_ems: bool, + 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, } /// Emits the initial ClientHello or a ClientHello in response to @@ -861,32 +861,18 @@ impl State for ExpectServerHello { // handshake_traffic_secret. match suite { SupportedCipherSuite::Tls13(suite) => { - #[allow(clippy::bind_instead_of_map)] - let resuming_session = self - .input - .resuming - .and_then(|resuming| match resuming.value { - ClientSessionValue::Tls13(inner) => Some(inner), - #[cfg(feature = "tls12")] - ClientSessionValue::Tls12(_) => None, - }); - tls13::handle_server_hello( - self.input.config, cx, server_hello, - resuming_session, - self.input.server_name, randoms, suite, transcript, self.early_data_key_schedule, - self.input.hello, // We always send a key share when TLS 1.3 is enabled. self.offered_key_share.unwrap(), - self.input.sent_tls13_fake_ccs, &m, self.ech_state, + self.input, ) } #[cfg(feature = "tls12")] @@ -1178,7 +1164,7 @@ fn process_cert_type_extension( } } -enum ClientSessionValue { +pub(super) enum ClientSessionValue { Tls13(persist::Tls13ClientSessionValue), #[cfg(feature = "tls12")] Tls12(persist::Tls12ClientSessionValue), diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index 31c1c0e4621..d73c5a88117 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -6,7 +6,7 @@ use pki_types::ServerName; use subtle::ConstantTimeEq; use super::client_conn::ClientConnectionData; -use super::hs::ClientContext; +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}; @@ -35,7 +35,7 @@ use crate::msgs::handshake::{ ServerHelloPayload, }; use crate::msgs::message::{Message, MessagePayload}; -use crate::msgs::persist; +use crate::msgs::persist::{self, Retrieved}; use crate::sign::{CertifiedKey, Signer}; use crate::suites::PartiallyExtractedSecrets; use crate::sync::Arc; @@ -68,20 +68,16 @@ static DISALLOWED_TLS13_EXTS: &[ExtensionType] = &[ /// `early_data_key_schedule` is `Some` if we sent the /// "early_data" extension to the server. pub(super) fn handle_server_hello( - config: Arc, cx: &mut ClientContext<'_>, server_hello: &ServerHelloPayload, - mut resuming_session: Option, - server_name: ServerName<'static>, mut randoms: ConnectionRandoms, suite: &'static Tls13CipherSuite, mut transcript: HandshakeHash, early_data_key_schedule: Option, - mut hello: ClientHelloDetails, our_key_share: Box, - mut sent_tls13_fake_ccs: bool, server_hello_msg: &Message<'_>, ech_state: Option, + input: ClientHelloInput, ) -> hs::NextStateOrError<'static> { validate_server_hello(cx.common, server_hello)?; @@ -95,6 +91,23 @@ pub(super) fn handle_server_hello( ) })?; + 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( @@ -348,7 +361,7 @@ pub(super) fn fill_in_psk_binder( pub(super) fn prepare_resumption( config: &ClientConfig, cx: &mut ClientContext<'_>, - resuming_session: &persist::Retrieved<&persist::Tls13ClientSessionValue>, + resuming_session: &Retrieved<&persist::Tls13ClientSessionValue>, exts: &mut ClientExtensions<'_>, doing_retry: bool, ) { From 4b3c0539a31cfd3d1985c813374f021bc4148603 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 24 Jun 2025 13:58:38 +0200 Subject: [PATCH 300/403] client: pass all of ClientHelloInput into tls12 handle_server_hello() --- rustls/src/client/hs.rs | 44 +++----------------------- rustls/src/client/tls12.rs | 65 +++++++++++++++++++++++++++----------- 2 files changed, 52 insertions(+), 57 deletions(-) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 9497ee50086..db198723e6f 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -187,8 +187,6 @@ pub(super) fn start_handshake( config, resuming, random, - #[cfg(feature = "tls12")] - using_ems: false, sent_tls13_fake_ccs: false, hello: ClientHelloDetails::new(alpn_protocols, extension_order_seed), session_id, @@ -225,8 +223,6 @@ pub(super) struct ClientHelloInput { pub(super) config: Arc, pub(super) resuming: Option>, pub(super) random: Random, - #[cfg(feature = "tls12")] - pub(super) using_ems: bool, pub(super) sent_tls13_fake_ccs: bool, pub(super) hello: ClientHelloDetails, pub(super) session_id: SessionId, @@ -876,42 +872,12 @@ impl State for ExpectServerHello { ) } #[cfg(feature = "tls12")] - SupportedCipherSuite::Tls12(suite) => { - // 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 resuming_session = self - .input - .resuming - .and_then(|resuming| match resuming.value { - ClientSessionValue::Tls12(inner) => Some(inner), - ClientSessionValue::Tls13(_) => None, - }); - - tls12::CompleteServerHelloHandling { - config: self.input.config, - resuming_session, - server_name: self.input.server_name, - randoms, - using_ems: self.input.using_ems, - transcript, - } - .handle_server_hello(cx, suite, server_hello, tls13_supported) + SupportedCipherSuite::Tls12(suite) => tls12::CompleteServerHelloHandling { + randoms, + transcript, + input: self.input, } + .handle_server_hello(cx, suite, server_hello, tls13_supported), } } diff --git a/rustls/src/client/tls12.rs b/rustls/src/client/tls12.rs index cb903c9b043..0fc5acee04e 100644 --- a/rustls/src/client/tls12.rs +++ b/rustls/src/client/tls12.rs @@ -38,15 +38,13 @@ 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) config: Arc, - pub(in crate::client) resuming_session: Option, - pub(in crate::client) server_name: ServerName<'static>, pub(in crate::client) randoms: ConnectionRandoms, - pub(in crate::client) using_ems: bool, pub(in crate::client) transcript: HandshakeHash, + pub(in crate::client) input: ClientHelloInput, } impl CompleteServerHelloHandling { @@ -74,11 +72,42 @@ mod server_hello { }); } + // 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? - self.using_ems = server_hello + let using_ems = server_hello .extended_master_secret_ack .is_some(); - if self.config.require_ems && !self.using_ems { + if config.require_ems && !using_ems { return Err({ cx.common.send_fatal_alert( AlertDescription::HandshakeFailure, @@ -108,7 +137,7 @@ mod server_hello { } // See if we're successfully resuming. - if let Some(resuming) = self.resuming_session { + if let Some(resuming) = resuming_session { if resuming.session_id == server_hello.session_id { debug!("Server agreed to resume"); @@ -118,13 +147,13 @@ mod server_hello { } // And about EMS support? - if resuming.extended_ms() != self.using_ems { + if resuming.extended_ms() != using_ems { return Err(PeerMisbehaved::ResumptionOfferedWithVariedEms.into()); } let secrets = ConnectionSecrets::new_resume(self.randoms, suite, resuming.secret()); - self.config.key_log.log( + config.key_log.log( "CLIENT_RANDOM", &secrets.randoms.client, &secrets.master_secret, @@ -146,12 +175,12 @@ mod server_hello { return if must_issue_new_ticket { Ok(Box::new(ExpectNewTicket { - config: self.config, + config, secrets, resuming_session: Some(resuming), session_id: server_hello.session_id, - server_name: self.server_name, - using_ems: self.using_ems, + server_name, + using_ems, transcript: self.transcript, resuming: true, cert_verified, @@ -159,12 +188,12 @@ mod server_hello { })) } else { Ok(Box::new(ExpectCcs { - config: self.config, + config, secrets, resuming_session: Some(resuming), session_id: server_hello.session_id, - server_name: self.server_name, - using_ems: self.using_ems, + server_name, + using_ems, transcript: self.transcript, ticket: None, resuming: true, @@ -177,12 +206,12 @@ mod server_hello { cx.common.handshake_kind = Some(HandshakeKind::Full); Ok(Box::new(ExpectCertificate { - config: self.config, + config, resuming_session: None, session_id: server_hello.session_id, - server_name: self.server_name, + server_name, randoms: self.randoms, - using_ems: self.using_ems, + using_ems, transcript: self.transcript, suite, may_send_cert_status, From fd92882184e2abc3118f5bc70466a8fe0a43e7d8 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Wed, 25 Jun 2025 11:11:40 +0200 Subject: [PATCH 301/403] client: move find_session() to ClientSessionValue::retrieve() --- rustls/src/client/hs.rs | 111 ++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 56 deletions(-) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index db198723e6f..dbc9ed20bbb 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -44,60 +44,6 @@ pub(super) type NextState<'a> = Box + 'a>; pub(super) type NextStateOrError<'a> = Result, Error>; pub(super) type ClientContext<'a> = crate::common_state::Context<'a, ClientConnectionData>; -fn find_session( - server_name: &ServerName<'static>, - config: &ClientConfig, - cx: &mut ClientContext<'_>, -) -> Option> { - 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 -} - pub(super) fn start_handshake( server_name: ServerName<'static>, extra_exts: ClientExtensionsInput<'_>, @@ -112,8 +58,6 @@ pub(super) fn start_handshake( transcript_buffer.set_client_auth_enabled(); } - let mut resuming = find_session(&server_name, &config, cx); - let key_share = if config.needs_key_share() { Some(tls13::initial_key_share( &config, @@ -124,6 +68,7 @@ pub(super) fn start_handshake( None }; + let mut resuming = ClientSessionValue::retrieve(&server_name, &config, cx); let session_id = match &mut resuming { Some(_resuming) => { debug!("Resuming session"); @@ -1137,6 +1082,60 @@ pub(super) enum ClientSessionValue { } impl ClientSessionValue { + fn retrieve( + server_name: &ServerName<'static>, + config: &ClientConfig, + cx: &mut ClientContext<'_>, + ) -> Option> { + 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, From 052493b833a028cd9d619c4105cd861f8d2c0683 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Wed, 25 Jun 2025 11:28:31 +0200 Subject: [PATCH 302/403] client: ClientHelloInput initialization out of start_handshake() --- rustls/src/client/client_conn.rs | 5 +- rustls/src/client/ech.rs | 20 ++++- rustls/src/client/hs.rs | 137 ++++++++++++++++--------------- 3 files changed, 92 insertions(+), 70 deletions(-) diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index 3d9e3c38c02..5ba26608704 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -6,7 +6,7 @@ use core::{fmt, mem}; use pki_types::{ServerName, UnixTime}; use super::handy::NoClientSessionStorage; -use super::hs; +use super::hs::{self, ClientHelloInput}; #[cfg(feature = "std")] use crate::WantsVerifier; use crate::builder::ConfigBuilder; @@ -861,7 +861,8 @@ impl ConnectionCore { sendable_plaintext: None, }; - let state = hs::start_handshake(name, extra_exts, config, &mut cx)?; + let input = ClientHelloInput::new(name, &extra_exts, &mut cx, config)?; + let state = hs::start_handshake(input, extra_exts, &mut cx)?; Ok(Self::new(state, data, common_state)) } diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index 132b3d11636..c396076640e 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -28,8 +28,8 @@ use crate::tls13::key_schedule::{ KeyScheduleEarly, KeyScheduleHandshakeStart, server_ech_hrr_confirmation_secret, }; use crate::{ - AlertDescription, CommonState, EncryptedClientHelloError, Error, PeerIncompatible, - PeerMisbehaved, ProtocolVersion, Tls13CipherSuite, + AlertDescription, ClientConfig, CommonState, EncryptedClientHelloError, Error, + PeerIncompatible, PeerMisbehaved, ProtocolVersion, Tls13CipherSuite, }; /// Controls how Encrypted Client Hello (ECH) is used in a client handshake. @@ -157,6 +157,22 @@ impl EchConfig { Err(EncryptedClientHelloError::NoCompatibleConfig.into()) } + pub(super) fn state( + &self, + server_name: ServerName<'static>, + config: &ClientConfig, + ) -> Result { + 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 . diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index dbc9ed20bbb..0fafdf2c65c 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -45,99 +45,43 @@ pub(super) type NextStateOrError<'a> = Result, Error>; pub(super) type ClientContext<'a> = crate::common_state::Context<'a, ClientConnectionData>; pub(super) fn start_handshake( - server_name: ServerName<'static>, + input: ClientHelloInput, extra_exts: ClientExtensionsInput<'_>, - config: Arc, cx: &mut ClientContext<'_>, ) -> NextStateOrError<'static> { let mut transcript_buffer = HandshakeHashBuffer::new(); - if config + if input + .config .client_auth_cert_resolver .has_certs() { transcript_buffer.set_client_auth_enabled(); } - let key_share = if config.needs_key_share() { + let key_share = if input.config.needs_key_share() { Some(tls13::initial_key_share( - &config, - &server_name, + &input.config, + &input.server_name, &mut cx.common.kx_state, )?) } else { None }; - 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, - } + let ech_state = match input.config.ech_mode.as_ref() { + Some(EchMode::Enable(ech_config)) => { + Some(ech_config.state(input.server_name.clone(), &input.config)?) } - _ => { - 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 random = Random::new(config.provider.secure_random)?; - let extension_order_seed = crate::rand::random_u16(config.provider.secure_random)?; - - let ech_state = match config.ech_mode.as_ref() { - Some(EchMode::Enable(ech_config)) => Some(EchState::new( - ech_config, - server_name.clone(), - config - .client_auth_cert_resolver - .has_certs(), - config.provider.secure_random, - config.enable_sni, - )?), _ => None, }; - let alpn_protocols = extra_exts - .protocols - .clone() - .unwrap_or_default(); - emit_client_hello_for_retry( transcript_buffer, None, key_share, extra_exts, None, - ClientHelloInput { - config, - resuming, - random, - sent_tls13_fake_ccs: false, - hello: ClientHelloDetails::new(alpn_protocols, extension_order_seed), - session_id, - server_name, - prev_ech_ext: None, - }, + input, cx, ech_state, ) @@ -175,6 +119,67 @@ pub(super) struct ClientHelloInput { pub(super) prev_ech_ext: Option, } +impl ClientHelloInput { + pub(super) fn new( + server_name: ServerName<'static>, + extra_exts: &ClientExtensionsInput<'_>, + cx: &mut ClientContext<'_>, + config: Arc, + ) -> Result { + 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, + }) + } +} + /// Emits the initial ClientHello or a ClientHello in response to /// a HelloRetryRequest. /// From 9a4e5a7f532695575436757a50c02c2af7950e93 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Wed, 25 Jun 2025 11:35:12 +0200 Subject: [PATCH 303/403] client: attach start_handshake() to ClientHelloInput --- rustls/src/client/client_conn.rs | 2 +- rustls/src/client/hs.rs | 86 ++++++++++++++++---------------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index 5ba26608704..a71005c37d8 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -862,7 +862,7 @@ impl ConnectionCore { }; let input = ClientHelloInput::new(name, &extra_exts, &mut cx, config)?; - let state = hs::start_handshake(input, extra_exts, &mut cx)?; + let state = input.start_handshake(extra_exts, &mut cx)?; Ok(Self::new(state, data, common_state)) } diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 0fafdf2c65c..f72af8fc462 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -44,49 +44,6 @@ pub(super) type NextState<'a> = Box + 'a>; pub(super) type NextStateOrError<'a> = Result, Error>; pub(super) type ClientContext<'a> = crate::common_state::Context<'a, ClientConnectionData>; -pub(super) fn start_handshake( - input: ClientHelloInput, - extra_exts: ClientExtensionsInput<'_>, - cx: &mut ClientContext<'_>, -) -> NextStateOrError<'static> { - let mut transcript_buffer = HandshakeHashBuffer::new(); - if input - .config - .client_auth_cert_resolver - .has_certs() - { - transcript_buffer.set_client_auth_enabled(); - } - - let key_share = if input.config.needs_key_share() { - Some(tls13::initial_key_share( - &input.config, - &input.server_name, - &mut cx.common.kx_state, - )?) - } else { - None - }; - - let ech_state = match input.config.ech_mode.as_ref() { - Some(EchMode::Enable(ech_config)) => { - Some(ech_config.state(input.server_name.clone(), &input.config)?) - } - _ => None, - }; - - emit_client_hello_for_retry( - transcript_buffer, - None, - key_share, - extra_exts, - None, - input, - cx, - ech_state, - ) -} - struct ExpectServerHello { input: ClientHelloInput, transcript_buffer: HandshakeHashBuffer, @@ -178,6 +135,49 @@ impl ClientHelloInput { config, }) } + + pub(super) fn start_handshake( + self, + extra_exts: ClientExtensionsInput<'_>, + 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 From 83662655d0f9b18cf2d772ae80b15c6f698cb9b9 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Wed, 25 Jun 2025 11:41:49 +0200 Subject: [PATCH 304/403] client: clarify ClientExtensionsInput lifetimes --- rustls/src/client/client_conn.rs | 2 +- rustls/src/client/hs.rs | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index a71005c37d8..d214c2a1f2f 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -844,7 +844,7 @@ impl ConnectionCore { pub(crate) fn for_client( config: Arc, name: ServerName<'static>, - extra_exts: ClientExtensionsInput<'_>, + extra_exts: ClientExtensionsInput<'static>, proto: Protocol, ) -> Result { let mut common_state = CommonState::new(Side::Client); diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index f72af8fc462..4669f33d081 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -138,7 +138,7 @@ impl ClientHelloInput { pub(super) fn start_handshake( self, - extra_exts: ClientExtensionsInput<'_>, + extra_exts: ClientExtensionsInput<'static>, cx: &mut ClientContext<'_>, ) -> NextStateOrError<'static> { let mut transcript_buffer = HandshakeHashBuffer::new(); @@ -189,7 +189,7 @@ fn emit_client_hello_for_retry( mut transcript_buffer: HandshakeHashBuffer, retryreq: Option<&HelloRetryRequest>, key_share: Option>, - extra_exts: ClientExtensionsInput<'_>, + extra_exts: ClientExtensionsInput<'static>, suite: Option, mut input: ClientHelloInput, cx: &mut ClientContext<'_>, @@ -208,11 +208,6 @@ fn emit_client_hello_for_retry( // should be unreachable thanks to config builder assert!(supported_versions.any(|_| true)); - let ClientExtensionsInput { - transport_parameters, - protocols, - } = extra_exts.clone().into_owned(); - let mut exts = Box::new(ClientExtensions { // offer groups which are usable for any offered version named_groups: Some( @@ -232,11 +227,11 @@ fn emit_client_hello_for_retry( ), extended_master_secret_request: Some(()), certificate_status_request: Some(CertificateStatusRequest::build_ocsp()), - protocols, + protocols: extra_exts.protocols.clone(), ..Default::default() }); - match transport_parameters { + 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 => {} From 14f77c2db67d405d3c68bd30cae1467cc7475c3e Mon Sep 17 00:00:00 2001 From: Thomas BESSOU Date: Wed, 25 Jun 2025 15:40:17 +0200 Subject: [PATCH 305/403] Simplify the simpleserver example by using rustls::Stream --- examples/src/bin/simpleserver.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/examples/src/bin/simpleserver.rs b/examples/src/bin/simpleserver.rs index f3fa54a144b..3b270c7d1d0 100644 --- a/examples/src/bin/simpleserver.rs +++ b/examples/src/bin/simpleserver.rs @@ -36,16 +36,14 @@ fn main() -> Result<(), Box> { .with_single_cert(certs, private_key)?; let listener = TcpListener::bind(format!("[::]:{}", 4443)).unwrap(); - let (mut stream, _) = listener.accept()?; - + let (mut tcp_stream, _) = listener.accept()?; let mut conn = rustls::ServerConnection::new(Arc::new(config))?; - conn.complete_io(&mut stream)?; + let mut tls_stream = rustls::Stream::new(&mut conn, &mut tcp_stream); - conn.writer() - .write_all(b"Hello from the server")?; - conn.complete_io(&mut stream)?; + tls_stream.write_all(b"Hello from the server")?; + tls_stream.flush()?; let mut buf = [0; 64]; - let len = conn.reader().read(&mut buf)?; + let len = tls_stream.read(&mut buf)?; println!("Received message from client: {:?}", &buf[..len]); Ok(()) From 6f1e6f47bb52383b70a90f91253cf55b57867153 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 25 Jun 2025 16:52:02 +0100 Subject: [PATCH 306/403] Add designated error for rejecting an OCSP response RFC6066 says: > Clients requesting an OCSP response and receiving an OCSP response in > a "CertificateStatus" message MUST check the OCSP response and abort > the handshake if the response is not satisfactory with > bad_certificate_status_response(113) alert. This alert is always > fatal. This error is a route to producing the prescribed alert. --- rustls/src/error.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/rustls/src/error.rs b/rustls/src/error.rs index d616769eecd..f3f7c98bd02 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -468,6 +468,16 @@ pub enum CertificateError { presented: Vec, }, + /// 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, @@ -540,6 +550,7 @@ impl PartialEq for CertificateError { presented: right_presented, }, ) => (left_required, left_presented) == (right_required, right_presented), + (InvalidOcspResponse, InvalidOcspResponse) => true, (ApplicationVerificationFailure, ApplicationVerificationFailure) => true, (UnknownRevocationStatus, UnknownRevocationStatus) => true, (ExpiredRevocationList, ExpiredRevocationList) => true, @@ -582,6 +593,7 @@ impl From for AlertDescription { | UnknownRevocationStatus | ExpiredRevocationList | ExpiredRevocationListContext { .. } => Self::UnknownCA, + InvalidOcspResponse => Self::BadCertificateStatusResponse, BadSignature | UnsupportedSignatureAlgorithm => Self::DecryptError, InvalidPurpose | InvalidPurposeContext { .. } => Self::UnsupportedCertificate, ApplicationVerificationFailure => Self::AccessDenied, @@ -1085,6 +1097,7 @@ mod tests { ApplicationVerificationFailure, ApplicationVerificationFailure ); + assert_eq!(InvalidOcspResponse, InvalidOcspResponse); let other = Other(OtherError( #[cfg(feature = "std")] Arc::from(Box::from("")), @@ -1186,6 +1199,7 @@ mod tests { 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, From 194ea36b908ae9be1f6fdcc98cfbea9d2b43f135 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 25 Jun 2025 16:02:48 +0100 Subject: [PATCH 307/403] bogo: test client use of OCSP stapling --- bogo/config.json.in | 3 +-- bogo/src/main.rs | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index e7373e349db..8a7d937848f 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -17,8 +17,7 @@ "CheckLeafCurve": "", "SendWarningAlerts-*": "", "Peek-*": "", - "ClientOCSPCallback*": "ocsp not supported yet", - "ServerOCSPCallback*": "", + "ServerOCSPCallback*": "ocsp not supported for servers", "SendUnsolicitedOCSPOnCertificate-TLS13": "we unconditionally request a stapled OCSP response", "DuplicateCertCompressionExt*-TLS12": "RFC8879: if TLS 1.2 or earlier is negotiated, the peers MUST ignore this extension", #if defined(RING) diff --git a/bogo/src/main.rs b/bogo/src/main.rs index df6bcca4982..bf89fb0a434 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -127,6 +127,7 @@ struct Options { on_initial_expect_curve_id: Option, on_resume_expect_curve_id: Option, wait_for_debugger: bool, + ocsp: OcspValidation, } impl Options { @@ -197,6 +198,7 @@ impl Options { on_initial_expect_curve_id: None, on_resume_expect_curve_id: None, wait_for_debugger: false, + ocsp: OcspValidation::default(), } } @@ -411,10 +413,11 @@ impl ClientCertVerifier for DummyClientAuth { #[derive(Debug)] struct DummyServerAuth { parent: Arc, + ocsp: OcspValidation, } impl DummyServerAuth { - fn new(trusted_cert_file: &str) -> Self { + fn new(trusted_cert_file: &str, ocsp: OcspValidation) -> Self { Self { parent: WebPkiServerVerifier::builder_with_provider( load_root_certs(trusted_cert_file), @@ -424,6 +427,7 @@ impl DummyServerAuth { ) .build() .unwrap(), + ocsp, } } } @@ -437,6 +441,9 @@ impl ServerCertVerifier for DummyServerAuth { _ocsp: &[u8], _now: UnixTime, ) -> Result { + if let OcspValidation::Reject = self.ocsp { + return Err(CertificateError::InvalidOcspResponse.into()); + } Ok(ServerCertVerified::assertion()) } @@ -465,6 +472,16 @@ impl ServerCertVerifier for DummyServerAuth { } } +#[derive(Clone, Copy, Debug, Default)] +enum OcspValidation { + /// Totally ignore `ocsp_response` value + #[default] + None, + + /// Return an error (irrespective of `ocsp_response` value) + Reject, +} + #[derive(Debug)] struct FixedSignatureSchemeSigningKey { key: Arc, @@ -807,7 +824,10 @@ fn make_client_cfg(opts: &Options) -> Arc { let cfg = cfg .dangerous() - .with_custom_certificate_verifier(Arc::new(DummyServerAuth::new(&opts.trusted_cert_file))); + .with_custom_certificate_verifier(Arc::new(DummyServerAuth::new( + &opts.trusted_cert_file, + opts.ocsp, + ))); let mut cfg = if !opts.cert_file.is_empty() && !opts.key_file.is_empty() { let cert = CertificateDer::pem_file_iter(&opts.cert_file) @@ -1016,6 +1036,10 @@ fn handle_err(opts: &Options, err: Error) -> ! { Error::InvalidCertificate(CertificateError::UnsupportedSignatureAlgorithm) => { quit(":WRONG_SIGNATURE_TYPE:") } + Error::InvalidCertificate(CertificateError::InvalidOcspResponse) => { + // note: only use is in this file. + quit(":OCSP_CB_ERROR:") + } Error::InvalidCertificate(e) => quit(&format!(":BAD_CERT: ({e:?})")), Error::PeerSentOversizedRecord => quit(":DATA_LENGTH_TOO_LONG:"), _ => { @@ -1645,6 +1669,9 @@ pub fn main() { "-server-preference" => { opts.server_preference = true; } + "-fail-ocsp-callback" => { + opts.ocsp = OcspValidation::Reject; + } "-wait-for-debugger" => { #[cfg(windows)] { @@ -1669,6 +1696,7 @@ pub fn main() { "-expect-no-session" | "-expect-ticket-renewal" | "-enable-ocsp-stapling" | + "-use-ocsp-callback" | "-forbid-renegotiation-after-handshake" | // internal openssl details: "-async" | From 4a0c0f1f4cef5e5229d18b5ca293d3d06e258a67 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Thu, 26 Jun 2025 21:17:04 +0200 Subject: [PATCH 308/403] Apply suggestions from clippy 1.88 --- rustls/src/check.rs | 8 ++------ rustls/src/msgs/handshake_test.rs | 16 ++++++++-------- rustls/src/server/hs.rs | 2 +- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/rustls/src/check.rs b/rustls/src/check.rs index beb70aa2805..9875bc8bdf3 100644 --- a/rustls/src/check.rs +++ b/rustls/src/check.rs @@ -42,9 +42,8 @@ pub(crate) fn inappropriate_message( content_types: &[ContentType], ) -> Error { warn!( - "Received a {:?} message while expecting {:?}", + "Received a {:?} message while expecting {content_types:?}", payload.content_type(), - content_types ); Error::InappropriateMessage { expect_types: content_types.to_vec(), @@ -60,10 +59,7 @@ pub(crate) fn inappropriate_handshake_message( match payload { MessagePayload::Handshake { parsed, .. } => { let got_type = parsed.0.handshake_type(); - warn!( - "Received a {:?} handshake message while expecting {:?}", - got_type, handshake_types - ); + warn!("Received a {got_type:?} handshake message while expecting {handshake_types:?}",); Error::InappropriateHandshakeMessage { expect_types: handshake_types.to_vec(), got_type, diff --git a/rustls/src/msgs/handshake_test.rs b/rustls/src/msgs/handshake_test.rs index e29aefca331..53cf88fa5ac 100644 --- a/rustls/src/msgs/handshake_test.rs +++ b/rustls/src/msgs/handshake_test.rs @@ -270,7 +270,7 @@ fn can_round_trip_psk_offer() { #[test] fn can_round_trip_cert_status_req_for_ocsp() { let ext = CertificateStatusRequest::build_ocsp(); - println!("{:?}", ext); + println!("{ext:?}"); let bytes = [ 0, 11, 1, // OCSP @@ -278,7 +278,7 @@ fn can_round_trip_cert_status_req_for_ocsp() { ]; let csr = CertificateStatusRequest::read(&mut Reader::init(&bytes)).unwrap(); - println!("{:?}", csr); + println!("{csr:?}"); assert_eq!(csr.get_encoding(), bytes.to_vec()); } @@ -290,7 +290,7 @@ fn can_round_trip_cert_status_req_for_other() { ]; let csr = CertificateStatusRequest::read(&mut Reader::init(&bytes)).unwrap(); - println!("{:?}", csr); + println!("{csr:?}"); assert_eq!(csr.get_encoding(), bytes.to_vec()); } @@ -496,7 +496,7 @@ fn test_truncated_client_extension_is_detected() { let chp = sample_client_hello_payload(); let enc = chp.extensions.get_encoding(); - println!("testing enc {:?}", enc); + println!("testing enc {enc:?}"); // "outer" truncation, i.e., where the extension-level length is longer than // the input @@ -510,7 +510,7 @@ 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); + println!("testing enc {enc:?}"); // "outer" truncation, i.e., where the extension-level length is longer than // the input @@ -522,7 +522,7 @@ fn test_truncated_hello_retry_extension_is_detected() { // 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 {:?} len {:?}", enc, l); + println!(" encoding {enc:?} len {l:?}"); assert!(HelloRetryRequestExtensions::read_bytes(&enc).is_err()); } } @@ -532,7 +532,7 @@ fn test_truncated_server_extension_is_detected() { let shp = sample_server_hello_payload(); let mut enc = shp.extensions.get_encoding(); - println!("testing enc {:?}", enc); + println!("testing enc {enc:?}"); // "outer" truncation, i.e., where the extension-level length is longer than // the input @@ -544,7 +544,7 @@ fn test_truncated_server_extension_is_detected() { // 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 {:?} len {:?}", enc, l); + println!(" encoding {enc:?} len {l:?}"); assert!(ServerExtensions::read_bytes(&enc).is_err()); } } diff --git a/rustls/src/server/hs.rs b/rustls/src/server/hs.rs index d3a360a6843..d98336e461b 100644 --- a/rustls/src/server/hs.rs +++ b/rustls/src/server/hs.rs @@ -107,7 +107,7 @@ impl ExtensionProcessing { }) .map(|bytes| ProtocolName::from(bytes.clone())); if let Some(selected_protocol) = &cx.common.alpn_protocol { - debug!("Chosen ALPN protocol {:?}", selected_protocol); + debug!("Chosen ALPN protocol {selected_protocol:?}"); self.extensions.selected_protocol = Some(SingleProtocolName::new(selected_protocol.clone())); From ed3af05275713ea286874c24d973752517eef2a5 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 26 Jun 2025 07:22:54 +0100 Subject: [PATCH 309/403] bogo: document `ConflictingVersionNegotiation` skip --- bogo/config.json.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index 8a7d937848f..4cccc88cb3d 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -6,7 +6,7 @@ "*-TLS1": "", "*TLS11-*": "", "*-TLS11": "", - "ConflictingVersionNegotiation": "", + "ConflictingVersionNegotiation": "expects to negotiate TLS1.1", "CertificateSelection-*": "TODO", "SendFallbackSCSV": "fallback scsv not implemented", "ECDSAKeyUsage-*": "TODO: we don't do anything with key usages", From 8f2be1b169fd48bb5be51905fffdf80060fdb58a Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 26 Jun 2025 07:26:16 +0100 Subject: [PATCH 310/403] bogo: clarify version skips --- bogo/config.json.in | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index 4cccc88cb3d..3b114a3bbf7 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -1,11 +1,11 @@ { "DisabledTests": { - "SendV2ClientHello-*": "only support TLS1.2", - "*SSL3*": "", - "*TLS1-*": "", - "*-TLS1": "", - "*TLS11-*": "", - "*-TLS11": "", + "SendV2ClientHello-*": "we only support >=TLS1.2", + "*SSL3*": "we only support >=TLS1.2", + "*TLS1-*": "we only support >=TLS1.2", + "*-TLS1": "we only support >=TLS1.2", + "*TLS11-*": "we only support >=TLS1.2", + "*-TLS11": "we only support >=TLS1.2", "ConflictingVersionNegotiation": "expects to negotiate TLS1.1", "CertificateSelection-*": "TODO", "SendFallbackSCSV": "fallback scsv not implemented", From f808a962f79e662206f1b096b53619c77b139a3b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 26 Jun 2025 07:56:01 +0100 Subject: [PATCH 311/403] bogo: prepare for shim to support multiple credentials --- bogo/src/main.rs | 113 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 78 insertions(+), 35 deletions(-) diff --git a/bogo/src/main.rs b/bogo/src/main.rs index bf89fb0a434..387684eae2f 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -84,8 +84,7 @@ struct Options { host_name: String, use_sni: bool, trusted_cert_file: String, - key_file: String, - cert_file: String, + credentials: Credentials, protocols: Vec, reject_alpn: bool, support_tls13: bool, @@ -93,7 +92,6 @@ struct Options { min_version: Option, max_version: Option, server_ocsp_response: Vec, - use_signing_scheme: u16, groups: Option>, export_keying_material: usize, export_keying_material_label: String, @@ -155,8 +153,7 @@ impl Options { root_hint_subjects: vec![], offer_no_client_cas: false, trusted_cert_file: "".to_string(), - key_file: "".to_string(), - cert_file: "".to_string(), + credentials: Credentials::default(), protocols: vec![], reject_alpn: false, support_tls13: true, @@ -164,7 +161,6 @@ impl Options { min_version: None, max_version: None, server_ocsp_response: vec![], - use_signing_scheme: 0, groups: None, export_keying_material: 0, export_keying_material_label: "".to_string(), @@ -230,6 +226,50 @@ impl Options { } } +#[derive(Debug, Default)] +struct Credentials { + default: Credential, + additional: Vec, +} + +impl Credentials { + fn last_mut(&mut self) -> &mut Credential { + self.additional + .last_mut() + .unwrap_or(&mut self.default) + } + + fn configured(&self) -> bool { + self.default.configured() + || self + .additional + .iter() + .any(|cred| cred.configured()) + } +} + +#[derive(Clone, Debug, Default)] +struct Credential { + key_file: String, + cert_file: String, + use_signing_scheme: Option, +} + +impl Credential { + fn load_from_file(&self) -> (Vec>, PrivateKeyDer<'static>) { + let certs = CertificateDer::pem_file_iter(&self.cert_file) + .unwrap() + .map(|cert| cert.unwrap()) + .collect::>(); + let key = PrivateKeyDer::from_pem_file(&self.key_file).unwrap(); + (certs, key) + } + + fn configured(&self) -> bool { + !self.cert_file.is_empty() && !self.key_file.is_empty() + } +} + #[derive(Clone, Copy, Debug, PartialEq)] enum SelectedProvider { AwsLcRs, @@ -640,11 +680,12 @@ fn make_server_cfg(opts: &Options) -> Arc { WebPkiClientVerifier::no_client_auth() }; - let cert = CertificateDer::pem_file_iter(&opts.cert_file) - .unwrap() - .map(|cert| cert.unwrap()) - .collect::>(); - let key = PrivateKeyDer::from_pem_file(&opts.key_file).unwrap(); + assert!( + opts.credentials.additional.is_empty(), + "TODO: server certificate switching not implemented yet" + ); + let cred = &opts.credentials.default; + let (certs, key) = cred.load_from_file(); let mut provider = opts.provider.clone(); @@ -658,7 +699,7 @@ fn make_server_cfg(opts: &Options) -> Arc { .with_protocol_versions(&opts.supported_versions()) .unwrap() .with_client_cert_verifier(client_auth) - .with_single_cert_with_ocsp(cert.clone(), key, opts.server_ocsp_response.clone()) + .with_single_cert_with_ocsp(certs, key, opts.server_ocsp_response.clone()) .unwrap(); cfg.session_storage = ServerCacheWithResumptionDelay::new(opts.resumption_delay); @@ -667,8 +708,8 @@ fn make_server_cfg(opts: &Options) -> Arc { cfg.require_ems = opts.require_ems; cfg.ignore_client_order = opts.server_preference; - if opts.use_signing_scheme > 0 { - let scheme = lookup_scheme(opts.use_signing_scheme); + if let Some(scheme) = cred.use_signing_scheme { + let scheme = lookup_scheme(scheme); cfg.cert_resolver = Arc::new(FixedSignatureSchemeServerCertResolver { resolver: cfg.cert_resolver.clone(), scheme, @@ -829,25 +870,27 @@ fn make_client_cfg(opts: &Options) -> Arc { opts.ocsp, ))); - let mut cfg = if !opts.cert_file.is_empty() && !opts.key_file.is_empty() { - let cert = CertificateDer::pem_file_iter(&opts.cert_file) - .unwrap() - .map(|item| item.unwrap()) - .collect(); - let key = PrivateKeyDer::from_pem_file(&opts.key_file).unwrap(); - cfg.with_client_auth_cert(cert, key) - .unwrap() - } else { - cfg.with_no_client_auth() - }; + let mut cfg = match opts.credentials.configured() { + true => { + assert!(opts.credentials.additional.is_empty()); - if !opts.cert_file.is_empty() && opts.use_signing_scheme > 0 { - let scheme = lookup_scheme(opts.use_signing_scheme); - cfg.client_auth_cert_resolver = Arc::new(FixedSignatureSchemeClientCertResolver { - resolver: cfg.client_auth_cert_resolver.clone(), - scheme, - }); - } + let cred = &opts.credentials.default; + let (certs, key) = cred.load_from_file(); + let mut cfg = cfg + .with_client_auth_cert(certs, key) + .unwrap(); + + if let Some(scheme) = cred.use_signing_scheme { + let scheme = lookup_scheme(scheme); + cfg.client_auth_cert_resolver = Arc::new(FixedSignatureSchemeClientCertResolver { + resolver: cfg.client_auth_cert_resolver.clone(), + scheme, + }); + } + cfg + } + false => cfg.with_no_client_auth(), + }; cfg.resumption = Resumption::store(ClientCacheWithoutKxHints::new(opts.resumption_delay)) .tls12_resumption(match opts.tickets { @@ -1369,10 +1412,10 @@ pub fn main() { opts.side = Side::Server; } "-key-file" => { - opts.key_file = args.remove(0); + opts.credentials.last_mut().key_file = args.remove(0); } "-cert-file" => { - opts.cert_file = args.remove(0); + opts.credentials.last_mut().cert_file = args.remove(0); } "-trust-cert" => { opts.trusted_cert_file = args.remove(0); @@ -1417,7 +1460,7 @@ pub fn main() { } "-signing-prefs" => { let alg = args.remove(0).parse::().unwrap(); - opts.use_signing_scheme = alg; + opts.credentials.last_mut().use_signing_scheme = Some(alg); } "-use-client-ca-list" => { match args.remove(0).as_ref() { From d752d31f7af2429062d2b1d4a02c41d73bad242b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 26 Jun 2025 08:29:44 +0100 Subject: [PATCH 312/403] bogo: enable `CertificateSelection-Client` tests --- Cargo.lock | 1 + bogo/Cargo.toml | 1 + bogo/config.json.in | 17 ++++- bogo/src/main.rs | 164 +++++++++++++++++++++++++++++++++++--------- 4 files changed, 150 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3528e45b41e..0a6aae6b0a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -483,6 +483,7 @@ dependencies = [ "nix", "rustls", "rustls-post-quantum", + "rustls-webpki", ] [[package]] diff --git a/bogo/Cargo.toml b/bogo/Cargo.toml index be08f06d38c..d5c9b96b7c1 100644 --- a/bogo/Cargo.toml +++ b/bogo/Cargo.toml @@ -10,6 +10,7 @@ env_logger = { workspace = true } nix = { version = "0.30", default-features = false, features = ["signal"] } rustls = { path = "../rustls", features = ["aws_lc_rs", "ring", "tls12"] } rustls-post-quantum = { path = "../rustls-post-quantum", optional = true } +webpki = { workspace = true } [features] default = [] diff --git a/bogo/config.json.in b/bogo/config.json.in index 3b114a3bbf7..9c35aad2267 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -6,8 +6,11 @@ "*-TLS1": "we only support >=TLS1.2", "*TLS11-*": "we only support >=TLS1.2", "*-TLS11": "we only support >=TLS1.2", + "CertificateSelection-*TrustAnchorIDs-*": "no support for trust anchor IDs draft", + "CertificateSelection-*ClientCertificateTypes-*": "no support for CertificateRequest::certificate_types", + "CertificateSelection-Client-SignatureAlgorithmECDSACurve-TLS-TLS12": "ResolvesClientCert does not receive protocol version", + "CertificateSelection-Server-*": "TODO certificate selection for servers", "ConflictingVersionNegotiation": "expects to negotiate TLS1.1", - "CertificateSelection-*": "TODO", "SendFallbackSCSV": "fallback scsv not implemented", "ECDSAKeyUsage-*": "TODO: we don't do anything with key usages", "CheckRecordVersion-*": "we don't look at record version", @@ -384,7 +387,17 @@ "DuplicateExtensionClient-TLS-TLS12": "remote error: illegal parameter", "DuplicateExtensionClient-TLS-TLS13": "remote error: illegal parameter", "DuplicateExtensionServer-TLS-TLS12": "remote error: illegal parameter", - "DuplicateExtensionServer-TLS-TLS13": "remote error: illegal parameter" + "DuplicateExtensionServer-TLS-TLS13": "remote error: illegal parameter", + "_": "no alerts sent for the following tests... (artificial error created in the shim)", + "CertificateSelection-Client-CheckIssuer-MatchNone-TLS-TLS12": "", + "CertificateSelection-Client-CheckIssuer-MatchNone-TLS-TLS13": "", + "CertificateSelection-Client-CheckIssuerFallback-MatchNone-TLS-TLS12": "", + "CertificateSelection-Client-CheckIssuerFallback-MatchNone-TLS-TLS13": "", + "CertificateSelection-Client-SignatureAlgorithm-MatchNone-TLS-TLS12": "", + "CertificateSelection-Client-SignatureAlgorithm-MatchNone-TLS-TLS13": "", + "CertificateSelection-Client-SignatureAlgorithmECDSACurve-MatchNone-TLS-TLS13": "", + "CertificateSelection-Client-SignatureAlgorithmKeyPrefs-MatchNone-TLS-TLS12": "", + "CertificateSelection-Client-SignatureAlgorithmKeyPrefs-MatchNone-TLS-TLS13": "" }, "HalfRTTTickets": 0 } diff --git a/bogo/src/main.rs b/bogo/src/main.rs index 387684eae2f..23ba3600911 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -230,6 +230,8 @@ impl Options { struct Credentials { default: Credential, additional: Vec, + /// Some(-1) means `default`, otherwise index into `additional` + expect_selected: Option, } impl Credentials { @@ -253,6 +255,7 @@ struct Credential { key_file: String, cert_file: String, use_signing_scheme: Option, + must_match_issuer: bool, } impl Credential { @@ -558,33 +561,111 @@ impl server::ResolvesServerCert for FixedSignatureSchemeServerCertResolver { } } -#[derive(Debug)] -struct FixedSignatureSchemeClientCertResolver { - resolver: Arc, - scheme: SignatureScheme, +#[derive(Debug, Default)] +struct MultipleClientCredentialResolver { + additional: Vec, + default: Option, + expect_selected: Option, } -impl client::ResolvesClientCert for FixedSignatureSchemeClientCertResolver { +impl MultipleClientCredentialResolver { + fn add(&mut self, key: sign::CertifiedKey, meta: &Credential) { + self.additional + .push(ClientCert::new(key, meta)); + } + + fn set_default(&mut self, key: sign::CertifiedKey, meta: &Credential) { + self.default = Some(ClientCert::new(key, meta)); + } +} + +impl client::ResolvesClientCert for MultipleClientCredentialResolver { fn resolve( &self, root_hint_subjects: &[&[u8]], - sigschemes: &[SignatureScheme], + sig_schemes: &[SignatureScheme], ) -> Option> { - if !sigschemes.contains(&self.scheme) { - quit(":NO_COMMON_SIGNATURE_ALGORITHMS:"); + // `sig_schemes` is in server preference order, so respect that. + for sig_scheme in sig_schemes.iter().copied() { + for (i, cert) in self.additional.iter().enumerate() { + // if the server sends any issuer hints, respect them + if cert.must_match_issuer + && !root_hint_subjects + .iter() + .any(|dn| *dn == cert.issuer_dn.as_ref()) + { + continue; + } + + if cert + .certkey + .key + .choose_scheme(&[sig_scheme]) + .is_some() + { + assert!( + Some(i as isize) == self.expect_selected || self.expect_selected.is_none() + ); + return Some(cert.certkey.clone()); + } + } } - let mut certkey = self - .resolver - .resolve(root_hint_subjects, sigschemes)?; - Arc::make_mut(&mut certkey).key = Arc::new(FixedSignatureSchemeSigningKey { - key: certkey.key.clone(), - scheme: self.scheme, - }); - Some(certkey) + + if let Some(cert) = &self.default { + if cert + .certkey + .key + .choose_scheme(sig_schemes) + .is_some() + { + assert!(matches!(self.expect_selected, Some(-1) | None)); + return Some(cert.certkey.clone()); + } + } + + assert_eq!(self.expect_selected, None); + + let all_must_match_issuer = self + .additional + .iter() + .chain(self.default.iter()) + .all(|item| item.must_match_issuer); + + quit(match all_must_match_issuer { + true => ":NO_MATCHING_ISSUER:", + false => ":NO_COMMON_SIGNATURE_ALGORITHMS:", + }) } fn has_certs(&self) -> bool { - self.resolver.has_certs() + self.default.is_some() || !self.additional.is_empty() + } +} + +#[derive(Debug)] +struct ClientCert { + certkey: Arc, + issuer_dn: DistinguishedName, + must_match_issuer: bool, +} + +impl ClientCert { + fn new(mut certkey: sign::CertifiedKey, meta: &Credential) -> Self { + let parsed_cert = webpki::EndEntityCert::try_from(certkey.cert.last().unwrap()).unwrap(); + let issuer_dn = DistinguishedName::in_sequence(parsed_cert.issuer()); + + if let Some(scheme) = meta.use_signing_scheme { + certkey.key = Arc::new(FixedSignatureSchemeSigningKey { + key: certkey.key, + scheme: lookup_scheme(scheme), + }); + } + + Self { + certkey: Arc::new(certkey), + issuer_dn, + must_match_issuer: meta.must_match_issuer, + } } } @@ -836,7 +917,8 @@ fn make_client_cfg(opts: &Options) -> Arc { .retain(|kxg| groups.contains(&kxg.name())); } - let cfg = ClientConfig::builder_with_provider(provider.into()); + let provider = Arc::new(provider); + let cfg = ClientConfig::builder_with_provider(provider.clone()); let cfg = if opts.selected_provider.supports_ech() { if let Some(ech_config_list) = &opts.ech_config_list { @@ -872,22 +954,33 @@ fn make_client_cfg(opts: &Options) -> Arc { let mut cfg = match opts.credentials.configured() { true => { - assert!(opts.credentials.additional.is_empty()); + let mut resolver = MultipleClientCredentialResolver { + expect_selected: opts.credentials.expect_selected, + ..Default::default() + }; - let cred = &opts.credentials.default; - let (certs, key) = cred.load_from_file(); - let mut cfg = cfg - .with_client_auth_cert(certs, key) - .unwrap(); + if opts.credentials.default.configured() { + let cred = &opts.credentials.default; + let (certs, key) = cred.load_from_file(); + let key = provider + .key_provider + .load_private_key(key) + .expect("cannot load private key"); + + resolver.set_default(sign::CertifiedKey::new(certs, key), cred) + } + + for cred in opts.credentials.additional.iter() { + let (certs, key) = cred.load_from_file(); + let key = provider + .key_provider + .load_private_key(key) + .expect("cannot load private key"); - if let Some(scheme) = cred.use_signing_scheme { - let scheme = lookup_scheme(scheme); - cfg.client_auth_cert_resolver = Arc::new(FixedSignatureSchemeClientCertResolver { - resolver: cfg.client_auth_cert_resolver.clone(), - scheme, - }); + resolver.add(sign::CertifiedKey::new(certs, key), cred); } - cfg + + cfg.with_client_cert_resolver(Arc::new(resolver)) } false => cfg.with_no_client_auth(), }; @@ -1414,6 +1507,12 @@ pub fn main() { "-key-file" => { opts.credentials.last_mut().key_file = args.remove(0); } + "-new-x509-credential" => { + opts.credentials.additional.push(Credential::default()); + } + "-expect-selected-credential" => { + opts.credentials.expect_selected = args.remove(0).parse::().ok(); + } "-cert-file" => { opts.credentials.last_mut().cert_file = args.remove(0); } @@ -1462,6 +1561,9 @@ pub fn main() { let alg = args.remove(0).parse::().unwrap(); opts.credentials.last_mut().use_signing_scheme = Some(alg); } + "-must-match-issuer" => { + opts.credentials.last_mut().must_match_issuer = true; + } "-use-client-ca-list" => { match args.remove(0).as_ref() { "" | "" => { From 06a5f6aca5cb34f7711b16809464cce14620d5ac Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Sat, 28 Jun 2025 17:11:57 +0100 Subject: [PATCH 313/403] bogo: replace sleep with orderly TCP closure --- bogo/src/main.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/bogo/src/main.rs b/bogo/src/main.rs index 23ba3600911..34c29676545 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -1035,7 +1035,6 @@ fn quit_err(why: &str) -> ! { fn handle_err(opts: &Options, err: Error) -> ! { println!("TLS error: {err:?}"); - thread::sleep(time::Duration::from_millis(100)); match err { Error::InappropriateHandshakeMessage { .. } | Error::InappropriateMessage { .. } => { @@ -1211,10 +1210,25 @@ const MAX_MESSAGE_SIZE: usize = 0xffff + 5; fn after_read(opts: &Options, sess: &mut Connection, conn: &mut net::TcpStream) { if let Err(err) = sess.process_new_packets() { flush(sess, conn); /* send any alerts before exiting */ + orderly_close(conn); handle_err(opts, err); } } +fn orderly_close(conn: &mut net::TcpStream) { + // assuming we just flush()'d, we will write no more. + conn.shutdown(net::Shutdown::Write) + .unwrap(); + + // wait for EOF + let mut buf = [0u8; 32]; + while let Ok(p @ 1..) = conn.peek(&mut buf) { + let _ = conn.read(&mut buf[..p]).unwrap(); + } + + let _ = conn.shutdown(net::Shutdown::Read); +} + fn read_n_bytes(opts: &Options, sess: &mut Connection, conn: &mut net::TcpStream, n: usize) { let mut bytes = [0u8; MAX_MESSAGE_SIZE]; match conn.read(&mut bytes[..n]) { From aab9b9b8a1dd1e3525fbb4bd80fd64856393997c Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Mon, 30 Jun 2025 13:37:24 +0200 Subject: [PATCH 314/403] Add SignatureSchemes for ML-DSA --- rustls/src/enums.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rustls/src/enums.rs b/rustls/src/enums.rs index 2290b73b107..f59ca3f9a46 100644 --- a/rustls/src/enums.rs +++ b/rustls/src/enums.rs @@ -514,6 +514,10 @@ enum_builder! { 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, } } From 42d64752ac6a9d03d8ec2f0b212c62f29b41ecec Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 27 Jun 2025 08:11:03 +0100 Subject: [PATCH 315/403] bogo: enable `SendWarningAlerts` These already pass. --- bogo/config.json.in | 1 - 1 file changed, 1 deletion(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index 9c35aad2267..a9ba0a4717c 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -18,7 +18,6 @@ "MTU*": "dtls only", "DisableEverything": "not useful", "CheckLeafCurve": "", - "SendWarningAlerts-*": "", "Peek-*": "", "ServerOCSPCallback*": "ocsp not supported for servers", "SendUnsolicitedOCSPOnCertificate-TLS13": "we unconditionally request a stapled OCSP response", From 479b909a93e9ed4e846107d09dffa476010b0283 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 27 Jun 2025 09:42:16 +0100 Subject: [PATCH 316/403] bogo: use specific error for `MessageInterleavedWithHandshakeMessage` --- bogo/config.json.in | 9 --------- bogo/src/main.rs | 3 +++ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index a9ba0a4717c..9f5fc9fbedc 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -296,14 +296,6 @@ "PartialServerHelloWithHelloRetryRequest": ":PEER_MISBEHAVIOUR:", "PartialNewSessionTicketWithServerHelloDone": ":PEER_MISBEHAVIOUR:", "PartialEndOfEarlyDataWithClientHello": ":PEER_MISBEHAVIOUR:", - "FragmentAcrossChangeCipherSpec-Client": ":PEER_MISBEHAVIOUR:", - "FragmentAcrossChangeCipherSpec-Server-Packed": ":PEER_MISBEHAVIOUR:", - "FragmentAcrossChangeCipherSpec-Client-Resume-Packed": ":PEER_MISBEHAVIOUR:", - "FragmentAcrossChangeCipherSpec-Client-Resume": ":PEER_MISBEHAVIOUR:", - "FragmentAcrossChangeCipherSpec-Server-Resume": ":PEER_MISBEHAVIOUR:", - "FragmentAcrossChangeCipherSpec-Server": ":PEER_MISBEHAVIOUR:", - "FragmentAcrossChangeCipherSpec-Client-Packed": ":PEER_MISBEHAVIOUR:", - "FragmentAcrossChangeCipherSpec-Server-Resume-Packed": ":PEER_MISBEHAVIOUR:", "PartialFinishedWithServerHelloDone": ":PEER_MISBEHAVIOUR:", "UnsupportedCurve-ServerHello-TLS13": ":PEER_MISBEHAVIOUR:", "PartialClientKeyExchangeWithClientHello": ":PEER_MISBEHAVIOUR:", @@ -369,7 +361,6 @@ "SkipEarlyData-Interleaved-TLS13": ":PEER_MISBEHAVIOUR:", "SkipEarlyData-TooMuchData-TLS13": ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:", "SkipEarlyData-HRR-FatalAlert-TLS13": ":HANDSHAKE_FAILURE:", - "SkipEarlyData-HRR-Interleaved-TLS13": ":PEER_MISBEHAVIOUR:", "SkipEarlyData-HRR-TooMuchData-TLS13": ":UNEXPECTED_MESSAGE:", "SkipEarlyData-SecondClientHelloEarlyData-TLS13": ":PEER_MISBEHAVIOUR:" }, diff --git a/bogo/src/main.rs b/bogo/src/main.rs index 34c29676545..ddb3685e169 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -1158,6 +1158,9 @@ fn handle_err(opts: &Options, err: Error) -> ! { } Error::PeerMisbehaved(PeerMisbehaved::SelectedUnofferedKxGroup) => quit(":WRONG_CURVE:"), Error::PeerMisbehaved(PeerMisbehaved::InvalidKeyShare) => quit(":BAD_ECPOINT:"), + Error::PeerMisbehaved(PeerMisbehaved::MessageInterleavedWithHandshakeMessage) => { + quit(":UNEXPECTED_MESSAGE:") + } Error::PeerMisbehaved(_) => quit(":PEER_MISBEHAVIOUR:"), Error::NoCertificatesPresented => quit(":NO_CERTS:"), Error::AlertReceived(AlertDescription::UnexpectedMessage) => quit(":BAD_ALERT:"), From 76973c5ea42958e2c1e388b38f815fed5f843561 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 27 Jun 2025 09:51:25 +0100 Subject: [PATCH 317/403] bogo: use specific error for `KeyEpochWithPendingFragment` --- bogo/config.json.in | 18 ------------------ bogo/src/main.rs | 3 +++ 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index 9f5fc9fbedc..18ce10c5f71 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -282,30 +282,12 @@ "DisabledCurve-HelloRetryRequest-TLS13": ":PEER_MISBEHAVIOUR:", "HelloRetryRequest-Empty-TLS13": ":PEER_MISBEHAVIOUR:", "HelloRetryRequest-EmptyCookie-TLS13": ":ILLEGAL_EMPTY_VALUE:", - "TrailingDataWithFinished-Client-TLS12": ":PEER_MISBEHAVIOUR:", - "TrailingDataWithFinished-Resume-Client-TLS12": ":PEER_MISBEHAVIOUR:", - "TrailingDataWithFinished-Server-TLS12": ":PEER_MISBEHAVIOUR:", - "TrailingDataWithFinished-Resume-Server-TLS12": ":PEER_MISBEHAVIOUR:", - "TrailingDataWithFinished-Client-TLS13": ":PEER_MISBEHAVIOUR:", - "TrailingDataWithFinished-Server-TLS13": ":PEER_MISBEHAVIOUR:", - "TrailingDataWithFinished-Resume-Client-TLS13": ":PEER_MISBEHAVIOUR:", - "TrailingDataWithFinished-Resume-Server-TLS13": ":PEER_MISBEHAVIOUR:", - "PartialSecondClientHelloAfterFirst": ":PEER_MISBEHAVIOUR:", - "PartialClientFinishedWithSecondClientHello": ":PEER_MISBEHAVIOUR:", - "PartialClientFinishedWithClientHello-TLS12-Resume": ":PEER_MISBEHAVIOUR:", - "PartialServerHelloWithHelloRetryRequest": ":PEER_MISBEHAVIOUR:", - "PartialNewSessionTicketWithServerHelloDone": ":PEER_MISBEHAVIOUR:", - "PartialEndOfEarlyDataWithClientHello": ":PEER_MISBEHAVIOUR:", - "PartialFinishedWithServerHelloDone": ":PEER_MISBEHAVIOUR:", "UnsupportedCurve-ServerHello-TLS13": ":PEER_MISBEHAVIOUR:", - "PartialClientKeyExchangeWithClientHello": ":PEER_MISBEHAVIOUR:", "MinimumVersion-Client-TLS13-TLS12-TLS": ":INCOMPATIBLE:", "MinimumVersion-Client2-TLS13-TLS12-TLS": ":INCOMPATIBLE:", "MinimumVersion-Server-TLS13-TLS12-TLS": ":INCOMPATIBLE:", "MinimumVersion-Server2-TLS13-TLS12-TLS": ":INCOMPATIBLE:", "DuplicateKeyShares-TLS13": ":PEER_MISBEHAVIOUR:", - "PartialEncryptedExtensionsWithServerHello": ":PEER_MISBEHAVIOUR:", - "PartialClientFinishedWithClientHello": ":PEER_MISBEHAVIOUR:", "PointFormat-EncryptedExtensions-TLS13": ":PEER_MISBEHAVIOUR:", "Ticket-Forbidden-TLS13": ":PEER_MISBEHAVIOUR:", "PointFormat-Server-MissingUncompressed": ":INCOMPATIBLE:", diff --git a/bogo/src/main.rs b/bogo/src/main.rs index ddb3685e169..ed397fa3435 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -1161,6 +1161,9 @@ fn handle_err(opts: &Options, err: Error) -> ! { Error::PeerMisbehaved(PeerMisbehaved::MessageInterleavedWithHandshakeMessage) => { quit(":UNEXPECTED_MESSAGE:") } + Error::PeerMisbehaved(PeerMisbehaved::KeyEpochWithPendingFragment) => { + quit(":EXCESS_HANDSHAKE_DATA:") + } Error::PeerMisbehaved(_) => quit(":PEER_MISBEHAVIOUR:"), Error::NoCertificatesPresented => quit(":NO_CERTS:"), Error::AlertReceived(AlertDescription::UnexpectedMessage) => quit(":BAD_ALERT:"), From 41559f24dea57bf182b563dbe65e788e8bf62cb2 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 27 Jun 2025 09:53:01 +0100 Subject: [PATCH 318/403] bogo: enable SendHalfHelloRequest-* tests --- bogo/config.json.in | 1 - 1 file changed, 1 deletion(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index 18ce10c5f71..598f8690ddf 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -116,7 +116,6 @@ "Shutdown-Shim-ApplicationData*": "tests boringssl/openssl-specific behaviour, we don't let application data overtake connection shutdown", "Renegotiate-Server-*": "", "Renegotiate-ForbidAfterHandshake": "", - "SendHalfHelloRequest-*": "", "RetainOnlySHA256-*": "", "ExtendedMasterSecret-Renego-*": "", "ALPN*SelectEmpty-*": "", From bc81fb94fee18b882f42cfc30aee4e469e8a6f0d Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 27 Jun 2025 10:04:31 +0100 Subject: [PATCH 319/403] bogo: enable `ExportTrafficSecrets*` tests --- bogo/config.json.in | 1 - bogo/src/main.rs | 90 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 80 insertions(+), 11 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index 598f8690ddf..71619d09f0d 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -94,7 +94,6 @@ "GREASE-*": "not implemented", "LargeMessage-Reject": "", "DelegatedCredentials-*": "not implemented", - "ExportTrafficSecrets-*": "", "NoCommonCurves": "nothing to fall back to", "ClientHelloPadding": "hello padding extension not implemented", "Resume-Client-CipherMismatch": "tries to vary to unimplemented CBC-mode cs", diff --git a/bogo/src/main.rs b/bogo/src/main.rs index ed397fa3435..ef52e4df292 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -21,7 +21,7 @@ use core::fmt::{Debug, Formatter}; use std::io::{self, Read, Write}; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use std::{env, net, process, thread, time}; use base64::prelude::{BASE64_STANDARD, Engine}; @@ -97,6 +97,7 @@ struct Options { export_keying_material_label: String, export_keying_material_context: String, export_keying_material_context_used: bool, + export_traffic_secrets: bool, read_size: usize, quic_transport_params: Vec, expect_quic_transport_params: Vec, @@ -166,6 +167,7 @@ impl Options { export_keying_material_label: "".to_string(), export_keying_material_context: "".to_string(), export_keying_material_context_used: false, + export_traffic_secrets: false, read_size: 512, quic_transport_params: vec![], expect_quic_transport_params: vec![], @@ -749,7 +751,7 @@ impl server::StoresServerSessions for ServerCacheWithResumptionDelay { } } -fn make_server_cfg(opts: &Options) -> Arc { +fn make_server_cfg(opts: &Options, key_log: &Arc) -> Arc { let client_auth = if opts.verify_peer || opts.offer_no_client_cas || opts.require_any_client_cert { Arc::new(DummyClientAuth::new( @@ -788,6 +790,9 @@ fn make_server_cfg(opts: &Options) -> Arc { cfg.send_tls13_tickets = 1; cfg.require_ems = opts.require_ems; cfg.ignore_client_order = opts.server_preference; + if opts.export_traffic_secrets { + cfg.key_log = key_log.clone(); + } if let Some(scheme) = cred.use_signing_scheme { let scheme = lookup_scheme(scheme); @@ -908,7 +913,7 @@ impl Debug for ClientCacheWithoutKxHints { } } -fn make_client_cfg(opts: &Options) -> Arc { +fn make_client_cfg(opts: &Options, key_log: &Arc) -> Arc { let mut provider = opts.provider.clone(); if let Some(groups) = &opts.groups { @@ -993,6 +998,9 @@ fn make_client_cfg(opts: &Options) -> Arc { cfg.enable_sni = opts.use_sni; cfg.max_fragment_size = opts.max_fragment; cfg.require_ems = opts.require_ems; + if opts.export_traffic_secrets { + cfg.key_log = key_log.clone(); + } if !opts.protocols.is_empty() { cfg.alpn_protocols = opts @@ -1260,7 +1268,7 @@ fn read_all_bytes(opts: &Options, sess: &mut Connection, conn: &mut net::TcpStre after_read(opts, sess, conn); } -fn exec(opts: &Options, mut sess: Connection, count: usize) { +fn exec(opts: &Options, mut sess: Connection, key_log: &KeyLogMemo, count: usize) { let mut sent_message = false; let addrs = [ @@ -1352,6 +1360,24 @@ fn exec(opts: &Options, mut sess: Connection, count: usize) { sent_exporter = true; } + if !sess.is_handshaking() && opts.export_traffic_secrets && !sent_exporter { + let secrets = key_log.clone_inner(); + assert_eq!( + secrets.client_traffic_secret.len(), + secrets.server_traffic_secret.len() + ); + sess.writer() + .write_all(&(secrets.client_traffic_secret.len() as u16).to_le_bytes()) + .unwrap(); + sess.writer() + .write_all(&secrets.server_traffic_secret) + .unwrap(); + sess.writer() + .write_all(&secrets.client_traffic_secret) + .unwrap(); + sent_exporter = true; + } + if opts.send_key_update && !sent_key_update && !sess.is_handshaking() { sess.refresh_traffic_keys().unwrap(); sent_key_update = true; @@ -1671,6 +1697,9 @@ pub fn main() { "-use-export-context" => { opts.export_keying_material_context_used = true; } + "-export-traffic-secrets" => { + opts.export_traffic_secrets = true; + } "-quic-transport-params" => { opts.quic_transport_params = BASE64_STANDARD.decode(args.remove(0).as_bytes()) .expect("invalid base64"); @@ -1953,9 +1982,11 @@ pub fn main() { signal::kill(Pid::from_raw(process::id() as i32), Signal::SIGSTOP).unwrap(); } + let key_log = Arc::new(KeyLogMemo::default()); + let (mut client_cfg, mut server_cfg) = match opts.side { - Side::Client => (Some(make_client_cfg(&opts)), None), - Side::Server => (None, Some(make_server_cfg(&opts))), + Side::Client => (Some(make_client_cfg(&opts, &key_log)), None), + Side::Server => (None, Some(make_server_cfg(&opts, &key_log))), }; fn make_session( @@ -1988,26 +2019,65 @@ pub fn main() { for i in 0..opts.resumes + 1 { let sess = make_session(&opts, &server_cfg, &client_cfg); - exec(&opts, sess, i); + exec(&opts, sess, &key_log, i); if opts.resume_with_tickets_disabled { opts.tickets = false; match opts.side { - Side::Server => server_cfg = Some(make_server_cfg(&opts)), - Side::Client => client_cfg = Some(make_client_cfg(&opts)), + Side::Server => server_cfg = Some(make_server_cfg(&opts, &key_log)), + Side::Client => client_cfg = Some(make_client_cfg(&opts, &key_log)), }; } if opts.on_resume_ech_config_list.is_some() { opts.ech_config_list .clone_from(&opts.on_resume_ech_config_list); opts.expect_ech_accept = opts.on_resume_expect_ech_accept; - client_cfg = Some(make_client_cfg(&opts)); + client_cfg = Some(make_client_cfg(&opts, &key_log)); } opts.expect_handshake_kind .clone_from(&opts.expect_handshake_kind_resumed); } } +#[derive(Debug, Default)] +struct KeyLogMemo(Mutex); + +impl KeyLogMemo { + fn clone_inner(&self) -> KeyLogMemoInner { + self.0.lock().unwrap().clone() + } +} + +impl rustls::KeyLog for KeyLogMemo { + fn log(&self, label: &str, _client_random: &[u8], secret: &[u8]) { + match label { + "CLIENT_TRAFFIC_SECRET_0" => { + self.0 + .lock() + .unwrap() + .client_traffic_secret = secret.to_vec() + } + "SERVER_TRAFFIC_SECRET_0" => { + self.0 + .lock() + .unwrap() + .server_traffic_secret = secret.to_vec() + } + _ => {} + } + } + + fn will_log(&self, _label: &str) -> bool { + true + } +} + +#[derive(Clone, Debug, Default)] +struct KeyLogMemoInner { + client_traffic_secret: Vec, + server_traffic_secret: Vec, +} + #[derive(Debug, PartialEq)] enum CompressionAlgs { None, From 41be2ebdbb9fdd945f252c674f4647bfd68a1c87 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 27 Jun 2025 08:48:44 +0100 Subject: [PATCH 320/403] bogo: further fill-in skip reasons --- bogo/config.json.in | 116 ++++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index 71619d09f0d..40884adf6ef 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -17,8 +17,8 @@ "*DTLS*": "not supported", "MTU*": "dtls only", "DisableEverything": "not useful", - "CheckLeafCurve": "", - "Peek-*": "", + "CheckLeafCurve": "we don't check this in TLS1.2 (note CheckLeafCurve-TLS13 works)", + "Peek-*": "no SSL_peek or equivalent", "ServerOCSPCallback*": "ocsp not supported for servers", "SendUnsolicitedOCSPOnCertificate-TLS13": "we unconditionally request a stapled OCSP response", "DuplicateCertCompressionExt*-TLS12": "RFC8879: if TLS 1.2 or earlier is negotiated, the peers MUST ignore this extension", @@ -41,110 +41,110 @@ "TLS-ECH-Client-Reject-NoClientCertificate-TLS12-Async": "we disable TLS1.2 w/ ECH", "TLS-ECH-Client-Reject-ResumeInnerSession-TLS13": "assumes no outer GREASE PSK, we send GREASE PSK", #endif - "ALPS-*": "", - "NPN-*": "", - "NoCheckClientCertificateTypes": "we don't have this check", - "CheckClientCertificateTypes": "^", + "ALPS-*": "no ALPS support yet", + "NPN-*": "no NPN support, never", + "NoCheckClientCertificateTypes": "we don't check TLS1.2 CertificateRequest.certificate_types", + "CheckClientCertificateTypes": "we don't check TLS1.2 CertificateRequest.certificate_types", "CheckECDSACurve-TLS12": "we don't have this check", - "NoCheckECDSACurve-TLS12": "^", - "CheckClientCertificateTypes": "^", + "NoCheckECDSACurve-TLS12": "we don't have this check", + "CheckClientCertificateTypes": "we don't check TLS1.2 CertificateRequest.certificate_types", "*-RSA_PKCS1_SHA256_LEGACY-*": "NYI on our side https://datatracker.ietf.org/doc/draft-ietf-tls-tls13-pkcs1/01/", "NoCommonSignatureAlgorithms-TLS12-Fallback": "requires TLS_RSA_WITH_AES_128_GCM_SHA256", #if defined(POST_QUANTUM) "MLKEMKeyShareIncludedSecond": "we only include a share for the first configured group", - "MLKEMKeyShareIncludedThird": "^", + "MLKEMKeyShareIncludedThird": "we only include a share for the first configured group", #else "*MLKEM*": "not implemented", #endif #if defined(AWS_LC_RS) "PostQuantumNotEnabledByDefaultInClients": "it is", - "PostQuantumNotEnabledByDefaultForAServer": "", + "PostQuantumNotEnabledByDefaultForAServer": "it is", #endif "*Kyber*": "old draft, not implemented", "ExtraClientEncryptedExtension-*": "we don't implement ALPS", "Server-JDK11*": "workarounds for oracle engineering quality", - "Client-RejectJDK11DowngradeRandom": "", + "Client-RejectJDK11DowngradeRandom": "workarounds for oracle engineering quality", "SendUnsolicitedSCTOnCertificate-TLS13": "SCT stapling not supported", - "SignedCertificateTimestampListEmpty-Client-*": "", - "SignedCertificateTimestampListEmptySCT-Client-*": "", - "SendSCTListOnResume-TLS-TLS12": "", + "SignedCertificateTimestampListEmpty-Client-*": "no sct stapling", + "SignedCertificateTimestampListEmptySCT-Client-*": "no sct stapling", + "SendSCTListOnResume-TLS-TLS12": "no sct stapling", "IgnoreExtensionsOnIntermediates-TLS13": "assumes SCT support", - "CBCRecordSplitting*": "insane ciphersuites", - "*CBCPadding*": "", - "RSAEphemeralKey": "", - "BadRSAClientKeyExchange-*": "", - "SendClientVersion-RSA": "", - "Basic-Server-RSA-*": "", - "RSAKeyUsage-*": "", - "*-RSA_WITH_3DES_EDE_CBC_SHA-*": "", - "*_WITH_AES_128_CBC_*": "", - "*_WITH_AES_256_CBC_*": "", + "CBCRecordSplitting*": "no cbc suites", + "*CBCPadding*": "no cbc suites", + "RSAEphemeralKey": "no rsa kem", + "BadRSAClientKeyExchange-*": "no rsa kem", + "SendClientVersion-RSA": "no rsa kem", + "Basic-Server-RSA-*": "no rsa kem", + "RSAKeyUsage-*": "no rsa kem", + "*-RSA_WITH_3DES_EDE_CBC_SHA-*": "no cbc suites", + "*_WITH_AES_128_CBC_*": "no cbc suites", + "*_WITH_AES_256_CBC_*": "no cbc suites", "*-ECDSA_SHA1-*": "no ecdsa-sha1", "*-Sign-RSA_PKCS1_SHA1-*": "no sha1", "*-SignDefault-RSA_PKCS1_SHA1-*": "no sha1", "*-VerifyDefault-RSA_PKCS1_SHA1-*": "no sha1", "VerifyPreferences-NoCommonAlgorithms": "we validate but don't actually implement -verify-prefs", - "VerifyPreferences-Enforced": "", + "VerifyPreferences-Enforced": "we validate but don't actually implement -verify-prefs", "*_P224_*": "no p224", - "*-P-224-*": "", + "*-P-224-*": "no p224", #ifdef RING "*-ECDSA_P521_SHA512-*": "no p521 signatures/verification", #endif "CurveTest-*-P-521-*": "no p521 key exchange", "GREASE-*": "not implemented", - "LargeMessage-Reject": "", + "LargeMessage-Reject": "not supported as a runtime option (cert size limit is compile-time constant)", "DelegatedCredentials-*": "not implemented", "NoCommonCurves": "nothing to fall back to", "ClientHelloPadding": "hello padding extension not implemented", "Resume-Client-CipherMismatch": "tries to vary to unimplemented CBC-mode cs", - "*Auth-SHA1-Fallback*": "", - "RSA-PSS-Large": "", - "*-RSA_WITH_AES_128_GCM_SHA256-*": "", - "*-RSA_WITH_AES_256_GCM_SHA384-*": "", - "*-RSA_WITH_AES_128_CBC_SHA-*": "", - "*-RSA_WITH_AES_256_CBC_SHA-*": "", - "OmitExtensions-ClientHello-TLS12": "", - "EmptyExtensions-ClientHello-TLS12": "", + "*Auth-SHA1-Fallback*": "no sha1 support, so no meaningful need to assume client supports it", + "RSA-PSS-Large": "no support for 1024-bit RSA keys", + "*-RSA_WITH_AES_128_GCM_SHA256-*": "no rsa kem", + "*-RSA_WITH_AES_256_GCM_SHA384-*": "no rsa kem", + "*-RSA_WITH_AES_128_CBC_SHA-*": "no rsa kem", + "*-RSA_WITH_AES_256_CBC_SHA-*": "no rsa kem", + "OmitExtensions-ClientHello-TLS12": "we require signature algorithms ext", + "EmptyExtensions-ClientHello-TLS12": "we require signature algorithms ext", "Resume-Server-OmitPSKsOnSecondClientHello": "not required by RFC", "FallbackSCSV*": "fallback countermeasure not yet implemented", "RequireAnyClientCertificate-TLS12": "we don't send an alert in this case", "ServerBogusVersion": "we ignore legacy_version if there's an extension", - "Renegotiate-Client-*": "no reneg", - "Shutdown-Shim-Renegotiate-*": "", - "Shutdown-Shim-HelloRequest-*": "", + "Renegotiate-Client-*": "no renegotiation", + "Shutdown-Shim-Renegotiate-*": "no renegotiation", + "Shutdown-Shim-HelloRequest-*": "no renegotiation", "Shutdown-Shim-ApplicationData*": "tests boringssl/openssl-specific behaviour, we don't let application data overtake connection shutdown", - "Renegotiate-Server-*": "", - "Renegotiate-ForbidAfterHandshake": "", - "RetainOnlySHA256-*": "", - "ExtendedMasterSecret-Renego-*": "", - "ALPN*SelectEmpty-*": "", + "Renegotiate-Server-*": "no renegotiation", + "Renegotiate-ForbidAfterHandshake": "no renegotiation", + "RetainOnlySHA256-*": "test for SSL_CTX_set_retain_only_sha256_of_client_certs api", + "ExtendedMasterSecret-Renego-*": "no renegotiation", + "ALPN*SelectEmpty-*": "our API design does not allow for this", "EarlyData-*ALPN*-*": "no alpn change in resumed sessions", "*EarlyKeyingMaterial-Client-*": "early exporter NYI", - "QUICTransportParams-*": "Bogo assumes this can be tested over TLS1.3 framing -- could make this work with some effort", - "QUICCompatibilityMode": "", + "QUICTransportParams-*": "quic mode does not work over TLS1.3 framing -- do this in the shim?", + "QUICCompatibilityMode": "quic mode does not work over TLS1.3 framing -- do this in the shim?", "PAKE-*": "no PAKE draft support", "TrustAnchors-*": "no TrustAnchor draft support", "TLS13-Client-*TicketFlags*": "no flags extension support (on tickets or elsewhere)", "Ed25519DefaultDisable-NoAccept": "not implemented (ed25519 accepted by default)", "Ed25519DefaultDisable-NoAdvertise": "not implemented (ed25519 advertised by default)", "Server-VerifyDefault-Ed25519-TLS13": "ed25519 accepted by default", - "Server-VerifyDefault-Ed25519-TLS12": "", - "Client-VerifyDefault-Ed25519-TLS13": "", - "Client-VerifyDefault-Ed25519-TLS12": "", + "Server-VerifyDefault-Ed25519-TLS12": "ed25519 accepted by default", + "Client-VerifyDefault-Ed25519-TLS13": "ed25519 accepted by default", + "Client-VerifyDefault-Ed25519-TLS12": "ed25519 accepted by default", "Server-VerifyDefault-ECDSA_P521_SHA512-TLS13": "p521-sha512 accepted by default (where supported)", - "Server-VerifyDefault-ECDSA_P521_SHA512-TLS12": "", - "Client-VerifyDefault-ECDSA_P521_SHA512-TLS13": "", - "Client-VerifyDefault-ECDSA_P521_SHA512-TLS12": "", + "Server-VerifyDefault-ECDSA_P521_SHA512-TLS12": "p521-sha512 accepted by default (where supported)", + "Client-VerifyDefault-ECDSA_P521_SHA512-TLS13": "p521-sha512 accepted by default (where supported)", + "Client-VerifyDefault-ECDSA_P521_SHA512-TLS12": "p521-sha512 accepted by default (where supported)", "*-HintMismatch-*": "hints are a boringssl-specific feature", #if defined(AWS_LC_RS) && defined(FIPS) - "Compliance-fips-202205-TLS-Client-ECDSA_P521_SHA512": "these algorithms are fips approved in aws-lc-rs", - "Compliance-fips-202205-TLS-Server-ECDSA_P521_SHA512": "", - "Compliance-fips-202205-TLS-Client-Ed25519": "", - "Compliance-fips-202205-TLS-Server-Ed25519": "", + "Compliance-fips-202205-TLS-Client-ECDSA_P521_SHA512": "fips approved in aws-lc-rs", + "Compliance-fips-202205-TLS-Server-ECDSA_P521_SHA512": "fips approved in aws-lc-rs", + "Compliance-fips-202205-TLS-Client-Ed25519": "fips approved in aws-lc-rs", + "Compliance-fips-202205-TLS-Server-Ed25519": "fips approved in aws-lc-rs", #endif - "*-QUIC-*" :"", - "QUIC-*": "", - "*-QUIC": "" + "*-QUIC-*" :"quic mode does not work over TLS1.3 framing -- do this in the shim?", + "QUIC-*": "quic mode does not work over TLS1.3 framing -- do this in the shim?", + "*-QUIC": "quic mode does not work over TLS1.3 framing -- do this in the shim?" }, "ErrorMap": { ":HTTP_REQUEST:": [":GARBAGE:"], From f2bbec68a16d85eebaade8444d0fe13b983bcf72 Mon Sep 17 00:00:00 2001 From: stormshield-gt Date: Tue, 1 Jul 2025 11:14:37 +0200 Subject: [PATCH 321/403] add From> for SingleCertAndKey --- rustls/src/crypto/signer.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rustls/src/crypto/signer.rs b/rustls/src/crypto/signer.rs index 76a6189bc52..8028e74b94f 100644 --- a/rustls/src/crypto/signer.rs +++ b/rustls/src/crypto/signer.rs @@ -101,6 +101,12 @@ impl From for SingleCertAndKey { } } +impl From> for SingleCertAndKey { + fn from(certified_key: Arc) -> Self { + Self(certified_key) + } +} + impl ResolvesClientCert for SingleCertAndKey { fn resolve( &self, From 08784445bc81465c2780a5ba24bfcd12a0fb1671 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 1 Jul 2025 13:36:43 +0100 Subject: [PATCH 322/403] Memoise computation of empty hash --- rustls/src/msgs/enums.rs | 28 ++++++++++++++++++- rustls/src/tls13/key_schedule.rs | 48 ++++++++++++++++++++++++++++---- 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/rustls/src/msgs/enums.rs b/rustls/src/msgs/enums.rs index 75b16326c40..6eaa2b3288c 100644 --- a/rustls/src/msgs/enums.rs +++ b/rustls/src/msgs/enums.rs @@ -1,6 +1,6 @@ #![allow(clippy::upper_case_acronyms)] #![allow(non_camel_case_types)] -use crate::crypto::KeyExchangeAlgorithm; +use crate::crypto::{KeyExchangeAlgorithm, hash}; use crate::msgs::codec::{Codec, Reader}; enum_builder! { @@ -19,6 +19,32 @@ enum_builder! { } } +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 { + 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. diff --git a/rustls/src/tls13/key_schedule.rs b/rustls/src/tls13/key_schedule.rs index a96d9021ca7..c8b9e65da40 100644 --- a/rustls/src/tls13/key_schedule.rs +++ b/rustls/src/tls13/key_schedule.rs @@ -773,12 +773,11 @@ impl KeySchedule { /// - `SecretKind::ResumptionPSKBinderKey` /// - `SecretKind::DerivedSecret` fn derive_for_empty_hash(&self, kind: SecretKind) -> OkmBlock { - let empty_hash = self - .suite - .common - .hash_provider - .start() - .finish(); + 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()) } @@ -992,6 +991,43 @@ mod tests { }; 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() { From 7bc3052304a07adc28f8e7f4cca5d9d471ad1952 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 1 Jul 2025 15:23:36 +0100 Subject: [PATCH 323/403] Take 0.3 version of hpke* crates --- Cargo.lock | 302 ++++++++++++++++++++++++++++++++++- Cargo.toml | 6 +- provider-example/src/hpke.rs | 10 +- 3 files changed, 302 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0a6aae6b0a1..2597056300a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -706,6 +706,17 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "core-models" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94950e87ea550d6d68f1993f3e7bebc8cb7235157bff84337d46195c3aa0b3f0" +dependencies = [ + "hax-lib", + "pastey", + "rand 0.9.1", +] + [[package]] name = "cpufeatures" version = "0.2.17" @@ -1319,6 +1330,43 @@ dependencies = [ "foldhash", ] +[[package]] +name = "hax-lib" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89999d4446ba7d86c777bc6a30c106b9bf60d12eb1952242af5d1d7cb33943d" +dependencies = [ + "hax-lib-macros", + "num-bigint", + "num-traits", +] + +[[package]] +name = "hax-lib-macros" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704a31fb12a8c50243e8d4c88d006f64852822b0e24488a0de9986803a661792" +dependencies = [ + "hax-lib-macros-types", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "hax-lib-macros-types" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f302d2a43ba5888c61454ffeb8719dc43e7c0e83082d0fe302ac82d8d898b075" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "serde_json", + "uuid", +] + [[package]] name = "heck" version = "0.5.0" @@ -1421,36 +1469,58 @@ dependencies = [ [[package]] name = "hpke-rs" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11bd4ee27b79fa1820e72ef8489cc729c87299ec3f7f52b8fc8dcb87cb2d485" +checksum = "36874953dfe0223fd877a77b0eefcd84f8da36161b446c6fcb47b8311fa0251a" dependencies = [ "hpke-rs-crypto", + "hpke-rs-libcrux", + "hpke-rs-rust-crypto", + "libcrux-sha3", "log", + "rand_core 0.9.3", "zeroize", ] [[package]] name = "hpke-rs-crypto" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c3f1ae0a26c18d6469a70db1217136056261c4a244b09a755bc60bd4e055b67" +checksum = "d51ffd304e06803f90f2e56a24a6910f19b8516f842d7b72a436c51026279876" dependencies = [ - "rand_core 0.6.4", + "rand_core 0.9.3", +] + +[[package]] +name = "hpke-rs-libcrux" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb9f3bdfd7bc6a45f985b47cce25c5409312af06c2dec07a2af2cca5c89579ae" +dependencies = [ + "hpke-rs-crypto", + "libcrux-chacha20poly1305", + "libcrux-ecdh", + "libcrux-hkdf", + "libcrux-kem", + "rand 0.9.1", + "rand_chacha 0.9.0", + "rand_core 0.9.3", ] [[package]] name = "hpke-rs-rust-crypto" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08d4500baf0aced746723d3515d08212bdb9d941df6d1aca3d46d1619b2a1cf" +checksum = "ff7dc0df494528a0b90005bb511c117453c6a89cd8819f6cf311d0f4446dcf45" dependencies = [ "aes-gcm", "chacha20poly1305", "hkdf", "hpke-rs-crypto", + "k256", "p256", "p384", + "rand 0.8.5", "rand_chacha 0.3.1", "rand_core 0.6.4", "sha2", @@ -1695,6 +1765,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "elliptic-curve", +] + [[package]] name = "kv-log-macro" version = "1.0.7" @@ -1725,6 +1805,185 @@ version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +[[package]] +name = "libcrux-chacha20poly1305" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b318f5f2b32dfbfd27d1c5a3201d27b2ac7a4b4a4bf15ea754a385e6c294c5" +dependencies = [ + "libcrux-hacl-rs", + "libcrux-macros", + "libcrux-poly1305", +] + +[[package]] +name = "libcrux-curve25519" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5514645ba1ee6c55dd71d62a50cc37ad8aab3f956826001aa8dad17482655c46" +dependencies = [ + "libcrux-hacl-rs", + "libcrux-macros", +] + +[[package]] +name = "libcrux-ecdh" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c4fa67cad871d7be9175141b23a174b77536b039945c91b6a5a6d697acd6371" +dependencies = [ + "libcrux-curve25519", + "libcrux-p256", + "rand 0.9.1", +] + +[[package]] +name = "libcrux-hacl-rs" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1134af11da3f24ae8d1a7e2b60ee871c9e3ffd3d8857deaeebab8088b005addd" +dependencies = [ + "libcrux-macros", +] + +[[package]] +name = "libcrux-hkdf" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed7a54a1b453200e8a18205ffbecbb0fee0cce9ec8d0bd635898b7eb2879ac06" +dependencies = [ + "libcrux-hacl-rs", + "libcrux-hmac", +] + +[[package]] +name = "libcrux-hmac" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743cdf6149a46b2cd5f62bea237a7c57011e85055486fc031513e1261cc6692e" +dependencies = [ + "libcrux-hacl-rs", + "libcrux-macros", + "libcrux-sha2", +] + +[[package]] +name = "libcrux-intrinsics" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d3b41dcbc21a5fb7efbbb5af7405b2e79c4bfe443924e90b13afc0080318d31" +dependencies = [ + "core-models", + "hax-lib", +] + +[[package]] +name = "libcrux-kem" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eefe0e9579f058b99995cbaf918de3cbab90c4d2dde544fe75247fb027ff5af9" +dependencies = [ + "libcrux-ecdh", + "libcrux-ml-kem", + "libcrux-sha3", + "libcrux-traits", + "rand 0.9.1", +] + +[[package]] +name = "libcrux-macros" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffd6aa2dcd5be681662001b81d493f1569c6d49a32361f470b0c955465cd0338" +dependencies = [ + "quote", + "syn 2.0.101", +] + +[[package]] +name = "libcrux-ml-kem" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d368d3e8d6a74e277178d54921eca112a1e6b7837d7d8bc555091acb5d817f5" +dependencies = [ + "hax-lib", + "libcrux-intrinsics", + "libcrux-platform", + "libcrux-secrets", + "libcrux-sha3", + "rand 0.9.1", +] + +[[package]] +name = "libcrux-p256" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00d21690ebcc7ce1f242e6c4bdadfd8529f9cf2d7b961c0344c9bcb2c82f78f" +dependencies = [ + "libcrux-hacl-rs", + "libcrux-macros", + "libcrux-sha2", +] + +[[package]] +name = "libcrux-platform" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db82d058aa76ea315a3b2092f69dfbd67ddb0e462038a206e1dcd73f058c0778" +dependencies = [ + "libc", +] + +[[package]] +name = "libcrux-poly1305" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1a2901c5a92bb236cacd3d16bd6654b7f3471eb417bedab85f6225060cd4a03" +dependencies = [ + "libcrux-hacl-rs", + "libcrux-macros", +] + +[[package]] +name = "libcrux-secrets" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "332737e629fe6ba7547f5c0f90559eac865d5dbecf98138ffae8f16ab8cbe33f" +dependencies = [ + "hax-lib", +] + +[[package]] +name = "libcrux-sha2" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91eed3bb0ae073f46ae03c83318013fba6e3302bf3292639417b68e908fec4bf" +dependencies = [ + "libcrux-hacl-rs", + "libcrux-macros", + "libcrux-traits", +] + +[[package]] +name = "libcrux-sha3" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29d95de4257eafdfaf3bffecadb615219b0ca920c553722b3646d32dde76c797" +dependencies = [ + "hax-lib", + "libcrux-intrinsics", + "libcrux-platform", +] + +[[package]] +name = "libcrux-traits" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cdbf9591a39f04d6da6b9bad51ac58378604a80708c2173dadf92029891b9e2" +dependencies = [ + "rand 0.9.1", +] + [[package]] name = "libloading" version = "0.8.8" @@ -2110,6 +2369,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pastey" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a8cb46bdc156b1c90460339ae6bfd45ba0394e5effbaa640badb4987fdc261" + [[package]] name = "pem" version = "3.0.5" @@ -2300,6 +2565,28 @@ dependencies = [ "elliptic-curve", ] +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "proc-macro2" version = "1.0.95" @@ -2330,6 +2617,7 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", ] diff --git a/Cargo.toml b/Cargo.toml index 1b438463be5..eb1aee6b979 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,9 +62,9 @@ hashbrown = { version = "0.15", default-features = false, features = ["default-h hex = "0.4" hickory-resolver = { version = "0.25", features = ["https-aws-lc-rs", "webpki-roots"] } hmac = "0.12" -hpke-rs = "0.2" -hpke-rs-crypto = "0.2" -hpke-rs-rust-crypto = "0.2" +hpke-rs = "0.3" +hpke-rs-crypto = "0.3" +hpke-rs-rust-crypto = "0.3" itertools = "0.14" log = { version = "0.4.8" } macro_rules_attribute = "0.2" diff --git a/provider-example/src/hpke.rs b/provider-example/src/hpke.rs index 07b9ef8e6c1..ab680b98f32 100644 --- a/provider-example/src/hpke.rs +++ b/provider-example/src/hpke.rs @@ -171,13 +171,11 @@ impl Hpke for HpkeRs { } }; - let secret_key = HpkeRustCrypto::kem_key_gen(kem_algorithm, &mut HpkeRustCrypto::prng()) - .map_err(other_err)?; - let public_key = HpkePublicKey( - HpkeRustCrypto::kem_derive_base(kem_algorithm, &secret_key).map_err(other_err)?, - ); + let (public_key, secret_key) = + HpkeRustCrypto::kem_key_gen(kem_algorithm, &mut HpkeRustCrypto::prng()) + .map_err(other_err)?; - Ok((public_key, HpkePrivateKey::from(secret_key))) + Ok((HpkePublicKey(public_key), HpkePrivateKey::from(secret_key))) } fn suite(&self) -> HpkeSuite { From f3b75e3229694b14ded4d2b7d9cd547ef7b91465 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Thu, 3 Jul 2025 17:34:21 +0200 Subject: [PATCH 324/403] Upgrade to rcgen 0.14 --- Cargo.lock | 4 +-- Cargo.toml | 2 +- examples/src/bin/server_acceptor.rs | 55 +++++++++++++---------------- provider-example/examples/server.rs | 5 +-- rustls/examples/internal/test_ca.rs | 50 ++++++++++++++------------ 5 files changed, 58 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2597056300a..79277177937 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2692,9 +2692,9 @@ dependencies = [ [[package]] name = "rcgen" -version = "0.13.2" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" +checksum = "218a7fbb357f6da42c9fd3610b1a5128d087d460e5386eaa5040705c464611dc" dependencies = [ "aws-lc-rs", "pem", diff --git a/Cargo.toml b/Cargo.toml index eb1aee6b979..465db28b141 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -77,7 +77,7 @@ pkcs8 = "0.10.2" pki-types = { package = "rustls-pki-types", version = "1.11", features = ["alloc"] } rand_core = { version = "0.6", features = ["getrandom"] } rayon = "1.7" -rcgen = { version = "0.13", features = ["pem", "aws_lc_rs"], default-features = false } +rcgen = { version = "0.14", features = ["pem", "aws_lc_rs"], default-features = false } regex = "1" ring = "0.17" rsa = { version = "0.9", features = ["sha2"], default-features = false } diff --git a/examples/src/bin/server_acceptor.rs b/examples/src/bin/server_acceptor.rs index 0239bb4442d..5579814ea5b 100644 --- a/examples/src/bin/server_acceptor.rs +++ b/examples/src/bin/server_acceptor.rs @@ -13,7 +13,7 @@ use std::time::Duration; use std::{fs, thread}; use clap::Parser; -use rcgen::KeyPair; +use rcgen::{Issuer, KeyPair, SerialNumber}; use rustls::RootCertStore; use rustls::pki_types::{CertificateRevocationListDer, PrivatePkcs8KeyDer}; use rustls::server::{Acceptor, ClientHello, ServerConfig, WebPkiClientVerifier}; @@ -41,13 +41,14 @@ fn main() { // Write out the parts of the test PKI a client will need to connect: // * The CA certificate for validating the server certificate. // * The client certificate and key for its presented mTLS identity. - write_pem(&args.ca_path, &test_pki.ca_cert.cert.pem()); - write_pem(&args.client_cert_path, &test_pki.client_cert.cert.pem()); + write_pem(&args.ca_path, &test_pki.ca_cert.1.pem()); + write_pem(&args.client_cert_path, &test_pki.client_cert.0.cert.pem()); write_pem( &args.client_key_path, &test_pki .client_cert - .key_pair + .0 + .signing_key .serialize_pem(), ); @@ -110,9 +111,9 @@ fn main() { /// A test PKI with a CA certificate, server certificate, and client certificate. struct TestPki { roots: Arc, - ca_cert: rcgen::CertifiedKey, - client_cert: rcgen::CertifiedKey, - server_cert: rcgen::CertifiedKey, + ca_cert: (Issuer<'static, rcgen::KeyPair>, rcgen::Certificate), + client_cert: (rcgen::CertifiedKey, SerialNumber), + server_cert: rcgen::CertifiedKey, } impl TestPki { @@ -135,6 +136,7 @@ impl TestPki { ]; let ca_key = KeyPair::generate_for(alg).unwrap(); let ca_cert = ca_params.self_signed(&ca_key).unwrap(); + let ca = Issuer::new(ca_params, ca_key); // Create a server end entity cert issued by the CA. let mut server_ee_params = @@ -143,7 +145,7 @@ impl TestPki { server_ee_params.extended_key_usages = vec![rcgen::ExtendedKeyUsagePurpose::ServerAuth]; let ee_key = KeyPair::generate_for(alg).unwrap(); let server_cert = server_ee_params - .signed_by(&ee_key, &ca_cert, &ca_key) + .signed_by(&ee_key, &ca) .unwrap(); // Create a client end entity cert issued by the CA. @@ -153,10 +155,11 @@ impl TestPki { .push(rcgen::DnType::CommonName, "Example Client"); client_ee_params.is_ca = rcgen::IsCa::NoCa; client_ee_params.extended_key_usages = vec![rcgen::ExtendedKeyUsagePurpose::ClientAuth]; - client_ee_params.serial_number = Some(rcgen::SerialNumber::from(vec![0xC0, 0xFF, 0xEE])); + let client_serial = rcgen::SerialNumber::from(vec![0xC0, 0xFF, 0xEE]); + client_ee_params.serial_number = Some(client_serial.clone()); let client_key = KeyPair::generate_for(alg).unwrap(); let client_cert = client_ee_params - .signed_by(&client_key, &ca_cert, &ca_key) + .signed_by(&client_key, &ca) .unwrap(); // Create a root cert store that includes the CA certificate. @@ -166,17 +169,17 @@ impl TestPki { .unwrap(); Self { roots: roots.into(), - ca_cert: rcgen::CertifiedKey { - cert: ca_cert, - key_pair: ca_key, - }, - client_cert: rcgen::CertifiedKey { - cert: client_cert, - key_pair: client_key, - }, + ca_cert: (ca, ca_cert), + client_cert: ( + rcgen::CertifiedKey { + cert: client_cert, + signing_key: client_key, + }, + client_ee_params.serial_number.unwrap(), + ), server_cert: rcgen::CertifiedKey { cert: server_cert, - key_pair: ee_key, + signing_key: ee_key, }, } } @@ -210,7 +213,7 @@ impl TestPki { vec![self.server_cert.cert.der().clone()], PrivatePkcs8KeyDer::from( self.server_cert - .key_pair + .signing_key .serialize_der(), ) .into(), @@ -254,7 +257,7 @@ impl TestPki { key_identifier_method: rcgen::KeyIdMethod::Sha256, }; crl_params - .signed_by(&self.ca_cert.cert, &self.ca_cert.key_pair) + .signed_by(&self.ca_cert.0) .unwrap() .into() } @@ -280,15 +283,7 @@ impl CrlUpdater { thread::sleep(self.sleep_duration); let revoked_certs = if revoked { - vec![ - self.pki - .client_cert - .cert - .params() - .serial_number - .clone() - .unwrap(), - ] + vec![self.pki.client_cert.1.clone()] } else { Vec::default() }; diff --git a/provider-example/examples/server.rs b/provider-example/examples/server.rs index eee2de189d2..fca01985abd 100644 --- a/provider-example/examples/server.rs +++ b/provider-example/examples/server.rs @@ -71,7 +71,7 @@ impl TestPki { rcgen::KeyUsagePurpose::DigitalSignature, ]; let ca_key = rcgen::KeyPair::generate_for(alg).unwrap(); - let ca_cert = ca_params.self_signed(&ca_key).unwrap(); + let ca = rcgen::Issuer::new(ca_params, ca_key); // Create a server end entity cert issued by the CA. let mut server_ee_params = @@ -79,8 +79,9 @@ impl TestPki { server_ee_params.is_ca = rcgen::IsCa::NoCa; server_ee_params.extended_key_usages = vec![rcgen::ExtendedKeyUsagePurpose::ServerAuth]; let server_key = rcgen::KeyPair::generate_for(alg).unwrap(); + let server_cert = server_ee_params - .signed_by(&server_key, &ca_cert, &ca_key) + .signed_by(&server_key, &ca) .unwrap(); Self { server_cert_der: server_cert.into(), diff --git a/rustls/examples/internal/test_ca.rs b/rustls/examples/internal/test_ca.rs index daf468a08f2..1df38484936 100644 --- a/rustls/examples/internal/test_ca.rs +++ b/rustls/examples/internal/test_ca.rs @@ -8,9 +8,10 @@ use std::str::FromStr; use std::sync::atomic::{AtomicU64, Ordering}; use std::time::Duration; +use rcgen::string::Ia5String; use rcgen::{ - BasicConstraints, CertificateParams, CertificateRevocationListParams, CertifiedKey, - DistinguishedName, DnType, ExtendedKeyUsagePurpose, Ia5String, IsCa, KeyIdMethod, KeyPair, + 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, @@ -18,7 +19,11 @@ use rcgen::{ use time::OffsetDateTime; fn main() -> Result<(), Box> { - let mut certified_keys = HashMap::with_capacity(ROLES.len() * SIG_ALGS.len()); + 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. @@ -29,23 +34,27 @@ fn main() -> Result<(), Box> { // 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 cert = match role { - Role::TrustAnchor => role - .params(alg) - .self_signed(&key_pair)?, + 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: &CertifiedKey = certified_keys + let issuer = certified_keys .get(&(Role::TrustAnchor, alg.inner)) .unwrap(); - role.params(alg) - .signed_by(&key_pair, &issuer.cert, &issuer.key_pair)? + 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(); - role.params(alg) - .signed_by(&key_pair, &issuer.cert, &issuer.key_pair)? + let params = role.params(alg); + let cert = params.signed_by(&key_pair, &issuer.0)?; + (params, cert) } }; @@ -71,20 +80,15 @@ fn main() -> Result<(), Box> { _ => panic!("unexpected role for CRL generation: {role:?}"), }; - let revoked_crl = crl_for_serial( - cert.params() - .serial_number - .clone() - .unwrap(), - ) - .signed_by(&issuer.cert, &issuer.key_pair)?; + 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.cert, &issuer.key_pair)?; + 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())), @@ -98,11 +102,11 @@ fn main() -> Result<(), Box> { let root = &certified_keys .get(&(Role::TrustAnchor, alg.inner)) .unwrap() - .cert; + .1; let intermediate = &certified_keys .get(&(Role::Intermediate, alg.inner)) .unwrap() - .cert; + .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 @@ -129,7 +133,7 @@ fn main() -> Result<(), Box> { raw_public_key_file.write_all(key_pair.public_key_pem().as_bytes())?; } - certified_keys.insert((role, alg.inner), CertifiedKey { cert, key_pair }); + certified_keys.insert((role, alg.inner), (Issuer::new(params, key_pair), cert)); } } From a5433a154b8eb24afbd11162b9ab93fb0aa365dc Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 4 Jul 2025 13:47:10 +0100 Subject: [PATCH 325/403] Correct calculation of ServerHello ECH confirmation This was another case where we were relying on the ability to round-trip received messages. That assumption as abandoned in 692f981446. This meant that we calculated the ECH confirmation based on a different extension ordering than the one the server sent, which meant it didn't match. bogo and the cloudflare test server continued to work, as they just happened to choose the same extension ordering as us. But OpenSSL didn't. --- rustls/src/client/ech.rs | 106 +++++++++++++++++++++++++++++++++-- rustls/src/client/tls13.rs | 12 ++++ rustls/src/msgs/handshake.rs | 24 +++----- 3 files changed, 120 insertions(+), 22 deletions(-) diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index c396076640e..616ebbfc533 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -449,6 +449,7 @@ impl EchState { self, ks: &mut KeyScheduleHandshakeStart, server_hello: &ServerHelloPayload, + server_hello_encoded: &Payload<'_>, hash: &'static dyn Hash, ) -> Result, Error> { // Start the inner transcript hash now that we know the hash algorithm to use. @@ -460,8 +461,10 @@ impl EchState { // 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 differs from the standard server hello encoding. - confirmation_transcript.add_message(&Self::server_hello_conf(server_hello)); + // 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( @@ -760,10 +763,29 @@ impl EchState { Ok(()) } - fn server_hello_conf(server_hello: &ServerHelloPayload) -> Message<'_> { - Self::ech_conf_message(HandshakeMessagePayload(HandshakePayload::ServerHello( - server_hello.clone(), - ))) + 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<'_> { @@ -785,6 +807,16 @@ impl EchState { } } +/// 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 = + (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. @@ -803,3 +835,65 @@ pub(crate) fn fatal_alert_required( 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/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index d73c5a88117..ec11876f08f 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -180,9 +180,21 @@ pub(super) fn handle_server_hello( // 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 diff --git a/rustls/src/msgs/handshake.rs b/rustls/src/msgs/handshake.rs index fd28ba1e4a6..093f2d12bd7 100644 --- a/rustls/src/msgs/handshake.rs +++ b/rustls/src/msgs/handshake.rs @@ -1599,20 +1599,13 @@ impl Codec<'_> for ServerHelloPayload { impl ServerHelloPayload { fn payload_encode(&self, bytes: &mut Vec, encoding: Encoding) { - self.legacy_version.encode(bytes); - - match encoding { - // When encoding a ServerHello for ECH confirmation, the random value - // has the last 8 bytes zeroed out. - Encoding::EchConfirmation => { - // Indexing safety: self.random is 32 bytes long by definition. - let rand_vec = self.random.get_encoding(); - bytes.extend_from_slice(&rand_vec.as_slice()[..24]); - bytes.extend_from_slice(&[0u8; 8]); - } - _ => self.random.encode(bytes), - } + 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); @@ -3109,12 +3102,11 @@ impl Codec<'_> for ServerEncryptedClientHello { /// 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. For example, a [ServerHelloPayload] may be encoded -/// with the last 8 bytes of the random zeroed out when being encoded for ECH confirmation. +/// the encoded message is being used for. pub(crate) enum Encoding { /// Standard RFC 8446 encoding. Standard, - /// Encoding for ECH confirmation. + /// Encoding for ECH confirmation for HRR. EchConfirmation, /// Encoding for ECH inner client hello. EchInnerHello { to_compress: Vec }, From efa2066469ba715979827d180bead43000b75d10 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 7 Jul 2025 12:11:46 +0100 Subject: [PATCH 326/403] Improve compactness of Debug impl for extensions --- rustls/src/msgs/macros.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/rustls/src/msgs/macros.rs b/rustls/src/msgs/macros.rs index 480950a6d67..53252a20947 100644 --- a/rustls/src/msgs/macros.rs +++ b/rustls/src/msgs/macros.rs @@ -121,7 +121,7 @@ macro_rules! extension_struct { ) => { $(#[doc = $comment])* #[non_exhaustive] - #[derive(Clone, Debug, Default)] + #[derive(Clone, Default)] $struct_vis struct $struct_name$(<$struct_lt>)* { $( $(#[$item_attr])* @@ -294,5 +294,20 @@ macro_rules! extension_struct { $($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() + } + } } } From 373ad888e2dfbaaab39be36496849eb3cc54cff1 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 1 Jul 2025 15:07:57 +0100 Subject: [PATCH 327/403] tls13::key_schedule: move `SecretKind` down --- rustls/src/tls13/key_schedule.rs | 104 +++++++++++++++---------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/rustls/src/tls13/key_schedule.rs b/rustls/src/tls13/key_schedule.rs index c8b9e65da40..4373b52c1d2 100644 --- a/rustls/src/tls13/key_schedule.rs +++ b/rustls/src/tls13/key_schedule.rs @@ -12,58 +12,6 @@ use crate::msgs::message::Message; use crate::suites::PartiallyExtractedSecrets; use crate::{ConnectionTrafficSecrets, KeyLog, Tls13CipherSuite, quic}; -/// 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; - } - }) - } -} - /// 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. @@ -978,6 +926,58 @@ where 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 { From 9620bec130da2426e29b0fbb7d2969d728f7badd Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 1 Jul 2025 15:11:35 +0100 Subject: [PATCH 328/403] tls13::key_schedule: move `KeySchedule` struct down --- rustls/src/tls13/key_schedule.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/rustls/src/tls13/key_schedule.rs b/rustls/src/tls13/key_schedule.rs index 4373b52c1d2..e9994bef6b6 100644 --- a/rustls/src/tls13/key_schedule.rs +++ b/rustls/src/tls13/key_schedule.rs @@ -12,14 +12,6 @@ use crate::msgs::message::Message; use crate::suites::PartiallyExtractedSecrets; use crate::{ConnectionTrafficSecrets, KeyLog, Tls13CipherSuite, quic}; -/// 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, - suite: &'static Tls13CipherSuite, -} - // 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 @@ -604,6 +596,14 @@ impl<'a> ResumptionSecret<'a> { } } +/// 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, + suite: &'static Tls13CipherSuite, +} + impl KeySchedule { fn new(suite: &'static Tls13CipherSuite, secret: &[u8]) -> Self { Self { From e5998cd100b832a769d79273f0e69fd127cf7dd0 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 2 Jul 2025 08:06:47 +0100 Subject: [PATCH 329/403] key_schedule: add state for derivations before finish `KeyScheduleBeforeFinished` encapsulates the first tranche of final derivations that do not include the client's finished message in the transcript. `KeyScheduleTraffic` contains all such final derivations, which means the client does not need to hang on to the transcript or rederive the resumption secret. --- rustls/src/client/tls13.rs | 10 +- rustls/src/server/tls13.rs | 26 ++-- rustls/src/tls13/key_schedule.rs | 203 +++++++++++++++++-------------- 3 files changed, 130 insertions(+), 109 deletions(-) diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index ec11876f08f..167d3964247 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -41,7 +41,6 @@ use crate::suites::PartiallyExtractedSecrets; use crate::sync::Arc; use crate::tls13::key_schedule::{ KeyScheduleEarly, KeyScheduleHandshake, KeySchedulePreHandshake, KeyScheduleTraffic, - ResumptionSecret, }; use crate::tls13::{ Tls13CipherSuite, construct_client_verify_message, construct_server_verify_message, @@ -1422,7 +1421,8 @@ impl State for ExpectFinished { /* Now move to our application traffic keys. */ cx.common.check_aligned_handshake()?; - let key_schedule_traffic = key_schedule_pre_finished.into_traffic(cx.common); + let key_schedule_traffic = + key_schedule_pre_finished.into_traffic(cx.common, st.transcript.current_hash()); cx.common .start_traffic(&mut cx.sendable_plaintext); @@ -1438,7 +1438,6 @@ impl State for ExpectFinished { session_storage: st.config.resumption.store.clone(), server_name: st.server_name, suite: st.suite, - transcript: st.transcript, key_schedule: key_schedule_traffic, _cert_verified: st.cert_verified, _sig_verified: st.sig_verified, @@ -1464,7 +1463,6 @@ struct ExpectTraffic { session_storage: Arc, server_name: ServerName<'static>, suite: &'static Tls13CipherSuite, - transcript: HandshakeHash, key_schedule: KeyScheduleTraffic, _cert_verified: verify::ServerCertVerified, _sig_verified: verify::HandshakeSignatureValid, @@ -1477,8 +1475,8 @@ impl ExpectTraffic { cx: &mut KernelContext<'_>, nst: &NewSessionTicketPayloadTls13, ) -> Result<(), Error> { - let handshake_hash = self.transcript.current_hash(); - let secret = ResumptionSecret::new(&self.key_schedule, &handshake_hash) + let secret = self + .key_schedule .derive_ticket_psk(&nst.nonce.0); let now = self.config.current_time()?; diff --git a/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index bc5d53870a7..3d7ba5c89ee 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -29,9 +29,7 @@ use crate::msgs::persist; use crate::server::ServerConfig; use crate::suites::PartiallyExtractedSecrets; use crate::sync::Arc; -use crate::tls13::key_schedule::{ - KeyScheduleTraffic, KeyScheduleTrafficWithClientFinishedPending, ResumptionSecret, -}; +use crate::tls13::key_schedule::{KeyScheduleTraffic, KeyScheduleTrafficWithClientFinishedPending}; use crate::tls13::{ Tls13CipherSuite, construct_client_verify_message, construct_server_verify_message, }; @@ -1224,7 +1222,7 @@ impl State for ExpectEarlyData { // --- Process client's Finished --- fn get_server_session_value( suite: &'static Tls13CipherSuite, - secret: &ResumptionSecret<'_>, + key_schedule: &KeyScheduleTraffic, cx: &ServerContext<'_>, nonce: &[u8], time_now: UnixTime, @@ -1232,7 +1230,7 @@ fn get_server_session_value( ) -> persist::ServerSessionValue { let version = ProtocolVersion::TLSv1_3; - let secret = secret.derive_ticket_psk(nonce); + let secret = key_schedule.derive_ticket_psk(nonce); persist::ServerSessionValue::new( cx.data.sni.as_ref(), @@ -1260,7 +1258,7 @@ impl ExpectFinished { flight: &mut HandshakeFlightTls13<'_>, suite: &'static Tls13CipherSuite, cx: &ServerContext<'_>, - secret: &ResumptionSecret<'_>, + key_schedule: &KeyScheduleTraffic, config: &ServerConfig, ) -> Result<(), Error> { let secure_random = config.provider.secure_random; @@ -1270,7 +1268,7 @@ impl ExpectFinished { let now = config.current_time()?; let plain = - get_server_session_value(suite, secret, cx, &nonce, now, age_add).get_encoding(); + get_server_session_value(suite, key_schedule, cx, &nonce, now, age_add).get_encoding(); let stateless = config.ticketer.enabled(); let (ticket, lifetime) = if stateless { @@ -1324,7 +1322,7 @@ impl State for ExpectFinished { require_handshake_msg!(m, HandshakeType::Finished, HandshakePayload::Finished)?; let handshake_hash = self.transcript.current_hash(); - let (key_schedule_traffic, expect_verify_data) = self + let (key_schedule_before_finished, expect_verify_data) = self .key_schedule .sign_client_finish(&handshake_hash, cx.common); @@ -1344,12 +1342,18 @@ impl State for ExpectFinished { cx.common.check_aligned_handshake()?; - let handshake_hash = self.transcript.current_hash(); - let resumption = ResumptionSecret::new(&key_schedule_traffic, &handshake_hash); + let key_schedule_traffic = + 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)?; + Self::emit_ticket( + &mut flight, + self.suite, + cx, + &key_schedule_traffic, + &self.config, + )?; } flight.finish(cx.common); diff --git a/rustls/src/tls13/key_schedule.rs b/rustls/src/tls13/key_schedule.rs index e9994bef6b6..6fe0804bef1 100644 --- a/rustls/src/tls13/key_schedule.rs +++ b/rustls/src/tls13/key_schedule.rs @@ -309,13 +309,14 @@ impl KeyScheduleHandshake { ) -> KeyScheduleTrafficWithClientFinishedPending { debug_assert_eq!(common.side, Side::Server); - let traffic = KeyScheduleTraffic::new(self.ks, hs_hash, key_log, client_random); + let before_finished = + KeyScheduleBeforeFinished::new(self.ks, hs_hash, key_log, client_random); let (_client_secret, server_secret) = ( - &traffic.current_client_traffic_secret, - &traffic.current_server_traffic_secret, + &before_finished.current_client_traffic_secret, + &before_finished.current_server_traffic_secret, ); - traffic + before_finished .ks .set_encrypter(server_secret, common); @@ -323,8 +324,8 @@ impl KeyScheduleHandshake { common.quic.traffic_secrets = Some(quic::Secrets::new( _client_secret.clone(), server_secret.clone(), - traffic.ks.suite, - traffic.ks.suite.quic.unwrap(), + before_finished.ks.suite, + before_finished.ks.suite.quic.unwrap(), common.side, common.quic.version, )); @@ -332,7 +333,7 @@ impl KeyScheduleHandshake { KeyScheduleTrafficWithClientFinishedPending { handshake_client_traffic_secret: self.client_handshake_traffic_secret, - traffic, + before_finished, } } @@ -343,49 +344,120 @@ impl KeyScheduleHandshake { key_log: &dyn KeyLog, client_random: &[u8; 32], ) -> (KeyScheduleClientBeforeFinished, hmac::Tag) { - let traffic = KeyScheduleTraffic::new(self.ks, pre_finished_hash, key_log, client_random); - let tag = traffic + 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 { traffic }, tag) + (KeyScheduleClientBeforeFinished(before_finished), tag) } } -pub(crate) struct KeyScheduleClientBeforeFinished { - traffic: KeyScheduleTraffic, +/// 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 { + 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, + current_client_traffic_secret, + current_server_traffic_secret, + current_exporter_secret, + 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) -> KeyScheduleTraffic { + pub(crate) fn into_traffic( + self, + common: &mut CommonState, + hs_hash: hash::Output, + ) -> KeyScheduleTraffic { + let next = self.0; + debug_assert_eq!(common.side, Side::Client); let (client_secret, server_secret) = ( - &self - .traffic - .current_client_traffic_secret, - &self - .traffic - .current_server_traffic_secret, + &next.current_client_traffic_secret, + &next.current_server_traffic_secret, ); - self.traffic - .ks + next.ks .set_decrypter(server_secret, common); - self.traffic - .ks + 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(), - self.traffic.ks.suite, - self.traffic.ks.suite.quic.unwrap(), + next.ks.suite, + next.ks.suite.quic.unwrap(), common.side, common.quic.version, )); } - self.traffic + next.into_traffic(hs_hash) } } @@ -394,13 +466,13 @@ impl KeyScheduleClientBeforeFinished { /// through signing the client finished hash. pub(crate) struct KeyScheduleTrafficWithClientFinishedPending { handshake_client_traffic_secret: OkmBlock, - traffic: KeyScheduleTraffic, + before_finished: KeyScheduleBeforeFinished, } impl KeyScheduleTrafficWithClientFinishedPending { pub(crate) fn update_decrypter(&self, common: &mut CommonState) { debug_assert_eq!(common.side, Side::Server); - self.traffic + self.before_finished .ks .set_decrypter(&self.handshake_client_traffic_secret, common); } @@ -409,22 +481,22 @@ impl KeyScheduleTrafficWithClientFinishedPending { self, hs_hash: &hash::Output, common: &mut CommonState, - ) -> (KeyScheduleTraffic, hmac::Tag) { + ) -> (KeyScheduleBeforeFinished, hmac::Tag) { debug_assert_eq!(common.side, Side::Server); let tag = self - .traffic + .before_finished .ks .sign_finish(&self.handshake_client_traffic_secret, hs_hash); // Install keying to read future messages. - self.traffic.ks.set_decrypter( + self.before_finished.ks.set_decrypter( &self - .traffic + .before_finished .current_client_traffic_secret, common, ); - (self.traffic, tag) + (self.before_finished, tag) } } @@ -435,46 +507,10 @@ pub(crate) struct KeyScheduleTraffic { current_client_traffic_secret: OkmBlock, current_server_traffic_secret: OkmBlock, current_exporter_secret: OkmBlock, + resumption_master_secret: OkmBlock, } impl KeyScheduleTraffic { - 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 update_encrypter_and_notify(&mut self, common: &mut CommonState) { let secret = self.next_application_traffic_secret(common.side); common.enqueue_key_update_notification(); @@ -508,6 +544,11 @@ impl KeyScheduleTraffic { secret } + pub(crate) fn derive_ticket_psk(&self, nonce: &[u8]) -> OkmBlock { + self.ks + .derive_ticket_psk(&self.resumption_master_secret, nonce) + } + pub(crate) fn export_keying_material( &self, out: &mut [u8], @@ -574,28 +615,6 @@ fn expand_secret(secret: &OkmBlock, hkdf: &'static dyn Hkdf, aead_key_len: usize ) } -pub(crate) struct ResumptionSecret<'a> { - kst: &'a KeyScheduleTraffic, - resumption_master_secret: OkmBlock, -} - -impl<'a> ResumptionSecret<'a> { - pub(crate) fn new(kst: &'a KeyScheduleTraffic, hs_hash: &hash::Output) -> Self { - ResumptionSecret { - kst, - resumption_master_secret: kst - .ks - .derive(SecretKind::ResumptionMasterSecret, hs_hash.as_ref()), - } - } - - pub(crate) fn derive_ticket_psk(&self, nonce: &[u8]) -> OkmBlock { - self.kst - .ks - .derive_ticket_psk(&self.resumption_master_secret, nonce) - } -} - /// 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. From d2c64f0416b3f6a5e6f74bee9f553a65c146395c Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 2 Jul 2025 09:31:48 +0100 Subject: [PATCH 330/403] key_schedule: separate ops not using current secret --- rustls/src/tls13/key_schedule.rs | 96 ++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 36 deletions(-) diff --git a/rustls/src/tls13/key_schedule.rs b/rustls/src/tls13/key_schedule.rs index 6fe0804bef1..2c4b6beb8ba 100644 --- a/rustls/src/tls13/key_schedule.rs +++ b/rustls/src/tls13/key_schedule.rs @@ -2,6 +2,7 @@ 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}; @@ -164,7 +165,7 @@ impl KeyScheduleHandshakeStart { ) -> KeyScheduleHandshake { debug_assert_eq!(common.side, Side::Client); // Suite might have changed due to resumption - self.ks.suite = suite; + 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 @@ -620,7 +621,7 @@ fn expand_secret(secret: &OkmBlock, hkdf: &'static dyn Hkdf, aead_key_len: usize /// typestates. struct KeySchedule { current: Box, - suite: &'static Tls13CipherSuite, + inner: KeyScheduleSuite, } impl KeySchedule { @@ -629,49 +630,17 @@ impl KeySchedule { current: suite .hkdf_provider .extract_from_secret(None, secret), - suite, + inner: suite.into(), } } - 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 { - 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) - } - /// 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), - suite, + inner: suite.into(), } } @@ -747,6 +716,55 @@ impl KeySchedule { .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 { + 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. @@ -827,6 +845,12 @@ impl KeySchedule { } } +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]: From 788b0df12216aab37117d227f141c59c28514aea Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 2 Jul 2025 09:43:17 +0100 Subject: [PATCH 331/403] key_schedule: erase master secret in traffic state --- rustls/src/tls13/key_schedule.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rustls/src/tls13/key_schedule.rs b/rustls/src/tls13/key_schedule.rs index 2c4b6beb8ba..c99bb19e86a 100644 --- a/rustls/src/tls13/key_schedule.rs +++ b/rustls/src/tls13/key_schedule.rs @@ -412,7 +412,7 @@ impl KeyScheduleBeforeFinished { ks.derive(SecretKind::ResumptionMasterSecret, hs_hash.as_ref()); KeyScheduleTraffic { - ks, + ks: ks.inner, current_client_traffic_secret, current_server_traffic_secret, current_exporter_secret, @@ -504,7 +504,7 @@ impl KeyScheduleTrafficWithClientFinishedPending { /// KeySchedule during traffic stage. All traffic & exporter keys are guaranteed /// to be available. pub(crate) struct KeyScheduleTraffic { - ks: KeySchedule, + ks: KeyScheduleSuite, current_client_traffic_secret: OkmBlock, current_server_traffic_secret: OkmBlock, current_exporter_secret: OkmBlock, From c84675e34b525b7597c5632202e483c0b68f7e1c Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 2 Jul 2025 10:20:29 +0100 Subject: [PATCH 332/403] key_schedule: minimise lifetime of resumption secret For servers, we can be sure we don't require this once we have sent all tickets. That means we can erase `KeyScheduleResumption` once that happens. For clients there's no ability to know a server has sent all possible tickets, so we have to keep this hanging around. --- rustls/src/client/tls13.rs | 11 +++++--- rustls/src/server/tls13.rs | 22 +++++++--------- rustls/src/tls13/key_schedule.rs | 44 +++++++++++++++++++++----------- 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index 167d3964247..fe8495cc341 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -40,7 +40,8 @@ use crate::sign::{CertifiedKey, Signer}; use crate::suites::PartiallyExtractedSecrets; use crate::sync::Arc; use crate::tls13::key_schedule::{ - KeyScheduleEarly, KeyScheduleHandshake, KeySchedulePreHandshake, KeyScheduleTraffic, + KeyScheduleEarly, KeyScheduleHandshake, KeySchedulePreHandshake, KeyScheduleResumption, + KeyScheduleTraffic, }; use crate::tls13::{ Tls13CipherSuite, construct_client_verify_message, construct_server_verify_message, @@ -1421,7 +1422,7 @@ impl State for ExpectFinished { /* Now move to our application traffic keys. */ cx.common.check_aligned_handshake()?; - let key_schedule_traffic = + let (key_schedule, resumption) = key_schedule_pre_finished.into_traffic(cx.common, st.transcript.current_hash()); cx.common .start_traffic(&mut cx.sendable_plaintext); @@ -1438,7 +1439,8 @@ impl State for ExpectFinished { session_storage: st.config.resumption.store.clone(), server_name: st.server_name, suite: st.suite, - key_schedule: key_schedule_traffic, + key_schedule, + resumption, _cert_verified: st.cert_verified, _sig_verified: st.sig_verified, _fin_verified: fin, @@ -1464,6 +1466,7 @@ struct ExpectTraffic { server_name: ServerName<'static>, suite: &'static Tls13CipherSuite, key_schedule: KeyScheduleTraffic, + resumption: KeyScheduleResumption, _cert_verified: verify::ServerCertVerified, _sig_verified: verify::HandshakeSignatureValid, _fin_verified: verify::FinishedMessageVerified, @@ -1476,7 +1479,7 @@ impl ExpectTraffic { nst: &NewSessionTicketPayloadTls13, ) -> Result<(), Error> { let secret = self - .key_schedule + .resumption .derive_ticket_psk(&nst.nonce.0); let now = self.config.current_time()?; diff --git a/rustls/src/server/tls13.rs b/rustls/src/server/tls13.rs index 3d7ba5c89ee..b8b70e721a7 100644 --- a/rustls/src/server/tls13.rs +++ b/rustls/src/server/tls13.rs @@ -29,7 +29,9 @@ use crate::msgs::persist; use crate::server::ServerConfig; use crate::suites::PartiallyExtractedSecrets; use crate::sync::Arc; -use crate::tls13::key_schedule::{KeyScheduleTraffic, KeyScheduleTrafficWithClientFinishedPending}; +use crate::tls13::key_schedule::{ + KeyScheduleResumption, KeyScheduleTraffic, KeyScheduleTrafficWithClientFinishedPending, +}; use crate::tls13::{ Tls13CipherSuite, construct_client_verify_message, construct_server_verify_message, }; @@ -1222,7 +1224,7 @@ impl State for ExpectEarlyData { // --- Process client's Finished --- fn get_server_session_value( suite: &'static Tls13CipherSuite, - key_schedule: &KeyScheduleTraffic, + resumption: &KeyScheduleResumption, cx: &ServerContext<'_>, nonce: &[u8], time_now: UnixTime, @@ -1230,7 +1232,7 @@ fn get_server_session_value( ) -> persist::ServerSessionValue { let version = ProtocolVersion::TLSv1_3; - let secret = key_schedule.derive_ticket_psk(nonce); + let secret = resumption.derive_ticket_psk(nonce); persist::ServerSessionValue::new( cx.data.sni.as_ref(), @@ -1258,7 +1260,7 @@ impl ExpectFinished { flight: &mut HandshakeFlightTls13<'_>, suite: &'static Tls13CipherSuite, cx: &ServerContext<'_>, - key_schedule: &KeyScheduleTraffic, + resumption: &KeyScheduleResumption, config: &ServerConfig, ) -> Result<(), Error> { let secure_random = config.provider.secure_random; @@ -1268,7 +1270,7 @@ impl ExpectFinished { let now = config.current_time()?; let plain = - get_server_session_value(suite, key_schedule, cx, &nonce, now, age_add).get_encoding(); + get_server_session_value(suite, resumption, cx, &nonce, now, age_add).get_encoding(); let stateless = config.ticketer.enabled(); let (ticket, lifetime) = if stateless { @@ -1342,18 +1344,12 @@ impl State for ExpectFinished { cx.common.check_aligned_handshake()?; - let key_schedule_traffic = + 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, - &key_schedule_traffic, - &self.config, - )?; + Self::emit_ticket(&mut flight, self.suite, cx, &resumption, &self.config)?; } flight.finish(cx.common); diff --git a/rustls/src/tls13/key_schedule.rs b/rustls/src/tls13/key_schedule.rs index c99bb19e86a..4bf04214674 100644 --- a/rustls/src/tls13/key_schedule.rs +++ b/rustls/src/tls13/key_schedule.rs @@ -400,7 +400,10 @@ impl KeyScheduleBeforeFinished { } } - pub(crate) fn into_traffic(self, hs_hash: hash::Output) -> KeyScheduleTraffic { + pub(crate) fn into_traffic( + self, + hs_hash: hash::Output, + ) -> (KeyScheduleTraffic, KeyScheduleResumption) { let Self { ks, current_client_traffic_secret, @@ -411,13 +414,18 @@ impl KeyScheduleBeforeFinished { 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, - resumption_master_secret, - } + ( + KeyScheduleTraffic { + ks: ks.inner, + current_client_traffic_secret, + current_server_traffic_secret, + current_exporter_secret, + }, + KeyScheduleResumption { + ks: ks.inner, + resumption_master_secret, + }, + ) } } @@ -433,7 +441,7 @@ impl KeyScheduleClientBeforeFinished { self, common: &mut CommonState, hs_hash: hash::Output, - ) -> KeyScheduleTraffic { + ) -> (KeyScheduleTraffic, KeyScheduleResumption) { let next = self.0; debug_assert_eq!(common.side, Side::Client); @@ -508,7 +516,6 @@ pub(crate) struct KeyScheduleTraffic { current_client_traffic_secret: OkmBlock, current_server_traffic_secret: OkmBlock, current_exporter_secret: OkmBlock, - resumption_master_secret: OkmBlock, } impl KeyScheduleTraffic { @@ -545,11 +552,6 @@ impl KeyScheduleTraffic { secret } - pub(crate) fn derive_ticket_psk(&self, nonce: &[u8]) -> OkmBlock { - self.ks - .derive_ticket_psk(&self.resumption_master_secret, nonce) - } - pub(crate) fn export_keying_material( &self, out: &mut [u8], @@ -607,6 +609,18 @@ impl KeyScheduleTraffic { } } +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); From b8540790dcca01b22dccb9f504c72801842c155c Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Mon, 30 Jun 2025 13:12:19 +0200 Subject: [PATCH 333/403] Propagate context for webpki signature algorithm errors --- Cargo.lock | 8 +- Cargo.toml | 4 +- bogo/src/main.rs | 9 ++- fuzz/Cargo.lock | 11 ++- rustls/src/error.rs | 152 +++++++++++++++++++++++++++++++++++- rustls/src/webpki/mod.rs | 101 +++++++++++++++++++++--- rustls/src/webpki/verify.rs | 11 ++- 7 files changed, 265 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 79277177937..0855e493d73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1991,7 +1991,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] @@ -3046,9 +3046,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.3" +version = "0.103.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ "aws-lc-rs", "ring", @@ -3760,7 +3760,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 465db28b141..f463185d64d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,7 +74,7 @@ once_cell = { version = "1.16", default-features = false, features = ["alloc", " openssl = "0.10" p256 = { version = "0.13.2", default-features = false, features = ["alloc", "ecdsa", "pkcs8"] } pkcs8 = "0.10.2" -pki-types = { package = "rustls-pki-types", version = "1.11", features = ["alloc"] } +pki-types = { package = "rustls-pki-types", version = "1.12", features = ["alloc"] } rand_core = { version = "0.6", features = ["getrandom"] } rayon = "1.7" rcgen = { version = "0.14", features = ["pem", "aws_lc_rs"], default-features = false } @@ -92,7 +92,7 @@ subtle = { version = "2.5.0", default-features = false } time = { version = "0.3.6", default-features = false } tikv-jemallocator = "0.6" tokio = { version = "1.34", features = ["io-util", "macros", "net", "rt"] } -webpki = { package = "rustls-webpki", version = "0.103.3", features = ["alloc"], default-features = false } +webpki = { package = "rustls-webpki", version = "0.103.4", features = ["alloc"], default-features = false } webpki-roots = "1" x25519-dalek = "2" x509-parser = "0.17" diff --git a/bogo/src/main.rs b/bogo/src/main.rs index ef52e4df292..20cc735ba3a 100644 --- a/bogo/src/main.rs +++ b/bogo/src/main.rs @@ -1182,9 +1182,12 @@ fn handle_err(opts: &Options, err: Error) -> ! { quit(":CANNOT_PARSE_LEAF_CERT:") } Error::InvalidCertificate(CertificateError::BadSignature) => quit(":BAD_SIGNATURE:"), - Error::InvalidCertificate(CertificateError::UnsupportedSignatureAlgorithm) => { - quit(":WRONG_SIGNATURE_TYPE:") - } + #[allow(deprecated)] + Error::InvalidCertificate( + CertificateError::UnsupportedSignatureAlgorithm + | CertificateError::UnsupportedSignatureAlgorithmContext { .. } + | CertificateError::UnsupportedSignatureAlgorithmForPublicKeyContext { .. }, + ) => quit(":WRONG_SIGNATURE_TYPE:"), Error::InvalidCertificate(CertificateError::InvalidOcspResponse) => { // note: only use is in this file. quit(":OCSP_CB_ERROR:") diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index d4b0bb07642..fc2d7f21410 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -304,15 +304,18 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] [[package]] name = "rustls-webpki" -version = "0.103.3" +version = "0.103.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ "ring", "rustls-pki-types", diff --git a/rustls/src/error.rs b/rustls/src/error.rs index f3f7c98bd02..3aaf3bb3c17 100644 --- a/rustls/src/error.rs +++ b/rustls/src/error.rs @@ -5,7 +5,7 @@ use core::fmt; #[cfg(feature = "std")] use std::time::SystemTimeError; -use pki_types::{ServerName, UnixTime}; +use pki_types::{AlgorithmIdentifier, ServerName, UnixTime}; use webpki::KeyUsage; use crate::enums::{AlertDescription, ContentType, HandshakeType}; @@ -432,8 +432,28 @@ pub enum CertificateError { 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, + /// Supported algorithms that were available for signature verification. + supported_algorithms: Vec, + }, + + /// A signature was made with an algorithm that doesn't match the relevant public key. + UnsupportedSignatureAlgorithmForPublicKeyContext { + /// The signature algorithm OID. + signature_algorithm_id: Vec, + /// The public key algorithm OID. + public_key_algorithm_id: Vec, + }, + /// The subject names in an end-entity certificate do not include /// the expected name. NotValidForName, @@ -527,7 +547,34 @@ impl PartialEq for CertificateError { (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 { @@ -594,7 +641,11 @@ impl From for AlertDescription { | ExpiredRevocationList | ExpiredRevocationListContext { .. } => Self::UnknownCA, InvalidOcspResponse => Self::BadCertificateStatusResponse, - BadSignature | UnsupportedSignatureAlgorithm => Self::DecryptError, + #[allow(deprecated)] + BadSignature + | UnsupportedSignatureAlgorithm + | UnsupportedSignatureAlgorithmContext { .. } + | UnsupportedSignatureAlgorithmForPublicKeyContext { .. } => Self::DecryptError, InvalidPurpose | InvalidPurposeContext { .. } => Self::UnsupportedCertificate, ApplicationVerificationFailure => Self::AccessDenied, // RFC 5246/RFC 8446 @@ -761,8 +812,28 @@ pub enum CertRevocationListError { 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, + /// Supported algorithms that were available for signature verification. + supported_algorithms: Vec, + }, + + /// A signature was made with an algorithm that doesn't match the relevant public key. + UnsupportedSignatureAlgorithmForPublicKeyContext { + /// The signature algorithm OID. + signature_algorithm_id: Vec, + /// The public key algorithm OID. + public_key_algorithm_id: Vec, + }, + /// The CRL contained an invalid CRL number. InvalidCrlNumber, @@ -806,7 +877,34 @@ impl PartialEq for 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, @@ -1065,7 +1163,30 @@ mod tests { } ); assert_eq!(BadSignature, BadSignature); - assert_eq!(UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm); + #[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") @@ -1110,7 +1231,30 @@ mod tests { fn crl_error_equality() { use super::CertRevocationListError::*; assert_eq!(BadSignature, BadSignature); - assert_eq!(UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm); + #[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, diff --git a/rustls/src/webpki/mod.rs b/rustls/src/webpki/mod.rs index bc8ee009507..24960a1ef9f 100644 --- a/rustls/src/webpki/mod.rs +++ b/rustls/src/webpki/mod.rs @@ -84,14 +84,44 @@ fn pki_error(error: webpki::Error) -> Error { 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(), @@ -118,9 +148,22 @@ 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, @@ -147,27 +190,64 @@ fn parse_crls( .map_err(crl_error) } +#[cfg(test)] mod tests { + use super::*; + use alloc::vec; + #[test] fn pki_crl_errors() { - use super::{CertRevocationListError, CertificateError, Error, pki_error}; - // 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::UnsupportedCrlSignatureAlgorithm), + pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmContext( + webpki::UnsupportedSignatureAlgorithmContext { + signature_algorithm_id: vec![], + supported_algorithms: vec![], + } + )), Error::InvalidCertRevocationList( - CertRevocationListError::UnsupportedSignatureAlgorithm - ), + CertRevocationListError::UnsupportedSignatureAlgorithmContext { + signature_algorithm_id: vec![], + supported_algorithms: vec![], + } + ) ); assert_eq!( - pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey), - Error::InvalidCertRevocationList( - CertRevocationListError::UnsupportedSignatureAlgorithm + 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. @@ -185,9 +265,8 @@ mod tests { #[test] fn crl_error_from_webpki() { - use super::CertRevocationListError::*; - use super::crl_error; - + use CertRevocationListError::*; + #[allow(deprecated)] let testcases = &[ (webpki::Error::InvalidCrlSignatureForPublicKey, BadSignature), ( diff --git a/rustls/src/webpki/verify.rs b/rustls/src/webpki/verify.rs index d99459be063..5c3e79bede5 100644 --- a/rustls/src/webpki/verify.rs +++ b/rustls/src/webpki/verify.rs @@ -161,17 +161,22 @@ pub fn verify_tls12_signature( 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(webpki::Error::UnsupportedSignatureAlgorithmForPublicKey) => continue, + Err(err @ webpki::Error::UnsupportedSignatureAlgorithmForPublicKeyContext(_)) => { + error = Some(err); + continue; + } Err(e) => return Err(pki_error(e)), Ok(()) => return Ok(HandshakeSignatureValid::assertion()), } } - Err(pki_error( + #[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 From 4e0b5fed1731d70447baecb14e87412dc5286078 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Mon, 30 Jun 2025 16:55:41 +0200 Subject: [PATCH 334/403] Bump version to 0.23.29 --- Cargo.lock | 4 ++-- fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0855e493d73..3c48d46768c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1991,7 +1991,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -2865,7 +2865,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.28" +version = "0.23.29" dependencies = [ "aws-lc-rs", "base64", diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index fc2d7f21410..10ed1427a7e 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.28" +version = "0.23.29" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 134d4c7c975..ee7f0d3cfcc 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.28" +version = "0.23.29" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From 8b8ba56ee06be638e9c5c57fa697f8c76dd17e3c Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 13 Jul 2025 21:02:30 +0200 Subject: [PATCH 335/403] Clarify the ambiguous process-level CryptoProvider error --- rustls/src/crypto/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rustls/src/crypto/mod.rs b/rustls/src/crypto/mod.rs index 3ce026b9df1..6559ad55bbe 100644 --- a/rustls/src/crypto/mod.rs +++ b/rustls/src/crypto/mod.rs @@ -246,7 +246,11 @@ impl CryptoProvider { } let provider = Self::from_crate_features() - .expect("no process-level CryptoProvider available -- call CryptoProvider::install_default() before this point"); + .expect(r###" +Could not automatically determine the process-level CryptoProvider from Rustls crate features. +Call CryptoProvider::install_default() before this point to select a provider manually, or make sure exactly one of the 'aws-lc-rs' and 'ring' features is enabled. +See the documentation of the CryptoProvider type for more information. + "###); // Ignore the error resulting from us losing a race, and accept the outcome. let _ = provider.install_default(); Self::get_default().unwrap() From caf6cbc994e533dd509674de2205ecb1416483a7 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 15 Jul 2025 16:07:57 +0200 Subject: [PATCH 336/403] conn: tweak style in complete_io() --- rustls/src/conn.rs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/rustls/src/conn.rs b/rustls/src/conn.rs index 1a95079fada..3496ed8172e 100644 --- a/rustls/src/conn.rs +++ b/rustls/src/conn.rs @@ -650,17 +650,12 @@ impl ConnectionCommon { } } - 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 let Err(e) = self.process_new_packets() { + // 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, From 247fd66d17b6fe8f4d1da28d8525c4c521025be5 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Mon, 14 Jul 2025 10:35:56 +0200 Subject: [PATCH 337/403] conn: handle blocking at the connection level --- rustls/src/conn.rs | 38 +++++++++++++++++++++++++------------- rustls/src/stream.rs | 7 +++++-- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/rustls/src/conn.rs b/rustls/src/conn.rs index 3496ed8172e..14ee8a5b364 100644 --- a/rustls/src/conn.rs +++ b/rustls/src/conn.rs @@ -587,9 +587,8 @@ impl ConnectionCommon { /// once. /// /// The return value is the number of bytes read from and written - /// to `io`, respectively. - /// - /// This function will block if `io` blocks. + /// to `io`, respectively. Once both `read()` and `write()` yield `WouldBlock`, + /// this function will propagate the error. /// /// Errors from TLS record handling (i.e., from [`process_new_packets`]) /// are wrapped in an `io::ErrorKind::InvalidData`-kind error. @@ -608,8 +607,8 @@ impl ConnectionCommon { let mut eof = false; let mut wrlen = 0; let mut rdlen = 0; - loop { + let (mut blocked_write, mut blocked_read) = (None, None); let until_handshaked = self.is_handshaking(); if !self.wants_write() && !self.wants_read() { @@ -618,15 +617,22 @@ impl ConnectionCommon { } while self.wants_write() { - match self.write_tls(io)? { - 0 => { + match self.write_tls(io) { + Ok(0) => { io.flush()?; return Ok((rdlen, wrlen)); // EOF. } - n => wrlen += n, + Ok(n) => wrlen += n, + Err(err) if err.kind() == io::ErrorKind::WouldBlock => { + blocked_write = Some(err); + break; + } + Err(err) => return Err(err), } } - io.flush()?; + if wrlen > 0 { + io.flush()?; + } if !until_handshaked && wrlen > 0 { return Ok((rdlen, wrlen)); @@ -642,6 +648,10 @@ impl ConnectionCommon { rdlen += n; Some(n) } + Err(err) if err.kind() == io::ErrorKind::WouldBlock => { + blocked_read = Some(err); + break; + } Err(err) if err.kind() == io::ErrorKind::Interrupted => None, // nothing to do Err(err) => return Err(err), }; @@ -665,11 +675,13 @@ impl ConnectionCommon { 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)), - (..) => {} + let blocked = blocked_write.zip(blocked_read); + match (eof, until_handshaked, self.is_handshaking(), blocked) { + (_, true, false, _) => return Ok((rdlen, wrlen)), + (_, false, _, _) => return Ok((rdlen, wrlen)), + (true, true, true, _) => return Err(io::Error::from(io::ErrorKind::UnexpectedEof)), + (_, _, _, Some((e, _))) => return Err(e), + _ => {} } } } diff --git a/rustls/src/stream.rs b/rustls/src/stream.rs index d92d05e3db7..9de94db1b26 100644 --- a/rustls/src/stream.rs +++ b/rustls/src/stream.rs @@ -6,6 +6,8 @@ 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. /// +/// Relies on [`ConnectionCommon::complete_io()`] to perform the necessary I/O. +/// /// 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> { @@ -153,8 +155,9 @@ where } /// This type implements `io::Read` and `io::Write`, encapsulating -/// and owning a Connection `C` and an underlying blocking transport -/// `T`, such as a socket. +/// and owning a Connection `C` and an underlying transport `T`, such as a socket. +/// +/// Relies on [`ConnectionCommon::complete_io()`] to perform the necessary I/O. /// /// This allows you to use a rustls Connection like a normal stream. #[derive(Debug)] From 6b9df65bb927dac726e28a66eb0cd1a5d3fc0988 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Sat, 26 Jul 2025 18:03:57 +0200 Subject: [PATCH 338/403] sign: make public_key_to_spki() public --- rustls/src/crypto/signer.rs | 4 ++-- rustls/src/lib.rs | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/rustls/src/crypto/signer.rs b/rustls/src/crypto/signer.rs index 8028e74b94f..659566adffb 100644 --- a/rustls/src/crypto/signer.rs +++ b/rustls/src/crypto/signer.rs @@ -207,8 +207,8 @@ impl CertifiedKey { } } -#[cfg_attr(not(any(feature = "aws_lc_rs", feature = "ring")), allow(dead_code))] -pub(crate) fn public_key_to_spki( +/// Convert a public key and algorithm identifier into [`SubjectPublicKeyInfoDer`]. +pub fn public_key_to_spki( alg_id: &AlgorithmIdentifier, public_key: impl AsRef<[u8]>, ) -> SubjectPublicKeyInfoDer<'static> { diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 845f4e94de0..1d153d6de60 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -680,7 +680,9 @@ pub mod pki_types { /// Message signing interfaces. pub mod sign { - pub use crate::crypto::signer::{CertifiedKey, Signer, SigningKey, SingleCertAndKey}; + pub use crate::crypto::signer::{ + CertifiedKey, Signer, SigningKey, SingleCertAndKey, public_key_to_spki, + }; } /// APIs for implementing QUIC TLS From 4c16f034435c52e16bf576a244111d4ede552378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Schre=CC=81ter?= Date: Fri, 25 Jul 2025 11:42:33 +0200 Subject: [PATCH 339/403] Fix: Do not try to call deframer on junk data After receiving close notify, the TLS stream ends. The receive buffer can contain additional junk data received past close notify record, which obviously cannot be interpreted anymore. However, `UnbufferedConnectionCommon::process_tls_records_common()` tried to interpret this junk data. Add a check for `has_received_close_notify` to prevent calling the deframer on junk data. Also update the test to test also with a longer junk data (original junk data didn't trigger the bug). --- rustls/src/conn/unbuffered.rs | 11 ++++-- rustls/tests/unbuffered.rs | 68 ++++++++++++++++++++--------------- 2 files changed, 48 insertions(+), 31 deletions(-) diff --git a/rustls/src/conn/unbuffered.rs b/rustls/src/conn/unbuffered.rs index 84fe3f0941a..9b1c1eae69c 100644 --- a/rustls/src/conn/unbuffered.rs +++ b/rustls/src/conn/unbuffered.rs @@ -80,7 +80,13 @@ impl UnbufferedConnectionCommon { ); } - let deframer_output = + let deframer_output = if self + .core + .common_state + .has_received_close_notify + { + None + } else { match self .core .deframe(None, buffer.filled_mut(), &mut buffer_progress) @@ -93,7 +99,8 @@ impl UnbufferedConnectionCommon { }; } Ok(r) => r, - }; + } + }; if let Some(msg) = deframer_output { let mut state = diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs index 4f32bf92296..d7e6b632a60 100644 --- a/rustls/tests/unbuffered.rs +++ b/rustls/tests/unbuffered.rs @@ -547,39 +547,49 @@ fn full_closure_server_to_client() { #[test] fn junk_after_close_notify_received() { // cf. test_junk_after_close_notify_received in api.rs - let mut outcome = handshake(&rustls::version::TLS13); - let mut client = outcome.client.take().unwrap(); - let mut server = outcome.server.take().unwrap(); - let mut client_send_buf = [0u8; 128]; - let mut len = dbg!( - write_traffic( - client.process_tls_records(&mut []), - |mut wt: WriteTraffic<_>| wt.queue_close_notify(&mut client_send_buf), - ) - .unwrap() - ); + // various junk data to test with + const JUNK_DATA: &[&[u8]] = &[ + &[0x17, 0x03, 0x03, 0x01], + &[11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25], + ]; - client_send_buf[len..len + 4].copy_from_slice(&[0x17, 0x03, 0x03, 0x01]); - len += 4; + for junk in JUNK_DATA { + let mut outcome = handshake(&rustls::version::TLS13); + let mut client = outcome.client.take().unwrap(); + let mut server = outcome.server.take().unwrap(); - let discard = match dbg!(server.process_tls_records(dbg!(&mut client_send_buf[..len]))) { - UnbufferedStatus { - discard, - state: Ok(ConnectionState::PeerClosed), - } => { - assert_eq!(discard, 24); - discard - } - st => { - panic!("unexpected server state {st:?} (wanted PeerClosed)"); - } - }; + let mut client_send_buf = [0u8; 128]; + let mut len = dbg!( + write_traffic( + client.process_tls_records(&mut []), + |mut wt: WriteTraffic<_>| wt.queue_close_notify(&mut client_send_buf), + ) + .unwrap() + ); - // further data in client_send_buf is ignored - let UnbufferedStatus { discard, .. } = - server.process_tls_records(dbg!(&mut client_send_buf[discard..len])); - assert_eq!(discard, 0); + client_send_buf[len..len + junk.len()].copy_from_slice(junk); + len += junk.len(); + + let discard = match dbg!(server.process_tls_records(dbg!(&mut client_send_buf[..len]))) { + UnbufferedStatus { + discard, + state: Ok(ConnectionState::PeerClosed), + .. + } => { + assert_eq!(discard, 24); + discard + } + st => { + panic!("unexpected server state {st:?} (wanted PeerClosed)"); + } + }; + + // further data in client_send_buf is ignored + let UnbufferedStatus { discard, .. } = + server.process_tls_records(dbg!(&mut client_send_buf[discard..len])); + assert_eq!(discard, 0); + } } #[test] From 0ccbc63df37c846691d87670c412decb3c4f23a1 Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Sat, 26 Jul 2025 09:03:23 -0400 Subject: [PATCH 340/403] Cargo: rustls version 0.23.29 -> 0.23.30 --- Cargo.lock | 4 ++-- fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3c48d46768c..e55a58da776 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1991,7 +1991,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] @@ -2865,7 +2865,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.29" +version = "0.23.30" dependencies = [ "aws-lc-rs", "base64", diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 10ed1427a7e..a45559fec75 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.29" +version = "0.23.30" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index ee7f0d3cfcc..31c656f4591 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.29" +version = "0.23.30" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From 41bfb22d5b2f0d6178107c9e426394f186623709 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 29 Jul 2025 10:20:35 +0100 Subject: [PATCH 341/403] rustls-test: add helper for non-blocking IO tests --- rustls-test/src/lib.rs | 64 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/rustls-test/src/lib.rs b/rustls-test/src/lib.rs index 696e039ad1f..2e191f690b3 100644 --- a/rustls-test/src/lib.rs +++ b/rustls-test/src/lib.rs @@ -983,6 +983,70 @@ impl io::Read for FailsReads { } } +/// An object that impls `io::Read` and `io::Write` for testing. +/// +/// The `reads` and `writes` fields set the behaviour of these trait +/// implementations. They return the `WouldBlock` error if not otherwise +/// configured -- `TestNonBlockIo::default()` does this permanently. +/// +/// This object panics on drop if the configured expected reads/writes +/// didn't take place. +#[derive(Debug, Default)] +pub struct TestNonBlockIo { + /// Each `write()` call is satisfied by inspecting this field. + /// + /// If it is empty, `WouldBlock` is returned. Otherwise the write is + /// satisfied by popping a value and returning it (reduced by the size + /// of the write buffer, if needed). + pub writes: Vec, + + /// Each `read()` call is satisfied by inspecting this field. + /// + /// If it is empty, `WouldBlock` is returned. Otherwise the read is + /// satisfied by popping a value and copying it into the output + /// buffer. Each value must be no longer than the buffer for that + /// call. + pub reads: Vec>, +} + +impl io::Read for TestNonBlockIo { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + println!("read {:?}", buf.len()); + match self.reads.pop() { + None => Err(io::ErrorKind::WouldBlock.into()), + Some(data) => { + assert!(data.len() <= buf.len()); + let take = core::cmp::min(data.len(), buf.len()); + buf[..take].clone_from_slice(&data[..take]); + Ok(take) + } + } + } +} + +impl io::Write for TestNonBlockIo { + fn write(&mut self, buf: &[u8]) -> io::Result { + println!("write {:?}", buf.len()); + match self.writes.pop() { + None => Err(io::ErrorKind::WouldBlock.into()), + Some(n) => Ok(core::cmp::min(n, buf.len())), + } + } + + fn flush(&mut self) -> io::Result<()> { + println!("flush"); + Ok(()) + } +} + +impl Drop for TestNonBlockIo { + fn drop(&mut self) { + // ensure the object was exhausted as expected + assert!(self.reads.is_empty()); + assert!(self.writes.is_empty()); + } +} + pub fn do_suite_and_kx_test( client_config: ClientConfig, server_config: ServerConfig, From 2f487cfc5ac4a73847524ef3b319e08db96c6530 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 29 Jul 2025 10:24:15 +0100 Subject: [PATCH 342/403] rustls-test: withdraw `FailsReads` helper --- rustls-test/src/lib.rs | 16 ---------------- rustls/benches/benchmarks.rs | 6 ++---- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/rustls-test/src/lib.rs b/rustls-test/src/lib.rs index 2e191f690b3..e4949424659 100644 --- a/rustls-test/src/lib.rs +++ b/rustls-test/src/lib.rs @@ -967,22 +967,6 @@ pub fn server_name(name: &'static str) -> ServerName<'static> { name.try_into().unwrap() } -pub struct FailsReads { - errkind: io::ErrorKind, -} - -impl FailsReads { - pub fn new(errkind: io::ErrorKind) -> Self { - Self { errkind } - } -} - -impl io::Read for FailsReads { - fn read(&mut self, _b: &mut [u8]) -> io::Result { - Err(io::Error::from(self.errkind)) - } -} - /// An object that impls `io::Read` and `io::Write` for testing. /// /// The `reads` and `writes` fields set the behaviour of these trait diff --git a/rustls/benches/benchmarks.rs b/rustls/benches/benchmarks.rs index 5aebc995f0c..5fc473de872 100644 --- a/rustls/benches/benchmarks.rs +++ b/rustls/benches/benchmarks.rs @@ -1,19 +1,17 @@ #![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}; +use rustls_test::{KeyType, TestNonBlockIo, 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)); + c.iter(|| server.read_tls(&mut TestNonBlockIo::default())); } benchmark_group!(benches, bench_ewouldblock); From 2a852c0244d9e235886c2e5e05b0c36d83b050ac Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 29 Jul 2025 11:04:38 +0100 Subject: [PATCH 343/403] Exit `complete_io` loop as soon as no progress is made --- rustls/src/conn.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/rustls/src/conn.rs b/rustls/src/conn.rs index 14ee8a5b364..62ebacf8e8b 100644 --- a/rustls/src/conn.rs +++ b/rustls/src/conn.rs @@ -638,6 +638,15 @@ impl ConnectionCommon { return Ok((rdlen, wrlen)); } + // If we want to write, but are WouldBlocked by the underlying IO, *and* + // have no desire to read; that is everything. + if let (Some(_), false) = (&blocked_write, self.wants_read()) { + return match wrlen { + 0 => Err(blocked_write.unwrap()), + _ => Ok((rdlen, wrlen)), + }; + } + while !eof && self.wants_read() { let read_size = match self.read_tls(io) { Ok(0) => { @@ -668,6 +677,15 @@ impl ConnectionCommon { return Err(io::Error::new(io::ErrorKind::InvalidData, e)); }; + // If we want to read, but are WouldBlocked by the underlying IO, *and* + // have no desire to write; that is everything. + if let (Some(_), false) = (&blocked_read, self.wants_write()) { + return match rdlen { + 0 => Err(blocked_read.unwrap()), + _ => Ok((rdlen, wrlen)), + }; + } + // 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. From 5e5d6296118e2f007be1affe0e64b2b0f847f05d Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 29 Jul 2025 12:24:14 +0100 Subject: [PATCH 344/403] `complete_io`: make non-blocking error return reachable This function is complex because it does too much (we should fix that) but roughly either operates in "handshake" or "data" mode. The condition here is unreachable in "data" mode (thanks to the line above). In "handshake" mode IO flips between reading and writing rather than doing both at once, so it is rare that both reading and writing are attempted in one loop. --- rustls/src/conn.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustls/src/conn.rs b/rustls/src/conn.rs index 62ebacf8e8b..344eb22bcbc 100644 --- a/rustls/src/conn.rs +++ b/rustls/src/conn.rs @@ -696,9 +696,9 @@ impl ConnectionCommon { let blocked = blocked_write.zip(blocked_read); match (eof, until_handshaked, self.is_handshaking(), blocked) { (_, true, false, _) => return Ok((rdlen, wrlen)), + (_, _, _, Some((e, _))) if rdlen == 0 && wrlen == 0 => return Err(e), (_, false, _, _) => return Ok((rdlen, wrlen)), (true, true, true, _) => return Err(io::Error::from(io::ErrorKind::UnexpectedEof)), - (_, _, _, Some((e, _))) => return Err(e), _ => {} } } From 668231f57373f4c6ad502d0091d240beaf878649 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 29 Jul 2025 10:07:40 +0100 Subject: [PATCH 345/403] Improve testing of non-blocking `complete_io()` --- rustls/tests/api.rs | 93 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index c6def2d2121..33c70ac0ea4 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -2655,6 +2655,99 @@ fn client_complete_io_for_write() { } } +#[test] +fn client_complete_io_with_nonblocking_io() { + let (mut client, _) = make_pair(KeyType::Rsa2048, &provider::default_provider()); + + // absolutely no progress writing ClientHello + assert_eq!( + client + .complete_io(&mut TestNonBlockIo::default()) + .unwrap_err() + .kind(), + io::ErrorKind::WouldBlock + ); + + // a little progress writing ClientHello + let (mut client, _) = make_pair(KeyType::Rsa2048, &provider::default_provider()); + assert_eq!( + client + .complete_io(&mut TestNonBlockIo { + writes: vec![1], + reads: vec![], + }) + .unwrap(), + (0, 1) + ); + + // complete writing ClientHello + let (mut client, _) = make_pair(KeyType::Rsa2048, &provider::default_provider()); + assert_eq!( + client + .complete_io(&mut TestNonBlockIo { + writes: vec![4096], + reads: vec![], + }) + .unwrap_err() + .kind(), + io::ErrorKind::WouldBlock + ); + + // complete writing ClientHello, partial read of ServerHello + let (mut client, _) = make_pair(KeyType::Rsa2048, &provider::default_provider()); + let (rd, wr) = dbg!(client.complete_io(&mut TestNonBlockIo { + writes: vec![4096], + reads: vec![vec![ContentType::Handshake.into()]], + })) + .unwrap(); + assert_eq!(rd, 1); + assert!(wr > 1); + + // data phase: + let (mut client, mut server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); + do_handshake(&mut client, &mut server); + + // read + assert_eq!( + client + .complete_io(&mut TestNonBlockIo { + reads: vec![vec![ContentType::ApplicationData.into()]], + writes: vec![], + }) + .unwrap(), + (1, 0) + ); + + // write + client + .writer() + .write_all(b"hello") + .unwrap(); + + // no progress + assert_eq!( + client + .complete_io(&mut TestNonBlockIo { + reads: vec![], + writes: vec![], + }) + .unwrap_err() + .kind(), + io::ErrorKind::WouldBlock + ); + + // some write progress + assert_eq!( + client + .complete_io(&mut TestNonBlockIo { + reads: vec![], + writes: vec![1], + }) + .unwrap(), + (0, 1) + ); +} + #[test] fn buffered_client_complete_io_for_write() { let provider = provider::default_provider(); From b2831e7490b82a944a43e60379e1b34165637efc Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 28 Jul 2025 14:18:53 +0100 Subject: [PATCH 346/403] rustls-bench: short circuit single threaded tests --- rustls-bench/src/main.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rustls-bench/src/main.rs b/rustls-bench/src/main.rs index aa814946ebe..f24bb043dec 100644 --- a/rustls-bench/src/main.rs +++ b/rustls-bench/src/main.rs @@ -448,6 +448,13 @@ fn multithreaded( server_config: &Arc, f: impl Fn(Arc, Arc) -> Timings + Send + Sync, ) -> Vec { + if count.get() == 1 { + // Use the current thread if possible; for mysterious reasons this is much + // faster for bulk tests on Intel, but makes little difference on AMD and + // elsewhere. + return vec![f(client_config.clone(), server_config.clone())]; + } + thread::scope(|s| { let threads = (0..count.into()) .map(|_| { From 647ece13463bbb6eaf756146596fe182644424b1 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 29 Jul 2025 17:27:49 +0100 Subject: [PATCH 347/403] Prepare 0.23.31 --- Cargo.lock | 4 ++-- fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e55a58da776..59883c2e67a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1991,7 +1991,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -2865,7 +2865,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.30" +version = "0.23.31" dependencies = [ "aws-lc-rs", "base64", diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index a45559fec75..d8e8131a11e 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.30" +version = "0.23.31" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 31c656f4591..9547631ddd1 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.30" +version = "0.23.31" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From 3a926655b2b832a8fad2022df51cf6f28045891b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 4 Aug 2025 09:35:48 +0100 Subject: [PATCH 348/403] Fix docs link errors --- rustls/src/conn/unbuffered.rs | 4 ++-- rustls/src/suites.rs | 3 ++- rustls/src/verify.rs | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/rustls/src/conn/unbuffered.rs b/rustls/src/conn/unbuffered.rs index 9b1c1eae69c..77927b5587f 100644 --- a/rustls/src/conn/unbuffered.rs +++ b/rustls/src/conn/unbuffered.rs @@ -424,8 +424,8 @@ impl<'c, 'i> ReadEarlyData<'c, 'i, ServerConnectionData> { 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 + /// 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 diff --git a/rustls/src/suites.rs b/rustls/src/suites.rs index c40b88dfce8..aebe1a37661 100644 --- a/rustls/src/suites.rs +++ b/rustls/src/suites.rs @@ -28,7 +28,7 @@ pub struct CipherSuiteCommon { /// /// This is to be set on the assumption that messages are maximally sized -- /// each is 214 bytes. It **does not** consider confidentiality limits for - /// QUIC connections - see the [`quic::KeyBuilder.confidentiality_limit`] field for + /// QUIC connections - see the [`quic::PacketKey::confidentiality_limit`] field for /// this context. /// /// For AES-GCM implementations, this should be set to 224 to limit attack @@ -43,6 +43,7 @@ pub struct CipherSuiteCommon { /// ``` /// [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 + /// [`quic::PacketKey::confidentiality_limit`]: crate::quic::PacketKey::confidentiality_limit /// /// For chacha20-poly1305 implementations, this should be set to `u64::MAX`: /// see diff --git a/rustls/src/verify.rs b/rustls/src/verify.rs index ce07e3a0eb0..46731548ad7 100644 --- a/rustls/src/verify.rs +++ b/rustls/src/verify.rs @@ -76,9 +76,10 @@ pub trait ServerCertVerifier: Debug + Send + Sync { /// /// 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. + /// [`Error::InvalidCertificate`] containing [`CertificateError::BadEncoding`] when these cases are encountered. /// /// [Certificate]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.4.2 + /// [`CertificateError::BadEncoding`]: crate::error::CertificateError::BadEncoding fn verify_server_cert( &self, end_entity: &CertificateDer<'_>, From 0cb4244a9c1029ffdc8c9b798fec9acbebe9fc11 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 7 Aug 2025 19:04:58 +0100 Subject: [PATCH 349/403] Track 1.89 lint changes Two instances of the new 1.89 `mismatched_lifetime_syntaxes` lint. Also `clippy::no_effect` has become `clippy::unnecessary_operation` for the case we are allowing. --- examples/src/bin/server_acceptor.rs | 2 +- rustls/tests/api.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/src/bin/server_acceptor.rs b/examples/src/bin/server_acceptor.rs index 5579814ea5b..fe378fa6b36 100644 --- a/examples/src/bin/server_acceptor.rs +++ b/examples/src/bin/server_acceptor.rs @@ -232,7 +232,7 @@ impl TestPki { &self, serials: Vec, next_update_seconds: u64, - ) -> CertificateRevocationListDer { + ) -> CertificateRevocationListDer<'static> { // In a real use-case you would want to set this to the current date/time. let now = rcgen::date_time_ymd(2023, 1, 1); diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index 33c70ac0ea4..eadfde0a227 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -2179,7 +2179,7 @@ fn client_flush_does_nothing() { assert!(matches!(client.writer().flush(), Ok(()))); } -#[allow(clippy::no_effect)] +#[allow(clippy::unnecessary_operation)] #[test] fn server_is_send_and_sync() { let (_, server) = make_pair(KeyType::Rsa2048, &provider::default_provider()); @@ -2187,7 +2187,7 @@ fn server_is_send_and_sync() { &server as &dyn Sync; } -#[allow(clippy::no_effect)] +#[allow(clippy::unnecessary_operation)] #[test] fn client_is_send_and_sync() { let (client, _) = make_pair(KeyType::Rsa2048, &provider::default_provider()); @@ -3621,7 +3621,7 @@ impl sign::SigningKey for SigningKeyNoneSpki { struct SigningKeySomeSpki; impl sign::SigningKey for SigningKeySomeSpki { - fn public_key(&self) -> Option { + fn public_key(&self) -> Option> { let chain = KeyType::Rsa2048.get_chain(); let cert = ParsedCertificate::try_from(chain.first().unwrap()).unwrap(); Some( From 20f548aab7642d4193ff7f89ca4a0554525731e7 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 27 Aug 2025 17:16:15 +0100 Subject: [PATCH 350/403] Withdraw use of async-std in example code --- Cargo.lock | 367 ++------------------ Cargo.toml | 1 - examples/Cargo.toml | 1 - examples/src/bin/unbuffered-async-client.rs | 11 +- 4 files changed, 33 insertions(+), 347 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 59883c2e67a..16b3bc190d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -172,7 +172,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", "synstructure", ] @@ -184,7 +184,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -195,134 +195,9 @@ checksum = "cdccf849b54365e3693e9a90ad36e4482b79937e6373ac8e2cf229c985187b21" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] -[[package]] -name = "async-attributes" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener 2.5.3", - "futures-core", -] - -[[package]] -name = "async-channel" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-executor" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "pin-project-lite", - "slab", -] - -[[package]] -name = "async-global-executor" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" -dependencies = [ - "async-channel 2.3.1", - "async-executor", - "async-io", - "async-lock", - "blocking", - "futures-lite", - "once_cell", -] - -[[package]] -name = "async-io" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3" -dependencies = [ - "async-lock", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite", - "parking", - "polling", - "rustix 1.0.7", - "slab", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "async-lock" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" -dependencies = [ - "event-listener 5.4.0", - "event-listener-strategy", - "pin-project-lite", -] - -[[package]] -name = "async-std" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "730294c1c08c2e0f85759590518f6333f0d5a0a766a27d519c1b244c3dfd8a24" -dependencies = [ - "async-attributes", - "async-channel 1.9.0", - "async-global-executor", - "async-io", - "async-lock", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - -[[package]] -name = "async-task" -version = "4.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" - [[package]] name = "async-trait" version = "0.1.88" @@ -331,7 +206,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -442,7 +317,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.101", + "syn", "which", ] @@ -461,19 +336,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "blocking" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" -dependencies = [ - "async-channel 2.3.1", - "async-task", - "futures-io", - "futures-lite", - "piper", -] - [[package]] name = "bogo" version = "0.1.0" @@ -667,7 +529,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -691,15 +553,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "const-oid" version = "0.9.6" @@ -868,7 +721,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -930,7 +783,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -988,7 +841,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -1030,39 +883,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "event-listener" -version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" -dependencies = [ - "event-listener 5.4.0", - "pin-project-lite", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - [[package]] name = "ff" version = "0.13.1" @@ -1142,19 +962,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" -[[package]] -name = "futures-lite" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] - [[package]] name = "futures-sink" version = "0.3.31" @@ -1259,18 +1066,6 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" -[[package]] -name = "gloo-timers" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - [[package]] name = "graviola" version = "0.2.1" @@ -1351,7 +1146,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -1373,12 +1168,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" - [[package]] name = "hex" version = "0.4.3" @@ -1742,7 +1531,7 @@ checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -1775,15 +1564,6 @@ dependencies = [ "elliptic-curve", ] -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -1897,7 +1677,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffd6aa2dcd5be681662001b81d493f1569c6d49a32361f470b0c955465cd0338" dependencies = [ "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -2006,12 +1786,6 @@ version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" -[[package]] -name = "linux-raw-sys" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" - [[package]] name = "litemap" version = "0.8.0" @@ -2033,9 +1807,6 @@ name = "log" version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" -dependencies = [ - "value-bag", -] [[package]] name = "loom" @@ -2291,7 +2062,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -2334,12 +2105,6 @@ dependencies = [ "primeorder", ] -[[package]] -name = "parking" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" - [[package]] name = "parking_lot" version = "0.12.4" @@ -2403,17 +2168,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "piper" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" -dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", -] - [[package]] name = "pkcs1" version = "0.7.5" @@ -2469,21 +2223,6 @@ dependencies = [ "plotters-backend", ] -[[package]] -name = "polling" -version = "3.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50" -dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi", - "pin-project-lite", - "rustix 1.0.7", - "tracing", - "windows-sys 0.59.0", -] - [[package]] name = "poly1305" version = "0.8.0" @@ -2553,7 +2292,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dee91521343f4c5c6a63edd65e54f31f5c92fe8978c40a4282f8372194c6a7d" dependencies = [ "proc-macro2", - "syn 2.0.101", + "syn", ] [[package]] @@ -2584,7 +2323,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -2846,20 +2585,7 @@ dependencies = [ "bitflags", "errno", "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustix" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys 0.9.4", + "linux-raw-sys", "windows-sys 0.59.0", ] @@ -2940,7 +2666,6 @@ dependencies = [ name = "rustls-examples" version = "0.0.1" dependencies = [ - "async-std", "clap", "env_logger", "hickory-resolver", @@ -3126,7 +2851,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -3236,17 +2961,6 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.101" @@ -3266,7 +2980,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -3301,7 +3015,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -3312,7 +3026,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -3435,7 +3149,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -3578,12 +3292,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" -[[package]] -name = "value-bag" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" - [[package]] name = "vcpkg" version = "0.2.15" @@ -3643,23 +3351,10 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.101", + "syn", "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" -dependencies = [ - "cfg-if", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" version = "0.2.100" @@ -3678,7 +3373,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3729,7 +3424,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.44", + "rustix", ] [[package]] @@ -3823,7 +3518,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -3834,7 +3529,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -4111,7 +3806,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", "synstructure", ] @@ -4132,7 +3827,7 @@ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -4152,7 +3847,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", "synstructure", ] @@ -4173,7 +3868,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] @@ -4206,7 +3901,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index f463185d64d..d3ee0f86b5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,6 @@ resolver = "2" [workspace.dependencies] anyhow = "1.0.73" asn1 = "0.22" -async-std = { version = "1.12.0", features = ["attributes"] } async-trait = "0.1.74" aws-lc-rs = { version = "1.12", default-features = false } base64 = "0.22" diff --git a/examples/Cargo.toml b/examples/Cargo.toml index cd0bad26bf5..ce694b8fceb 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -7,7 +7,6 @@ description = "Rustls example code and tests." publish = false [dependencies] -async-std = { workspace = true, optional = true } clap = { workspace = true } env_logger = { workspace = true } hickory-resolver = { workspace = true } diff --git a/examples/src/bin/unbuffered-async-client.rs b/examples/src/bin/unbuffered-async-client.rs index 15081a627b4..b032c08c65f 100644 --- a/examples/src/bin/unbuffered-async-client.rs +++ b/examples/src/bin/unbuffered-async-client.rs @@ -1,14 +1,10 @@ //! This is a simple client using rustls' unbuffered API. Meaning that the application layer must //! handle the buffers required to receive, process and send TLS data. Additionally it demonstrates -//! using asynchronous I/O using either async-std or tokio. +//! using asynchronous I/O via tokio. use std::error::Error; use std::sync::Arc; -#[cfg(feature = "async-std")] -use async_std::io::{ReadExt, WriteExt}; -#[cfg(feature = "async-std")] -use async_std::net::TcpStream; use rustls::client::{ClientConnectionData, UnbufferedClientConnection}; use rustls::unbuffered::{ AppDataRecord, ConnectionState, EncodeError, EncryptError, InsufficientSizeError, @@ -16,13 +12,10 @@ use rustls::unbuffered::{ }; use rustls::version::TLS13; use rustls::{ClientConfig, RootCertStore}; -#[cfg(not(feature = "async-std"))] use tokio::io::{AsyncReadExt, AsyncWriteExt}; -#[cfg(not(feature = "async-std"))] use tokio::net::TcpStream; -#[cfg_attr(not(feature = "async-std"), tokio::main(flavor = "current_thread"))] -#[cfg_attr(feature = "async-std", async_std::main)] +#[tokio::main(flavor = "current_thread")] async fn main() -> Result<(), Box> { let root_store = RootCertStore { roots: webpki_roots::TLS_SERVER_ROOTS.into(), From 2d03fa7bef575577590fdd69ba3e45e2e4cb0e59 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 28 Aug 2025 11:54:10 +0100 Subject: [PATCH 351/403] Remove test of async-std example --- .github/workflows/daily-tests.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/daily-tests.yml b/.github/workflows/daily-tests.yml index 20f88d5bd77..f3b28127f2c 100644 --- a/.github/workflows/daily-tests.yml +++ b/.github/workflows/daily-tests.yml @@ -107,9 +107,6 @@ jobs: - name: Check unbuffered tokio client run: cargo run --locked -p rustls-examples --bin unbuffered-async-client - - name: Check unbuffered async-std client - run: cargo run --locked -p rustls-examples --bin unbuffered-async-client --features=async-std - # Test the server_acceptor binary builds - we invoke with --help since it # will run a server process that doesn't exit when invoked with no args - name: Check server acceptor From e029d31522a672a61c9ff21851694334578adf3e Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Sun, 10 Aug 2025 19:38:07 +0100 Subject: [PATCH 352/403] cargo-check-external-types: take updated nightly --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 567427dd2b2..759ec844c55 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -511,7 +511,7 @@ jobs: - name: Install rust toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: nightly-2025-05-04 + toolchain: nightly-2025-08-06 # ^ sync with https://github.com/awslabs/cargo-check-external-types/blob/main/rust-toolchain.toml - name: Install cargo-check-external-types uses: taiki-e/cache-cargo-install-action@v2 From 1492c951b237815de35b60e67bec37efc791fa1f Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 11 Sep 2025 07:05:53 +0100 Subject: [PATCH 353/403] Fix `clippy::needless_borrows_for_generic_args` (triggered by non-breaking change in aws-lc-rs rev) --- rustls/src/crypto/aws_lc_rs/hpke.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rustls/src/crypto/aws_lc_rs/hpke.rs b/rustls/src/crypto/aws_lc_rs/hpke.rs index de0e5d630d0..2e5c3a5ece6 100644 --- a/rustls/src/crypto/aws_lc_rs/hpke.rs +++ b/rustls/src/crypto/aws_lc_rs/hpke.rs @@ -576,7 +576,7 @@ impl DhKem { 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| { + 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)?; @@ -616,7 +616,7 @@ impl DhKem { .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| { + 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)?; From 77a01488bfea41607cbb518e6ef4c56d15b38a83 Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Sat, 6 Sep 2025 10:48:53 -0400 Subject: [PATCH 354/403] ci-bench: RUSTSEC-2025-0057 fxhash -> rustc-hash See https://rustsec.org/advisories/RUSTSEC-2025-0057.html --- Cargo.lock | 19 ++++++++----------- Cargo.toml | 2 +- ci-bench/Cargo.toml | 2 +- ci-bench/src/benchmark.rs | 2 +- ci-bench/src/main.rs | 2 +- 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 16b3bc190d6..70a80fff9c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -315,7 +315,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash", + "rustc-hash 1.1.0", "shlex", "syn", "which", @@ -987,15 +987,6 @@ dependencies = [ "slab", ] -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - [[package]] name = "generator" version = "0.8.5" @@ -2558,6 +2549,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustc_version" version = "0.4.1" @@ -2642,9 +2639,9 @@ dependencies = [ "byteorder", "clap", "crabgrind", - "fxhash", "itertools 0.14.0", "rayon", + "rustc-hash 2.1.1", "rustls", "rustls-fuzzing-provider", "rustls-test", diff --git a/Cargo.toml b/Cargo.toml index d3ee0f86b5e..f87a2b6a23d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,7 +56,6 @@ criterion = "0.6" der = "0.7" ecdsa = "0.16.8" env_logger = "0.11" -fxhash = "0.2.1" hashbrown = { version = "0.15", default-features = false, features = ["default-hasher", "inline-more"] } hex = "0.4" hickory-resolver = { version = "0.25", features = ["https-aws-lc-rs", "webpki-roots"] } @@ -80,6 +79,7 @@ rcgen = { version = "0.14", features = ["pem", "aws_lc_rs"], default-features = regex = "1" ring = "0.17" rsa = { version = "0.9", features = ["sha2"], default-features = false } +rustc-hash = "2" rustls-graviola = { version = "0.2" } rustls-test = { path = "rustls-test/" } rustls-fuzzing-provider = { path = "rustls-fuzzing-provider/" } diff --git a/ci-bench/Cargo.toml b/ci-bench/Cargo.toml index ef3b5566121..63ae7d71236 100644 --- a/ci-bench/Cargo.toml +++ b/ci-bench/Cargo.toml @@ -11,9 +11,9 @@ anyhow = { workspace = true } async-trait = { workspace = true } byteorder = { workspace = true } clap = { workspace = true } -fxhash = { workspace = true } itertools = { workspace = true } rayon = { workspace = true } +rustc-hash = { workspace = true } rustls = { path = "../rustls", features = ["ring", "aws_lc_rs"] } rustls-test = { workspace = true } rustls-fuzzing-provider = { workspace = true } diff --git a/ci-bench/src/benchmark.rs b/ci-bench/src/benchmark.rs index 4e4a9446e1a..fc7ca65cc65 100644 --- a/ci-bench/src/benchmark.rs +++ b/ci-bench/src/benchmark.rs @@ -1,7 +1,7 @@ use std::sync::Arc; -use fxhash::FxHashMap; use itertools::Itertools; +use rustc_hash::FxHashMap; use rustls_test::KeyType; use crate::Side; diff --git a/ci-bench/src/main.rs b/ci-bench/src/main.rs index 6fa165c9fb1..d4b517883a7 100644 --- a/ci-bench/src/main.rs +++ b/ci-bench/src/main.rs @@ -26,10 +26,10 @@ use std::time::Instant; use anyhow::Context; use async_trait::async_trait; use clap::{Parser, Subcommand, ValueEnum}; -use fxhash::FxHashMap; use itertools::Itertools; use rayon::iter::Either; use rayon::prelude::*; +use rustc_hash::FxHashMap; use rustls::client::Resumption; use rustls::crypto::{CryptoProvider, GetRandomFailed, SecureRandom, aws_lc_rs, ring}; use rustls::server::{NoServerSessionStorage, ServerSessionMemoryCache, WebPkiClientVerifier}; From ef7063d21f2c2cb7bbd497786ab3ac6f9e11e702 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 15 Aug 2025 06:41:40 +0100 Subject: [PATCH 355/403] take webpki 0.103.5 (also aws-lc-rs 1.14 and zeroize 1.8 solely to satisfy ropey cargo minimum versions check) --- Cargo.lock | 38 +++++++++++++++++++++++++++++--------- Cargo.toml | 6 +++--- fuzz/Cargo.lock | 4 ++-- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 70a80fff9c3..abd4feafac3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -227,7 +227,7 @@ version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e99d74bb793a19f542ae870a6edafbc5ecf0bc0ba01d4636b7f7e0aba9ee9bd3" dependencies = [ - "bindgen", + "bindgen 0.69.5", "cc", "cmake", "dunce", @@ -237,9 +237,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fcc8f365936c834db5514fc45aee5b1202d677e6b40e48468aaaa8183ca8c7" +checksum = "94b8ff6c09cd57b16da53641caa860168b88c172a5ee163b0288d3d6eea12786" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", @@ -248,11 +248,11 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.29.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b1d86e7705efe1be1b569bab41d4fa1e14e220b60a160f78de2db687add079" +checksum = "0e44d16778acaf6a9ec9899b92cebd65580b83f685446bf2e1f5d3d732f99dcd" dependencies = [ - "bindgen", + "bindgen 0.72.1", "cc", "cmake", "dunce", @@ -321,6 +321,26 @@ dependencies = [ "which", ] +[[package]] +name = "bindgen" +version = "0.72.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 2.1.1", + "shlex", + "syn", +] + [[package]] name = "bitflags" version = "2.9.1" @@ -1762,7 +1782,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] @@ -2768,9 +2788,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.4" +version = "0.103.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +checksum = "b5a37813727b78798e53c2bec3f5e8fe12a6d6f8389bf9ca7802add4c9905ad8" dependencies = [ "aws-lc-rs", "ring", diff --git a/Cargo.toml b/Cargo.toml index f87a2b6a23d..94f353ee9c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ resolver = "2" anyhow = "1.0.73" asn1 = "0.22" async-trait = "0.1.74" -aws-lc-rs = { version = "1.12", default-features = false } +aws-lc-rs = { version = "1.14", default-features = false } base64 = "0.22" bencher = "0.1.5" brotli = { version = "8", default-features = false, features = ["std"] } @@ -91,11 +91,11 @@ subtle = { version = "2.5.0", default-features = false } time = { version = "0.3.6", default-features = false } tikv-jemallocator = "0.6" tokio = { version = "1.34", features = ["io-util", "macros", "net", "rt"] } -webpki = { package = "rustls-webpki", version = "0.103.4", features = ["alloc"], default-features = false } +webpki = { package = "rustls-webpki", version = "0.103.5", features = ["alloc"], default-features = false } webpki-roots = "1" x25519-dalek = "2" x509-parser = "0.17" -zeroize = "1.7" +zeroize = "1.8" zlib-rs = "0.5" [profile.bench] diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index d8e8131a11e..3e2e60fb13b 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -313,9 +313,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.4" +version = "0.103.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +checksum = "b5a37813727b78798e53c2bec3f5e8fe12a6d6f8389bf9ca7802add4c9905ad8" dependencies = [ "ring", "rustls-pki-types", From d3c502e0f5b6ffa8e3c8fa0bb6c1d9b7406fda89 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 15 Aug 2025 06:44:04 +0100 Subject: [PATCH 356/403] Improve compatibility of TLS1.2 with ECDSA+SHA512 --- rustls/src/crypto/aws_lc_rs/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rustls/src/crypto/aws_lc_rs/mod.rs b/rustls/src/crypto/aws_lc_rs/mod.rs index 1a7d226387c..336866e0251 100644 --- a/rustls/src/crypto/aws_lc_rs/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/mod.rs @@ -195,7 +195,11 @@ static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms ), ( SignatureScheme::ECDSA_NISTP521_SHA512, - &[webpki_algs::ECDSA_P521_SHA512], + &[ + webpki_algs::ECDSA_P521_SHA512, + webpki_algs::ECDSA_P384_SHA512, + webpki_algs::ECDSA_P256_SHA512, + ], ), (SignatureScheme::ED25519, &[webpki_algs::ED25519]), ( From 5abe33e71d150aa93ebab1dde400b63af5f198c0 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 19 Sep 2025 11:15:51 +0100 Subject: [PATCH 357/403] Prepare 0.23.32 --- Cargo.lock | 6 +++--- fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index abd4feafac3..b6ce49afb68 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -338,7 +338,7 @@ dependencies = [ "regex", "rustc-hash 2.1.1", "shlex", - "syn", + "syn 2.0.101", ] [[package]] @@ -1782,7 +1782,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -2608,7 +2608,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.31" +version = "0.23.32" dependencies = [ "aws-lc-rs", "base64", diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 3e2e60fb13b..8691ffc05bd 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.31" +version = "0.23.32" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 9547631ddd1..198cb061740 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.31" +version = "0.23.32" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From 6a188a70a0e1bf4547884a9cdd7710936d653a22 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 19 Sep 2025 11:46:06 +0100 Subject: [PATCH 358/403] Take semver-compatible updates --- Cargo.lock | 689 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 397 insertions(+), 292 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b6ce49afb68..f7234f254c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aead" @@ -84,9 +84,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.19" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" dependencies = [ "anstyle", "anstyle-parse", @@ -114,29 +114,29 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.9" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" [[package]] name = "asn1" @@ -160,7 +160,7 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror 2.0.12", + "thiserror 2.0.16", "time", ] @@ -200,9 +200,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.88" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", @@ -217,15 +217,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-fips-sys" -version = "0.13.6" +version = "0.13.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e99d74bb793a19f542ae870a6edafbc5ecf0bc0ba01d4636b7f7e0aba9ee9bd3" +checksum = "2608e5a7965cc9d58c56234d346c9c89b824c4c8652b6f047b3bd0a777c0644f" dependencies = [ "bindgen 0.69.5", "cc", @@ -307,7 +307,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "itertools 0.10.5", + "itertools 0.12.1", "lazy_static", "lazycell", "log", @@ -338,14 +338,14 @@ dependencies = [ "regex", "rustc-hash 2.1.1", "shlex", - "syn 2.0.101", + "syn", ] [[package]] name = "bitflags" -version = "2.9.1" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" [[package]] name = "block-buffer" @@ -370,9 +370,9 @@ dependencies = [ [[package]] name = "brotli" -version = "8.0.1" +version = "8.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d" +checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -391,9 +391,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.18.1" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "byteorder" @@ -415,10 +415,11 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.26" +version = "1.2.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" +checksum = "80f41ae168f955c12fb8960b057d70d0ca153fb83182b57d86380443527be7e9" dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", @@ -435,9 +436,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "cfg_aliases" @@ -520,9 +521,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.39" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" +checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" dependencies = [ "clap_builder", "clap_derive", @@ -530,9 +531,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.39" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" +checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" dependencies = [ "anstream", "anstyle", @@ -542,9 +543,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.32" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" dependencies = [ "heck", "proc-macro2", @@ -554,9 +555,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "cmake" @@ -587,7 +588,7 @@ checksum = "94950e87ea550d6d68f1993f3e7bebc8cb7235157bff84337d46195c3aa0b3f0" dependencies = [ "hax-lib", "pastey", - "rand 0.9.1", + "rand 0.9.2", ] [[package]] @@ -683,9 +684,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-bigint" @@ -776,9 +777,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.4.0" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" dependencies = [ "powerfmt", ] @@ -895,12 +896,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.12" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.0", ] [[package]] @@ -919,6 +920,12 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "find-msvc-tools" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" + [[package]] name = "fnv" version = "1.0.7" @@ -948,9 +955,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -1009,9 +1016,9 @@ dependencies = [ [[package]] name = "generator" -version = "0.8.5" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" +checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2" dependencies = [ "cc", "cfg-if", @@ -1040,7 +1047,7 @@ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", ] [[package]] @@ -1052,7 +1059,7 @@ dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasi 0.14.7+wasi-0.2.4", ] [[package]] @@ -1073,9 +1080,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "graviola" @@ -1100,9 +1107,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" dependencies = [ "atomic-waker", "bytes", @@ -1129,18 +1136,24 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.3" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + [[package]] name = "hax-lib" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89999d4446ba7d86c777bc6a30c106b9bf60d12eb1952242af5d1d7cb33943d" +checksum = "7bf40682e31dc3961209a4657f6fe7c412879b59f212bac3d14bd7ece5af76a3" dependencies = [ "hax-lib-macros", "num-bigint", @@ -1149,9 +1162,9 @@ dependencies = [ [[package]] name = "hax-lib-macros" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704a31fb12a8c50243e8d4c88d006f64852822b0e24488a0de9986803a661792" +checksum = "e33a5a4ff169bcc4e9189f4bace3ed22d03fcd8e52eee90a00b7b1e2621cb490" dependencies = [ "hax-lib-macros-types", "proc-macro-error2", @@ -1162,9 +1175,9 @@ dependencies = [ [[package]] name = "hax-lib-macros-types" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f302d2a43ba5888c61454ffeb8719dc43e7c0e83082d0fe302ac82d8d898b075" +checksum = "a39dc59c01c2eec9bce75698c4f9ca01d11759ace2a28e1691b66fb0008c6a21" dependencies = [ "proc-macro2", "quote", @@ -1204,10 +1217,10 @@ dependencies = [ "idna", "ipnet", "once_cell", - "rand 0.9.1", + "rand 0.9.2", "ring", "rustls", - "thiserror 2.0.12", + "thiserror 2.0.16", "tinyvec", "tokio", "tokio-rustls", @@ -1229,11 +1242,11 @@ dependencies = [ "moka", "once_cell", "parking_lot", - "rand 0.9.1", + "rand 0.9.2", "resolv-conf", "rustls", "smallvec", - "thiserror 2.0.12", + "thiserror 2.0.16", "tokio", "tokio-rustls", "tracing", @@ -1302,7 +1315,7 @@ dependencies = [ "libcrux-ecdh", "libcrux-hkdf", "libcrux-kem", - "rand 0.9.1", + "rand 0.9.2", "rand_chacha 0.9.0", "rand_core 0.9.3", ] @@ -1426,9 +1439,9 @@ dependencies = [ [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -1447,12 +1460,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.9.0" +version = "2.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.16.0", ] [[package]] @@ -1464,13 +1477,24 @@ dependencies = [ "generic-array", ] +[[package]] +name = "io-uring" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" +dependencies = [ + "bitflags", + "cfg-if", + "libc", +] + [[package]] name = "ipconfig" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2", + "socket2 0.5.10", "widestring", "windows-sys 0.48.0", "winreg", @@ -1497,6 +1521,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.13.0" @@ -1523,9 +1556,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93" +checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" dependencies = [ "jiff-static", "log", @@ -1536,9 +1569,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442" +checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" dependencies = [ "proc-macro2", "quote", @@ -1547,9 +1580,9 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ "getrandom 0.3.3", "libc", @@ -1557,9 +1590,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "852f13bec5eba4ba9afbeb93fd7c13fe56147f055939ae21c43a29a0ecb2702e" dependencies = [ "once_cell", "wasm-bindgen", @@ -1592,9 +1625,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.172" +version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" [[package]] name = "libcrux-chacha20poly1305" @@ -1625,7 +1658,7 @@ checksum = "6c4fa67cad871d7be9175141b23a174b77536b039945c91b6a5a6d697acd6371" dependencies = [ "libcrux-curve25519", "libcrux-p256", - "rand 0.9.1", + "rand 0.9.2", ] [[package]] @@ -1678,7 +1711,7 @@ dependencies = [ "libcrux-ml-kem", "libcrux-sha3", "libcrux-traits", - "rand 0.9.1", + "rand 0.9.2", ] [[package]] @@ -1702,7 +1735,7 @@ dependencies = [ "libcrux-platform", "libcrux-secrets", "libcrux-sha3", - "rand 0.9.1", + "rand 0.9.2", ] [[package]] @@ -1772,7 +1805,7 @@ version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cdbf9591a39f04d6da6b9bad51ac58378604a80708c2173dadf92029891b9e2" dependencies = [ - "rand 0.9.1", + "rand 0.9.2", ] [[package]] @@ -1782,7 +1815,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.53.3", ] [[package]] @@ -1815,9 +1848,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "loom" @@ -1850,18 +1883,18 @@ checksum = "670fdfda89751bc4a84ac13eaa63e205cf0fd22b4c9a5fbfa085b63c1f1d3a30" [[package]] name = "matchers" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "regex-automata 0.1.10", + "regex-automata", ] [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "minimal-lexical" @@ -1871,9 +1904,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", ] @@ -1886,7 +1919,7 @@ checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.59.0", ] @@ -1933,12 +1966,11 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" dependencies = [ - "overload", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -2088,12 +2120,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "p256" version = "0.13.2" @@ -2147,9 +2173,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pastey" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a8cb46bdc156b1c90460339ae6bfd45ba0394e5effbaa640badb4987fdc261" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" [[package]] name = "pem" @@ -2163,9 +2189,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pin-project-lite" @@ -2274,9 +2300,9 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" dependencies = [ "zerovec", ] @@ -2298,9 +2324,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.33" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dee91521343f4c5c6a63edd65e54f31f5c92fe8978c40a4282f8372194c6a7d" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", "syn", @@ -2339,9 +2365,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -2357,9 +2383,9 @@ dependencies = [ [[package]] name = "r-efi" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" @@ -2374,9 +2400,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", @@ -2422,9 +2448,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ "either", "rayon-core", @@ -2432,9 +2458,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -2442,9 +2468,9 @@ dependencies = [ [[package]] name = "rcgen" -version = "0.14.1" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "218a7fbb357f6da42c9fd3610b1a5128d087d460e5386eaa5040705c464611dc" +checksum = "4c83367ba62b3f1dbd0f086ede4e5ebfb4713fb234dbbc5807772a31245ff46d" dependencies = [ "aws-lc-rs", "pem", @@ -2455,62 +2481,47 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.12" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", + "regex-automata", + "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.5", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" [[package]] name = "resolv-conf" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95325155c684b1c89f7765e30bc1c42e4a6da51ca513615660cb8a62ef9a88e3" +checksum = "6b3789b30bd25ba102de4beabd95d21ac45b69b1be7d14522bab988c526d6799" [[package]] name = "rfc6979" @@ -2559,9 +2570,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustc-hash" @@ -2616,7 +2627,7 @@ dependencies = [ "brotli", "brotli-decompressor", "env_logger", - "hashbrown", + "hashbrown 0.15.5", "hex", "log", "macro_rules_attribute", @@ -2632,7 +2643,7 @@ dependencies = [ "serde_json", "subtle", "time", - "webpki-roots 1.0.0", + "webpki-roots 1.0.2", "x509-parser", "zeroize", "zlib-rs", @@ -2692,7 +2703,7 @@ dependencies = [ "rustls", "serde", "tokio", - "webpki-roots 1.0.0", + "webpki-roots 1.0.2", ] [[package]] @@ -2741,7 +2752,7 @@ dependencies = [ "criterion", "env_logger", "rustls", - "webpki-roots 1.0.0", + "webpki-roots 1.0.2", ] [[package]] @@ -2764,7 +2775,7 @@ dependencies = [ "rustls", "sha2", "signature", - "webpki-roots 1.0.0", + "webpki-roots 1.0.2", "x25519-dalek", ] @@ -2788,9 +2799,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.5" +version = "0.103.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a37813727b78798e53c2bec3f5e8fe12a6d6f8389bf9ca7802add4c9905ad8" +checksum = "8572f3c2cb9934231157b45499fc41e1f58c589fdfb81a844ba873265e80f8eb" dependencies = [ "aws-lc-rs", "ring", @@ -2800,9 +2811,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" @@ -2847,24 +2858,34 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.225" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "fd6c24dee235d0da097043389623fb913daddf92c76e9f5a1db88607a0bcbd1d" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.225" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "659356f9a0cb1e529b24c01e43ad2bdf520ec4ceaf83047b83ddcc2251f96383" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.225" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "0ea936adf78b1f766949a4977b91d2f5595825bd6ec079aa9543ad2685fc4516" dependencies = [ "proc-macro2", "quote", @@ -2873,14 +2894,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -2921,18 +2943,15 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" -version = "1.15.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" @@ -2944,6 +2963,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "spin" version = "0.9.8" @@ -2980,9 +3009,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.101" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -3017,11 +3046,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.16", ] [[package]] @@ -3037,9 +3066,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" dependencies = [ "proc-macro2", "quote", @@ -3048,12 +3077,11 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", ] [[package]] @@ -3078,9 +3106,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.41" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ "deranged", "itoa", @@ -3093,15 +3121,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" [[package]] name = "time-macros" -version = "0.2.22" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" dependencies = [ "num-conv", "time-core", @@ -3129,9 +3157,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" dependencies = [ "tinyvec_macros", ] @@ -3144,18 +3172,20 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.45.1" +version = "1.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" dependencies = [ "backtrace", "bytes", + "io-uring", "libc", "mio", "pin-project-lite", - "socket2", + "slab", + "socket2 0.6.0", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3171,9 +3201,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "05f63835928ca123f1bef57abbcd23bb2ba0ac9ae1235f1e65bda0d06e7786bd" dependencies = [ "rustls", "tokio", @@ -3181,9 +3211,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.15" +version = "0.7.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" dependencies = [ "bytes", "futures-core", @@ -3225,14 +3255,14 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "regex", + "regex-automata", "sharded-slab", "smallvec", "thread_local", @@ -3249,9 +3279,9 @@ checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" [[package]] name = "universal-hash" @@ -3271,13 +3301,14 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -3294,9 +3325,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.17.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ "getrandom 0.3.3", "js-sys", @@ -3333,36 +3364,46 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.14.2+wasi-0.2.4" +version = "0.14.7+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "ab10a69fbd0a177f5f649ad4d8d3305499c42bab9aef2f7ff592d0ec8f833819" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.100" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "0bb702423545a6007bbc368fde243ba47ca275e549c8a28617f56f6ba53b1d1c" dependencies = [ "bumpalo", "log", @@ -3374,9 +3415,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "fc65f4f411d91494355917b605e1480033152658d71f722a90647f56a70c88a0" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3384,9 +3425,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "ffc003a991398a8ee604a401e194b6b3a39677b3173d6e74495eb51b82e99a32" dependencies = [ "proc-macro2", "quote", @@ -3397,18 +3438,18 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "293c37f4efa430ca14db3721dfbe48d8c33308096bd44d80ebaa775ab71ba1cf" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "fbe734895e869dc429d78c4b433f8d17d95f8d05317440b4fad5ab2d33e596dc" dependencies = [ "js-sys", "wasm-bindgen", @@ -3420,14 +3461,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.0", + "webpki-roots 1.0.2", ] [[package]] name = "webpki-roots" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" +checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" dependencies = [ "rustls-pki-types", ] @@ -3450,47 +3491,25 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d" -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.0", ] -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows" -version = "0.61.1" +version = "0.61.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ "windows-collections", "windows-core", "windows-future", - "windows-link", + "windows-link 0.1.3", "windows-numerics", ] @@ -3511,7 +3530,7 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", - "windows-link", + "windows-link 0.1.3", "windows-result", "windows-strings", ] @@ -3523,7 +3542,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ "windows-core", - "windows-link", + "windows-link 0.1.3", "windows-threading", ] @@ -3551,9 +3570,15 @@ dependencies = [ [[package]] name = "windows-link" -version = "0.1.1" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" [[package]] name = "windows-numerics" @@ -3562,7 +3587,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ "windows-core", - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -3571,7 +3596,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -3580,7 +3605,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -3610,6 +3635,24 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", +] + +[[package]] +name = "windows-sys" +version = "0.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" +dependencies = [ + "windows-link 0.2.0", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -3634,20 +3677,37 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link 0.1.3", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + [[package]] name = "windows-threading" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -3662,6 +3722,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -3674,6 +3740,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -3686,12 +3758,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[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_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -3704,6 +3788,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -3716,6 +3806,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -3728,6 +3824,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -3740,6 +3842,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winreg" version = "0.50.0" @@ -3751,13 +3859,10 @@ dependencies = [ ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" @@ -3790,7 +3895,7 @@ dependencies = [ "nom", "oid-registry", "rusticata-macros", - "thiserror 2.0.12", + "thiserror 2.0.16", "time", ] @@ -3829,18 +3934,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.25" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.25" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", @@ -3901,9 +4006,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.2" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" dependencies = [ "yoke", "zerofrom", @@ -3923,6 +4028,6 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626bd9fa9734751fc50d6060752170984d7053f5a39061f524cda68023d4db8a" +checksum = "2f06ae92f42f5e5c42443fd094f245eb656abf56dd7cce9b8b263236565e00f2" From 48b2fd919f69563e52d11c98c70d4c9c47694765 Mon Sep 17 00:00:00 2001 From: Floris Bruynooghe Date: Tue, 8 Apr 2025 17:17:14 +0200 Subject: [PATCH 359/403] Support encryption for QUIC multipath https://datatracker.ietf.org/doc/draft-ietf-quic-multipath/ defines new semantics to encrypt QUIC packets, which are implemented here. --- rustls/src/crypto/cipher.rs | 30 ++++++--- rustls/src/crypto/ring/quic.rs | 117 +++++++++++++++++++++++++++++++++ rustls/src/quic.rs | 39 +++++++++++ 3 files changed, 178 insertions(+), 8 deletions(-) diff --git a/rustls/src/crypto/cipher.rs b/rustls/src/crypto/cipher.rs index 64901a577bf..b5a6046c444 100644 --- a/rustls/src/crypto/cipher.rs +++ b/rustls/src/crypto/cipher.rs @@ -213,18 +213,32 @@ impl 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..]); + let mut seq_bytes = [0u8; NONCE_LEN]; + codec::put_u64(seq, &mut seq_bytes[4..]); + Self::new_from_seq(iv, seq_bytes) + } - nonce - .0 - .iter_mut() + /// Creates a unique nonce based on the `iv`, the packet number `pn` and multipath `path_id`. + /// + /// The nonce is computed as the XOR between the `iv` and the 96-bit big-ending integer formed + /// by concatenating `path_id` and `pn`. + pub fn for_path(path_id: u32, iv: &Iv, pn: u64) -> Self { + let mut seq_bytes = [0u8; NONCE_LEN]; + seq_bytes[0..4].copy_from_slice(&path_id.to_be_bytes()); + codec::put_u64(pn, &mut seq_bytes[4..]); + Self::new_from_seq(iv, seq_bytes) + } + + /// Creates a unique nonce based on the `iv` and sequence number `seq`. + #[inline] + fn new_from_seq(iv: &Iv, mut seq: [u8; NONCE_LEN]) -> Self { + seq.iter_mut() .zip(iv.0.iter()) - .for_each(|(nonce, iv)| { - *nonce ^= *iv; + .for_each(|(s, iv)| { + *s ^= *iv; }); - nonce + Self(seq) } } diff --git a/rustls/src/crypto/ring/quic.rs b/rustls/src/crypto/ring/quic.rs index 3d0dc928916..354e6aea1ed 100644 --- a/rustls/src/crypto/ring/quic.rs +++ b/rustls/src/crypto/ring/quic.rs @@ -140,6 +140,23 @@ impl quic::PacketKey for PacketKey { Ok(quic::Tag::from(tag.as_ref())) } + fn encrypt_in_place_for_path( + &self, + path_id: u32, + packet_number: u64, + header: &[u8], + payload: &mut [u8], + ) -> Result { + let aad = aead::Aad::from(header); + let nonce = + aead::Nonce::assume_unique_for_key(Nonce::for_path(path_id, &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 @@ -164,6 +181,25 @@ impl quic::PacketKey for PacketKey { Ok(&payload[..plain_len]) } + fn decrypt_in_place_for_path<'a>( + &self, + path_id: u32, + 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::for_path(path_id, &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 { @@ -413,4 +449,85 @@ mod tests { ]; assert_eq!(server_packet[..], expected_server_packet[..]); } + + // This test is based on picoquic's output for `multipath_aead_test` in + // `picoquictest/multipath_test.c`. + // + // See + #[test] + fn test_multipath_aead_basic() { + const SECRET: &[u8; 32] = &[ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 35, 26, 27, 28, 29, 30, 31, + ]; + const PN: u64 = 12345; + const PATH_ID: u32 = 2; + const PAYLOAD: &[u8] = b"The quick brown fox jumps over the lazy dog"; + const HEADER: &[u8] = b"This is a test"; + + const EXPECTED: &[u8] = &[ + 123, 139, 232, 52, 136, 25, 201, 143, 250, 89, 87, 39, 37, 63, 0, 210, 220, 227, 186, + 140, 183, 251, 13, 203, 6, 116, 204, 100, 166, 64, 43, 185, 174, 85, 212, 163, 242, + 141, 24, 166, 62, 228, 187, 137, 248, 31, 152, 126, 240, 151, 79, 51, 253, 130, 43, + 114, 173, 234, 254, + ]; + + let secret = OkmBlock::new(SECRET); + let builder = KeyBuilder::new( + &secret, + Version::V1, + TLS13_AES_128_GCM_SHA256_INTERNAL + .quic + .unwrap(), + TLS13_AES_128_GCM_SHA256_INTERNAL.hkdf_provider, + ); + + let packet = builder.packet_key(); + let mut buf = PAYLOAD.to_vec(); + let tag = packet + .encrypt_in_place_for_path(PATH_ID, PN, HEADER, &mut buf) + .unwrap(); + buf.extend_from_slice(tag.as_ref()); + + assert_eq!(buf.as_slice(), EXPECTED); + } + + // This test is based on `multipath_aead_test` in `picoquictest/multipath_test.c` + // + // See + #[test] + fn test_multipath_aead_roundtrip() { + const SECRET: &[u8; 32] = &[ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 35, 26, 27, 28, 29, 30, 31, + ]; + const PAYLOAD: &[u8] = b"The quick brown fox jumps over the lazy dog"; + const HEADER: &[u8] = b"This is a test"; + const PN: u64 = 12345; + + const TEST_PATH_IDS: &[u32] = &[0, 1, 2, 0xaead]; + + let secret = OkmBlock::new(SECRET); + let builder = KeyBuilder::new( + &secret, + Version::V1, + TLS13_AES_128_GCM_SHA256_INTERNAL + .quic + .unwrap(), + TLS13_AES_128_GCM_SHA256_INTERNAL.hkdf_provider, + ); + let packet = builder.packet_key(); + + for &path_id in TEST_PATH_IDS { + let mut buf = PAYLOAD.to_vec(); + let tag = packet + .encrypt_in_place_for_path(path_id, PN, HEADER, &mut buf) + .unwrap(); + buf.extend_from_slice(tag.as_ref()); + let decrypted = packet + .decrypt_in_place_for_path(path_id, PN, HEADER, &mut buf) + .unwrap(); + assert_eq!(decrypted, PAYLOAD); + } + } } diff --git a/rustls/src/quic.rs b/rustls/src/quic.rs index f00f3bba77f..0136ee79f21 100644 --- a/rustls/src/quic.rs +++ b/rustls/src/quic.rs @@ -731,6 +731,25 @@ pub trait PacketKey: Send + Sync { payload: &mut [u8], ) -> Result; + /// Encrypts a multipath QUIC packet + /// + /// Takes a `path_id` and `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. + /// + /// See . + fn encrypt_in_place_for_path( + &self, + _path_id: u32, + _packet_number: u64, + _header: &[u8], + _payload: &mut [u8], + ) -> Result { + Err(Error::EncryptError) + } + /// Decrypt a QUIC packet /// /// Takes the packet `header`, which is used as the additional authenticated data, and the @@ -745,6 +764,26 @@ pub trait PacketKey: Send + Sync { payload: &'a mut [u8], ) -> Result<&'a [u8], Error>; + /// Decrypt a multipath QUIC packet + /// + /// Takes a `path_id` and `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. + /// + /// If the return value is `Ok`, the decrypted payload can be found in `payload`, up to the + /// length found in the return value. + /// + /// See . + fn decrypt_in_place_for_path<'a>( + &self, + _path_id: u32, + _packet_number: u64, + _header: &[u8], + _payload: &'a mut [u8], + ) -> Result<&'a [u8], Error> { + Err(Error::DecryptError) + } + /// Tag length for the underlying AEAD algorithm fn tag_len(&self) -> usize; From 667a71d51365e0f6d72bad701cda846508afa473 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 17 Oct 2025 09:31:15 +0100 Subject: [PATCH 360/403] Reset KeyUpdate counter on AppData --- rustls/src/common_state.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/rustls/src/common_state.rs b/rustls/src/common_state.rs index 4d47cf15076..77ba0bbf57e 100644 --- a/rustls/src/common_state.rs +++ b/rustls/src/common_state.rs @@ -481,6 +481,7 @@ impl CommonState { } pub(crate) fn take_received_plaintext(&mut self, bytes: Payload<'_>) { + self.temper_counters.received_app_data(); self.received_plaintext .append(bytes.into_vec()); } @@ -964,6 +965,14 @@ impl TemperCounters { } } } + + fn received_app_data(&mut self) { + self.allowed_key_update_requests = Self::INITIAL_KEY_UPDATE_REQUESTS; + } + + // cf. BoringSSL `kMaxKeyUpdates` + // + const INITIAL_KEY_UPDATE_REQUESTS: u8 = 32; } impl Default for TemperCounters { @@ -977,9 +986,7 @@ impl Default for TemperCounters { // a second request after this is fatal. allowed_renegotiation_requests: 1, - // cf. BoringSSL `kMaxKeyUpdates` - // - allowed_key_update_requests: 32, + allowed_key_update_requests: Self::INITIAL_KEY_UPDATE_REQUESTS, // At most two CCS are allowed: one after each ClientHello (recall a second // ClientHello happens after a HelloRetryRequest). From b4597ca1f6d386eee64e99b528dd58c8b4e073b5 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 17 Oct 2025 10:08:19 +0100 Subject: [PATCH 361/403] Prepare 0.23.33 --- Cargo.lock | 2 +- fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f7234f254c9..0e9e5837511 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2619,7 +2619,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.32" +version = "0.23.33" dependencies = [ "aws-lc-rs", "base64", diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 8691ffc05bd..5d9ebd08932 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.32" +version = "0.23.33" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 198cb061740..6df11eb49e6 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.32" +version = "0.23.33" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From 31ca6afe91654c2093b9f00a7c56baf379790100 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 29 Sep 2025 09:49:00 +0100 Subject: [PATCH 362/403] Avoid use of `docsrs` cfg cfg is a global namespace, and we don't want to trigger this in dependencies. --- .github/workflows/docs.yml | 2 +- rustls/Cargo.toml | 9 +++++++-- rustls/src/crypto/mod.rs | 4 ++-- rustls/src/lib.rs | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e937cfed4a5..25457c21d1a 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -41,7 +41,7 @@ jobs: # keep features in sync with Cargo.toml `[package.metadata.docs.rs]` section run: cargo doc --locked --features read_buf,ring --no-deps --package rustls env: - RUSTDOCFLAGS: -Dwarnings --cfg=docsrs --html-after-content tag.html + RUSTDOCFLAGS: -Dwarnings --cfg=rustls_docsrs --html-after-content tag.html - name: Generate other pages run: | diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 6df11eb49e6..9242c150367 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -114,7 +114,7 @@ path = "tests/runners/unbuffered.rs" [package.metadata.docs.rs] # all non-default features except fips (cannot build on docs.rs environment) features = ["read_buf", "ring"] -rustdoc-args = ["--cfg", "docsrs"] +rustdoc-args = ["--cfg", "rustls_docsrs"] [package.metadata.cargo_check_external_types] allowed_external_types = [ @@ -127,4 +127,9 @@ allowed_external_types = [ enum_no_repr_variant_discriminant_changed = "warn" [lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ["cfg(bench)", "cfg(coverage_nightly)", "cfg(read_buf)"] } +unexpected_cfgs = { level = "warn", check-cfg = [ + "cfg(bench)", + "cfg(coverage_nightly)", + "cfg(read_buf)", + "cfg(rustls_docsrs)", +] } diff --git a/rustls/src/crypto/mod.rs b/rustls/src/crypto/mod.rs index 6559ad55bbe..1060d130231 100644 --- a/rustls/src/crypto/mod.rs +++ b/rustls/src/crypto/mod.rs @@ -690,8 +690,8 @@ impl From> for SharedSecret { /// .with_no_client_auth(); /// # } /// ``` -#[cfg(all(feature = "aws_lc_rs", any(feature = "fips", docsrs)))] -#[cfg_attr(docsrs, doc(cfg(feature = "fips")))] +#[cfg(all(feature = "aws_lc_rs", any(feature = "fips", rustls_docsrs)))] +#[cfg_attr(rustls_docsrs, doc(cfg(feature = "fips")))] pub fn default_fips_provider() -> CryptoProvider { aws_lc_rs::default_provider() } diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 1d153d6de60..7f6a386acdd 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -364,7 +364,7 @@ clippy::new_without_default )] // Enable documentation for all features on docs.rs -#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +#![cfg_attr(rustls_docsrs, feature(doc_cfg, doc_auto_cfg))] // Enable coverage() attr for nightly coverage builds, see // // (`coverage_nightly` is a cfg set by `cargo-llvm-cov`) From 278391eb38901615549d27b5ef1e26dca79203e5 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 29 Sep 2025 09:59:34 +0100 Subject: [PATCH 363/403] Remove use of `doc_auto_cfg` --- rustls/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 7f6a386acdd..16d67a8e441 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -364,7 +364,7 @@ clippy::new_without_default )] // Enable documentation for all features on docs.rs -#![cfg_attr(rustls_docsrs, feature(doc_cfg, doc_auto_cfg))] +#![cfg_attr(rustls_docsrs, feature(doc_cfg))] // Enable coverage() attr for nightly coverage builds, see // // (`coverage_nightly` is a cfg set by `cargo-llvm-cov`) From 4cee226dbeb3fafeedda9041a2673d139319b51f Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Tue, 21 Oct 2025 17:12:30 -0400 Subject: [PATCH 364/403] Cargo: rustls v0.23.33 -> v0.23.34 --- Cargo.lock | 19 +++++-------------- fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0e9e5837511..9fb8b458fb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -307,7 +307,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools 0.10.5", "lazy_static", "lazycell", "log", @@ -330,7 +330,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "itertools 0.13.0", + "itertools 0.10.5", "log", "prettyplease", "proc-macro2", @@ -1521,15 +1521,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -1815,7 +1806,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.53.3", + "windows-targets 0.48.5", ] [[package]] @@ -2619,7 +2610,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.33" +version = "0.23.34" dependencies = [ "aws-lc-rs", "base64", @@ -3497,7 +3488,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.0", + "windows-sys 0.48.0", ] [[package]] diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 5d9ebd08932..58b36e72ed5 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.33" +version = "0.23.34" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 9242c150367..46317b68a29 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.33" +version = "0.23.34" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From 90e28d66851b9ba9da13b8040ed3fa0314560ee2 Mon Sep 17 00:00:00 2001 From: vuongDang Date: Tue, 4 Nov 2025 01:03:10 +0100 Subject: [PATCH 365/403] fix: only add ocsp in `ConfigBuilder::with_single_cert_with_ocsp` if parameter `ocsp` is not empty --- rustls/src/server/builder.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rustls/src/server/builder.rs b/rustls/src/server/builder.rs index d1b7b24a638..b1dc00b3da8 100644 --- a/rustls/src/server/builder.rs +++ b/rustls/src/server/builder.rs @@ -92,7 +92,9 @@ impl ConfigBuilder { ) -> Result { let mut certified_key = CertifiedKey::from_der(cert_chain, key_der, self.crypto_provider())?; - certified_key.ocsp = Some(ocsp); + if !ocsp.is_empty() { + certified_key.ocsp = Some(ocsp); + } Ok(self.with_cert_resolver(Arc::new(SingleCertAndKey::from(certified_key)))) } From 645095f7e692e57df3486e8dccbfa5b45394bd77 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 4 Nov 2025 15:13:44 +0100 Subject: [PATCH 366/403] Pass through attributes for enum_builder! Adapted from 7d052521d58281f7648dfd3f478ee7c124a87599. --- rustls/src/msgs/macros.rs | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/rustls/src/msgs/macros.rs b/rustls/src/msgs/macros.rs index 53252a20947..d6a18910c72 100644 --- a/rustls/src/msgs/macros.rs +++ b/rustls/src/msgs/macros.rs @@ -3,20 +3,36 @@ macro_rules! enum_builder { ( $(#[doc = $comment:literal])* #[repr($uint:ty)] + $(#[$metas:meta])* $enum_vis:vis enum $enum_name:ident { - $( $enum_var:ident => $enum_val:literal),* $(,)? + $( + $(#[$enum_metas:meta])* + $enum_var:ident => $enum_val:literal),* $(,)? $( !Debug: - $( $enum_var_nd:ident => $enum_val_nd:literal),* $(,)? + $( + $(#[$enum_metas_nd:meta])* + $enum_var_nd:ident => $enum_val_nd:literal + ),* $(,)? )? } ) => { $(#[doc = $comment])* + $(#[$metas])* #[non_exhaustive] #[derive(PartialEq, Eq, Clone, Copy)] $enum_vis enum $enum_name { - $( $enum_var),* - $(, $($enum_var_nd),* )? + $( + $(#[$enum_metas])* + $enum_var + ),* + $( + , + $( + $(#[$enum_metas_nd])* + $enum_var_nd + ),* + )? ,Unknown($uint) } From 6ed925e55ad9cee7cba557e71ec08966994bff6c Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 22 Oct 2025 11:25:49 +0100 Subject: [PATCH 367/403] Address nightly `clippy::derivable_impls` lints --- rustls/src/enums.rs | 2 ++ rustls/src/msgs/enums.rs | 20 ++++++-------------- rustls/src/quic.rs | 9 ++------- rustls/src/server/server_conn.rs | 8 ++------ 4 files changed, 12 insertions(+), 27 deletions(-) diff --git a/rustls/src/enums.rs b/rustls/src/enums.rs index f59ca3f9a46..4b450aafc84 100644 --- a/rustls/src/enums.rs +++ b/rustls/src/enums.rs @@ -615,7 +615,9 @@ enum_builder! { /// [RFC 6091 Section 5]: /// [RFC 7250 Section 7]: #[repr(u8)] + #[derive(Default)] pub enum CertificateType { + #[default] X509 => 0x00, RawPublicKey => 0x02, } diff --git a/rustls/src/msgs/enums.rs b/rustls/src/msgs/enums.rs index 6eaa2b3288c..fb10bbea13b 100644 --- a/rustls/src/msgs/enums.rs +++ b/rustls/src/msgs/enums.rs @@ -355,27 +355,26 @@ enum_builder! { /// /// [RFC 9180 Section 7.2]: #[repr(u16)] + #[derive(Default)] pub enum HpkeKdf { + // TODO(XXX): revisit the default configuration. This is just what Cloudflare ships right now. + #[default] 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]: #[repr(u16)] + #[derive(Default)] pub enum HpkeAead { + // TODO(XXX): revisit the default configuration. This is just what Cloudflare ships right now. + #[default] AES_128_GCM => 0x0001, AES_256_GCM => 0x0002, CHACHA20_POLY_1305 => 0x0003, @@ -396,13 +395,6 @@ impl HpkeAead { } } -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`). /// diff --git a/rustls/src/quic.rs b/rustls/src/quic.rs index 0136ee79f21..d1b732663aa 100644 --- a/rustls/src/quic.rs +++ b/rustls/src/quic.rs @@ -976,11 +976,12 @@ pub enum KeyChange { /// /// Governs version-specific behavior in the TLS layer #[non_exhaustive] -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, Default)] pub enum Version { /// Draft versions 29, 30, 31 and 32 V1Draft, /// First stable RFC + #[default] V1, /// Anti-ossification variant of V1 V2, @@ -1039,12 +1040,6 @@ impl Version { } } -impl Default for Version { - fn default() -> Self { - Self::V1 - } -} - #[cfg(test)] mod tests { use std::prelude::v1::*; diff --git a/rustls/src/server/server_conn.rs b/rustls/src/server/server_conn.rs index d1024b14319..29dda6fedbc 100644 --- a/rustls/src/server/server_conn.rs +++ b/rustls/src/server/server_conn.rs @@ -1111,7 +1111,9 @@ impl State for Accepting { } } +#[derive(Default)] pub(super) enum EarlyDataState { + #[default] New, Accepted { received: ChunkVecBuffer, @@ -1120,12 +1122,6 @@ pub(super) enum EarlyDataState { Rejected, } -impl Default for EarlyDataState { - fn default() -> Self { - Self::New - } -} - impl EarlyDataState { pub(super) fn reject(&mut self) { *self = Self::Rejected; From 7768cd2b44049e040685d48318d13bfa7f7d32a8 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 4 Nov 2025 14:45:44 +0100 Subject: [PATCH 368/403] Bump version to 0.23.35 --- Cargo.lock | 6 +++--- fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9fb8b458fb0..846c1fa78d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -330,7 +330,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "itertools 0.10.5", + "itertools 0.13.0", "log", "prettyplease", "proc-macro2", @@ -1806,7 +1806,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.53.3", ] [[package]] @@ -2610,7 +2610,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.34" +version = "0.23.35" dependencies = [ "aws-lc-rs", "base64", diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 58b36e72ed5..fba72df9f85 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.34" +version = "0.23.35" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 46317b68a29..68600cf3a3a 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.34" +version = "0.23.35" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From ba00982f24b56f2f5c633e14fc9613367b23b797 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 5 Jan 2026 13:24:29 +0000 Subject: [PATCH 369/403] Support P256+SHA512 and P384+SHA512 signatures in certificates --- rustls/src/crypto/aws_lc_rs/mod.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/rustls/src/crypto/aws_lc_rs/mod.rs b/rustls/src/crypto/aws_lc_rs/mod.rs index 336866e0251..8a7fda7e39e 100644 --- a/rustls/src/crypto/aws_lc_rs/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/mod.rs @@ -159,8 +159,10 @@ static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms all: &[ webpki_algs::ECDSA_P256_SHA256, webpki_algs::ECDSA_P256_SHA384, + webpki_algs::ECDSA_P256_SHA512, webpki_algs::ECDSA_P384_SHA256, webpki_algs::ECDSA_P384_SHA384, + webpki_algs::ECDSA_P384_SHA512, webpki_algs::ECDSA_P521_SHA256, webpki_algs::ECDSA_P521_SHA384, webpki_algs::ECDSA_P521_SHA512, @@ -304,6 +306,8 @@ pub(super) fn unspecified_err(_e: aws_lc_rs::error::Unspecified) -> Error { #[cfg(test)] mod tests { + use std::collections::HashSet; + #[cfg(feature = "fips")] #[test] fn default_suites_are_fips() { @@ -319,4 +323,25 @@ mod tests { fn default_suites() { assert_eq!(super::DEFAULT_CIPHER_SUITES, super::ALL_CIPHER_SUITES); } + + #[test] + fn certificate_sig_algs() { + // `all` should not contain duplicates (not incorrect, but a waste of time) + assert_eq!( + super::SUPPORTED_SIG_ALGS + .all + .iter() + .map(|alg| { + ( + alg.public_key_alg_id() + .as_ref() + .to_vec(), + alg.signature_alg_id().as_ref().to_vec(), + ) + }) + .collect::>() + .len(), + super::SUPPORTED_SIG_ALGS.all.len(), + ); + } } From 99308d266596f4d0cf727c36769e08d93ce4e4d9 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Fri, 12 Dec 2025 14:33:40 +0100 Subject: [PATCH 370/403] Bump nightly toolchain for cargo-check-external-types Per https://github.com/awslabs/cargo-check-external-types/releases/tag/v0.4.0. --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 759ec844c55..55d7c288e65 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -511,7 +511,7 @@ jobs: - name: Install rust toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: nightly-2025-08-06 + toolchain: nightly-2025-10-18 # ^ sync with https://github.com/awslabs/cargo-check-external-types/blob/main/rust-toolchain.toml - name: Install cargo-check-external-types uses: taiki-e/cache-cargo-install-action@v2 From b47bf5466a282cd63db8fc73a533ea05c1a90d5e Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 5 Jan 2026 16:28:10 +0000 Subject: [PATCH 371/403] Prepare 0.23.36 --- Cargo.lock | 4 ++-- fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 846c1fa78d8..dc0d55b8bd7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1806,7 +1806,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.53.3", + "windows-targets 0.48.5", ] [[package]] @@ -2610,7 +2610,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.35" +version = "0.23.36" dependencies = [ "aws-lc-rs", "base64", diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index fba72df9f85..4bb2e85a94a 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.35" +version = "0.23.36" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 68600cf3a3a..58e904e9080 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.35" +version = "0.23.36" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From 132a9aa89977313c240f40af86c10d641007022c Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 22 Jan 2026 16:38:09 +0000 Subject: [PATCH 372/403] tlsserver-mio: fix lint with better style --- examples/src/bin/tlsserver-mio.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/examples/src/bin/tlsserver-mio.rs b/examples/src/bin/tlsserver-mio.rs index 1ca5319dd0a..c66fcc9d331 100644 --- a/examples/src/bin/tlsserver-mio.rs +++ b/examples/src/bin/tlsserver-mio.rs @@ -362,13 +362,9 @@ impl OpenConnection { .register(&mut self.socket, self.token, event_set) .unwrap(); - if self.back.is_some() { + if let Some(back) = &mut self.back { registry - .register( - self.back.as_mut().unwrap(), - self.token, - mio::Interest::READABLE, - ) + .register(back, self.token, mio::Interest::READABLE) .unwrap(); } } From ec4ae59214688346bc9b0f9537e2a3e40c64989d Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 13 Feb 2026 11:55:48 +0000 Subject: [PATCH 373/403] Take hpke-rs* 0.6 For GHSA-435g-fcv3-8j26. --- Cargo.lock | 588 +++++++++++++++++++++++++++++++++++++++++++++-------- Cargo.toml | 6 +- 2 files changed, 510 insertions(+), 84 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc0d55b8bd7..32ceba0416a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common", + "crypto-common 0.1.6", "generic-array", ] @@ -356,6 +356,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96eb4cdd6cf1b31d671e9efe75c5d1ec614776856cefbe109ca373554a6d514f" +dependencies = [ + "hybrid-array", +] + [[package]] name = "bogo" version = "0.1.0" @@ -503,7 +512,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", + "crypto-common 0.1.6", "inout", "zeroize", ] @@ -582,9 +591,9 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "core-models" -version = "0.0.3" +version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94950e87ea550d6d68f1993f3e7bebc8cb7235157bff84337d46195c3aa0b3f0" +checksum = "657f625ff361906f779745d08375ae3cc9fef87a35fba5f22874cf773010daf4" dependencies = [ "hax-lib", "pastey", @@ -710,6 +719,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "211f05e03c7d03754740fd9e585de910a095d6b99f8bcfffdef8319fa02a8331" +dependencies = [ + "hybrid-array", + "rand_core 0.10.0", +] + [[package]] name = "ctr" version = "0.9.2" @@ -728,12 +747,26 @@ dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", - "fiat-crypto", + "fiat-crypto 0.2.9", "rustc_version", "subtle", "zeroize", ] +[[package]] +name = "curve25519-dalek" +version = "5.0.0-pre.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335f1947f241137a14106b6f5acc5918a5ede29c9d71d3f2cb1678d5075d9fc3" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "fiat-crypto 0.3.0", + "rustc_version", + "subtle", +] + [[package]] name = "curve25519-dalek-derive" version = "0.1.1" @@ -790,12 +823,22 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", + "block-buffer 0.10.4", "const-oid", - "crypto-common", + "crypto-common 0.1.6", "subtle", ] +[[package]] +name = "digest" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8bf3682cdec91817be507e4aa104314898b95b84d74f3d43882210101a545b6" +dependencies = [ + "block-buffer 0.11.0", + "crypto-common 0.2.0", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -820,7 +863,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", - "digest", + "digest 0.10.7", "elliptic-curve", "rfc6979", "signature", @@ -841,7 +884,7 @@ checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", - "digest", + "digest 0.10.7", "ff", "generic-array", "group", @@ -920,6 +963,12 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "fiat-crypto" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" + [[package]] name = "find-msvc-tools" version = "0.1.2" @@ -1062,6 +1111,20 @@ dependencies = [ "wasi 0.14.7+wasi-0.2.4", ] +[[package]] +name = "getrandom" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "rand_core 0.10.0", + "wasip2", + "wasip3", +] + [[package]] name = "ghash" version = "0.5.1" @@ -1151,9 +1214,9 @@ checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" [[package]] name = "hax-lib" -version = "0.3.4" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bf40682e31dc3961209a4657f6fe7c412879b59f212bac3d14bd7ece5af76a3" +checksum = "543f93241d32b3f00569201bfce9d7a93c92c6421b23c77864ac929dc947b9fc" dependencies = [ "hax-lib-macros", "num-bigint", @@ -1162,9 +1225,9 @@ dependencies = [ [[package]] name = "hax-lib-macros" -version = "0.3.4" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33a5a4ff169bcc4e9189f4bace3ed22d03fcd8e52eee90a00b7b1e2621cb490" +checksum = "f8755751e760b11021765bb04cb4a6c4e24742688d9f3aa14c2079638f537b0f" dependencies = [ "hax-lib-macros-types", "proc-macro-error2", @@ -1175,9 +1238,9 @@ dependencies = [ [[package]] name = "hax-lib-macros-types" -version = "0.3.4" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a39dc59c01c2eec9bce75698c4f9ca01d11759ace2a28e1691b66fb0008c6a21" +checksum = "f177c9ae8ea456e2f71ff3c1ea47bf4464f772a05133fcbba56cd5ba169035a2" dependencies = [ "proc-macro2", "quote", @@ -1268,7 +1331,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] @@ -1282,62 +1345,71 @@ dependencies = [ [[package]] name = "hpke-rs" -version = "0.3.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36874953dfe0223fd877a77b0eefcd84f8da36161b446c6fcb47b8311fa0251a" +checksum = "762ad77634765543485d098af3d352b2ffca88370b4eb3c329a088a3c708832a" dependencies = [ "hpke-rs-crypto", "hpke-rs-libcrux", "hpke-rs-rust-crypto", - "libcrux-sha3", + "libcrux-sha3 0.0.6", "log", "rand_core 0.9.3", + "subtle", "zeroize", ] [[package]] name = "hpke-rs-crypto" -version = "0.3.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51ffd304e06803f90f2e56a24a6910f19b8516f842d7b72a436c51026279876" +checksum = "46a198e2bf992951574b61616f1a27521adf032c8db1db06f4cec423c32cf99d" dependencies = [ "rand_core 0.9.3", + "zeroize", ] [[package]] name = "hpke-rs-libcrux" -version = "0.3.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb9f3bdfd7bc6a45f985b47cce25c5409312af06c2dec07a2af2cca5c89579ae" +checksum = "e9ae3953c75416aff09945e0aa7d18c8cb43faf2855c38c4afee0ef9a42d14b3" dependencies = [ "hpke-rs-crypto", - "libcrux-chacha20poly1305", + "libcrux-aead", "libcrux-ecdh", "libcrux-hkdf", "libcrux-kem", - "rand 0.9.2", - "rand_chacha 0.9.0", - "rand_core 0.9.3", + "libcrux-traits 0.0.6", + "rand 0.10.0", + "rand_chacha 0.10.0", + "rand_core 0.10.0", + "zeroize", ] [[package]] name = "hpke-rs-rust-crypto" -version = "0.3.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff7dc0df494528a0b90005bb511c117453c6a89cd8819f6cf311d0f4446dcf45" +checksum = "2d82d8b517d9a0ebf6675a23b126df957ca3d4b04f596dbe639bbc88091e1ad8" dependencies = [ "aes-gcm", "chacha20poly1305", "hkdf", "hpke-rs-crypto", "k256", + "ml-kem", "p256", "p384", "rand 0.8.5", "rand_chacha 0.3.1", + "rand_core 0.10.0", "rand_core 0.6.4", "sha2", - "x25519-dalek", + "subtle", + "x-wing", + "x25519-dalek 2.0.1", + "zeroize", ] [[package]] @@ -1351,6 +1423,16 @@ dependencies = [ "itoa", ] +[[package]] +name = "hybrid-array" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b229d73f5803b562cc26e4da0396c8610a4ee209f4fac8fa4f8d709166dc45" +dependencies = [ + "subtle", + "typenum", +] + [[package]] name = "icu_collections" version = "2.0.0" @@ -1437,6 +1519,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "idna" version = "1.1.0" @@ -1466,6 +1554,8 @@ checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", "hashbrown 0.16.0", + "serde", + "serde_core", ] [[package]] @@ -1599,6 +1689,25 @@ dependencies = [ "elliptic-curve", ] +[[package]] +name = "keccak" +version = "0.2.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a412fe37705d515cba9dbf1448291a717e187e2351df908cfc0137cbec3d480" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "kem" +version = "0.3.0-rc.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ae2c3347ff4a7af4f679a9e397c2c7e6034a00b773dd2dd3c001d7f40897c9" +dependencies = [ + "crypto-common 0.2.0", + "rand_core 0.10.0", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -1614,38 +1723,72 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libc" version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +[[package]] +name = "libcrux-aead" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f44098a02cdfd8f41cffe672e1d449538a75fd77a9a8093b3d6d77c4b43a7363" +dependencies = [ + "libcrux-aesgcm", + "libcrux-chacha20poly1305", + "libcrux-secrets", + "libcrux-traits 0.0.6", +] + +[[package]] +name = "libcrux-aesgcm" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99f2a019dab4097585a7d4f5b9deebe46cd1e628b16a5bc4cb0ce35e1da334e6" +dependencies = [ + "libcrux-intrinsics 0.0.6", + "libcrux-platform", + "libcrux-secrets", + "libcrux-traits 0.0.6", +] + [[package]] name = "libcrux-chacha20poly1305" -version = "0.0.3" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b318f5f2b32dfbfd27d1c5a3201d27b2ac7a4b4a4bf15ea754a385e6c294c5" +checksum = "c627fca7f9cb4cedaa9667670de8f591859dd2417ce4006c4f0ebbe5626f5e0a" dependencies = [ "libcrux-hacl-rs", "libcrux-macros", "libcrux-poly1305", + "libcrux-secrets", + "libcrux-traits 0.0.6", ] [[package]] name = "libcrux-curve25519" -version = "0.0.3" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5514645ba1ee6c55dd71d62a50cc37ad8aab3f956826001aa8dad17482655c46" +checksum = "bb1e5fd8476a6ed609d24ef42aee5ab6f99f7c65d054f92412da9f499e423299" dependencies = [ "libcrux-hacl-rs", "libcrux-macros", + "libcrux-secrets", + "libcrux-traits 0.0.6", ] [[package]] name = "libcrux-ecdh" -version = "0.0.3" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c4fa67cad871d7be9175141b23a174b77536b039945c91b6a5a6d697acd6371" +checksum = "b65f73ce79337c762eb38bbac91e4c9b9e60cf318e8501b812750c640814d45e" dependencies = [ "libcrux-curve25519", "libcrux-p256", @@ -1654,28 +1797,29 @@ dependencies = [ [[package]] name = "libcrux-hacl-rs" -version = "0.0.3" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1134af11da3f24ae8d1a7e2b60ee871c9e3ffd3d8857deaeebab8088b005addd" +checksum = "2637dc87d158e1f1b550fd9b226443e84153fded4de69028d897b534d16d22e6" dependencies = [ "libcrux-macros", ] [[package]] name = "libcrux-hkdf" -version = "0.0.3" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed7a54a1b453200e8a18205ffbecbb0fee0cce9ec8d0bd635898b7eb2879ac06" +checksum = "8c1a89ca0c89be3a268a921e47105fb7873badf7267f5e3ebf4ea46baedd73ef" dependencies = [ "libcrux-hacl-rs", "libcrux-hmac", + "libcrux-secrets", ] [[package]] name = "libcrux-hmac" -version = "0.0.3" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743cdf6149a46b2cd5f62bea237a7c57011e85055486fc031513e1261cc6692e" +checksum = "8a7a242707d65960770bd7e14e4f18a92bdf0b967777dd404887db8d087a643b" dependencies = [ "libcrux-hacl-rs", "libcrux-macros", @@ -1684,9 +1828,19 @@ dependencies = [ [[package]] name = "libcrux-intrinsics" -version = "0.0.3" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aa4779454e853d1de200cd12f19a8185aac47d99a5ec404cea3295c943d48f1" +dependencies = [ + "core-models", + "hax-lib", +] + +[[package]] +name = "libcrux-intrinsics" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d3b41dcbc21a5fb7efbbb5af7405b2e79c4bfe443924e90b13afc0080318d31" +checksum = "b1b5db005ff8001e026b73a6842ee81bbef8ec5ff0e1915a67ae65fd2a9fafa5" dependencies = [ "core-models", "hax-lib", @@ -1694,14 +1848,16 @@ dependencies = [ [[package]] name = "libcrux-kem" -version = "0.0.3" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eefe0e9579f058b99995cbaf918de3cbab90c4d2dde544fe75247fb027ff5af9" +checksum = "391e6b5cb93ef7f77b9bf53dbe1820b8759aee761d6bf15e871b0ab0317299d3" dependencies = [ + "libcrux-curve25519", "libcrux-ecdh", "libcrux-ml-kem", - "libcrux-sha3", - "libcrux-traits", + "libcrux-p256", + "libcrux-sha3 0.0.7", + "libcrux-traits 0.0.6", "rand 0.9.2", ] @@ -1717,43 +1873,47 @@ dependencies = [ [[package]] name = "libcrux-ml-kem" -version = "0.0.3" +version = "0.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d368d3e8d6a74e277178d54921eca112a1e6b7837d7d8bc555091acb5d817f5" +checksum = "aca7de713c6dddcf7aaf76e8ef9dc0097c8d7ce23a8eadf04c8761734714e184" dependencies = [ "hax-lib", - "libcrux-intrinsics", + "libcrux-intrinsics 0.0.6", "libcrux-platform", "libcrux-secrets", - "libcrux-sha3", + "libcrux-sha3 0.0.7", + "libcrux-traits 0.0.6", "rand 0.9.2", + "tls_codec", ] [[package]] name = "libcrux-p256" -version = "0.0.3" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b00d21690ebcc7ce1f242e6c4bdadfd8529f9cf2d7b961c0344c9bcb2c82f78f" +checksum = "f4778ba25cb08bb8a96bd100e19ed9aecf78337198fd176036e21042b2dd99bc" dependencies = [ "libcrux-hacl-rs", "libcrux-macros", + "libcrux-secrets", "libcrux-sha2", + "libcrux-traits 0.0.6", ] [[package]] name = "libcrux-platform" -version = "0.0.2" +version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db82d058aa76ea315a3b2092f69dfbd67ddb0e462038a206e1dcd73f058c0778" +checksum = "1d9e21d7ed31a92ac539bd69a8c970b183ee883872d2d19ce27036e24cb8ecc4" dependencies = [ "libc", ] [[package]] name = "libcrux-poly1305" -version = "0.0.3" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1a2901c5a92bb236cacd3d16bd6654b7f3471eb417bedab85f6225060cd4a03" +checksum = "ccfb6399682b2dee13b728c779ab5dcc51afbe982b63508ca524806994336134" dependencies = [ "libcrux-hacl-rs", "libcrux-macros", @@ -1761,41 +1921,65 @@ dependencies = [ [[package]] name = "libcrux-secrets" -version = "0.0.3" +version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332737e629fe6ba7547f5c0f90559eac865d5dbecf98138ffae8f16ab8cbe33f" +checksum = "1ce650f3041b44ba40d4263852347d007cd2cd9d1cc856a6f6c8b2e10c3fd40b" dependencies = [ "hax-lib", ] [[package]] name = "libcrux-sha2" -version = "0.0.3" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91eed3bb0ae073f46ae03c83318013fba6e3302bf3292639417b68e908fec4bf" +checksum = "e9d253473f259fc74a280c43f29c464f7e374abdf28b4942234dc707f529d4b7" dependencies = [ "libcrux-hacl-rs", "libcrux-macros", - "libcrux-traits", + "libcrux-traits 0.0.6", ] [[package]] name = "libcrux-sha3" -version = "0.0.3" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29d95de4257eafdfaf3bffecadb615219b0ca920c553722b3646d32dde76c797" +checksum = "e3dabce2795479bd7294f853f7966a678cadf7a26d3d29f61cf15f5123e7ba4f" dependencies = [ "hax-lib", - "libcrux-intrinsics", + "libcrux-intrinsics 0.0.5", "libcrux-platform", + "libcrux-traits 0.0.5", +] + +[[package]] +name = "libcrux-sha3" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c50f6e04a184511b782c5cc1eb6a227c6d36f2c935e93d698655a93a99696b5" +dependencies = [ + "hax-lib", + "libcrux-intrinsics 0.0.6", + "libcrux-platform", + "libcrux-traits 0.0.6", ] [[package]] name = "libcrux-traits" -version = "0.0.3" +version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cdbf9591a39f04d6da6b9bad51ac58378604a80708c2173dadf92029891b9e2" +checksum = "695ff2fb97627e4d57315a2fdfbfe50df1c80c6ef7d91ba34216169bd6f41c00" dependencies = [ + "libcrux-secrets", + "rand 0.9.2", +] + +[[package]] +name = "libcrux-traits" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e4fa89f3f5e34b47f928b22b1b78395a0d4ec23b1f583db635f128159d65f" +dependencies = [ + "libcrux-secrets", "rand 0.9.2", ] @@ -1806,7 +1990,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.53.3", ] [[package]] @@ -1914,6 +2098,31 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "ml-kem" +version = "0.3.0-rc.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc807923f3029ad8676c21a667e1dc941e323538190a6d46cde130e7d55beef" +dependencies = [ + "hybrid-array", + "kem", + "module-lattice", + "rand_core 0.10.0", + "sha3", + "subtle", +] + +[[package]] +name = "module-lattice" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dfecc750073acc09af2f8899b2342d520d570392ba1c3aed53eeb0d84ca4103" +dependencies = [ + "hybrid-array", + "num-traits", + "subtle", +] + [[package]] name = "moka" version = "0.12.10" @@ -2164,9 +2373,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pastey" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" +checksum = "b867cad97c0791bbd3aaa6472142568c6c9e8f71937e98379f584cfb0cf35bec" [[package]] name = "pem" @@ -2399,6 +2608,16 @@ dependencies = [ "rand_core 0.9.3", ] +[[package]] +name = "rand" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +dependencies = [ + "getrandom 0.4.1", + "rand_core 0.10.0", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -2419,6 +2638,16 @@ dependencies = [ "rand_core 0.9.3", ] +[[package]] +name = "rand_chacha" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e6af7f3e25ded52c41df4e0b1af2d047e45896c2f3281792ed68a1c243daedb" +dependencies = [ + "ppv-lite86", + "rand_core 0.10.0", +] + [[package]] name = "rand_core" version = "0.6.4" @@ -2437,6 +2666,12 @@ dependencies = [ "getrandom 0.3.3", ] +[[package]] +name = "rand_core" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" + [[package]] name = "rayon" version = "1.11.0" @@ -2545,7 +2780,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" dependencies = [ "const-oid", - "digest", + "digest 0.10.7", "num-bigint-dig", "num-integer", "num-traits", @@ -2767,7 +3002,7 @@ dependencies = [ "sha2", "signature", "webpki-roots 1.0.2", - "x25519-dalek", + "x25519-dalek 2.0.1", ] [[package]] @@ -2904,7 +3139,17 @@ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.11.0-rc.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5bfe7820113e633d8886e839aae78c1184b8d7011000db6bc7eb61e34f28350" +dependencies = [ + "digest 0.11.0", + "keccak", ] [[package]] @@ -2928,7 +3173,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest", + "digest 0.10.7", "rand_core 0.6.4", ] @@ -3161,6 +3406,27 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tls_codec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de2e01245e2bb89d6f05801c564fa27624dbd7b1846859876c7dad82e90bf6b" +dependencies = [ + "tls_codec_derive", + "zeroize", +] + +[[package]] +name = "tls_codec_derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2e76690929402faae40aebdda620a2c0e25dd6d3b9afe48867dfd95991f4bd" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tokio" version = "1.47.1" @@ -3274,13 +3540,19 @@ version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "universal-hash" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common", + "crypto-common 0.1.6", "subtle", ] @@ -3374,7 +3646,16 @@ version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.46.0", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", ] [[package]] @@ -3436,6 +3717,40 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + [[package]] name = "web-sys" version = "0.3.80" @@ -3488,7 +3803,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.0", ] [[package]] @@ -3855,24 +4170,135 @@ version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + [[package]] name = "writeable" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +[[package]] +name = "x-wing" +version = "0.1.0-rc.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17d0d5f4d1f26b9b9e7477af1d3bef960e1d1fb64edab7912fde472a8a8432e" +dependencies = [ + "kem", + "ml-kem", + "rand_core 0.10.0", + "sha3", + "x25519-dalek 3.0.0-pre.6", +] + [[package]] name = "x25519-dalek" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ - "curve25519-dalek", + "curve25519-dalek 4.1.3", "rand_core 0.6.4", "serde", "zeroize", ] +[[package]] +name = "x25519-dalek" +version = "3.0.0-pre.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d5d6ff67acd3945b933e592bfa7143db4fcbb2f871754b6b9fbd7847fc5aea" +dependencies = [ + "curve25519-dalek 5.0.0-pre.6", + "rand_core 0.10.0", +] + [[package]] name = "x509-parser" version = "0.17.0" @@ -3966,9 +4392,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" dependencies = [ "zeroize_derive", ] diff --git a/Cargo.toml b/Cargo.toml index 94f353ee9c3..48a74628f94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,9 +60,9 @@ hashbrown = { version = "0.15", default-features = false, features = ["default-h hex = "0.4" hickory-resolver = { version = "0.25", features = ["https-aws-lc-rs", "webpki-roots"] } hmac = "0.12" -hpke-rs = "0.3" -hpke-rs-crypto = "0.3" -hpke-rs-rust-crypto = "0.3" +hpke-rs = "0.6" +hpke-rs-crypto = "0.6" +hpke-rs-rust-crypto = "0.6" itertools = "0.14" log = { version = "0.4.8" } macro_rules_attribute = "0.2" From c3a6a11a615a50f1ba3dfa8901d5d802263fd8c1 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 23 Jan 2026 19:00:21 +0100 Subject: [PATCH 374/403] upgrade to zlib-rs 0.6.0 --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- rustls/src/compress.rs | 15 ++++++++------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 32ceba0416a..e57444de089 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4445,6 +4445,6 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.5.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f06ae92f42f5e5c42443fd094f245eb656abf56dd7cce9b8b263236565e00f2" +checksum = "a7948af682ccbc3342b6e9420e8c51c1fe5d7bf7756002b4a3c6cabfe96a7e3c" diff --git a/Cargo.toml b/Cargo.toml index 48a74628f94..48adb4a2336 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -96,7 +96,7 @@ webpki-roots = "1" x25519-dalek = "2" x509-parser = "0.17" zeroize = "1.8" -zlib-rs = "0.5" +zlib-rs = "0.6" [profile.bench] codegen-units = 1 diff --git a/rustls/src/compress.rs b/rustls/src/compress.rs index d34cbaff096..14df129032e 100644 --- a/rustls/src/compress.rs +++ b/rustls/src/compress.rs @@ -125,8 +125,9 @@ 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 zlib_rs::{ + DeflateConfig, InflateConfig, ReturnCode, compress_bound, compress_slice, decompress_slice, + }; use super::*; @@ -139,7 +140,7 @@ mod feat_zlib_rs { 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()) { + match decompress_slice(output, input, InflateConfig::default()) { (output_filled, ReturnCode::Ok) if output_filled.len() == output_len => Ok(()), (_, _) => Err(DecompressionFailed), } @@ -162,12 +163,12 @@ mod feat_zlib_rs { input: Vec, level: CompressionLevel, ) -> Result, CompressionFailed> { - let mut output = alloc::vec![0u8; deflate::compress_bound(input.len())]; + let mut output = alloc::vec![0u8; compress_bound(input.len())]; let config = match level { - CompressionLevel::Interactive => deflate::DeflateConfig::default(), - CompressionLevel::Amortized => deflate::DeflateConfig::new(Z_BEST_COMPRESSION), + CompressionLevel::Interactive => DeflateConfig::default(), + CompressionLevel::Amortized => DeflateConfig::best_compression(), }; - let (output_filled, rc) = deflate::compress_slice(&mut output, &input, config); + let (output_filled, rc) = compress_slice(&mut output, &input, config); if rc != ReturnCode::Ok { return Err(CompressionFailed); } From c91fce039aa994a1fd0e946b147c3eca21b6e19e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 31 Dec 2025 15:11:05 +0000 Subject: [PATCH 375/403] chore(deps): update taiki-e/cache-cargo-install-action action to v3 --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 55d7c288e65..2bc5f76d42d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -250,7 +250,7 @@ jobs: uses: dtolnay/rust-toolchain@nightly - name: Install cargo fuzz - uses: taiki-e/cache-cargo-install-action@v2 + uses: taiki-e/cache-cargo-install-action@v3 with: tool: cargo-fuzz @@ -326,7 +326,7 @@ jobs: components: llvm-tools - name: Install cargo-llvm-cov - uses: taiki-e/cache-cargo-install-action@v2 + uses: taiki-e/cache-cargo-install-action@v3 with: tool: cargo-llvm-cov @@ -393,14 +393,14 @@ jobs: - name: Install rust toolchain uses: dtolnay/rust-toolchain@stable - name: Install cross - uses: taiki-e/cache-cargo-install-action@v2 + uses: taiki-e/cache-cargo-install-action@v3 with: tool: cross git: https://github.com/cross-rs/cross # known-working main in feb 2025, bump as needed rev: c7dee4d - name: Install bindgen-cli - uses: taiki-e/cache-cargo-install-action@v2 + uses: taiki-e/cache-cargo-install-action@v3 with: tool: bindgen-cli - name: Enable bindgen feature for aws-lc-sys (as needed for many cross targets) @@ -514,7 +514,7 @@ jobs: toolchain: nightly-2025-10-18 # ^ sync with https://github.com/awslabs/cargo-check-external-types/blob/main/rust-toolchain.toml - name: Install cargo-check-external-types - uses: taiki-e/cache-cargo-install-action@v2 + uses: taiki-e/cache-cargo-install-action@v3 with: tool: cargo-check-external-types - name: run cargo-check-external-types for rustls/ @@ -533,7 +533,7 @@ jobs: - name: Install rust toolchain uses: dtolnay/rust-toolchain@stable - name: Install taplo-cli - uses: taiki-e/cache-cargo-install-action@v2 + uses: taiki-e/cache-cargo-install-action@v3 with: tool: taplo-cli - run: taplo format --check From 1735677c858e87a746e2a2a2928d7ec1b998d579 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 13 Dec 2025 20:09:20 +0000 Subject: [PATCH 376/403] chore(deps): update actions/upload-artifact action to v6 --- .github/workflows/cifuzz.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml index af7f2fea25d..8f5cc258208 100644 --- a/.github/workflows/cifuzz.yml +++ b/.github/workflows/cifuzz.yml @@ -24,7 +24,7 @@ jobs: dry-run: false language: rust - name: Upload Crash - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 if: failure() && steps.build.outcome == 'success' with: name: artifacts From 3c1841c73263683a80c2eaa2f70754bbc44012df Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 12 Dec 2025 13:57:06 +0000 Subject: [PATCH 377/403] chore(deps): update actions/cache action to v5 --- .github/workflows/build.yml | 2 +- .github/workflows/docs.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2bc5f76d42d..6180342d446 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -553,7 +553,7 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: Cache ${{ env.VERSION }} - uses: actions/cache@v4 + uses: actions/cache@v5 id: cache-openssl with: path: ${{ env.VERSION }} diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 25457c21d1a..caef3cfdf3b 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -48,7 +48,7 @@ jobs: cd website && zola build --output-dir ../target/website/ - name: Restore lychee cache - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: .lycheecache key: cache-lychee-${{ github.sha }} From ff6f7985aa89a67a7ac29e0a5663af7953af0c3b Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Mon, 29 Sep 2025 15:27:17 +0100 Subject: [PATCH 378/403] ci-bench: "pre-warm" per-thread entropy source --- ci-bench/src/main.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ci-bench/src/main.rs b/ci-bench/src/main.rs index d4b517883a7..e05596bb5d5 100644 --- a/ci-bench/src/main.rs +++ b/ci-bench/src/main.rs @@ -424,6 +424,13 @@ fn aws_lc_rs_ticketer() -> Arc { } fn derandomize(base: CryptoProvider) -> CryptoProvider { + // "Warm up" provider's actual entropy source. aws-lc-rs particularly + // has an expensive process here, which is one-time (per calling thread) + // so not useful to include in benchmark measurements. + base.secure_random + .fill(&mut [0u8]) + .unwrap(); + CryptoProvider { secure_random: &NotRandom, ..base From 4df9216e57f2650f05f88e9dc826946fb848a5b6 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 30 Oct 2025 11:45:27 +0000 Subject: [PATCH 379/403] Do not "warm up" aws-lc-rs RNG in other benchmarks --- ci-bench/src/benchmark.rs | 4 ++++ ci-bench/src/main.rs | 33 ++++++++++++++++++++++++++------- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/ci-bench/src/benchmark.rs b/ci-bench/src/benchmark.rs index fc7ca65cc65..07eb7377291 100644 --- a/ci-bench/src/benchmark.rs +++ b/ci-bench/src/benchmark.rs @@ -95,6 +95,8 @@ pub struct BenchmarkParams { pub version: &'static rustls::SupportedProtocolVersion, /// A user-facing label that identifies these params pub label: String, + /// Call this once this BenchmarkParams is sure to be used + pub warm_up: Option, } impl BenchmarkParams { @@ -106,6 +108,7 @@ impl BenchmarkParams { ciphersuite: rustls::SupportedCipherSuite, version: &'static rustls::SupportedProtocolVersion, label: String, + warm_up: Option, ) -> Self { Self { provider, @@ -114,6 +117,7 @@ impl BenchmarkParams { ciphersuite, version, label, + warm_up, } } } diff --git a/ci-bench/src/main.rs b/ci-bench/src/main.rs index e05596bb5d5..99b244859ed 100644 --- a/ci-bench/src/main.rs +++ b/ci-bench/src/main.rs @@ -150,6 +150,10 @@ fn main() -> anyhow::Result<()> { .get(index as usize) .ok_or(anyhow::anyhow!("Benchmark not found: {index}"))?; + if let Some(warm_up) = bench.params.warm_up { + warm_up(); + } + let stdin_lock = io::stdin().lock(); let stdout_lock = io::stdout().lock(); @@ -310,13 +314,14 @@ fn all_benchmarks() -> anyhow::Result> { fn all_benchmarks_params() -> Vec { let mut all = Vec::new(); - for (provider, suites, ticketer, provider_name) in [ + for (provider, suites, ticketer, provider_name, warm_up) in [ ( derandomize(ring::default_provider()), ring::ALL_CIPHER_SUITES, #[allow(trivial_casts)] &(ring_ticketer as fn() -> Arc), "ring", + None, ), ( derandomize(aws_lc_rs::default_provider()), @@ -324,6 +329,8 @@ fn all_benchmarks_params() -> Vec { #[allow(trivial_casts)] &(aws_lc_rs_ticketer as fn() -> Arc), "aws_lc_rs", + #[expect(trivial_casts)] + Some(warm_up_aws_lc_rs as fn()), ), ] { for (key_type, suite_name, version, name) in [ @@ -377,6 +384,7 @@ fn all_benchmarks_params() -> Vec { find_suite(suites, suite_name), version, format!("{provider_name}_{name}"), + warm_up, )); } } @@ -392,6 +400,7 @@ fn all_benchmarks_params() -> Vec { rustls_fuzzing_provider::TLS13_FUZZING_SUITE, &rustls::version::TLS13, "1.3_no_crypto".to_string(), + None, )); all.push(BenchmarkParams::new( @@ -401,6 +410,7 @@ fn all_benchmarks_params() -> Vec { rustls_fuzzing_provider::TLS_FUZZING_SUITE, &rustls::version::TLS12, "1.2_no_crypto".to_string(), + None, )); all @@ -424,17 +434,20 @@ fn aws_lc_rs_ticketer() -> Arc { } fn derandomize(base: CryptoProvider) -> CryptoProvider { + CryptoProvider { + secure_random: &NotRandom, + ..base + } +} + +fn warm_up_aws_lc_rs() { // "Warm up" provider's actual entropy source. aws-lc-rs particularly // has an expensive process here, which is one-time (per calling thread) // so not useful to include in benchmark measurements. - base.secure_random + aws_lc_rs::default_provider() + .secure_random .fill(&mut [0u8]) .unwrap(); - - CryptoProvider { - secure_random: &NotRandom, - ..base - } } #[derive(Debug)] @@ -483,6 +496,12 @@ pub fn run_all( output_dir: PathBuf, benches: &[Benchmark], ) -> anyhow::Result> { + for bench in benches { + if let Some(warm_up) = bench.params.warm_up { + warm_up(); + } + } + // Run the benchmarks in parallel let runner = CallgrindRunner::new(executable, output_dir)?; let results: Vec<_> = benches From 86ad94b64bf0a87e103e5a79ffbec42b7c07bbef Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Wed, 4 Feb 2026 12:43:43 +0100 Subject: [PATCH 380/403] Refresh verify-bench certificates --- rustls/src/testdata/cert-arstechnica.0.der | Bin 1509 -> 1496 bytes rustls/src/testdata/cert-arstechnica.1.der | Bin 1122 -> 1122 bytes rustls/src/testdata/cert-duckduckgo.0.der | Bin 1776 -> 1779 bytes rustls/src/testdata/cert-github.0.der | Bin 1189 -> 1008 bytes rustls/src/testdata/cert-github.1.der | Bin 940 -> 867 bytes rustls/src/testdata/cert-github.2.der | Bin 983 -> 842 bytes rustls/src/testdata/cert-google.0.der | Bin 1114 -> 1114 bytes rustls/src/testdata/cert-hn.0.der | Bin 956 -> 922 bytes rustls/src/testdata/cert-hn.1.der | Bin 1115 -> 1114 bytes rustls/src/testdata/cert-reddit.0.der | Bin 1764 -> 1756 bytes rustls/src/testdata/cert-rustlang.0.der | Bin 1531 -> 1303 bytes rustls/src/testdata/cert-rustlang.1.der | Bin 1122 -> 1290 bytes rustls/src/testdata/cert-rustlang.2.der | Bin 1174 -> 0 bytes rustls/src/testdata/cert-rustlang.3.der | Bin 1145 -> 0 bytes rustls/src/testdata/cert-servo.0.der | Bin 932 -> 931 bytes rustls/src/testdata/cert-stackoverflow.0.der | Bin 972 -> 938 bytes rustls/src/testdata/cert-stackoverflow.1.der | Bin 1115 -> 1114 bytes rustls/src/testdata/cert-twitter.0.der | Bin 985 -> 1328 bytes rustls/src/testdata/cert-twitter.1.der | Bin 1115 -> 1289 bytes rustls/src/testdata/cert-wapo.0.der | Bin 1731 -> 1462 bytes rustls/src/testdata/cert-wapo.1.der | Bin 1003 -> 874 bytes rustls/src/testdata/cert-wikipedia.0.der | Bin 2126 -> 1635 bytes rustls/src/testdata/cert-wikipedia.1.der | Bin 1051 -> 1114 bytes rustls/src/verifybench.rs | 5 ++--- 24 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 rustls/src/testdata/cert-rustlang.2.der delete mode 100644 rustls/src/testdata/cert-rustlang.3.der diff --git a/rustls/src/testdata/cert-arstechnica.0.der b/rustls/src/testdata/cert-arstechnica.0.der index a0d033ae6ce70ebaadfb4cb033f3ccf49281afd8..5a68def3600d82744cae95af77945c42ed51fa9e 100644 GIT binary patch delta 1161 zcmaFLeS=%xpo#U0K@-cK1<@AfEe!hHPC(8Rs85_un^BS2N zm>ZcJfI$?HYi3|!WIVCet$sJ(#a&fv4K6QiZt;HBc2ad`5U0kz-xGgb348ppvtgy5 z_=kS;pSyP)kYC~!5@9N>?kT+YXtMR^a?#A?xi=G{7D)e1+w?dxzs>T&!`%NrN`e|% zufN;>AoGQ2^CY$2r>Yz)e@Z-c6*>Fmjb|VK8WG2bO&{eiwj1Sgo0{>>y5^i(KS|^3 zvp|*wzEkcT*)nh2hM#$&{(*k4k2BQ@&%6EL2usy*`}xN?G{#i&vYT|Z}5|c z3p^vz_A?a4t*q#n{Hypuf_cf)#?vBQA0B=$FDiGhy8TB<@>5MDOG^ji&yxoZas}^L z=W4OTMNQ)4xm^u!>(?+o{C)TMarLBA`WOBD7uGT{GcqtPZesdi(8Tn{K%R{`R92Zq z!a%G+B=n|4{3V$)j1MEW>|1>^)QR!B9+QDANC6*<7>me{X-$)6C;muTS>3;a!=$a? zT|l?gWC^BF5n+%LRTdrtE;bHrHbz!fc4o%O-Aqd2#(IgliB3A3FXr{yM|{pG_x?qf#GU*vwcge&EE>%yI?>#u=WL$A2&| zurM>Y8@MtlWE|N3?*eCG{knfu0ZP|;rSkZNt$O`5OjrB9@0hJ&sLuisdy))FhgP|9$~urAzHaG& zX@C9It!v9>-Q){83$gfwI@n@20~aO*J#DVFpEDGuPW$3!$CX$gdYid%maBd7W8RCU zX?IUNul~oR;Al4U{)X2}&OERX{_(POWliIf9=+&OB}%EKHU_29m3%-CPw{hZ|MlkJ z`^L|bDrzevQW=k5j<;Z9v@c4p4K>%3yaBb>3GQJOsrDu2;h%nG~dEtlZ&jX=Cl`>~?@*L+{-OZy@S5 zwYp}@vF@tZq@%{Ht6|hN^r;D+x8%&6G&;51qAeWTo6St6C z9i}07mM^qCeQu{n#F^^F%lo$__V1c`_8oK3#9ea~b0@`FEp7Y~V_s$5uKVws-RGk< VD_l!bCwVSB&3=)~W+9V&8UW!f_B;Rp delta 1173 zcmcb?{ghkYpo#UNK@-c#1P-v;=kw81;*3%&N7**cX}>M_z!LdPoJlk{w>kYTNfbKrhWP4 zp6$w?ymU(EoEF9-_1srawDJeX6`sJLTRj->K8OVYZ@Ue)oh)k_-@30fxe(V0Eo|4LcC*M!q zb>rw{38qjvuo6`kF#{1c4sA9@R#tXqMmURUawC(HxRG9BZemq_UP)1Dafx1Xey)Cz zQLcf}2Vg_*&_z>P_fVO`?4pO4Fb zPhO;2V<6og#^!ot<~vuj*oU5#*)8j9ER29kw#o}Abk(OF&5-i^eD1-o`VKzJhDY%S zTaQeOR(s0E-4Mc1#!wq6C-ksFt6C;8y(aGOj|=TFA`ASc&fCeXf0M6AuW|>}=3=nT z?gp+*3ZDCNmfsC;S@%b$T|}P!j<9I2v`x5o;Q7xPCRyu5cIW^to^&L!$4q~w9%-Xj&%N{TR`(aFhw}aaz5MKwVX{Mc&p`o4w(EsE&mFwv@NHU4+wWcN zMzVk9%=-eM7WW`|`J71byV{p41(;7p-gnx0eA0^GO10jd(|ldsp0U)T-)+)K@@e=h)F`*3xylk9WZ60mkc^MhGSs9p{7#SHN z1q~M4AKWSCyHa)?|EJtD&rc})`94o!sj9=I6^}aSEk3pRF7mw4 zy|``qz518Er_UGjWL@QBRrUy8$>{!4rDt72#uAnF>%tc-Ol1CUUVHc5uFyKiS6A)7 z)MaLxrF0%W#J2wrkH+lUmWpkW*MgeEsyBpXF<*&FJW_X&q22UT?g=Ze-2YC~8G4+5 z-TLuh>iW6q^IuFdd%~cUcg`qe(usm=kN)LxA69-6>yS|)RWm`&`O^HS*)@08=JWl0 Q5Pt1cXk?{McS-wy0F$ljC;$Ke diff --git a/rustls/src/testdata/cert-arstechnica.1.der b/rustls/src/testdata/cert-arstechnica.1.der index 3b2debb7e51462c914bba879a82148964c081623..66c211b49d9e31ee8650ff942d6d5d627136c541 100644 GIT binary patch delta 617 zcmV-v0+#*a2;vALFoFbLFoFX{paTK{0s<2Ua}rF{2GVE1nH=3Inx8l^d4-W8R}wZb zG+Gx8GcYhXGBYwVGBz+Yk&8Y7Gm*+6f46_7St#=RjN`sje~w32a9avr!StNG^ld^$ zL1S?CH0fYHl`p$>X4C_*tyw~-lFIt_5{$vaEH<2F!?yR0<;8;#bocq@YF7YS*~`pd zi)b>01CY>~^0T@fXMBh15+Z^@DVJUyJzme9JGUn0rrIxPVKk7E0qER|2QN5Se+4!H z3`dQyo1%ymdk|Z1BZLpNyYn=sr`5q1t`Y`cE%$NrWAV_kT$6cHPjLbKm)my7PR~5x z<%t;8*Y2tRGUfFiXRxzbcGHgN@L%-kzGs#w4f<5Dv+tI(TdPAh;OFb1PNV?YXWAxJ zp?U_RNrj7I7RoNI{(j3eI;aIf3tJzgT0oN`9vswZO z0e=RK<)+!dzTZ8J%^;_>?mGXnS-w5uL6F$&OU?|}Sr?6G?^5fN*&BS^9;~e$RNU6z zrJjDiKgt;WW@!T&>}0(rsJK=&4MzSYpWLU7&KTC^dFaV{vWT z0bnEzYhjod!B8P$?tt2N<)n_J%(`${a(|dqD42@pIRWr1S?^VjD#SF2F;Cz$ob~KK z0Ic(Oo(b}2Wbk^Dbhr`?&vCi6?W=TE1>!Ck+!p&4NkUs8=&b`m2~WZzks zf+Dvj@$~C>J}cWt1FhM4I0}MyWryX6`#bxKjt6>_S&R)uV+I-ZTmSV*0_BYS|0O!* z_#j7I7z%f$IT2RA+d~|Wn%jul?dh3GXvswZO z0e>w{E`_r|Gk!0k!fxZQKY~jU$NJ&r?6$Dn#1dUwQSlXd-1|}LzxsgMYL_=?X08P( zumg)*{RZj$MUMmLTb^|nb}ZfmA17XCvJZX4r?o&%J}Aw{ch!Maegt8?G_f|i z)0Em)kx4Y0a7;e`EQ5bF9uPXXMktU@YJc|ZEdO>SDx_i)J=3wJrY52hW)mBL2kGqY z#Zv)DZ?y=rnjmE&u{?!|rx=f;ble50n{8WAIm1y~K57XEL$Xpf$*ii=uQr$;IQXzG^g{h6wf8h@Ca$P2)L!5`$V<+GkpKZ%U8^k^-%d DEfO4B diff --git a/rustls/src/testdata/cert-duckduckgo.0.der b/rustls/src/testdata/cert-duckduckgo.0.der index 2f0fd204d98ebef9431eca5ba0ca1502efa12a6b..9a64c211f1cacbd27da001581fb7a66a3e8ee20c 100644 GIT binary patch delta 1043 zcmV+u1nm3p4f72jFoFi}FoFfwpaTK{0s;^MWoc>IGz4~Gf+ylRGRHxYA8;HoF)=wX zFfcGMFj^N4GBzY2nEEQFSh%+bUM@!hPGi2d&uD^2#+ z4E$@;yzih{S}QG%0{&%k(rM+J5%l7UYG)t|3SRz3HS~DMH=Ni0N6N6(xgIo zNIA?-$kReA@O@>0j3Xzxjg6Gg@Wg(6a$^7r@BHX?Fks0h*ioRw4iZ1Oos^Fhv3&Z+p+8*WjhC z-h~cR9O0Ho!dIGC!K^Ei)^Z2cfqqLH0wDmnP42;0LtDv5=6Y0?|863GR)*ek%4Bg` z>ur)02LuNJ0CxbwF@9G?8KXt+e>mQN@Dq3vri?v?@}0Pufq=1dW1 z=X?oUUMJnvJN-fXu)GR?drc249jNy)kO0fOW^b$HA0#TD zG=t7_)ZL6u0wDn4Q3&q)&S71kgzX=B2w=|zByOxK5qP(pg)B3Fs`f_YFbxI?Duzgg z_YDC73k3iJf&l>lH6a`_n4RW|0cBRrbbb5o0K~x^uw^@6biqDLOSi%~SA9Vzq7;_ZtBKZO0Wi4l{Lv4e$*gFoFi`FoFftpaTK{0s;^P^@0q6f3UL}0V7BwdJc7wA8;HnGch?Z zFfcGMFj^N4GBq(WF*!0bH90joS}<&pFcp!&cz=#){JA)8cXH%4(bjS0^x&ndUA$pO z5#C%Hp52nzNe~zd4|0D4MHC^`q7`lMtc07fx25p7Y6QsLu%Xrgzi~@MQZsHTq#~{6 z`5yL?rUhToe;7)3U==;&wvw(!XXJTQk-Jw-ZzvH6zt~I@_1ulo8gLi3=DNGT$e{ES zAb-RN|I%Awtm{Q3aX*@FVqIXGYfuP=I7Yv^)F zG;!j<+GLB*k$YaJ4^t96 z5(s-?3U5UtDiwuY9t2=SAh@TU^q%Xk#}6mh0s{d60i%Kgn=pa{my<;TEEMlN$6gN# z6|hhJCx4l)W%E5b<2kd10@(q7eFh3E1_1;C)_DR10tA8qZ3Kb=X#r;dbpR6aPBgt! za!iB<8N-i1dK38PwPJ^eoNX`#gzM#oCOQBB0hO)MNUi_?1Oos@Fhl|%74R0nvRt3N zXB5_ydOV;QH!la@ASKG@Z;y3}{Q7`SphQ)9XAlF%*&utb@O4S)%dVwy@d^I^SwZI|UfIZm1f)tnA)aQj_joVHJoV+&p6rF_z@x)I zqG8%{Ll=*-(GAgm(vd8C#s_;Vv6Q=|Ndw({?s@Rn3$4q_78GWfc-PXeR-5#$)WeXhlfM)Qs3Z|((6 z5r1~;{Z;Quor$|c+Fg$;P0mrmMu3zhpYuP4+&txQVI4poyu(KpyBW zS!EUp1F;4X@tG@F4(316Em*-NV9R{@rPL0!WCK}{0zMWo7LkaZ#vFp5^{fB(KjCzr zn5DGC>?FtJ$uk(`MT9|WR9SdHzSd@AWMyS%W}JMLu|pB!Plz{Bed+Az5(f0*Bc z*z3|v7ucIGy}O5bsg0wM$dwL>uP+TZE1#aq0 err*vzuDVHXTh6=i^-FW!i%Iy%r)a-m*Z=_d`1uw9 delta 873 zcmeyszLc}xpowK65PK|OW@2Pw5@cAN*0wdN`UUH>CSe1iHqWmHTx=X#Z64=rS(up& z8v6~o4LI4DLs{5_ncSTWr41xO91dY2_oCFqlGGvv-^9G+jMQQv(@?;G4C<_}IyF3C*KSMZtWCu!^I?5yCDpPQJOrx2EylbMoOl9`{U08~<1 zlnSJZ%7ErNI~vG|^BS2N7#WxvfI$?HYi3|Hafx-kf=P_qf1T4mRA#OFuv@=;rTlb7 zv%+16)Fh6|IscvO`QVJ(oYp^@TYlDPa4*(59?>-?3d=+{E<9 zpo!^+fjrQ8vdSz#cQ%N8Yvr;QY~M3}itH_*lePM1oJ$-)5z}`dJvSRWh+Ku{1H}0dW>%216;swCO4PLnEfI{qEeJVb0-H z{_=y>)o)8ao8`GJvFAUv@)!dHZx_uUi2p8vTox2 zf&&cY43ceEj%%#S|F?@dze3BGapJ0Tx(0d%IO?kU9KQmwck)}Xy&eW`Oo|Lo z*K~e-Gk?3`uLVbB_lf=5UUD+!+KL}V!W;fSe3BS`>;h29k$)-+1ZurIN(497?O83g zN5{hUrQ6xu`V%~xCSE?~#x2ZH#&Fu=yJ%-k%R-m<=!18EpUnF-EAp&6S0-!ghSMU4 zMIxRBt`3tzZs_OoBqqsU_dG3 diff --git a/rustls/src/testdata/cert-github.1.der b/rustls/src/testdata/cert-github.1.der index 89e8d88b0e082b7570753b57f6c4ce6650b2e550..bd4e397246f6af680488936281c31a5eea1bd381 100644 GIT binary patch literal 867 zcmXqLVvaXxVtTfKnTe5!Nxh17S@Hy1e7M_WF{*F zrxul^7AZKEmSm*nm1HI-mSpDVDFo%`mngWJm>I~4^BNf%7#kTGfI*Zvudx}BYiML_ zYH4a2WspFu1I!IfAr8ZUx6Ylfp)Wiaw1iKrz7r9j{bkW#VV&75N25z>H*cy^n}ZS0)&s@QBF#m~e!3r(`Tjt9zrFN(#8}Nao`577iv#}?NMSOF z=9(kI+`dlr*Z*08t&4e-yd2KB2Rbe*W{}|NIQebb#e{Ajj-JY6Z#4q*L literal 940 zcmaJ=TSydP6rP*2x75~IZ|LfXY=qf*Mp;ZlWZg{N^18cSMABtubVv81v*U`1m4b_e zQ4mE5*@j@!gV96z)JsHxghGiBM7U334{AvEAW}2CD*DneFz1}_pYMEg&NncM&%!8f zj^G%IVR~eXYv}PKP5C!8=id%Re;YwdstdxkixmWp!^k+J0}YA02$I5F4u%4~lBg+d z13y69c`?WjG6qOdiYiJMFVHqY8f0=HTd8WPRHuihU5@G&XN$|>q#Jl?ARzWIW++r} zoHE5Qu|Fu$)ixV#<3&m66j-+;1pKtMU-AS*nGbT(6PYs%1H}-#TGJCtfGIAKZ%dh_ ztQAJ?9+Fy9#biNdTxv><$h#$8r0d;&*24$okU0)Xamgx&+uIosIVJY;Bq$)N_4BeY4 zj;in~gc!`Yzwp#I<-LsLCzR^ildrVC|9;aoy_U1`)ubJd(01eX#ss*{)=?8&p6bDF zxg}~}ytkS0r{bk&W@ou}dKC4;DB2CVvNB^nA&b9dD35Bw%S)N>9)_g4(6?2~2bP@# zqjDgLNFxl}W7@O&aFiHMdZ8=)y#9$B8k&nu!I+Gqe+fdiLpZibBc1*eTqaA5>&YSIeQTXSxN_*kWBz2Nys4rYLe_4Ifh~=G$~*%Q3o|p9kE5M;YyDr z^_CYEv7*=9ACyy-Qa=B{T#4x$pN|aA95?l zIhC$9t4t_?>3{$YXYLUM*kJEbhQoga?m>XZ;KGlOeQmGWG``8Ij`rZ%=E{lX*Ue6E z-|6hJj{1|o>Ss0=Li6_OjakgTeW!8Gk1@zzT-GXqz#;O8a;z_t8Jv{S#jR diff --git a/rustls/src/testdata/cert-github.2.der b/rustls/src/testdata/cert-github.2.der index e987bd2e07c39fabc33a0874a53b0f42df098f16..8a65485d0bb3c7544a22f948610e4a57460e9761 100644 GIT binary patch delta 669 zcmcc4eu_=opo!Vdpo!`90%j&gCME%?dF$WgzIZr0M$*u6TknLs23%|$T5TTZY+0C@ zC!X%9mlNkTGBhwYGBN;zC~;n63j;$#3nODwOH<1zgLp%315P&PP!={}CU+-82?H?@ zhfA10I5oK>Gd*9yCo?y*BsIm*%)kUB!z`=|lL;tI%E?St2u>|3OD$4xEG@}M%`3@F zPAtjH&r=A>&o5DMHK{i+tm3azpe_k(t%x=Bn zwr#w{i`Aja!u+p!yn0iwyXx?!qm^%FCe{m79%qXB$zuN1#8kWdT)jen&|-$pH&>T0 z%8h>PJ!$fShOdlM?tI8#mpl9JpK8!n1!o!Qf3GFaIWJz^#He7<#K$OOAP;o6tTGGG zYYmhCGm6Q{g7|zaVk{yTm2UY&e)Nu4vsg9v+Pl}hhkvh3oGikmR1a37$|7bU!p5P^ z#>mRb&ddmBF&PMgOi*CqGT<;^V`Bj_84LnILh>x02JQx~3!E1?w%KQtloVL$>n9iG z=#>_y7L^p07MJKH=jZB&2D=7@fOxLX&dxxI%rt1Afr2o9Q=Z{Ac>)3pBb%UMihpz{|#|)#lOmotKf3 zhn2yg+K}6TlZ`o)g-w{r-N{heKoZ2^;1O~!N=+ zV96E(S&#xg7BLnPtB0IzSI$cwnpRfgS$5}v>9OSGS(CprD%A^ulqj%p8E_b|v9SP| z3^^=Qo^pe40nVbk>=mWzJDd=D!rw3GLV8X_s z&Bn;e%Ff8hqG6zBpaSC?Ft$lR&C5?Nt}j3_5iJEUH!(6YNWOVJw^K)fo25Zk;-1sY zqM2ewd->*+M(c<^(samu_rK`&?bQ?Hd!~NsvgIgp>I`6iWGR}%*nU$?>g$10?W51a z1ljN3n6am3zNF>-?o$jY#e3WYW=~e`-6wWfkE6b6PMdK_nYD&bFSAqY=0}^9ovzAP zm1ap@tXY+=c*NMsGB^0-qPIy(D|SB$&6%0woIP>+MIP?SOtP2uWR`nAllJ|-U!;P0 z!?Io6TOPL7>)&y*UR%QGaqn8rL&+JOaa^0z-T%ovxO!0Iy;rx3p&E;MZ)b^_-utCW z{LLkvla7B^5je!7`Fs1`UG4!&aZ%{<~t*zoSAH^+Wcoabq;I^no)<|F=bvU zE+b7x)7BW{5__zS!k`zIO2$PF-{|XnX{u84hjIpUFA_VElK}xn6cWv{eV*S!E-k_8 zKI9qmXZNEgK9gGk)C+GyMp;>5XnJQ>Ns~GPAAb&4l)Uq^ zCEX#ZC9Gk^P9XpQ0h_UsZBzgN1Oos^Fhv3&SZ;8EL)}^VMZym$TyWCwv#yg{kX3eu zAK2lD;8)1&0wDme9@S;u?LiR7Oo>TXN!_dk%IhaFL6$UI75I?@7tSdFb^sQGEvxXU zC4UbO@H(YM|H!|{BhZIS_5>*>_~#!p6ZQH400En^l5K?m00aX7M=(VKAXp71i&+;Y zlo*KVBV0BWrj2jL)pB)UY4SouAp&A0mI5IF-ZN5z4mie!mWrPb2@Ap1E*=l=)I z8OcpW?Bi;aFbxI?Duzgg_YDC73k3iJf`0)402Z*#Zp%`f_VISMN#Jmy_NQUWh5Dbn z+TY2J@1o`4#qhaONhNqBx*H=-)e3T)jxxD-KyQ%42q*1uU eKa7>T65_T$SGmo(0e+XHRXUb=Fa>3;yXloenKVTJ delta 696 zcmV;p0!RJY2-*lAFoFbDFoFX4!;70dkO(S?W6M;w@b7*zJJSf!+xT_3g)#bdr z(f+|YqX$5qrk?Z~g(uGCbY7rr9JfHJDy`7quan8Hf=dGVlK}xn6k9M$u(y53Gn8|d zgb+V`TPVUMK$BYm)C)&bc~mh@G*CivXOlVtAAipgR_@g;UHv%9;cP^(Y-@zoy({As(puVVdgkaW>-SoJ6X#5~BY=HtGMx_HAm26-#rBa|JG@~2kJc~%{G{rG1 z(}dVfCQ|d}FbxI?Duzgg_YDC73k3iJf`0)409qnuoUZN@uz9J=J(1BGt zf*aQ3x-?l*Vh?Ew@;XshhHfYxQ+Q;77S{1@MDk)d8IFzKZ{Tsk;U!gTu}k58@EgfM emKyS-30Wt=f!<-pLiB}DtS*#*N)GK+Pzj=#rR{%-kfP2)&}9l z$Ewz)D&%YaH8!+f!u{#m*M;h*m7lzF=eZcde2cem&+<n_k_;fE;59i`d9M<)VqF z42;+~wAmP0S=kvGS=0sjJ^O)yfpPX4Upp%X1{P)p4+A$QMTV8z&rN-uXP)3VBTYdujIsON zjfA}?+EzPS1W5VV)SG@Q2dbHH=IK34hB;UEEZxrgpz+eI`d@B41acyH?fmbh{=Uh7 zi=m8R+VqtDp%K&9es^xqFz0Y8fBC`c>bE7I&GOuq*z=!Sc?@cE8`x%d16QD_^G%%` z^sbs8xEaU(tt|JY)6bgV)6Pu}jbGBU^1APSwPRA?tgqVoW7=I+kyu`Pldp%1b1u66 znJN=C(RbfR|6t?t|CJkHs&Ff%h}Fc_pV8L(vg9$OuFqusdW^}Pz~RFgGc zALn>}>Q}b2UbnT*-F~n#&>{-VwJw+SC&7-xpBz$08 zFzq~#cJ;~orh8d87>ca;wYE=8!Faa$-oHP#JxkS@``dkj_KC$!Os)n^OpcRT89nNE z1Z>_e>L3!G+2dJc^rhF1b5);+fjk>?sH`%Jgn?Lt$b9Yi^EQh9b6K{()z&$3tf2eS zbzXx|HV$nzMpjmKMn)D-19t;O7~g=gO*EsVq`*pFKh;z(UoR&$FS$rBzbM^639f{x zO$@GN@=C_IdQ-h*ghG8wL%rmp9D^oC7B()RB`l2BDw$ZASQ@{wG=5_Ez);3;<~M&< zYawUqzp1l>&%NAKqx7;hhIe}Jwv}}u2mbl+ZeUr1&c>&&W1Ek}vcLM+ zqa}0H>GYnzN@mGF<}Ta(&5=Hwc%w!D7Yre+1T zxDUzVvwL2yyPS5lzp=g8k=cal`XQmB88@Bn3+&p~E!-x*Y&DaDNpQVLc0cpAw-uMy zKl|_f#eNxU{jWea-DT2yH$H27R&>dLi;Y98&EuRc3o|ow27^H=lOe;q-@8rseKIhT zK31^U{=Ad0;EB>zjV*s~_WpeF?)vFFCpR}0Uz(V)bguuSD}u*-JSQ+2ur9qcafhBD-kIH3GxNN`+xPB105|{-YXATM diff --git a/rustls/src/testdata/cert-hn.1.der b/rustls/src/testdata/cert-hn.1.der index bbfc07a596e2953d85c84819c81b9d7b0ada6b27..b187e36c701953011c794aac8f903d780efe9390 100644 GIT binary patch delta 713 zcmV;)0yh2I2-*lAFoFbDFoFU;paTK{0s;_Ym6Kz_PH=*8Ss1^=*X>r3AhUlsFm^By z1_vsJNX|V10R{ytfdl{|17ZLK(Pi>p+)K0!0-Vya`tIp$t2(YYq4d-_GBd?O)XXys zG{+$zkZ@e+VlNzVvqIN-zD5nf+ee`jpvT{VCSyC)jUDzqf-^Gq^egA}mO8W(XBc~H zK8;A(>fY_HZ9a!gqk;G^f%TJ80ZtT;4HKgFE`HHaY%>@*U0IGJa*@iDv;n7oXA?+9 zAkwS}g`&}Xb;=Aw=BS|(HgrUd?MR<5Lv_39vW=t3GRC&}yHDxCIcHKysN_jz3)HIMhS~3Am#Ht-LwrE?y9?f*0dU3 zxVtNX)0b)^l65ZdGb-hsA~f~1|0)WMQWN}Xiyt9hXKmgezmDkCfK$b1K^13AQpgig v7jqk+W@lk>RK}BIO=HTXr~@37CaSO;4rPg)%LQY2(z{rozjK}hes!Zsei>FR delta 714 zcmV;*0yX{G2-^rCFoFbEFoFUeXgcNJQkgkR7z)?XwT8DoIP1OEi(fVvH;eC}5 zh@uEo51ATF=IRQp*rS2?FoE@xQ2|aApDSO_JRwh=1h?%gEX2lei_+H(ld}P*e;;z4 zG(|!|+N993vbfSFOs7#LjY8V&Hb|DEx*DX&W7zO7v(C$(XX&7x8S2yxid6%W%0q;m zM)B3my5G9N0w{6!y8dm<8)VL`Ofni0xRLzwiu5gL09*vherZpN90e zAHPz)mf+?|I0or+MIhd9e2!qVfB8&5DkBibNX)NWmC1JhTgt@m78oZZzQi@0pU=YI z3qg=yI9!!n|1N9_e`@XBbAbw2Z%jL!+{apz_v2SYXH{Dfub2^00jS)F$Ja1TS-5GW z-|>!;fDG-KBW7t{%83uuv9p=-Tv6X_?dPu7|9^T8SCw~v=aH>qFbw!Ee*+tsyLqE( za&3kCELb4>dU3YxVN*#6XUAHh#6y8tO4TwJd;GFIs#DCVftHOY)|GK&hzPTY6JOB3 z{^%;n*$HBO+pHAn8iv&74;bjR&fo!rygJp(k5n}F@^ljY?z8uo30|!pD^Of$o}VR~ zCT=uf51MzH@gL^*P&2ave-iaHw07*rVmX*`$)Es7Z^D%Z1*!g57a3@lY2&g7v`_fw z!?yUgI>xERc$Mz+RkOFumb7DISm-ILrkf`x2JkA^fCO&bi?LVEORj4crYMFoFiyFoFfZpaTK{0s;^MyE>Dz!MbpLd_KybUi1BtA8->fF)}nT zFfcGMFj^N4GBz+ZGBUBEngIoiFoFYzlR*Nu6cYvmRUIV+3@{1?2rC8w1qBBK0kahY zJpq4z1_~<%0R#coc>)9i1cCu?1cCu;0cikt0AvxwY@`zGr->Y*0xkf&t4}Bg)E+e_ ztLpyM1Ic~O@Bjb-nzJdk4*&oJ0{}=cMgk!K)E$=q;0}UNsqsC-CgrzUQNs!XvdvYP zbVVJy-(#!90wDnE5l0KXw|tSt5PV@DUX*_z?Y`frqhcetkH4w62lajc0CfNkSCqW- zuBkpV8!VXzv-gnSo5DSDG9}$1sU@so#ZDmr00Ek_DYgFq00aX7MleJIAaHm?u?!Xx zDN_mf)Kq=0mvZfe=aiWzYi<8dZKnbu0M&bQ7RUHG(U)+<>1r&c%PdkKj9p3~qHpV!3r8|2jo@8xz z0ESKH(Cbsj@){M>7m6}7V_%?2H*B3j6nroGJv|+NE$St& zjx1ElbJk>32))Z1bcd|?97aC7Sm>KW?RPk zS~f1A6bs|EN+uR2mL|qrAkJh=XDDM3`sin}H@L{Bg-!BszkQYPkLO#H+B@dt8nCv! ze%hvH#lXNg)y=fY_{SDzbRt1Z5wF47$FCcQAds^m>U zR>E4#*GvlRhnFu>-?L6~f9j2=JW+An^*roc-e*}DE(TuR?fEz+Kv|RE8N{~Xa4|VaS_k~K#ScBT$mK(HlHgwxV+A^C@kpz zf;$uTG+yvfc)T&W{e*MOu0%JLr%Vd=PZnPlZ<5;kuKt|T;^TE5D}MNfDm6sTs#kxu zMm2BWEMB08pItIcb|~*TDB#F;y>REbgO?n>O>1fUy{p|w_OG0IUjWqJA|wwtyqmV+ zTkC`Et5^0~e44}`$uZmSWZ;r(FBd&u8+#_H#wAUE8-o5w+Ap4cK-YkmjZ>@5qwPB{ zBO^B}gMqOjw*e;`b0`a&FjHu-p_qXPh{Gk!>yuidUaa7nmt0g?P-4hqzy%U#7G@4I zG%}DA=QT1jFf=kTG&V3bF^B?lO@LfsAm7+B%0L2U5VJ7v#JPI)GiF4*esg+TdE<)$ zzIG+U_m`5B(;4SX@DmW5GUu!0HdceMZB33zR}8r;4_tY8&`el9ra(;bf=sY*j}1>x ztf>2s<5M&p`wuRZeZRrBrJM7;5+u2mMiBHly zx$cgbj?UqnDayL@=U#ERHKSh5Hoe_^o6nNP?}7{;x9hyMcvrA=>x|mN?bCkix#ld& zQTd~uQ=K%(&tS}?ve-!+MI_?nrd1iwmU^7Iq5Z;X z)BgH>u4x$t@*rtt76}8f1`&p>nxAz0@(o|i_E}qD_v_9}o{N_ZjM+G}*%(<_*%=vG z)D2V(lwo`WrZ(}6l9B=|ef=UsBfU($oK#?(>g6jHrRy7LgNzkqQ87?z;w>sIF44_N z%uCnHFG_C`EH5vg9KfVfuLn{h4>5Cr;sW_LStQevVWt5MGcnUkF3K@zV&r4v0y>3- z@meJl3lmG@f0o8S48Iu48N`}(SASTk%FqA7YN_l06Z=mnUugIK#-geI;!W+m zH#*a}V?tB9YZ)9qy&0X; zU&NStsQ1R)Zf4v4V)YcO4~d_=x_~Y?&i>VVrd(Rzj?3TXrA>1au=;4SUgDLr>gP!z zY8%%^@}lKA<|al)2Ih%nl0R0Pc5s>K$$She_c`Kbk~lr{srAa)ALd7BS0>C|_c_LD zX~?VkyT4!eo#M&e>)jj6BzAg1@5;$BEw7*DoN-eVvhONC=E!S!S;+hcPr-?WuQ-1^ z{yAay`{kaZ1`{sMeYN-K$v1Ja>VNDQ4fn^!y>j!>vz;nfSIaSreg1w%-3uE(-l;k{ z`|4)4#C66`o=oaBT9?13QI#=$a`TbP+l0+-Bwo)D^!^#S-s{(e6Gxhy7gg^`>zehz zLc8wo|MM<$9(g_Y==jgMa;3M6P4!cL9x>lzj|)D1dE4EbA7uN>Det*e+QIh^v_$tT dQTM0{^LWeLCsQbKSCG!FB_*;n@8JsUPeZ4Rt5tb zLv903Hs(+kHesgFU_*YOJdndB%;uPzSe2h=C}SW65?~enRhJgkWNbP;_^1S`*4E`zZ3nLd_EGT|?%RT9; zc5c|DL)HdPvG(0Bb3;4cZ{ZjB`{egYR_(zAR=$Jm=Q)?XHPA}oIo8a%EMk`V)Y~4r zp1%9-bbqR0&rFS`tAT%&$|uO^>4YAMXOcFXH(^gN6Eh*y40}(b3Z8k<$R(57aIE%@^8l+sF#RQmu3>N4u&}q}k zC@Cqh($`Ne%F!z_$~7?3O9ZFB5>R^4OU}>Lhlm2@4N74KF*34b8l)TO!uSS^ZHiEH z@{@}Tup4Ax23O96WNis{)i7&Qiwt-`ZWac4k;wp*LhISMfIeekyjID?!o6MO!fvB`LwV}9`3iV68`agYf^j1oLmFeme)_))T|g77$@*I3V&l@U}0wP zFmPj1WVn0eN$|PgB%kQp$0|Opez)g$$(?QMrN2ozShOrET$*qIsATyC4GANKk1zk9 zdz0?)-KX-%;{ETmT7Rv~*I1e=9`@=ALm5MDq@2*h3ax6H#PpiDzdtUt$A~QOn>ueN zv;IxK9=*yPP>Tz}7P}j`0!{r|u!TKX=F8^qMU#{cWN%Tsyq2wE(~Ty5`L_W=Z@;{K z!lb~q@s!S)x%1OwKO8jsb0)5L?&bBZdf}T*7q6OqRY&>2W1zjyE*T~}l=mDIaAdn) zxbxh>OAgmQtz-`T%2DfnHK&T;-R<&^32M=C03m$1*?)1MYn`nqbS;^8&xZtg}YIDq9Cu;5^1 zP~NuhnH+!F+!gV^4r(v!-=@1PTH@~ehhMXDwU;~;_vY%#bAMs?`E7Ke?aME*c0cbo$y>SU|Kc6_Dol=%Nqoj<%MPl{x@o#+s-5SqbMK6HzL{=e zpA`Im22&V!WNla60*lWq{C8_(JWrqb-@EnMaXxvAl4MMs)7yRdce3+cS6?lA#$LzS>%_O)FEv9K zY+wHNsa)`(?aJO8k29#f%KajI;_v6!^}YTJWJ2bxPd}*nPiV>VNh-_s9Xx-Jt=9GX Q>epV}8yo(8o@TiW0FKl_2><{9 diff --git a/rustls/src/testdata/cert-rustlang.1.der b/rustls/src/testdata/cert-rustlang.1.der index 3b2debb7e51462c914bba879a82148964c081623..f583b217ae5d960d2ba534fbbbf2a5b1e492777f 100644 GIT binary patch literal 1290 zcmXqLVr4UEVtTiLnTe5!Ns!@?kdb%6$}JNM?>Kya)T(AH4p|VWftb~3=VQv2+GedQHU@!kQ3)MGBGeVG&TT(C?MAy$Tc!DHnlXhi~=%I zEEF>kfmq1vlUkx)tl*lLTvS<5V#s5_1u>mD$k523iBSpJ;f$;d%uS5^3_x)%rY1&4 zhFdc>fbJBHmWn5{^o^Y|5D*z?wNXWXBh)+eV%IMafTYM zTB;OV^hKBbkgtQyeMaS-73N>1QjJWWwH3}~dEdejy_ZR9=IdpQ46}+Sk@vO+nW;hMS1&4yu7Vd9MhSY zI`7|Gn`Ni{@}JE6$>6s6zof5L^5(v@V-l?e#{*LHtxKMIH1l&r#Of-~ja&Th#chU# zm%cof^!@a%>YMt!r)THrF8WkIM||yjVROriTTbXWUTZt>@{Qt;Na^~WRyFfu80RLj z9Mag!wbtg8z#C~MW=00a#f?7<8owIw0mDs}pONuD3kxs}v>C{P_^K?RfacI^ErSlqzTaY8EM+soN`21YRR85vpB3{(u1V0;6nHnEJ7k^(Dz z{R%_9Oud{`V07!{7p3ci6O*h03ozadIM~?I8+jO+7{Q5AR-Q${K+ZsBfz$#CWZlWg zx=~X#a}&@P{iPQ;&u5i+q#8}Sx7FoDYuOjkmL8`4Wv@4XeDpJ~WkuM;hm*X&KYYbd z;n80@>G2b{YUu=Rh4l;0i9B`X&3X{jw&e3I5s{TE<3HxQ{R|2acX;_kuJ)N|#J`o@ zf8Kwcm;4~@(cyAydB%3NDQ_JF?rfj==5F}qm_o;Q1_}%;ccyv=Xtd9q^lw$elx=Jr zB0prB>q;Dsazyd?$6Rcgd*tu!$b0W9^OSw3ewuV;hGtgGYo>!vAAWrGOHrs^@!0Ul zfecRf?i)KR7M$|)+Lx)Kc^z_(u#D2ceNd;TM z7WURHKR#I~uPJ13cwXP@X3~`9cm4ria{R8$S?-(yO8>k)wofb#IXzkKiP-Dl^VRpv zeD{Cb`1+aGOJkef%tbTyt*BqTI(}Qo3*Tug*L>a(by~X0Y_iJia}hxe^G&(pboZCc zPEr$}Gtp3!`*Z!-!%5v4$IHLebN@aT`IR}%ds)Ej3-6cyVcL@5%j})#e^i0J+hc>_ z*KKnyo?Kflac9$U{(TSJIPN|0zPEG7w&P;^%rfoUGQ3L~g*yX|W>qn*IqI>LuQoRE z$=Qo(3rdf(#=Yp=nk=cjJ7CL%H-}2i?MjzPH>+weDEb|^Y;}6hs{{Stxe2Ui hVtaRBTlf{;H9a@3FZkS^clgoimws0k*8DBA1^{mD_1pje literal 1122 zcmXqLVu>?oVs=}=%*4pVB+Oncm?<>akRK=ywhn8i<1gn1ux(0t!L-`6UX@jtYhb za^k#3Mg|r}#zsa)rp5+Q;=INNNL&LO0!GUiNI{Gih8Z2~s9+z|- z{i4=>=1BUqV3y{!$~D)P{Mw%$XyI3(nI(EpBVJwc|CgAzy>jtEy%A+X%E2l3BWE-z zZCCsF<#mOf_HB3OwKpp*xSGmS+n;v)w*KAS$6hrhvWM3-nN9L*^#8A(Oiz3M{8zPl z`a?Oxe?v&IMfEo$?kt@(Ut8WW)s+@AF*7nSE^cCs0)|MKfe`Pi-dt#gGh_SnO2iGdw8Zy(c_4mb9|G49~Xx~HOwqVMwWbo zTmyX=-+-}AIisYcz)D{~Ke@O-uLziek`oQ}62U2~q^PvGL@zl%*T4#{fvHUosv)_k z1ebb!m^sO*MF#dD*U7V37?>HDEHGMNfMh@pVFQYC41_@jD6sGta2as0v86ZiFfuVB zr$1m`0j57j23S1SH^%Q)#K7P@z)+%zSY6cPUGzH z@~e%Zbu5W{O*WeCx;*7p*hEj0*#$m!|8<({P2~ivcDQLw@XPx4M(2N-iq?`OVcW|a zmo8IVB$y^F-N63x&AX$)j2`)0IX2BwNLAWs)7rUQqJMG89oChzbE5++4+louWpT1Q zZwfLyxn|X++R1T^pG=gF$e((-VM?gN#++u4J8#5V*PJ~1cXt&%@HGdA42zO&3iHgVpPe@$jfpL&Ho zaeesn?-sFNCAa3xHnr6MwLu|(EvM>2!=`0F*S~R>><_SDzq6>_GUCUst1Ewcq#I0o zH>DyjzjJZm0fV-*g|2D4LS8REJn^T;o&OhK80gmOmK2y??@;+Z??`0c?&5awPeyJU zJDh)QmtA#g%cuD&e7fG>3uEFk|G%2bblRe8U4TXY?ccgd(npWWg*+^OkbZ)HPP_6o zdk2Mjg@z*yK6chBYJDv0a%P=a#mmIZ$iTR`i4hc1x(58fV3ZYRWc<&BXZ91O#*&g90u|rX=N4(1F;5?Iq?kl zS212U(6;DUv?JGR&L_c%%?1^09NKJ*tgP&ej4U|@Sq6GAz5!#KQbtKhft9{~esXbv zUJ)?Kq#Nlaf+M)3sI<65FF8NgzyhwGsZ9r}KDnp_hjM+WDaolt2DTul$+MUlm>3u> zFj%06q&gUl2?wuSxc5gSU+HB1acyiV>Yx!i8X-0}GJzQ4Ld2736RdMcw_D3L6N5MA(J7f|K)0N{Ukwb5eYzHCKm)Z-)bolIh;O^CBy1|pF@brm-wq|5 z7mj4oZa8D&et+k^38}eE=XEA7TlV~3tAuAwn%`op+?8A3ndt4}W!_|WKI zv(GhNbagYDR?vQriOL92MMqM(_))}EJy(# zix`W@oOp)&s~E2vXj^nF+L7xu=ab;XW&?SUv@(l?fmnmc{`l<|&)t=8`w|_x=FWA2 zLwqYco*VeHacHwKva+%>GO{=uI2y>n_y&w^0vRPG1y=g{`Fh30MtY^i`UZ+{S*A8o zsB8sHwn8sCwa7pXWTQNbyn(EN^a9BR;&64vFm*+G$wfKf#3!r3!ezi=z{bWBDyzVN zoG5^q379At8I)xocZHv-eJNh)^HDDJ@0s8{J9qy3$3j1CVljK$ARl}r)90=P*H74Fd{#O_po!_n5B;yg30GLpeQe}7cz1c}bbpDRx%a+Lp2)GQ&Oztx!B@M> z<{7h<%kpy62j7)WS>2@mG4rZ#+`2Cd50@^FaMAr_Q!r!AuFP#y%j@|K<8=NkXt#3D z{7@PHMI>a&)HuNkp#=4F^ADB(R}L%Sm?WBn diff --git a/rustls/src/testdata/cert-servo.0.der b/rustls/src/testdata/cert-servo.0.der index 3dc2e824c118712fe4cb9ab593a9dd748c8edd54..b807621035bea26a1c2b0461a2b438508e4323f7 100644 GIT binary patch delta 513 zcmV+c0{;D^2cricFoFZ0FoFX_paTK{0s;_PXO{YHzhtEmIK?6mqiV{LAWj-KFflST zGB7hYFg02i4Kg+`G%_?YF*7tWG?9ohKpCS+HcZytdmY)UiSX;H0a#&p29kI*3Vxa{ zfuzc1U0kQE0f%u?vLt7|1utFz5FMdL0od~p5W7dAMKRsj2a)^CEX#ZC9Gk^P9XpQ0h{sgbUOe51Oos^Fhv3(0Mea*$;fXAYRRUuc-vmB za{#?^&RKG@sj(#$E$V@{j{+catW!%bXwQ-oFbv%aH0dN_5kQuhWYKq7E`d6(H*!S) zb^y_CsikNKet%{)pg%XI-Mj;(JV6o^)QA}M=`ph-%asHG00Eov@O2sh00aX7M=(VK zAU1gZ>P2w}42Lu{tzt=FVK%SIyGnW?#9sBkVu}vBqOzp z<1~W3c|2TpB|`%^cTvS^FbW0;DuzhTJp=;+14#fdMn(c50KPxvU+^QSaU`c-Tkr*U zLVlGT(%vvO0EcdEHFQQGvH~Fh_x->d2nl4g?DwXt{*dyv$(eHrA@n~4+k1(CRflXL DxKYZ~ delta 514 zcmV+d0{#7?2c!oeFoFZ1FoFX`paTK{0s;{L(HOSZYOTs<5xNnjcU9a*ksnSPH838QR?FiEYIaAsn1vj?w_3~TjoK>?H1)Co;|WMz-J6!~S-c~+76MiiotMU829<;;`g z-YJr4wW^*t9k!EG0apVsQfHH`0f-A)YifE`SW81ycU6->0v~_f+{!eS*Wnfg=an-0 z$DjB;98lle06G*Bb_y)4yT~d400EW#)=|;`00aX7M=(VKAppGfJg}K?^>QHPZe?xt zF9{z&>xJJtM% z&xqS#kD{{FSIDy{P zBQE)#E4U&T6j6lOio}5AFNXpl0GsYHCwA5jM+!=T3||wIQU&9Z7L3Wdp$AITVtcS> E{-hY!FaQ7m diff --git a/rustls/src/testdata/cert-stackoverflow.0.der b/rustls/src/testdata/cert-stackoverflow.0.der index b42a06f60954d4f131c1f758271dc703834c89f5..a0a73350878941aa8d6995bee189fdd01f2943a9 100644 GIT binary patch delta 659 zcmX@ZzKUJZpow`I5Nj`BW@2Pw5@HQqd-uQwzS$=>#7EBibm?Za=0rt%1q%Z?ab6=+ zLn9+2LlYBIW8)|w*UZ2e$~BtUVC7*}mArWAiRyEgw;i$M;yb!uy;5WP!u4iC1`pFO zH$6FRUv?z9=&@MsT5;=-FD0CI7VdD^;0b-pJXhkx6n)0%Sp{kF4D^{ zO4m0r(n~JNF=%3BW#a;xz`}T~l8J?hrSTg}<7bAC3}p-{f=61bz>KPbVm>Jv+T$vOZrmtR-?RKef>5=Z$`rf`r zEiRsUld~%%{s+Hxy?$bS)RzJ#1q;J1=dUx?Bws#ptjF5=O_EE_u{keZMMq5GlHOfg z^3su^oZ({L%B30Xb!nyx?9G?n-NU@p#!*P*N{7VPmxh~_PfulmSR9`Kw%EhK4QTO& z#xtye)BR*VEc~Eyu>HWpuH)0iIgfeV=XS9w7ni$t2&iOV{hqxMQk9#YEWU9hKVw04 z<7Lh;A@!{^%W+)id~CqQ#-Y{ban6>7nVC70!61#vkYUBN2Z7A9vOAe4J_^-y z{<5?4?$ZTzuL=UDetLU|QX3-AS)*jZ^ipdhYKFWj6oKOuXyapVO}y8GYz{@Zu(>aDyhM;K@vk9vKc- zHuZfxbd%vi=thQ?>4m2zPg}-kAkW4eDyz&QVIbBZGG9CXyp5v&T$b%`wRMghE9ky- zo!20gjYFG_k(HI5k&(sIz}-L*#y4PW6U`_oDX`MlPc_xc*UL%GOD@vOFG`=>&nU)d zI(ZpmLA|M7GD2M6(nK%0D950Qk%f&5XeJBewMr%yCYHvpERCNSJ}{Iq2z~T3*&AHs z)50csxZl1?_{a0DN$nkTat&BpUO#P9vtnRioYsCxE0KYLg_*(Kz?DgnVV$gpmJ8FH znd-mPirBa_BulPN?(80i(>^^%=_?@f%awIgAPeToUcOl{t4&}#EIXUoFO%$&(!kj7-lFwLz?dnOb+QaLxjtmP_m%M+5m*rSvk- tx-)A}`t%6CxGO)ui3ImLi7`aa6F9N?@$KE~B`?{=c7Oi*E{5m+K>)NA0lEMH diff --git a/rustls/src/testdata/cert-stackoverflow.1.der b/rustls/src/testdata/cert-stackoverflow.1.der index bbfc07a596e2953d85c84819c81b9d7b0ada6b27..b187e36c701953011c794aac8f903d780efe9390 100644 GIT binary patch delta 713 zcmV;)0yh2I2-*lAFoFbDFoFU;paTK{0s;_Ym6Kz_PH=*8Ss1^=*X>r3AhUlsFm^By z1_vsJNX|V10R{ytfdl{|17ZLK(Pi>p+)K0!0-Vya`tIp$t2(YYq4d-_GBd?O)XXys zG{+$zkZ@e+VlNzVvqIN-zD5nf+ee`jpvT{VCSyC)jUDzqf-^Gq^egA}mO8W(XBc~H zK8;A(>fY_HZ9a!gqk;G^f%TJ80ZtT;4HKgFE`HHaY%>@*U0IGJa*@iDv;n7oXA?+9 zAkwS}g`&}Xb;=Aw=BS|(HgrUd?MR<5Lv_39vW=t3GRC&}yHDxCIcHKysN_jz3)HIMhS~3Am#Ht-LwrE?y9?f*0dU3 zxVtNX)0b)^l65ZdGb-hsA~f~1|0)WMQWN}Xiyt9hXKmgezmDkCfK$b1K^13AQpgig v7jqk+W@lk>RK}BIO=HTXr~@37CaSO;4rPg)%LQY2(z{rozjK}hes!Zsei>FR delta 714 zcmV;*0yX{G2-^rCFoFbEFoFUeXgcNJQkgkR7z)?XwT8DoIP1OEi(fVvH;eC}5 zh@uEo51ATF=IRQp*rS2?FoE@xQ2|aApDSO_JRwh=1h?%gEX2lei_+H(ld}P*e;;z4 zG(|!|+N993vbfSFOs7#LjY8V&Hb|DEx*DX&W7zO7v(C$(XX&7x8S2yxid6%W%0q;m zM)B3my5G9N0w{6!y8dm<8)VL`Ofni0xRLzwiu5gL09*vherZpN90e zAHPz)mf+?|I0or+MIhd9e2!qVfB8&5DkBibNX)NWmC1JhTgt@m78oZZzQi@0pU=YI z3qg=yI9!!n|1N9_e`@XBbAbw2Z%jL!+{apz_v2SYXH{Dfub2^00jS)F$Ja1TS-5GW z-|>!;fDG-KBW7t{%83uuv9p=-Tv6X_?dPu7|9^T8SCw~v=aH>qFbw!Ee*+tsyLqE( za&3kCELb4>dU3YxVN*#6XUAHh#6y8tO4TwJd;GFIs#DCVftHOY)|GK&hzPTY6JOB3 z{^%;n*$HBO+pHAn8iv&74;bjR&fo!rygJp(k5n}F@^ljY?z8uo30|!pD^Of$o}VR~ zCT=uf51MzH@gL^*P&2ave-iaHw07*rVmX*`$)Es7Z^D%Z1*!g57a3@lY2&g7v`_fw z!?yUgI>xERc$Mz+RkOFumb7DISm-ILrkf`x2JkA^fCO&bi?LVEORjN&32Cxs3rY8>d#AN85K^ zMn-N{1_R@X`fBw&23%~+p)Ab8%t40626E!OMrHK5QDCkKlxq@YAYjO6 zzyndwTA`PmpKH*>sDx}TBP#=Q6C*zZP@IdYiII`v%*L%vA{`Z)iEO6V)ebM{%Be=Oaduzqr&K^tQlsCl&Z|8Mv2>lwpswD1J^|f0( zGneMs7Wy-J@y)JDn3MHpmP*)!HFGOj6v9jY=bY6)XSHFQ;=SgS;^Lcgx#gZ8+4eBw z$)b9*6@ovXex00mELQi4(j$(8+S^-e_UgO*d1HL_hQp1IErqo~70+GjuRQ;7+o*oo z+A1B_)Wh7fb_%Www7sjws+P$SyhUskOV`gZ zT~(o(w>&&MCSC%u7dJ6Q z8#FP68}I=`PnMsN@jnX-GZX8A$vlh}^#szdG z3*)s)CKe`^#&0Z*pBX+flrx;R_%7O6)3VSdKKkI@-zW1v&5Ath&Xvj9y5Y3QVUdXE z3=E93Un)lBGcd3)Gk6%dF)1=Ex+ea4Zf}^8WoRFd?1!3jc4Y-0m%of#{w%(+UQ1M6 zm=CDt*|sefOO(0#ct5>bB$#F}+ie^{x?&;P+{ zsq6m}`%freX!ricqN)DlxxBIP*I!VZo4_`^8@K{Z{d7&Gcrgq6OM&OknR62B{#>3q zSt#P8O!xc4UKjdO{vTzkS4f%hup{oM+mDO)Wv>}UTL_udi85}u{B_#~1G9`Rz7tiE zGYK&B0W%3BgYB=$yJouFpYp8sb*s|xjtyQu32i$sz4f>yuq*7Wc9`e|OAn$&k);F~Y?cdfCc6p-U@9mGWZyrErcWX2i}$g9)3jcNDJdJxANskUbKc@QfAS$4 zt;B`GhiqCLW#vA$n(qxUv~8-b)6{bQHDTkCHJc@ZeP(RSbC|Jl_2!KCaY4(UaCNM1 Y-`nSK>rug(Nf$o~TxY0$G_5Qh0P$eo2><{9 delta 838 zcmdnMb(3A+po#e^5JxRwW@2Pw5@M~JcUjB(X~oH#Z>lz}XOaH!#DI&9L#xf>oGlA8 zvw_h>Bei;N15P&PP!?ukCRZ~9IdNViQv*{2Lqkg=BV)rTFxTAJ0L(RrG7vKqF%W_% z=PoJFEGbDX(o4?IHHb72W@87N%ftw^fSHk<*@=PWgxRhI65I=%IE&}JYdC0d=1@({ zo?jX~y313}U8vjlENtOjB{s5?AYNr-{3^3uSQ~0m5BDtGv7Y# zte^PdC__2Jncw_bt@VYRssE#_gC+|b5mjNmS>`V zF%mn!y*t{H%Dp6j$HFr4{xAN^$mx_hGn2s}jmePV-i2j3#eH+`$lvDD4-JV3o)odC zmbGH7hK41tb+Wza9I30Pk2Wt`lx_A`#BRgxUs6CV8$(Rlr__`cR}{WD7cKLx|DNU4 jHM@56{qpj=pZ7zsy6S^o`USp;nsejCeX7^#ocss?Z6Puj diff --git a/rustls/src/testdata/cert-twitter.1.der b/rustls/src/testdata/cert-twitter.1.der index 67d933a8327620d3db96399972e27b6dfe20c8e6..6d4977b41acf80f199251fb42a598c135f8722c5 100644 GIT binary patch delta 900 zcmV-~1AF}22#E?GFoFdIFoFW@paTK{0s;_P0P+&p)U<%}l0jGMDT4)(Ab|lhk)kGl z3@{1?162eA69ZB)GcbYyA}|dG2`Yw2hW8Bt0RaU71A+k$05F093Ic)w0RW|EaE;Jb zfn*gIVa>S))U6qij3!Vwm=>e9_4P_nZUv{0d$4+I!~Pc0zFL^i3k# z0C#WJ$zK=!+I23aR}A**T(;nIrD)HgbmDb_eh{C*^`h$m={T_pM9kB|iS zvmEJ&!beVm4hlB#M^B3JDFk)e&Ec9{|6ZM#mAaZk&`P2g1px#w(=xM<0s{d60h3Gt zR21i{pARfEpi|RcPk6|(gbq8_k~5RE0jGaaH&{}kBAYe4O}fs?lIjWa`&8^0fAl-_ z;rVcK!e!_neF#HxiRF{BpohlvzAwLC<*w`_e4q6XdJS)*alW;s;;y`{wiF_q0mi}4 z)OEA6fR??^;9OTKs2^~bO>oGaKfG(_H)usnCuFVql&9h6ep*23@+jaSS^OfZJtAqUUS+s61=`;)w#}JpNoGSo&e%#-a=Eu0{n4ibC1YvS~^vX1W zzalW`y-*_RWD5O~1mM&E5X0UF&_g1x>be!+ZG?sKG6Kb^nuzg?B?1~Op!czF4%xpn zt&2&|Wy!L!2ffJKZ}F|6BZix)|J%t_e|ITG)(@Xc>b4e}Xli^q{)O zTIp-R=q-KHOk-1CSl4NXQ;&hiBz)@dvH zP_1!w?7QwFvdC0HoRMGRRqC_=>NciGJ*R{bBP}f}XJSM{OGsUc z%E54Lj)B{tMR;2`zgrkp7)4vz%aH2OR+=jbEegq*pTSW4_N0@RcP%Z(XCbTOD#Dbz aS-{pMG|7V>!bR) z>e?N-5~tKA*-;d+VSII#zak4cAJx9m3P!3eJW2_KF1|pORp}W(H)eJ1GER2{N%(Mk z!x-nz_i+&ZtaR7_)a`8?a~3lYoI0}V1#DvUy||P50aO%|Cq|e9sZnT-nAXHXNZTX7 zSd`L}VgjdseT#caAT_cDh6svoo=!TifCR*ZTr(L8fk;i3y6@B-wS?xEH~wabPm4J= z>vCm3Gu*EWqZMPl^cc}-FTx=w$o#&ui=@Uj*yH+bq_vaQ46e}AmjXwiX7ba7;Y~+@ z4oedC7_J`poMxb2bq7cnu4!iIX?QmV1;XNCs}Qe$@ebw;akRXXnhOU=*bPB=eG9<(qjxmNugpssMv+ctC8MXBhPNE~}4ook|*YBAPcwS7ZsG_-{pEHC# z_K;M6P?HwCxsA)fvprO<> zFC@UGzwb{?SUgTTyxRjV0>0tG`cAyU{jL^rVR=asec#OMzxQq=a@RnKF6R9{69cm6 z(cPOv)BH;R^M^xMK$4Brf7yGPGkGb>#ELEe^>CJkHs&Ff$tj z8gd(OvN4CUun99cI~qzDh=Dj;7xtS%YDTW#bY9JYAVR@L0f0#mu zPq2b#adBy8Ub=#-v$KM;qk@rvqMSIdk*R^DfvEu)L;<;Gh6Vvnnj^r7$l;=!ehW?z`@3r z-pB(CbOTqApgfD6fsKLH0*eJ^Z6+BdB?VUc`pHE(dc~>9C7J2@ddc~@`q0qy4+DlJ zG$?@~>Fj8v2UKZL%EqD1#>mRb&dA7;X^?K<0OK1l!A#Tx8d*ZLktLJ&GD+1VIl!Qa zv7U_!XbB7BwMr%yCYC0~d?3zd%w#BIxWO4}J;lH3{|Pb4{3-set2g}k6W1Q9#xHtN zuV}Zcw+I6R<4kE|_sa|nEX)k<2Chts3|qtdzOvMOo&8!Vf1_*L9I?Y^{Y4gMeQF8H z%)hv2<5B}Ah2W$07beK6xGhoisp%;RdGP$?(mCf(uMb;b&;0mhzb~Dr z0rE3#90EO0WG-}UsXKd3lvV!f5}=a)^PW-e8^Z3@3ug0h9yL%@lCF9$Cf50K$1%|b zg*Q%r6a{+udTy=2#pPei4;_CQf1P3f&!&^cQK=6vY-TJLKXBq`W;xX6b#N~$SVTG< zTVuJ+_11c}B))prgpV>yTZ}~>uIQa2oxb_xz1={I_pEX}sp@v@kDauSWa9yGLE~K) z_UY8dY36z-uJ$SZoXaxVompe@E@sKeub2}jUt*S+yb#E4W|o_r&n#SqoMD+W7z|RG z3>o@sa^B7P$M~RwYt7Q48Of7eil^=RnYGYYTF+WC0bjtR&9$mlHen1YgLqjDK)|RXscAL3TlI|*cn(Yw(F1iaqm6np8MT1 z^9_*jqd>xQT2KT=kkE{w+;bD-iGJs-p|k79t(^rlc)(O|-ubsM6a{tdR3I3KqeU1_ zAVte4EeKZv4H1;<5cx_$oJKBiFnTHpBr5qpB5oPWl5V$K&yLph4pvOHu@>5vBC@<) zpfZ7J6bX`;WYPer>EtV|$P}{7$&+-YXm#>jHM^Ru6j;*fuz4swn5IxsVzQ4x&SiO# zE8`eiIPpuTnva(`Ueo< zIh-K!93zs>GIFldR%tKgXo>(6l(L%8m}$YvIV_^nF_H|_;V=eErkMzgj%+CsMBrnR z2oaFO+Gsb;vs4PuDNQuQq~%tY{I?NV;1onM$y^}o* z#ut5YRaHrM9u)ScT0xuwPQWGtZEg68N4e;c(~kmY=BD2t;BVjTAK2Oi7(75;uS%tc zVayDQK*Ea{z}^U}D7t2(raBqHHTH!A`j;TY`=$>>bM#nDs*Ng7VHrx#usldprijC) zfvF&=C9!4FOA^D|UL~cNCN8O%`Dc6M0 zHdKDiMh!#}@U{Xcu^cc5sBx90ZafUj*Ma7JZyxM@Y}3F9NCs10;1O6GrFbXE4*&N? z;a#-6|2kYV^6CBTK`;c9;5G7NhbtgAbfcSMvfZ1Ght9@(*Bm~7ygU2vPd0d;wAUMA zp2eCr7eEl)U~I$f5QL#n9+-#3L(SixsURA;>`=B?wpld@w*AsL+yEJUvts?!? z`C`r2y?=tc!E<8U)-K*-^aCaBRxB~smde6mgNuzF%lP~ac;tyK zS=Gew&4Z=&A2i#6YQw-E-ozO`Ve=T_AKRMxf9U90y32E!?sPS#?arBLD*^Tc16GTt z3*UED7M6&Hr+upZx$f@3eFxjWI%_(8?$eWf+p+xvWI9Lpbd3F3pd19s5DMyCdC_&a z16^<+XxoCCd4*BqSH(3giEB8v^|L2O`5xOni&%dovUp`8b96$GqgzGuH?UWLy4S9_%5?)3io>6n>_g2fBXHykV6|HYk3li=G{K?ij8Th ztmvVWzRg`*HgV6MQpC9Xe%rf0i<=lL4VoBB4dj9DlvQQ{hGm1uMWtIlksrO|)ht%c zz4q=k@8RDo6AffR3iw#WSVT74{?O$+zf)tr|-~&nXGcx{XVF5;A zn}HCBFAU;y7_b2;CPoH`5vnX=1|n=6+H8!htnAE;a2At+Fi4963y%Sp0S6mfdLs`o zB^ZQ&1m#(L4ZICJ7q~BQZF9~jDJihh*H13W(JO|;w_b97u0Aw|ArTCTU)1OY#V#;% z^?(`;8e3rYGBUDM00ZA2#y4O>vY~`L8w$*m4V2*qGPa3Bot&RsT!3sMa-wEVXD~=% zGDuPIIhl3d?|a&m#7)yR^2E~f-kqM%DZ;~AcI5cF$E9$LbF6h?l%dKVS6Lem?e3=1$4|MF&gf|6lo{ F1OS!h8N&bo literal 1003 zcmXqLVt#JW#GJE$nTe5!Nr0>QN`qb9{6GdE2)uIey8#y)hgO@%Ia?NHW`oB4hTI06 zY|No7Y{E>T!G>Z6A|MWzFt2M~Nl|HWiH?G2Ub3E{hJhMLoLg8vI5kzFyu4g56(X;f zms+BqlbW8Gqg#?%lv`|QX zajHUoUQVTc`REI)PetwC9b81mZW?E))Vo7Fxo`NGpV@V~@AXjHY137VC zLo)*t15=S^ z%*LV3#>mRb&dA83ZlG$Q4C5OxwuxtyloVL$>*psI7a*q?peCR}@+>+AS_T>m)E20; zDM3{x7v&%;)K5(|ECMD1J)pROHAs^Ji;01efdLx}kjY>GN|#XUnHa^SpoXBQ&!U1v z16hz}RTfYJhiYJEgtM3+(tIppEFy=0x-#!O@sr!e)%5f0qBqZ9yq+@KKpv!9nMJ}t ztU+XZ@^h)Xy)QYIg*GpFkQLyVD(K{ioT->I84S{x3>ki2Wq7qw!@PQb-4V7d|CI?% z5rY1jdF@MO$|YUrd_6YLp~q&;+xFNF`R`fLf2}zafLdmFTsReYe$tQIf~D?PIc&ce la-31vRNARa~zc}VAiGFzWX-Pp(lK~eShgO@%Ia?NHW&=1>+kVW!YvLoovp5Qj^c*C(|^y;#9DFS)3)paiCfS(wSy!az=(*T~e+$iTwL z$jIE(APUGeGcbm5O)R4fqzokt#6ZR{^YClwm1kyW7Nn+RChFxEr5i*V2(z(+ZD(SH zI)j;!o!NEM^}rslR8&%|FG7IdDr|NqOLfDbi=fdoSE@sk-tYV)ee; z-!}*@oxq_bQe0ov&St^&c-z8N2{teL7B{hcGH7CXXTS%vT9%)Y@jnX-GZTA*fh>rx z$^!Blhc+7{D=RxQ&}t})$$$qWEeul5WWWGX%*P_eB4QoY8&l93En;E{(*^i8ksVnB|ughgy*pK{T}QwByblNlLV)C^P%lwf=VrZ%yR zl9B=|ef?Amy-dBFRAA78f<)h-iRmrKSV5L1rYAtogC;>OyH<))PurxqpW=ar=9m4F?@iyAU)mVD*R)5C^Hi=6|q3aNmPK!zasn;*nS_BB`mlAl3*WFHG* z`WILP0F%1{3y%Sp0S6mfdLs`b6Qh9+NKl?d)j-)mae@2-**0lJc1cFcF2;JvML7md zjI3;2z&y;tc&(C&g^8u{8%yJ7hK~$o45ux=i+0wuEOd#FK6v-{$-GaqBG0;WWwN$z zI4yEmB;q*(1LJH4&nZ0&3@pqH?gp+*iVT;UB@SQs6P5N`UrS2x!CD=k-4j~B_gMO* z)7O4?ZqG31a4LWK!RqR_C7;dm+?Lq$pIUhgYVT37y&eW`KznZ-wr|=Vvfl7no^pi5 zy;FkR^~UxLX-8E*7Ir@GDYh;KDp_@?(e~%5;`qk(+I7mNi7k_A-#J99>@pY6Z#=P{ ze?}v6Va}Y+V35LOkh#%%mA~GbJ4@tlJ-OL(cADPT)elb1mel&GRBL_i?qr|qukU2~ z7>ksoss^3fT-58wWFUGxE`cK;M!SD@-1gaztrB}~-Boi{->1tbn`JS(<+pakE$f2Y QTN4gksjK!d3{bZL05nTBumAu6 literal 2126 zcmbVNYfuwc6wW@_L<}Jz5v2+S@KLZXH-R*URzZV^)Ippm3O+h9gcu z)k>?QGis~&8Z8}d$5%nCR_SPQQm~G#QcA0}Xe+gr>9k56ZTIdbn}B~h%}i$Yoco>g zo%5Z$X8|M02aLF*5knCal}p`=FZW~>%U`;`cg9Np-AoWkNK$=y?UQi~14WvlUIFgfP-c+dwhfqnHx_MFL7-h!~qD!c(3;M7?dyiE%l z+}oz^+6Rf=z0xndr~F8sFx(0 zf8SmM81y~_C~yY-i8XFAgPUNYU{74@uqP&pdxSpTgilMI&T2oPfl~^09BNU(gj}(yWMze!vbwq0ke^kHGhiv9`~zJ9 zMMEM9`9m%le{}@q?FDCB)n^k0#;mBMOk1{{=%^}KjQ>b;B{By zdY}X81YxU_vWp9(fboQ60)a$Ch*2bV~gZO%Zao&9cjiw6Oh69 zXaxBO$1xOJ&%a+|akxPO88G%;=W}5wsM`tgqw%^epza-z+nCch&6gd>Z=oyF2NDE# z9=r1RjmIuLe&4}$$8Nic8j_8AHc!U?%Tu>DSSo_xUf=;^f;K>WBLZbQEw0J|>A`FP zh5C%aX3S6~*8pJJf9uB$q);R!6cq&`z#yxMNLE1{`NoUlD9#`h`(KVM6IF|1`U*16 znCMycL|kh_R*mw}-4jdKt$)t}BI)+OfOo+V$__6SLm;k3`i9JzX?Cf7F822mQy9%{zPjt$maFqA!5D zbT06>YTe;-PqbutcsTvEm?rOo(I%OM4Z!^zZctzk=hyUC_x^_VZlt`gilY8eRde_#Jy^{o!vo zNnNS!E~vecFD|;Y`YV?A&Q*;i+q3b!d@6B$MN9kntJ!~TtM@%VwN4xVBtgHaFu;2| z#9O){bHuNH>X!U%eYfH0pDJ+p&(*^Vj^gOwyUxJ(M~-vvGca`%kssEN>b*5A>UJ-@wr!oP|W+a&-1 diff --git a/rustls/src/testdata/cert-wikipedia.1.der b/rustls/src/testdata/cert-wikipedia.1.der index 7d8413a3474b4cfb6a84d46dc35f75628d29ccc6..b187e36c701953011c794aac8f903d780efe9390 100644 GIT binary patch literal 1114 zcmXqLVhJ;7VzOJn%*4pVB#=CHa`GX+f~LYqiT#JKzYR0sW#iOp^Jx3d%gD&h%3$Dc z$Zf#M#vIDRCd?EXY^Z6V4&rbLD|qIWq!#6+mM8?LCYKgvmQ*SPr52|q7A0pWxEJM@ z78r^e2!oU|3-fpe2e~T*<>!|uL>L;#iSrtn7#JHG8-PI+kZTU)8W|azTAEr$85p5j zC}to6v5?m%wM4yG!8I?rsIs60rifXX$<@N3%s_yR9q8(FwoHs{tlEt%3`)#N3@jH@ zKgHeg-onE)=hCKM?_TDtwpwSg@XHlTBjck^SI!vom>gGBm{1V&B1vDSaI@3(%6)FU z2XDJC6kc%rexq8l^_5=PZ?;XwM&G_@KmR(-YKw5XM0K`ZugA?-_uj6{wQKiT-1x(w z@v8wJ(1Ei2jEw(TSb$;LW*`gVtFnMx&Y{i5$jZvj%mimK8VG@;g+apI&}Zx;{8|WEEI= z47dz9*x1q=c^H`(!LchV&!S);XCSjcYJmi@?qp=$sL6!63FwP-VGlQjOKUh=7hS9= zJ;mevY{fz$vl5ryx4v_}9(o`wUsjOtN%Q+oF~K#n=GZ1*Jn&Gl=hFjC=EWHYKiK77 zT(>zj=jri*8>pc-tA+v3=9W6OoeJfA6*Cbvyk$^h{yzqSTvCt6OJ%D|_^<*ynb09?5LiFNZ;|EMPrf!@Ovi60*y7q#WYTf(7b0@5`k1*bsz3r3o zru?sR@$3G7U3IK_Ybu}e()Cl9Jxh{!8Mbao|JPRvB`=($wAD|(5mRRguv)bBHAmaY z=@XBgKUn2s_3V$3;?fkh-Tj^BXRLZ9+dD+F&%aV*mR8-f`Y_|(_x9)AIJ-3zo_@By zyMdY1ZV5OS>Z$ M>@S{ISGw2}0BRni`Tzg` literal 1051 zcmXqLVi7lJV*0;;nTe5!Nr3&+=a}{t>ot+heJsgcKOcaa^j0}L*8XA-t2(YmO z{d&%piII&}yOD)Ki8+aZ<)HMjSC6$Y{X9#s*>l zg*=olE&J_v@P;n?KR3j Date: Tue, 24 Feb 2026 08:53:45 +0000 Subject: [PATCH 381/403] Take semver-compatible updates --- Cargo.lock | 1167 +++++++++++++++++----------------------------------- 1 file changed, 371 insertions(+), 796 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e57444de089..cf9d3a09976 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,28 +2,13 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - [[package]] name = "aead" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common 0.1.6", + "crypto-common 0.1.7", "generic-array", ] @@ -54,9 +39,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -84,9 +69,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.20" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -99,9 +84,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" @@ -114,29 +99,29 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.10" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "anyhow" -version = "1.0.99" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "asn1" @@ -160,7 +145,7 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror 2.0.16", + "thiserror", "time", ] @@ -223,11 +208,11 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-fips-sys" -version = "0.13.7" +version = "0.13.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2608e5a7965cc9d58c56234d346c9c89b824c4c8652b6f047b3bd0a777c0644f" +checksum = "df6ea8e07e2df15b9f09f2ac5ee2977369b06d116f0c4eb5fa4ad443b73c7f53" dependencies = [ - "bindgen 0.69.5", + "bindgen", "cc", "cmake", "dunce", @@ -237,43 +222,28 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.14.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b8ff6c09cd57b16da53641caa860168b88c172a5ee163b0288d3d6eea12786" +checksum = "d9a7b350e3bb1767102698302bc37256cbd48422809984b98d292c40e2579aa9" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", + "untrusted 0.7.1", "zeroize", ] [[package]] name = "aws-lc-sys" -version = "0.31.0" +version = "0.37.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e44d16778acaf6a9ec9899b92cebd65580b83f685446bf2e1f5d3d732f99dcd" +checksum = "b092fe214090261288111db7a2b2c2118e5a7f30dc2569f1732c4069a6840549" dependencies = [ - "bindgen 0.72.1", "cc", "cmake", "dunce", "fs_extra", ] -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - [[package]] name = "base16ct" version = "0.2.0" @@ -288,9 +258,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.8.0" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "bencher" @@ -298,29 +268,6 @@ 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 0.10.5", - "lazy_static", - "lazycell", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash 1.1.0", - "shlex", - "syn", - "which", -] - [[package]] name = "bindgen" version = "0.72.1" @@ -336,16 +283,16 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash 2.1.1", + "rustc-hash", "shlex", "syn", ] [[package]] name = "bitflags" -version = "2.9.4" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "block-buffer" @@ -400,9 +347,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "byteorder" @@ -412,9 +359,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "cast" @@ -424,9 +371,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.38" +version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80f41ae168f955c12fb8960b057d70d0ca153fb83182b57d86380443527be7e9" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", "jobserver", @@ -445,9 +392,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -512,7 +459,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common 0.1.6", + "crypto-common 0.1.7", "inout", "zeroize", ] @@ -530,9 +477,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.47" +version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" +checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" dependencies = [ "clap_builder", "clap_derive", @@ -540,9 +487,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.47" +version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" +checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" dependencies = [ "anstream", "anstyle", @@ -552,9 +499,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.47" +version = "4.5.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" dependencies = [ "heck", "proc-macro2", @@ -564,15 +511,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" [[package]] name = "cmake" -version = "0.1.54" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" dependencies = [ "cc", ] @@ -711,9 +658,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", @@ -780,9 +727,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" [[package]] name = "der" @@ -810,9 +757,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.3" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", ] @@ -825,7 +772,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "const-oid", - "crypto-common 0.1.6", + "crypto-common 0.1.7", "subtle", ] @@ -910,9 +857,9 @@ dependencies = [ [[package]] name = "env_filter" -version = "0.1.3" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f" dependencies = [ "log", "regex", @@ -920,9 +867,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" dependencies = [ "anstream", "anstyle", @@ -937,16 +884,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys 0.61.0", -] - [[package]] name = "ff" version = "0.13.1" @@ -971,9 +908,9 @@ checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" [[package]] name = "find-msvc-tools" -version = "0.1.2" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "fnv" @@ -1019,64 +956,49 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-core", "futures-task", "pin-project-lite", - "pin-utils", "slab", ] -[[package]] -name = "generator" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2" -dependencies = [ - "cc", - "cfg-if", - "libc", - "log", - "rustversion", - "windows", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -1090,25 +1012,25 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.7+wasi-0.2.4", + "wasip2", ] [[package]] @@ -1135,12 +1057,6 @@ dependencies = [ "polyval", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "glob" version = "0.3.3" @@ -1154,7 +1070,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00678994ed89e22df4c4d99e3105b0ae69206d4b9aaeaeec3a52c2bec55c1f01" dependencies = [ "cfg-if", - "getrandom 0.3.3", + "getrandom 0.3.4", ] [[package]] @@ -1170,9 +1086,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" dependencies = [ "atomic-waker", "bytes", @@ -1189,12 +1105,13 @@ dependencies = [ [[package]] name = "half" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", + "zerocopy", ] [[package]] @@ -1208,9 +1125,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" [[package]] name = "hax-lib" @@ -1283,7 +1200,7 @@ dependencies = [ "rand 0.9.2", "ring", "rustls", - "thiserror 2.0.16", + "thiserror", "tinyvec", "tokio", "tokio-rustls", @@ -1309,7 +1226,7 @@ dependencies = [ "resolv-conf", "rustls", "smallvec", - "thiserror 2.0.16", + "thiserror", "tokio", "tokio-rustls", "tracing", @@ -1334,15 +1251,6 @@ dependencies = [ "digest 0.10.7", ] -[[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 = "hpke-rs" version = "0.6.0" @@ -1354,7 +1262,7 @@ dependencies = [ "hpke-rs-rust-crypto", "libcrux-sha3 0.0.6", "log", - "rand_core 0.9.3", + "rand_core 0.9.5", "subtle", "zeroize", ] @@ -1365,7 +1273,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46a198e2bf992951574b61616f1a27521adf032c8db1db06f4cec423c32cf99d" dependencies = [ - "rand_core 0.9.3", + "rand_core 0.9.5", "zeroize", ] @@ -1414,12 +1322,11 @@ dependencies = [ [[package]] name = "http" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", - "fnv", "itoa", ] @@ -1435,9 +1342,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -1448,9 +1355,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -1461,11 +1368,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -1476,42 +1382,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -1548,12 +1450,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.4" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", - "hashbrown 0.16.0", + "hashbrown 0.16.1", "serde", "serde_core", ] @@ -1567,17 +1469,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "io-uring" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" -dependencies = [ - "bitflags", - "cfg-if", - "libc", -] - [[package]] name = "ipconfig" version = "0.3.2" @@ -1598,9 +1489,9 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -1631,28 +1522,28 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jiff" -version = "0.2.15" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +checksum = "b3e3d65f018c6ae946ab16e80944b97096ed73c35b221d1c478a6c81d8f57940" dependencies = [ "jiff-static", "log", "portable-atomic", "portable-atomic-util", - "serde", + "serde_core", ] [[package]] name = "jiff-static" -version = "0.2.15" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +checksum = "a17c2b211d863c7fde02cbea8a3c1a439b98e109286554f2860bdded7ff83818" dependencies = [ "proc-macro2", "quote", @@ -1665,15 +1556,15 @@ version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "libc", ] [[package]] name = "js-sys" -version = "0.3.80" +version = "0.3.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852f13bec5eba4ba9afbeb93fd7c13fe56147f055939ae21c43a29a0ecb2702e" +checksum = "f4eacb0641a310445a4c513f2a5e23e19952e269c6a38887254d5f837a305506" dependencies = [ "once_cell", "wasm-bindgen", @@ -1717,12 +1608,6 @@ dependencies = [ "spin", ] -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "leb128fmt" version = "0.1.0" @@ -1731,9 +1616,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.175" +version = "0.2.182" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" [[package]] name = "libcrux-aead" @@ -1985,60 +1870,40 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-targets 0.53.3", + "windows-link", ] [[package]] name = "libm" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" - -[[package]] -name = "linux-raw-sys" -version = "0.4.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" - -[[package]] -name = "loom" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "tracing", - "tracing-subscriber", -] +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "macro_rules_attribute" @@ -2056,20 +1921,11 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "670fdfda89751bc4a84ac13eaa63e205cf0fd22b4c9a5fbfa085b63c1f1d3a30" -[[package]] -name = "matchers" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" -dependencies = [ - "regex-automata", -] - [[package]] name = "memchr" -version = "2.7.5" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "minimal-lexical" @@ -2077,25 +1933,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", -] - [[package]] name = "mio" -version = "1.0.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", "log", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] @@ -2125,20 +1972,18 @@ dependencies = [ [[package]] name = "moka" -version = "0.12.10" +version = "0.12.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926" +checksum = "b4ac832c50ced444ef6be0767a008b02c106a909ba79d1d830501e94b96f6b7e" dependencies = [ "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", - "loom", + "equivalent", "parking_lot", "portable-atomic", - "rustc_version", "smallvec", "tagptr", - "thiserror 1.0.69", "uuid", ] @@ -2164,15 +2009,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "nu-ansi-term" -version = "0.50.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "num-bigint" version = "0.4.6" @@ -2185,11 +2021,10 @@ dependencies = [ [[package]] name = "num-bigint-dig" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" dependencies = [ - "byteorder", "lazy_static", "libm", "num-integer", @@ -2202,9 +2037,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" [[package]] name = "num-integer" @@ -2236,15 +2071,6 @@ dependencies = [ "libm", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "oid-registry" version = "0.8.1" @@ -2266,9 +2092,9 @@ dependencies = [ [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "oorandom" @@ -2284,9 +2110,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.73" +version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ "bitflags", "cfg-if", @@ -2310,9 +2136,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.109" +version = "0.9.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" dependencies = [ "cc", "libc", @@ -2344,9 +2170,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -2354,15 +2180,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -2379,12 +2205,12 @@ checksum = "b867cad97c0791bbd3aaa6472142568c6c9e8f71937e98379f584cfb0cf35bec" [[package]] name = "pem" -version = "3.0.5" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" dependencies = [ "base64", - "serde", + "serde_core", ] [[package]] @@ -2399,12 +2225,6 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - [[package]] name = "pkcs1" version = "0.7.5" @@ -2485,24 +2305,24 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +checksum = "7a9db96d7fa8782dd8c15ce32ffe8680bbd1e978a43bf51a34d39483540495f5" dependencies = [ "portable-atomic", ] [[package]] name = "potential_utf" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -2565,18 +2385,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] @@ -2605,7 +2425,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -2635,7 +2455,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -2654,16 +2474,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", ] [[package]] @@ -2694,31 +2514,32 @@ dependencies = [ [[package]] name = "rcgen" -version = "0.14.4" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c83367ba62b3f1dbd0f086ede4e5ebfb4713fb234dbbc5807772a31245ff46d" +checksum = "10b99e0098aa4082912d4c649628623db6aba77335e4f4569ff5083a6448b32e" dependencies = [ "aws-lc-rs", "pem", "rustls-pki-types", "time", + "x509-parser 0.18.1", "yasna", ] [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.11.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -2728,9 +2549,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.10" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -2739,15 +2560,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.6" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" [[package]] name = "resolv-conf" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3789b30bd25ba102de4beabd95d21ac45b69b1be7d14522bab988c526d6799" +checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" [[package]] name = "rfc6979" @@ -2767,17 +2588,17 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", - "untrusted", + "untrusted 0.9.0", "windows-sys 0.52.0", ] [[package]] name = "rsa" -version = "0.9.8" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" +checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" dependencies = [ "const-oid", "digest 0.10.7", @@ -2794,18 +2615,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc-hash" version = "2.1.1" @@ -2830,19 +2639,6 @@ 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.36" @@ -2869,8 +2665,8 @@ dependencies = [ "serde_json", "subtle", "time", - "webpki-roots 1.0.2", - "x509-parser", + "webpki-roots 1.0.6", + "x509-parser 0.17.0", "zeroize", "zlib-rs", ] @@ -2898,7 +2694,7 @@ dependencies = [ "crabgrind", "itertools 0.14.0", "rayon", - "rustc-hash 2.1.1", + "rustc-hash", "rustls", "rustls-fuzzing-provider", "rustls-test", @@ -2929,7 +2725,7 @@ dependencies = [ "rustls", "serde", "tokio", - "webpki-roots 1.0.2", + "webpki-roots 1.0.6", ] [[package]] @@ -2964,9 +2760,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ "zeroize", ] @@ -2978,7 +2774,7 @@ dependencies = [ "criterion", "env_logger", "rustls", - "webpki-roots 1.0.2", + "webpki-roots 1.0.6", ] [[package]] @@ -3001,7 +2797,7 @@ dependencies = [ "rustls", "sha2", "signature", - "webpki-roots 1.0.2", + "webpki-roots 1.0.6", "x25519-dalek 2.0.1", ] @@ -3025,14 +2821,14 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.6" +version = "0.103.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8572f3c2cb9934231157b45499fc41e1f58c589fdfb81a844ba873265e80f8eb" +checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" dependencies = [ "aws-lc-rs", "ring", "rustls-pki-types", - "untrusted", + "untrusted 0.9.0", ] [[package]] @@ -3041,12 +2837,6 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - [[package]] name = "same-file" version = "1.0.6" @@ -3056,12 +2846,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scopeguard" version = "1.2.0" @@ -3090,9 +2874,9 @@ checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" -version = "1.0.225" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6c24dee235d0da097043389623fb913daddf92c76e9f5a1db88607a0bcbd1d" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", @@ -3100,18 +2884,18 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.225" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "659356f9a0cb1e529b24c01e43ad2bdf520ec4ceaf83047b83ddcc2251f96383" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.225" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea936adf78b1f766949a4977b91d2f5595825bd6ec079aa9543ad2685fc4516" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -3120,15 +2904,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -3152,15 +2936,6 @@ dependencies = [ "keccak", ] -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - [[package]] name = "shlex" version = "1.3.0" @@ -3179,9 +2954,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" @@ -3201,12 +2976,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -3227,9 +3002,9 @@ dependencies = [ [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "strsim" @@ -3245,9 +3020,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.106" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -3273,58 +3048,29 @@ checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" [[package]] name = "thiserror" -version = "1.0.69" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" -dependencies = [ - "thiserror-impl 2.0.16", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.16" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", "syn", ] -[[package]] -name = "thread_local" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" -dependencies = [ - "cfg-if", -] - [[package]] name = "tikv-jemalloc-sys" -version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" +version = "0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d" +checksum = "cd8aa5b2ab86a2cefa406d889139c162cbb230092f7d1d7cbc1716405d852a3b" dependencies = [ "cc", "libc", @@ -3332,9 +3078,9 @@ dependencies = [ [[package]] name = "tikv-jemallocator" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cec5ff18518d81584f477e9bfdf957f5bb0979b0bac3af4ca30b5b3ae2d2865" +checksum = "0359b4327f954e0567e69fb191cf1436617748813819c94b8cd4a431422d053a" dependencies = [ "libc", "tikv-jemalloc-sys", @@ -3342,30 +3088,30 @@ dependencies = [ [[package]] name = "time" -version = "0.3.44" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", "num-conv", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.24" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -3373,9 +3119,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -3429,27 +3175,24 @@ dependencies = [ [[package]] name = "tokio" -version = "1.47.1" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "pin-project-lite", - "slab", - "socket2 0.6.0", + "socket2 0.6.2", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", @@ -3458,9 +3201,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.3" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f63835928ca123f1bef57abbcd23bb2ba0ac9ae1235f1e65bda0d06e7786bd" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", "tokio", @@ -3468,9 +3211,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -3481,9 +3224,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", "tracing-core", @@ -3491,54 +3234,24 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex-automata", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", ] [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-ident" -version = "1.0.19" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-xid" @@ -3552,10 +3265,16 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common 0.1.6", + "crypto-common 0.1.7", "subtle", ] +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "untrusted" version = "0.9.0" @@ -3564,9 +3283,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", @@ -3588,21 +3307,15 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.18.1" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.4.1", "js-sys", "wasm-bindgen", ] -[[package]] -name = "valuable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" - [[package]] name = "vcpkg" version = "0.2.15" @@ -3631,22 +3344,13 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" -[[package]] -name = "wasi" -version = "0.14.7+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" -dependencies = [ - "wasip2", -] - [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ - "wit-bindgen 0.46.0", + "wit-bindgen", ] [[package]] @@ -3655,14 +3359,14 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen 0.51.0", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.103" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab10a69fbd0a177f5f649ad4d8d3305499c42bab9aef2f7ff592d0ec8f833819" +checksum = "05d7d0fce354c88b7982aec4400b3e7fcf723c32737cef571bd165f7613557ee" dependencies = [ "cfg-if", "once_cell", @@ -3671,25 +3375,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb702423545a6007bbc368fde243ba47ca275e549c8a28617f56f6ba53b1d1c" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - [[package]] name = "wasm-bindgen-macro" -version = "0.2.103" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc65f4f411d91494355917b605e1480033152658d71f722a90647f56a70c88a0" +checksum = "55839b71ba921e4f75b674cb16f843f4b1f3b26ddfcb3454de1cf65cc021ec0f" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3697,22 +3387,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.103" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc003a991398a8ee604a401e194b6b3a39677b3173d6e74495eb51b82e99a32" +checksum = "caf2e969c2d60ff52e7e98b7392ff1588bffdd1ccd4769eba27222fd3d621571" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.103" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "293c37f4efa430ca14db3721dfbe48d8c33308096bd44d80ebaa775ab71ba1cf" +checksum = "0861f0dcdf46ea819407495634953cdcc8a8c7215ab799a7a7ce366be71c7b30" dependencies = [ "unicode-ident", ] @@ -3753,9 +3443,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.80" +version = "0.3.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbe734895e869dc429d78c4b433f8d17d95f8d05317440b4fad5ab2d33e596dc" +checksum = "10053fbf9a374174094915bbce141e87a6bf32ecd9a002980db4b638405e8962" dependencies = [ "js-sys", "wasm-bindgen", @@ -3767,35 +3457,23 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.2", + "webpki-roots 1.0.6", ] [[package]] name = "webpki-roots" -version = "1.0.2" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" 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 = "widestring" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" [[package]] name = "winapi-util" @@ -3803,116 +3481,14 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] -[[package]] -name = "windows" -version = "0.61.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" -dependencies = [ - "windows-collections", - "windows-core", - "windows-future", - "windows-link 0.1.3", - "windows-numerics", -] - -[[package]] -name = "windows-collections" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" -dependencies = [ - "windows-core", -] - -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link 0.1.3", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-future" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" -dependencies = [ - "windows-core", - "windows-link 0.1.3", - "windows-threading", -] - -[[package]] -name = "windows-implement" -version = "0.60.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.59.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - [[package]] name = "windows-link" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" - -[[package]] -name = "windows-numerics" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" -dependencies = [ - "windows-core", - "windows-link 0.1.3", -] - -[[package]] -name = "windows-result" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link 0.1.3", -] - -[[package]] -name = "windows-strings" -version = "0.4.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link 0.1.3", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-sys" @@ -3932,31 +3508,22 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "windows-targets 0.53.5", ] [[package]] name = "windows-sys" -version = "0.61.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.0", + "windows-link", ] [[package]] @@ -3992,28 +3559,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link 0.1.3", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", -] - -[[package]] -name = "windows-threading" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" -dependencies = [ - "windows-link 0.1.3", + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -4030,9 +3588,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -4048,9 +3606,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -4066,9 +3624,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -4078,9 +3636,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -4096,9 +3654,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -4114,9 +3672,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -4132,9 +3690,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -4150,9 +3708,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winreg" @@ -4164,12 +3722,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "wit-bindgen" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" - [[package]] name = "wit-bindgen" version = "0.51.0" @@ -4260,9 +3812,9 @@ dependencies = [ [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "x-wing" @@ -4312,7 +3864,25 @@ dependencies = [ "nom", "oid-registry", "rusticata-macros", - "thiserror 2.0.16", + "thiserror", + "time", +] + +[[package]] +name = "x509-parser" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d43b0f71ce057da06bc0851b23ee24f3f86190b07203dd8f567d0b706a185202" +dependencies = [ + "asn1-rs", + "aws-lc-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "rusticata-macros", + "thiserror", "time", ] @@ -4327,11 +3897,10 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -4339,9 +3908,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", @@ -4351,18 +3920,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.27" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.27" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" dependencies = [ "proc-macro2", "quote", @@ -4401,9 +3970,9 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", @@ -4412,9 +3981,9 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -4423,9 +3992,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -4434,9 +4003,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", @@ -4445,6 +4014,12 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.6.0" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c745c48e1007337ed136dc99df34128b9faa6ed542d80a1c673cf55a6d7236c8" + +[[package]] +name = "zmij" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7948af682ccbc3342b6e9420e8c51c1fe5d7bf7756002b4a3c6cabfe96a7e3c" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" From 245963b1510fa2f42aaca217bba8d04393ab7fef Mon Sep 17 00:00:00 2001 From: Vale Tolpegin Date: Mon, 23 Feb 2026 09:39:55 -0600 Subject: [PATCH 382/403] Add ML-KEM-1024 key encapsulation mechanism --- bogo/config.json.in | 2 ++ rustls-post-quantum/src/lib.rs | 2 +- rustls/src/crypto/aws_lc_rs/mod.rs | 3 ++- rustls/src/crypto/aws_lc_rs/pq/mlkem.rs | 19 ++++++++++++------- rustls/src/crypto/aws_lc_rs/pq/mod.rs | 20 +++++++++++++++++--- 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/bogo/config.json.in b/bogo/config.json.in index 40884adf6ef..1fa69242e88 100644 --- a/bogo/config.json.in +++ b/bogo/config.json.in @@ -52,7 +52,9 @@ "NoCommonSignatureAlgorithms-TLS12-Fallback": "requires TLS_RSA_WITH_AES_128_GCM_SHA256", #if defined(POST_QUANTUM) "MLKEMKeyShareIncludedSecond": "we only include a share for the first configured group", + "MLKEMKeyShareIncludedSecond-MLKEM1024": "we only include a share for the first configured group", "MLKEMKeyShareIncludedThird": "we only include a share for the first configured group", + "MLKEMKeyShareIncludedThird-MLKEM1024": "we only include a share for the first configured group", #else "*MLKEM*": "not implemented", #endif diff --git a/rustls-post-quantum/src/lib.rs b/rustls-post-quantum/src/lib.rs index 71650ec53dd..91b10c47d24 100644 --- a/rustls-post-quantum/src/lib.rs +++ b/rustls-post-quantum/src/lib.rs @@ -4,4 +4,4 @@ //! using post-quantum algorithms instead of using this crate. pub use rustls::crypto::aws_lc_rs::default_provider as provider; -pub use rustls::crypto::aws_lc_rs::kx_group::{MLKEM768, X25519MLKEM768}; +pub use rustls::crypto::aws_lc_rs::kx_group::{MLKEM768, MLKEM1024, X25519MLKEM768}; diff --git a/rustls/src/crypto/aws_lc_rs/mod.rs b/rustls/src/crypto/aws_lc_rs/mod.rs index 8a7fda7e39e..1ab57dae6c5 100644 --- a/rustls/src/crypto/aws_lc_rs/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/mod.rs @@ -237,7 +237,7 @@ static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms /// [`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}; + pub use super::pq::{MLKEM768, MLKEM1024, SECP256R1MLKEM768, X25519MLKEM768}; } /// A list of the default key exchange groups supported by this provider. @@ -268,6 +268,7 @@ pub static ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[ #[cfg(not(feature = "prefer-post-quantum"))] kx_group::SECP256R1MLKEM768, kx_group::MLKEM768, + kx_group::MLKEM1024, ]; #[cfg(feature = "std")] diff --git a/rustls/src/crypto/aws_lc_rs/pq/mlkem.rs b/rustls/src/crypto/aws_lc_rs/pq/mlkem.rs index fa2be078dd9..9e48fedc432 100644 --- a/rustls/src/crypto/aws_lc_rs/pq/mlkem.rs +++ b/rustls/src/crypto/aws_lc_rs/pq/mlkem.rs @@ -9,11 +9,14 @@ use crate::ffdhe_groups::FfdheGroup; use crate::{Error, NamedGroup, ProtocolVersion}; #[derive(Debug)] -pub(crate) struct MlKem768; +pub(crate) struct MlKem { + pub(crate) alg: &'static kem::Algorithm, + pub(crate) group: NamedGroup, +} -impl SupportedKxGroup for MlKem768 { +impl SupportedKxGroup for MlKem { fn start(&self) -> Result, Error> { - let decaps_key = kem::DecapsulationKey::generate(&kem::ML_KEM_768) + let decaps_key = kem::DecapsulationKey::generate(self.alg) .map_err(|_| Error::General("key generation failed".into()))?; let pub_key_bytes = decaps_key @@ -24,12 +27,13 @@ impl SupportedKxGroup for MlKem768 { Ok(Box::new(Active { decaps_key: Box::new(decaps_key), encaps_key_bytes: Vec::from(pub_key_bytes.as_ref()), + group: self.group, })) } fn start_and_complete(&self, client_share: &[u8]) -> Result { - let encaps_key = kem::EncapsulationKey::new(&kem::ML_KEM_768, client_share) - .map_err(|_| INVALID_KEY_SHARE)?; + let encaps_key = + kem::EncapsulationKey::new(self.alg, client_share).map_err(|_| INVALID_KEY_SHARE)?; let (ciphertext, shared_secret) = encaps_key .encapsulate() @@ -47,7 +51,7 @@ impl SupportedKxGroup for MlKem768 { } fn name(&self) -> NamedGroup { - NamedGroup::MLKEM768 + self.group } fn fips(&self) -> bool { @@ -74,6 +78,7 @@ impl SupportedKxGroup for MlKem768 { struct Active { decaps_key: Box>, encaps_key_bytes: Vec, + group: NamedGroup, } impl ActiveKeyExchange for Active { @@ -98,6 +103,6 @@ impl ActiveKeyExchange for Active { } fn group(&self) -> NamedGroup { - NamedGroup::MLKEM768 + self.group } } diff --git a/rustls/src/crypto/aws_lc_rs/pq/mod.rs b/rustls/src/crypto/aws_lc_rs/pq/mod.rs index a2252da506b..2a61dd88232 100644 --- a/rustls/src/crypto/aws_lc_rs/pq/mod.rs +++ b/rustls/src/crypto/aws_lc_rs/pq/mod.rs @@ -1,5 +1,8 @@ +use aws_lc_rs::kem; + use crate::crypto::SupportedKxGroup; use crate::crypto::aws_lc_rs::kx_group; +use crate::crypto::aws_lc_rs::pq::mlkem::MlKem; use crate::{Error, NamedGroup, PeerMisbehaved}; mod hybrid; @@ -35,10 +38,21 @@ pub static SECP256R1MLKEM768: &dyn SupportedKxGroup = &hybrid::Hybrid { }, }; -/// This is the [MLKEM] key exchange. +/// This is the [MLKEM] key encapsulation mechanism in NIST with security category 3. /// -/// [MLKEM]: https://datatracker.ietf.org/doc/draft-connolly-tls-mlkem-key-agreement -pub static MLKEM768: &dyn SupportedKxGroup = &mlkem::MlKem768; +/// [MLKEM]: https://datatracker.ietf.org/doc/draft-ietf-tls-mlkem +pub static MLKEM768: &dyn SupportedKxGroup = &MlKem { + alg: &kem::ML_KEM_768, + group: NamedGroup::MLKEM768, +}; + +/// This is the [MLKEM] key encapsulation mechanism in NIST with security category 5. +/// +/// [MLKEM]: https://datatracker.ietf.org/doc/draft-ietf-tls-mlkem +pub static MLKEM1024: &dyn SupportedKxGroup = &MlKem { + alg: &kem::ML_KEM_1024, + group: NamedGroup::MLKEM1024, +}; const INVALID_KEY_SHARE: Error = Error::PeerMisbehaved(PeerMisbehaved::InvalidKeyShare); From 4b455b819962978b4b6e009def15107ac5f4c5e8 Mon Sep 17 00:00:00 2001 From: Vale Tolpegin Date: Mon, 23 Feb 2026 10:21:14 -0600 Subject: [PATCH 383/403] Bump version of rustls --- Cargo.lock | 2 +- fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cf9d3a09976..1b408cea0c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2641,7 +2641,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.36" +version = "0.23.37" dependencies = [ "aws-lc-rs", "base64", diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 4bb2e85a94a..809e353bfb2 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.36" +version = "0.23.37" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 58e904e9080..22fb7690e1b 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.36" +version = "0.23.37" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From 7e99b52071b967f4cffcbf619f1c7e95dcb9ff37 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 9 Apr 2026 15:24:52 +0100 Subject: [PATCH 384/403] Update semver-compatible dependencies --- Cargo.lock | 755 ++++++++++++++++------------------------------------- 1 file changed, 231 insertions(+), 524 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1b408cea0c9..c942d8b3e47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common 0.1.7", + "crypto-common", "generic-array", ] @@ -69,9 +69,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.21" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -84,15 +84,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] @@ -208,9 +208,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-fips-sys" -version = "0.13.11" +version = "0.13.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df6ea8e07e2df15b9f09f2ac5ee2977369b06d116f0c4eb5fa4ad443b73c7f53" +checksum = "d3d619165468401dec3caa3366ebffbcb83f2f31883e5b3932f8e2dec2ddc568" dependencies = [ "bindgen", "cc", @@ -222,9 +222,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.16.0" +version = "1.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9a7b350e3bb1767102698302bc37256cbd48422809984b98d292c40e2579aa9" +checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", @@ -234,9 +234,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.37.1" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b092fe214090261288111db7a2b2c2118e5a7f30dc2569f1732c4069a6840549" +checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" dependencies = [ "cc", "cmake", @@ -303,15 +303,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-buffer" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96eb4cdd6cf1b31d671e9efe75c5d1ec614776856cefbe109ca373554a6d514f" -dependencies = [ - "hybrid-array", -] - [[package]] name = "bogo" version = "0.1.0" @@ -371,9 +362,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.56" +version = "1.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" dependencies = [ "find-msvc-tools", "jobserver", @@ -459,7 +450,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common 0.1.7", + "crypto-common", "inout", "zeroize", ] @@ -477,9 +468,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.60" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" dependencies = [ "clap_builder", "clap_derive", @@ -487,9 +478,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.60" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -499,9 +490,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.55" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" dependencies = [ "heck", "proc-macro2", @@ -511,24 +502,24 @@ dependencies = [ [[package]] name = "clap_lex" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "cmake" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" dependencies = [ "cc", ] [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "const-oid" @@ -666,16 +657,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "crypto-common" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "211f05e03c7d03754740fd9e585de910a095d6b99f8bcfffdef8319fa02a8331" -dependencies = [ - "hybrid-array", - "rand_core 0.10.0", -] - [[package]] name = "ctr" version = "0.9.2" @@ -694,26 +675,12 @@ dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", - "fiat-crypto 0.2.9", + "fiat-crypto", "rustc_version", "subtle", "zeroize", ] -[[package]] -name = "curve25519-dalek" -version = "5.0.0-pre.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335f1947f241137a14106b6f5acc5918a5ede29c9d71d3f2cb1678d5075d9fc3" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "fiat-crypto 0.3.0", - "rustc_version", - "subtle", -] - [[package]] name = "curve25519-dalek-derive" version = "0.1.1" @@ -770,22 +737,12 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", + "block-buffer", "const-oid", - "crypto-common 0.1.7", + "crypto-common", "subtle", ] -[[package]] -name = "digest" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8bf3682cdec91817be507e4aa104314898b95b84d74f3d43882210101a545b6" -dependencies = [ - "block-buffer 0.11.0", - "crypto-common 0.2.0", -] - [[package]] name = "displaydoc" version = "0.2.5" @@ -810,7 +767,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", - "digest 0.10.7", + "digest", "elliptic-curve", "rfc6979", "signature", @@ -831,7 +788,7 @@ checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", - "digest 0.10.7", + "digest", "ff", "generic-array", "group", @@ -857,9 +814,9 @@ dependencies = [ [[package]] name = "env_filter" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f" +checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" dependencies = [ "log", "regex", @@ -867,9 +824,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.9" +version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" +checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" dependencies = [ "anstream", "anstyle", @@ -900,12 +857,6 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" -[[package]] -name = "fiat-crypto" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" - [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -1029,19 +980,19 @@ checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", ] [[package]] name = "getrandom" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 6.0.0", "rand_core 0.10.0", "wasip2", "wasip3", @@ -1248,19 +1199,19 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] name = "hpke-rs" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "762ad77634765543485d098af3d352b2ffca88370b4eb3c329a088a3c708832a" +checksum = "b6ad6a58eb3e0ee30be8bfc7a9770ae98adcfa1d9bc820a5847732ce84f70837" dependencies = [ "hpke-rs-crypto", "hpke-rs-libcrux", "hpke-rs-rust-crypto", - "libcrux-sha3 0.0.6", + "libcrux-sha3", "log", "rand_core 0.9.5", "subtle", @@ -1269,9 +1220,9 @@ dependencies = [ [[package]] name = "hpke-rs-crypto" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a198e2bf992951574b61616f1a27521adf032c8db1db06f4cec423c32cf99d" +checksum = "0a73a99d9008010d73289f41335a3f6e14fb8c04eaf60e9111b450463b1bbc7f" dependencies = [ "rand_core 0.9.5", "zeroize", @@ -1279,16 +1230,16 @@ dependencies = [ [[package]] name = "hpke-rs-libcrux" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9ae3953c75416aff09945e0aa7d18c8cb43faf2855c38c4afee0ef9a42d14b3" +checksum = "c0ce6b7e54aebe540faee869c67ee253bede44ea6cb67c6e72c7847d6c59f1df" dependencies = [ "hpke-rs-crypto", "libcrux-aead", "libcrux-ecdh", "libcrux-hkdf", "libcrux-kem", - "libcrux-traits 0.0.6", + "libcrux-traits", "rand 0.10.0", "rand_chacha 0.10.0", "rand_core 0.10.0", @@ -1297,16 +1248,15 @@ dependencies = [ [[package]] name = "hpke-rs-rust-crypto" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d82d8b517d9a0ebf6675a23b126df957ca3d4b04f596dbe639bbc88091e1ad8" +checksum = "14b28be6cba9081c7feda2651d51c2a900029798e78b4c1e093e792f4571a870" dependencies = [ "aes-gcm", "chacha20poly1305", "hkdf", "hpke-rs-crypto", "k256", - "ml-kem", "p256", "p384", "rand 0.8.5", @@ -1315,8 +1265,7 @@ dependencies = [ "rand_core 0.6.4", "sha2", "subtle", - "x-wing", - "x25519-dalek 2.0.1", + "x25519-dalek", "zeroize", ] @@ -1330,24 +1279,15 @@ dependencies = [ "itoa", ] -[[package]] -name = "hybrid-array" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b229d73f5803b562cc26e4da0396c8610a4ee209f4fac8fa4f8d709166dc45" -dependencies = [ - "subtle", - "typenum", -] - [[package]] name = "icu_collections" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", + "utf8_iter", "yoke", "zerofrom", "zerovec", @@ -1355,9 +1295,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -1368,9 +1308,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -1382,15 +1322,15 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ "icu_collections", "icu_locale_core", @@ -1402,15 +1342,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", @@ -1450,9 +1390,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -1471,21 +1411,22 @@ dependencies = [ [[package]] name = "ipconfig" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222" dependencies = [ - "socket2 0.5.10", + "socket2", "widestring", - "windows-sys 0.48.0", - "winreg", + "windows-registry", + "windows-result", + "windows-sys 0.61.2", ] [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "is_terminal_polyfill" @@ -1522,15 +1463,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" -version = "0.2.21" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e3d65f018c6ae946ab16e80944b97096ed73c35b221d1c478a6c81d8f57940" +checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359" dependencies = [ "jiff-static", "log", @@ -1541,9 +1482,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.21" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17c2b211d863c7fde02cbea8a3c1a439b98e109286554f2860bdded7ff83818" +checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" dependencies = [ "proc-macro2", "quote", @@ -1562,9 +1503,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.89" +version = "0.3.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4eacb0641a310445a4c513f2a5e23e19952e269c6a38887254d5f837a305506" +checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" dependencies = [ "once_cell", "wasm-bindgen", @@ -1580,25 +1521,6 @@ dependencies = [ "elliptic-curve", ] -[[package]] -name = "keccak" -version = "0.2.0-rc.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a412fe37705d515cba9dbf1448291a717e187e2351df908cfc0137cbec3d480" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "kem" -version = "0.3.0-rc.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ae2c3347ff4a7af4f679a9e397c2c7e6034a00b773dd2dd3c001d7f40897c9" -dependencies = [ - "crypto-common 0.2.0", - "rand_core 0.10.0", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -1616,20 +1538,20 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.182" +version = "0.2.184" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" [[package]] name = "libcrux-aead" -version = "0.0.6" +version = "0.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f44098a02cdfd8f41cffe672e1d449538a75fd77a9a8093b3d6d77c4b43a7363" +checksum = "13297ce29869a5c0edab0378837b0fc5f88bf99a843712d9201c3b1150b3b476" dependencies = [ "libcrux-aesgcm", "libcrux-chacha20poly1305", "libcrux-secrets", - "libcrux-traits 0.0.6", + "libcrux-traits", ] [[package]] @@ -1638,23 +1560,23 @@ version = "0.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99f2a019dab4097585a7d4f5b9deebe46cd1e628b16a5bc4cb0ce35e1da334e6" dependencies = [ - "libcrux-intrinsics 0.0.6", + "libcrux-intrinsics", "libcrux-platform", "libcrux-secrets", - "libcrux-traits 0.0.6", + "libcrux-traits", ] [[package]] name = "libcrux-chacha20poly1305" -version = "0.0.6" +version = "0.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627fca7f9cb4cedaa9667670de8f591859dd2417ce4006c4f0ebbe5626f5e0a" +checksum = "cc08d044676af21343b32b988411fa98dbb5cf65a03c9df478ced221bbdfdb1b" dependencies = [ "libcrux-hacl-rs", "libcrux-macros", "libcrux-poly1305", "libcrux-secrets", - "libcrux-traits 0.0.6", + "libcrux-traits", ] [[package]] @@ -1666,7 +1588,7 @@ dependencies = [ "libcrux-hacl-rs", "libcrux-macros", "libcrux-secrets", - "libcrux-traits 0.0.6", + "libcrux-traits", ] [[package]] @@ -1711,16 +1633,6 @@ dependencies = [ "libcrux-sha2", ] -[[package]] -name = "libcrux-intrinsics" -version = "0.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa4779454e853d1de200cd12f19a8185aac47d99a5ec404cea3295c943d48f1" -dependencies = [ - "core-models", - "hax-lib", -] - [[package]] name = "libcrux-intrinsics" version = "0.0.6" @@ -1733,16 +1645,16 @@ dependencies = [ [[package]] name = "libcrux-kem" -version = "0.0.6" +version = "0.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391e6b5cb93ef7f77b9bf53dbe1820b8759aee761d6bf15e871b0ab0317299d3" +checksum = "12631592f491d22fd1a176d32b2c6edfb673998fd3987e9d95f8fa79ad2a737b" dependencies = [ "libcrux-curve25519", "libcrux-ecdh", "libcrux-ml-kem", "libcrux-p256", - "libcrux-sha3 0.0.7", - "libcrux-traits 0.0.6", + "libcrux-sha3", + "libcrux-traits", "rand 0.9.2", ] @@ -1758,16 +1670,16 @@ dependencies = [ [[package]] name = "libcrux-ml-kem" -version = "0.0.7" +version = "0.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aca7de713c6dddcf7aaf76e8ef9dc0097c8d7ce23a8eadf04c8761734714e184" +checksum = "a14ab3e477de9df6ee1273a114018ff62c4996ca9220070c4e5cb1743f94a67d" dependencies = [ "hax-lib", - "libcrux-intrinsics 0.0.6", + "libcrux-intrinsics", "libcrux-platform", "libcrux-secrets", - "libcrux-sha3 0.0.7", - "libcrux-traits 0.0.6", + "libcrux-sha3", + "libcrux-traits", "rand 0.9.2", "tls_codec", ] @@ -1782,7 +1694,7 @@ dependencies = [ "libcrux-macros", "libcrux-secrets", "libcrux-sha2", - "libcrux-traits 0.0.6", + "libcrux-traits", ] [[package]] @@ -1796,9 +1708,9 @@ dependencies = [ [[package]] name = "libcrux-poly1305" -version = "0.0.4" +version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccfb6399682b2dee13b728c779ab5dcc51afbe982b63508ca524806994336134" +checksum = "02491808ee5b9db8cb65fad64ae0be812db64beef179d945c00c7787dc7dfcf9" dependencies = [ "libcrux-hacl-rs", "libcrux-macros", @@ -1821,41 +1733,19 @@ checksum = "e9d253473f259fc74a280c43f29c464f7e374abdf28b4942234dc707f529d4b7" dependencies = [ "libcrux-hacl-rs", "libcrux-macros", - "libcrux-traits 0.0.6", + "libcrux-traits", ] [[package]] name = "libcrux-sha3" -version = "0.0.6" +version = "0.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3dabce2795479bd7294f853f7966a678cadf7a26d3d29f61cf15f5123e7ba4f" +checksum = "b1ae0b7d0e1cc4793a609fd0ff2ca3b3a3fabae523770c619a3d4bc86417b0d7" dependencies = [ "hax-lib", - "libcrux-intrinsics 0.0.5", + "libcrux-intrinsics", "libcrux-platform", - "libcrux-traits 0.0.5", -] - -[[package]] -name = "libcrux-sha3" -version = "0.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c50f6e04a184511b782c5cc1eb6a227c6d36f2c935e93d698655a93a99696b5" -dependencies = [ - "hax-lib", - "libcrux-intrinsics 0.0.6", - "libcrux-platform", - "libcrux-traits 0.0.6", -] - -[[package]] -name = "libcrux-traits" -version = "0.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "695ff2fb97627e4d57315a2fdfbfe50df1c80c6ef7d91ba34216169bd6f41c00" -dependencies = [ - "libcrux-secrets", - "rand 0.9.2", + "libcrux-traits", ] [[package]] @@ -1886,9 +1776,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "litemap" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "lock_api" @@ -1935,9 +1825,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "mio" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "log", @@ -1945,36 +1835,11 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "ml-kem" -version = "0.3.0-rc.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc807923f3029ad8676c21a667e1dc941e323538190a6d46cde130e7d55beef" -dependencies = [ - "hybrid-array", - "kem", - "module-lattice", - "rand_core 0.10.0", - "sha3", - "subtle", -] - -[[package]] -name = "module-lattice" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dfecc750073acc09af2f8899b2342d520d570392ba1c3aed53eeb0d84ca4103" -dependencies = [ - "hybrid-array", - "num-traits", - "subtle", -] - [[package]] name = "moka" -version = "0.12.13" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac832c50ced444ef6be0767a008b02c106a909ba79d1d830501e94b96f6b7e" +checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046" dependencies = [ "crossbeam-channel", "crossbeam-epoch", @@ -2037,9 +1902,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" [[package]] name = "num-integer" @@ -2082,9 +1947,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" dependencies = [ "critical-section", "portable-atomic", @@ -2110,9 +1975,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.75" +version = "0.10.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" dependencies = [ "bitflags", "cfg-if", @@ -2136,9 +2001,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.111" +version = "0.9.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" dependencies = [ "cc", "libc", @@ -2221,9 +2086,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkcs1" @@ -2311,18 +2176,18 @@ checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9db96d7fa8782dd8c15ce32ffe8680bbd1e978a43bf51a34d39483540495f5" +checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" dependencies = [ "portable-atomic", ] [[package]] name = "potential_utf" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -2394,9 +2259,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -2407,6 +2272,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "rand" version = "0.8.5" @@ -2434,7 +2305,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" dependencies = [ - "getrandom 0.4.1", + "getrandom 0.4.2", "rand_core 0.10.0", ] @@ -2560,9 +2431,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "resolv-conf" @@ -2601,7 +2472,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" dependencies = [ "const-oid", - "digest 0.10.7", + "digest", "num-bigint-dig", "num-integer", "num-traits", @@ -2798,7 +2669,7 @@ dependencies = [ "sha2", "signature", "webpki-roots 1.0.6", - "x25519-dalek 2.0.1", + "x25519-dalek", ] [[package]] @@ -2821,9 +2692,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.9" +version = "0.103.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" +checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" dependencies = [ "aws-lc-rs", "ring", @@ -2868,9 +2739,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" @@ -2923,17 +2794,7 @@ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha3" -version = "0.11.0-rc.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5bfe7820113e633d8886e839aae78c1184b8d7011000db6bc7eb61e34f28350" -dependencies = [ - "digest 0.11.0", - "keccak", + "digest", ] [[package]] @@ -2948,7 +2809,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest 0.10.7", + "digest", "rand_core 0.6.4", ] @@ -2966,22 +2827,12 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.5.10" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "socket2" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" -dependencies = [ - "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -3119,9 +2970,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -3139,9 +2990,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -3175,24 +3026,24 @@ dependencies = [ [[package]] name = "tokio" -version = "1.49.0" +version = "1.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c" dependencies = [ "bytes", "libc", "mio", "pin-project-lite", - "socket2 0.6.2", + "socket2", "tokio-macros", "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", @@ -3265,7 +3116,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common 0.1.7", + "crypto-common", "subtle", ] @@ -3307,11 +3158,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.21.0" +version = "1.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb" +checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" dependencies = [ - "getrandom 0.4.1", + "getrandom 0.4.2", "js-sys", "wasm-bindgen", ] @@ -3364,9 +3215,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.112" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d7d0fce354c88b7982aec4400b3e7fcf723c32737cef571bd165f7613557ee" +checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" dependencies = [ "cfg-if", "once_cell", @@ -3377,9 +3228,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.112" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55839b71ba921e4f75b674cb16f843f4b1f3b26ddfcb3454de1cf65cc021ec0f" +checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3387,9 +3238,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.112" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf2e969c2d60ff52e7e98b7392ff1588bffdd1ccd4769eba27222fd3d621571" +checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" dependencies = [ "bumpalo", "proc-macro2", @@ -3400,9 +3251,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.112" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0861f0dcdf46ea819407495634953cdcc8a8c7215ab799a7a7ce366be71c7b30" +checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" dependencies = [ "unicode-ident", ] @@ -3443,9 +3294,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.89" +version = "0.3.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10053fbf9a374174094915bbce141e87a6bf32ecd9a002980db4b638405e8962" +checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" dependencies = [ "js-sys", "wasm-bindgen", @@ -3491,54 +3342,50 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows-sys" -version = "0.48.0" +name = "windows-registry" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ - "windows-targets 0.48.5", + "windows-link", + "windows-result", + "windows-strings", ] [[package]] -name = "windows-sys" -version = "0.52.0" +name = "windows-result" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-targets 0.52.6", + "windows-link", ] [[package]] -name = "windows-sys" -version = "0.60.2" +name = "windows-strings" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-targets 0.53.5", + "windows-link", ] [[package]] name = "windows-sys" -version = "0.61.2" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-link", + "windows-targets", ] [[package]] -name = "windows-targets" -version = "0.48.5" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-link", ] [[package]] @@ -3547,181 +3394,64 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "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-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - [[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_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - [[package]] name = "wit-bindgen" version = "0.51.0" @@ -3812,22 +3542,9 @@ dependencies = [ [[package]] name = "writeable" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" - -[[package]] -name = "x-wing" -version = "0.1.0-rc.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d0d5f4d1f26b9b9e7477af1d3bef960e1d1fb64edab7912fde472a8a8432e" -dependencies = [ - "kem", - "ml-kem", - "rand_core 0.10.0", - "sha3", - "x25519-dalek 3.0.0-pre.6", -] +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "x25519-dalek" @@ -3835,22 +3552,12 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ - "curve25519-dalek 4.1.3", + "curve25519-dalek", "rand_core 0.6.4", "serde", "zeroize", ] -[[package]] -name = "x25519-dalek" -version = "3.0.0-pre.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d5d6ff67acd3945b933e592bfa7143db4fcbb2f871754b6b9fbd7847fc5aea" -dependencies = [ - "curve25519-dalek 5.0.0-pre.6", - "rand_core 0.10.0", -] - [[package]] name = "x509-parser" version = "0.17.0" @@ -3897,9 +3604,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -3908,9 +3615,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", @@ -3920,18 +3627,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.39" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.39" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", @@ -3940,18 +3647,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", @@ -3981,9 +3688,9 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -3992,9 +3699,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -4003,9 +3710,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", @@ -4014,9 +3721,9 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c745c48e1007337ed136dc99df34128b9faa6ed542d80a1c673cf55a6d7236c8" +checksum = "3be3d40e40a133f9c916ee3f9f4fa2d9d63435b5fbe1bfc6d9dae0aa0ada1513" [[package]] name = "zmij" From 0f0fbf5a59f6c4ae0cb5cda9f06a0029067d6a11 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Thu, 9 Apr 2026 15:27:31 +0100 Subject: [PATCH 385/403] Fix `clippy::result_large_err` Fixed on main in 6d09f24fec3af56b8b5dc403cd5b8514d5f0e859 --- openssl-tests/src/validate_ffdhe_params.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/openssl-tests/src/validate_ffdhe_params.rs b/openssl-tests/src/validate_ffdhe_params.rs index d7beafccab2..83c85207bc7 100644 --- a/openssl-tests/src/validate_ffdhe_params.rs +++ b/openssl-tests/src/validate_ffdhe_params.rs @@ -63,6 +63,7 @@ fn get_ffdhe_params_from_openssl(ffdhe_group: NamedGroup) -> (Vec, Vec) } /// Parse PEM-encoded DH parameters, returning `(p, g)` +#[allow(clippy::result_large_err)] // For the closure passed to `asn1::parse()` fn parse_dh_params_pem(data: &[u8]) -> (Vec, Vec) { let output_str = str::from_utf8(data).unwrap(); let output_str_lines = output_str.lines().collect::>(); From 5b3ef11c60e801f77f57035147d7bf041ac319be Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 10 Apr 2026 13:43:56 +0100 Subject: [PATCH 386/403] Fix ambiguous panic! warning --- rustls/src/client/ech.rs | 3 +-- rustls/src/client/test.rs | 5 +++-- rustls/src/server/test.rs | 6 ++++-- rustls/src/webpki/mod.rs | 3 ++- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index 616ebbfc533..ad5298c1b76 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -838,11 +838,10 @@ pub(crate) fn fatal_alert_required( #[cfg(test)] mod tests { + use super::*; 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 { diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs index f4ea9580ea5..e4051d61b67 100644 --- a/rustls/src/client/test.rs +++ b/rustls/src/client/test.rs @@ -1,7 +1,8 @@ #![cfg(any(feature = "ring", feature = "aws_lc_rs"))] +use alloc::boxed::Box; +use alloc::vec; +use alloc::vec::Vec; use core::sync::atomic::{AtomicBool, Ordering}; -use std::prelude::v1::*; -use std::vec; use pki_types::{CertificateDer, ServerName}; diff --git a/rustls/src/server/test.rs b/rustls/src/server/test.rs index 9254dbc64be..12fbf62cbf2 100644 --- a/rustls/src/server/test.rs +++ b/rustls/src/server/test.rs @@ -1,5 +1,5 @@ -use std::prelude::v1::*; -use std::vec; +use alloc::boxed::Box; +use alloc::vec; use super::ServerConnectionData; use crate::common_state::Context; @@ -64,6 +64,8 @@ fn test_process_client_hello(hello: ClientHelloPayload) -> Result<(), Error> { #[macro_rules_attribute::apply(test_for_each_provider)] mod tests { + use alloc::vec::Vec; + use super::super::*; use crate::common_state::KxState; use crate::crypto::{ diff --git a/rustls/src/webpki/mod.rs b/rustls/src/webpki/mod.rs index 24960a1ef9f..ead32d0cc4f 100644 --- a/rustls/src/webpki/mod.rs +++ b/rustls/src/webpki/mod.rs @@ -192,9 +192,10 @@ fn parse_crls( #[cfg(test)] mod tests { - use super::*; use alloc::vec; + use super::*; + #[test] fn pki_crl_errors() { // CRL signature errors should be turned into BadSignature. From a1da268c892e27bf937795490efec7467efae865 Mon Sep 17 00:00:00 2001 From: Tae Hagen Date: Tue, 31 Mar 2026 11:01:55 -0700 Subject: [PATCH 387/403] client: allow skipping selected ALPN validation --- rustls-test/src/lib.rs | 33 +++++++++++++++++++++ rustls/src/client/builder.rs | 1 + rustls/src/client/client_conn.rs | 5 ++++ rustls/src/client/hs.rs | 4 ++- rustls/src/client/tls13.rs | 1 + rustls/tests/api.rs | 49 ++++++++++++++++++++++++++++++++ 6 files changed, 92 insertions(+), 1 deletion(-) diff --git a/rustls-test/src/lib.rs b/rustls-test/src/lib.rs index e4949424659..e47b3502696 100644 --- a/rustls-test/src/lib.rs +++ b/rustls-test/src/lib.rs @@ -1727,6 +1727,32 @@ pub mod encoding { handshake_framing(HandshakeType::ClientHello, out) } + pub fn server_hello( + legacy_version: ProtocolVersion, + random: &[u8; 32], + session_id: &[u8], + cipher_suite: CipherSuite, + extensions: Vec, + ) -> Vec { + let mut out = vec![]; + + out.extend_from_slice(&legacy_version.to_array()); + out.extend_from_slice(random); + out.extend_from_slice(session_id); + out.extend_from_slice(&cipher_suite.to_array()); + out.extend_from_slice(&[0x00]); // null compression + + let mut exts = vec![]; + for e in extensions { + exts.extend_from_slice(&e.typ.to_array()); + exts.extend_from_slice(&(e.body.len() as u16).to_be_bytes()); + exts.extend_from_slice(&e.body); + } + + out.extend(len_u16(exts)); + handshake_framing(HandshakeType::ServerHello, out) + } + /// Apply handshake framing to `body`. /// /// This does not do fragmentation. @@ -1794,6 +1820,13 @@ pub mod encoding { body: len_u16(share), } } + + pub fn new_alpn(body: &[u8]) -> Self { + Self { + typ: ExtensionType::ALProtocolNegotiation, + body: len_u16(body.to_vec()), + } + } } /// Prefix with u8 length diff --git a/rustls/src/client/builder.rs b/rustls/src/client/builder.rs index b301e75077e..844806837f2 100644 --- a/rustls/src/client/builder.rs +++ b/rustls/src/client/builder.rs @@ -165,6 +165,7 @@ impl ConfigBuilder { ClientConfig { provider: self.provider, alpn_protocols: Vec::new(), + check_selected_alpn: true, resumption: Resumption::default(), max_fragment_size: None, client_auth_cert_resolver, diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index d214c2a1f2f..c04382a0ce5 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -166,6 +166,11 @@ pub struct ClientConfig { /// If empty, no ALPN extension is sent. pub alpn_protocols: Vec>, + /// Whether to check the selected ALPN was offered. + /// + /// The default is true. + pub check_selected_alpn: bool, + /// How and when the client can resume a previous session. /// /// # Sharing `resumption` between `ClientConfig`s diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index 4669f33d081..b0dec256e03 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -590,11 +590,12 @@ pub(super) fn process_alpn_protocol( common: &mut CommonState, offered_protocols: &[ProtocolName], selected: Option<&ProtocolName>, + check_selected_offered: bool, ) -> Result<(), Error> { common.alpn_protocol = selected.map(ToOwned::to_owned); if let Some(alpn_protocol) = &common.alpn_protocol { - if !offered_protocols.contains(alpn_protocol) { + if check_selected_offered && !offered_protocols.contains(alpn_protocol) { return Err(common.send_fatal_alert( AlertDescription::IllegalParameter, PeerMisbehaved::SelectedUnofferedApplicationProtocol, @@ -743,6 +744,7 @@ impl State for ExpectServerHello { .selected_protocol .as_ref() .map(|s| s.as_ref()), + self.input.config.check_selected_alpn, )?; } diff --git a/rustls/src/client/tls13.rs b/rustls/src/client/tls13.rs index fe8495cc341..5f15f36c7b7 100644 --- a/rustls/src/client/tls13.rs +++ b/rustls/src/client/tls13.rs @@ -506,6 +506,7 @@ impl State for ExpectEncryptedExtensions { exts.selected_protocol .as_ref() .map(|protocol| protocol.as_ref()), + self.config.check_selected_alpn, )?; hs::process_client_cert_type_extension( cx.common, diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index eadfde0a227..e592f4942af 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -258,6 +258,55 @@ fn connection_level_alpn_protocols() { assert_eq!(client.alpn_protocol(), Some(&b"http/1.1"[..])); } +#[test] +fn server_selects_unoffered_alpn_checked() { + let result = unoffered_alpn_test(true); + assert_eq!( + result.err(), + Some(PeerMisbehaved::SelectedUnofferedApplicationProtocol.into()) + ); +} + +#[test] +fn server_selects_unoffered_alpn_unchecked() { + let result = unoffered_alpn_test(false); + assert_ne!( + result.err(), + Some(PeerMisbehaved::SelectedUnofferedApplicationProtocol.into()) + ); +} + +fn unoffered_alpn_test(check_selected_alpn: bool) -> Result { + let mut config = make_client_config(KeyType::Rsa2048, &provider::default_provider()); + config.check_selected_alpn = check_selected_alpn; + let mut client = ClientConnection::new_with_alpn( + Arc::new(config), + server_name("localhost"), + vec![b"http/1.1".to_vec()], + ) + .unwrap(); + client + .write_tls(&mut Vec::new()) + .unwrap(); + client + .read_tls( + &mut encoding::message_framing( + ContentType::Handshake, + ProtocolVersion::TLSv1_2, + encoding::server_hello( + ProtocolVersion::TLSv1_2, + &[b'a'; 32], + &[0], + CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + vec![encoding::Extension::new_alpn(b"\x05blorp")], + ), + ) + .as_slice(), + ) + .unwrap(); + client.process_new_packets() +} + fn version_test( client_versions: &[&'static rustls::SupportedProtocolVersion], server_versions: &[&'static rustls::SupportedProtocolVersion], From 6b116bc5e8556fd65286a1b4220f57dd9fbb5e54 Mon Sep 17 00:00:00 2001 From: Tae Hagen Date: Thu, 9 Apr 2026 07:14:36 -0700 Subject: [PATCH 388/403] Bump version of rustls --- Cargo.lock | 6 +++--- fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c942d8b3e47..690c965d662 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -277,7 +277,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "itertools 0.13.0", + "itertools 0.10.5", "log", "prettyplease", "proc-macro2", @@ -2512,7 +2512,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.37" +version = "0.23.38" dependencies = [ "aws-lc-rs", "base64", @@ -3332,7 +3332,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 809e353bfb2..b6f4bc86651 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.37" +version = "0.23.38" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index 22fb7690e1b..fd4964ade92 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.37" +version = "0.23.38" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From d4b3ec5af32c4c488375ffaa80ad93b2bcab81d2 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 21 Apr 2026 10:36:18 +0200 Subject: [PATCH 389/403] Apply suggestions from clippy 1.95 --- fuzz/fuzzers/unbuffered.rs | 8 +++----- rustls/src/client/hs.rs | 14 +++++++------- rustls/tests/api.rs | 2 +- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/fuzz/fuzzers/unbuffered.rs b/fuzz/fuzzers/unbuffered.rs index 67a50d07823..a13a9ac5541 100644 --- a/fuzz/fuzzers/unbuffered.rs +++ b/fuzz/fuzzers/unbuffered.rs @@ -72,11 +72,9 @@ fn process(status: UnbufferedStatus<'_, '_, S>) -> Option { Ok(ConnectionState::TransmitTlsData(xmit)) => xmit.done(), Ok(ConnectionState::WriteTraffic(_)) => return None, Ok(ConnectionState::BlockedHandshake) => return None, - Ok(ConnectionState::ReadTraffic(mut read)) => loop { - let Some(_app_data) = read.next_record() else { - break; - }; - }, + Ok(ConnectionState::ReadTraffic(mut read)) => { + while let Some(_app_data) = read.next_record() {} + } Ok(st) => panic!("unhandled state {st:?}"), Err(_) => return None, }; diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index b0dec256e03..12e885ee1c9 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -962,13 +962,13 @@ impl ExpectServerHelloOrHelloRetryRequest { // 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; - } + // 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. + (Some(ech_state), Some(tls13_cs)) + if !ech_state.confirm_hrr_acceptance(hrr, tls13_cs, cx.common)? => + { + cx.data.ech_status = EchStatus::Rejected } (Some(_), None) => { unreachable!("ECH state should only be set when TLS 1.3 was negotiated") diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs index e592f4942af..cadb29696db 100644 --- a/rustls/tests/api.rs +++ b/rustls/tests/api.rs @@ -2003,7 +2003,7 @@ fn client_cert_resolve_server_added_hint() { // Create a verifier that adds the extra_name as a hint subject in addition to the ones // from the root cert store. let verifier = webpki_client_verifier_builder(get_client_root_store(*key_type), &provider) - .add_root_hint_subjects([DistinguishedName::from(extra_name.clone())].into_iter()); + .add_root_hint_subjects([DistinguishedName::from(extra_name.clone())]); let server_config = make_server_config_with_client_verifier(*key_type, verifier, &provider); test_client_cert_resolve(*key_type, server_config.into(), expected_hint_subjects); } From 6134204146e967bf320a148e97fdf9b94eb3be8b Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 21 Apr 2026 10:45:57 +0200 Subject: [PATCH 390/403] Adapt to updated nightly features --- rustls/src/lib.rs | 1 + rustls/tests/runners/api.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs index 16d67a8e441..33c0d9cdd25 100644 --- a/rustls/src/lib.rs +++ b/rustls/src/lib.rs @@ -378,6 +378,7 @@ // 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))] #![cfg_attr(read_buf, feature(core_io_borrowed_buf))] #![cfg_attr(bench, feature(test))] #![no_std] diff --git a/rustls/tests/runners/api.rs b/rustls/tests/runners/api.rs index 99cb0c29487..dd768c0c971 100644 --- a/rustls/tests/runners/api.rs +++ b/rustls/tests/runners/api.rs @@ -1,4 +1,5 @@ #![cfg_attr(read_buf, feature(read_buf))] +#![cfg_attr(read_buf, feature(core_io))] #![cfg_attr(read_buf, feature(core_io_borrowed_buf))] use std::cell::RefCell; From 7b374684a26d9acbeb379e758b47d0965e36758d Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 21 Apr 2026 10:51:16 +0200 Subject: [PATCH 391/403] Take semver-compatible dependency updates --- Cargo.lock | 176 +++++++++++++++++++++++++++-------------------------- 1 file changed, 91 insertions(+), 85 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 690c965d662..6c1545b83c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -222,9 +222,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.16.2" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" +checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", @@ -234,9 +234,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.39.1" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" +checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" dependencies = [ "cc", "cmake", @@ -277,7 +277,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "itertools 0.10.5", + "itertools 0.13.0", "log", "prettyplease", "proc-macro2", @@ -290,9 +290,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "block-buffer" @@ -362,9 +362,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.59" +version = "1.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" dependencies = [ "find-msvc-tools", "jobserver", @@ -468,9 +468,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -490,9 +490,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck", "proc-macro2", @@ -535,7 +535,7 @@ checksum = "657f625ff361906f779745d08375ae3cc9fef87a35fba5f22874cf773010daf4" dependencies = [ "hax-lib", "pastey", - "rand 0.9.2", + "rand 0.9.4", ] [[package]] @@ -993,7 +993,7 @@ dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "rand_core 0.10.0", + "rand_core 0.10.1", "wasip2", "wasip3", ] @@ -1076,9 +1076,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" [[package]] name = "hax-lib" @@ -1148,7 +1148,7 @@ dependencies = [ "idna", "ipnet", "once_cell", - "rand 0.9.2", + "rand 0.9.4", "ring", "rustls", "thiserror", @@ -1173,7 +1173,7 @@ dependencies = [ "moka", "once_cell", "parking_lot", - "rand 0.9.2", + "rand 0.9.4", "resolv-conf", "rustls", "smallvec", @@ -1240,9 +1240,9 @@ dependencies = [ "libcrux-hkdf", "libcrux-kem", "libcrux-traits", - "rand 0.10.0", + "rand 0.10.1", "rand_chacha 0.10.0", - "rand_core 0.10.0", + "rand_core 0.10.1", "zeroize", ] @@ -1259,9 +1259,9 @@ dependencies = [ "k256", "p256", "p384", - "rand 0.8.5", + "rand 0.8.6", "rand_chacha 0.3.1", - "rand_core 0.10.0", + "rand_core 0.10.1", "rand_core 0.6.4", "sha2", "subtle", @@ -1390,12 +1390,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "serde", "serde_core", ] @@ -1503,9 +1503,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.94" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" dependencies = [ "once_cell", "wasm-bindgen", @@ -1538,9 +1538,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.184" +version = "0.2.185" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" [[package]] name = "libcrux-aead" @@ -1599,7 +1599,7 @@ checksum = "b65f73ce79337c762eb38bbac91e4c9b9e60cf318e8501b812750c640814d45e" dependencies = [ "libcrux-curve25519", "libcrux-p256", - "rand 0.9.2", + "rand 0.9.4", ] [[package]] @@ -1655,7 +1655,7 @@ dependencies = [ "libcrux-p256", "libcrux-sha3", "libcrux-traits", - "rand 0.9.2", + "rand 0.9.4", ] [[package]] @@ -1680,7 +1680,7 @@ dependencies = [ "libcrux-secrets", "libcrux-sha3", "libcrux-traits", - "rand 0.9.2", + "rand 0.9.4", "tls_codec", ] @@ -1755,7 +1755,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812e4fa89f3f5e34b47f928b22b1b78395a0d4ec23b1f583db635f128159d65f" dependencies = [ "libcrux-secrets", - "rand 0.9.2", + "rand 0.9.4", ] [[package]] @@ -1895,7 +1895,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "smallvec", "zeroize", ] @@ -1975,9 +1975,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.76" +version = "0.10.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" +checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" dependencies = [ "bitflags", "cfg-if", @@ -2001,9 +2001,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.112" +version = "0.9.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" +checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" dependencies = [ "cc", "libc", @@ -2113,9 +2113,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plotters" @@ -2176,9 +2176,9 @@ checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" dependencies = [ "portable-atomic", ] @@ -2280,9 +2280,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -2291,9 +2291,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -2301,12 +2301,12 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ "getrandom 0.4.2", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -2336,7 +2336,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e6af7f3e25ded52c41df4e0b1af2d047e45896c2f3281792ed68a1c243daedb" dependencies = [ "ppv-lite86", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -2359,15 +2359,15 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "rayon" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", @@ -2536,7 +2536,7 @@ dependencies = [ "serde_json", "subtle", "time", - "webpki-roots 1.0.6", + "webpki-roots 1.0.7", "x509-parser 0.17.0", "zeroize", "zlib-rs", @@ -2596,7 +2596,7 @@ dependencies = [ "rustls", "serde", "tokio", - "webpki-roots 1.0.6", + "webpki-roots 1.0.7", ] [[package]] @@ -2645,7 +2645,7 @@ dependencies = [ "criterion", "env_logger", "rustls", - "webpki-roots 1.0.6", + "webpki-roots 1.0.7", ] [[package]] @@ -2668,7 +2668,7 @@ dependencies = [ "rustls", "sha2", "signature", - "webpki-roots 1.0.6", + "webpki-roots 1.0.7", "x25519-dalek", ] @@ -2692,9 +2692,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.10" +version = "0.103.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" +checksum = "8279bb85272c9f10811ae6a6c547ff594d6a7f3c6c6b02ee9726d1d0dcfcdd06" dependencies = [ "aws-lc-rs", "ring", @@ -3026,9 +3026,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.51.1" +version = "1.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" dependencies = [ "bytes", "libc", @@ -3094,9 +3094,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "unicode-ident" @@ -3158,9 +3158,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ "getrandom 0.4.2", "js-sys", @@ -3197,11 +3197,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.2+wasi-0.2.9" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", ] [[package]] @@ -3210,14 +3210,14 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.51.0", ] [[package]] name = "wasm-bindgen" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ "cfg-if", "once_cell", @@ -3228,9 +3228,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3238,9 +3238,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ "bumpalo", "proc-macro2", @@ -3251,9 +3251,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" dependencies = [ "unicode-ident", ] @@ -3294,9 +3294,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.94" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" +checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" dependencies = [ "js-sys", "wasm-bindgen", @@ -3308,14 +3308,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.6", + "webpki-roots 1.0.7", ] [[package]] name = "webpki-roots" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" dependencies = [ "rustls-pki-types", ] @@ -3332,7 +3332,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3461,6 +3461,12 @@ dependencies = [ "wit-bindgen-rust-macro", ] +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + [[package]] name = "wit-bindgen-core" version = "0.51.0" From 860798e7290c8624c00339711ee40f203246d8fc Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Wed, 22 Apr 2026 16:46:15 -0400 Subject: [PATCH 392/403] Cargo: update semver compat deps --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6c1545b83c7..e628720384f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2064,9 +2064,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pastey" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b867cad97c0791bbd3aaa6472142568c6c9e8f71937e98379f584cfb0cf35bec" +checksum = "c5a797f0e07bdf071d15742978fc3128ec6c22891c31a3a931513263904c982a" [[package]] name = "pem" @@ -2692,9 +2692,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.12" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8279bb85272c9f10811ae6a6c547ff594d6a7f3c6c6b02ee9726d1d0dcfcdd06" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "aws-lc-rs", "ring", From 05416057db6a08b70581c179f9fb32144e288b30 Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Wed, 22 Apr 2026 16:46:29 -0400 Subject: [PATCH 393/403] Cargo: version 0.23.38 -> 0.23.39 --- Cargo.lock | 4 ++-- fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e628720384f..0fa8510190e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -277,7 +277,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "itertools 0.13.0", + "itertools 0.10.5", "log", "prettyplease", "proc-macro2", @@ -2512,7 +2512,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.38" +version = "0.23.39" dependencies = [ "aws-lc-rs", "base64", diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index b6f4bc86651..babe2dada18 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.38" +version = "0.23.39" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index fd4964ade92..c0b7675ef7b 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.38" +version = "0.23.39" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From a612901957ad6f8c2e6a61e79dc776ef1004b087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20R=C3=BCth?= <1324490+janrueth@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:45:52 +0200 Subject: [PATCH 394/403] Default require_ems based on CryptoProvider FIPS status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, require_ems was defaulted solely based on cfg!(feature = "fips"), which is a compile-time check tied to the fips cargo feature. The fips feature unconditionally pulls in aws-lc-rs as the cryptographic provider, making it impossible for third-party FIPS-compliant CryptoProvider implementations (e.g., those backed by BoringSSL) to get correct FIPS policy defaults without also pulling in aws-lc-rs — which may conflict with their own crypto backend. This change also considers the runtime CryptoProvider::fips() status when defaulting require_ems in both ClientConfig and ServerConfig builders. If the configured provider reports itself as FIPS-compliant, require_ems is now automatically set to true, ensuring that ClientConfig::fips() and ServerConfig::fips() return the correct result without requiring the fips cargo feature. This is backward-compatible: existing users of the fips feature see no behavior change, while third-party providers now work correctly out of the box. --- rustls/src/client/builder.rs | 5 ++++- rustls/src/client/client_conn.rs | 3 ++- rustls/src/manual/fips.rs | 5 +++-- rustls/src/server/builder.rs | 5 ++++- rustls/src/server/server_conn.rs | 3 ++- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/rustls/src/client/builder.rs b/rustls/src/client/builder.rs index 844806837f2..4b110d185e8 100644 --- a/rustls/src/client/builder.rs +++ b/rustls/src/client/builder.rs @@ -162,6 +162,9 @@ impl ConfigBuilder { self, client_auth_cert_resolver: Arc, ) -> ClientConfig { + #[cfg(feature = "tls12")] + let require_ems = self.provider.fips(); + ClientConfig { provider: self.provider, alpn_protocols: Vec::new(), @@ -176,7 +179,7 @@ impl ConfigBuilder { enable_secret_extraction: false, enable_early_data: false, #[cfg(feature = "tls12")] - require_ems: cfg!(feature = "fips"), + require_ems, time_provider: self.time_provider, cert_compressors: compress::default_cert_compressors().to_vec(), cert_compression_cache: Arc::new(compress::CompressionCache::default()), diff --git a/rustls/src/client/client_conn.rs b/rustls/src/client/client_conn.rs index c04382a0ce5..374a70d7b26 100644 --- a/rustls/src/client/client_conn.rs +++ b/rustls/src/client/client_conn.rs @@ -229,7 +229,8 @@ pub struct ClientConfig { /// 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, + /// The default is `true` if the configured [`CryptoProvider`] is + /// FIPS-compliant (i.e., [`CryptoProvider::fips()`] returns `true`), /// `false` otherwise. /// /// It must be set to `true` to meet FIPS requirement mentioned in section diff --git a/rustls/src/manual/fips.rs b/rustls/src/manual/fips.rs index 203a759e415..04a2428dd1b 100644 --- a/rustls/src/manual/fips.rs +++ b/rustls/src/manual/fips.rs @@ -1,7 +1,8 @@ /*! # Using rustls with FIPS-approved cryptography -To use FIPS-approved cryptography with rustls, you should take -these actions: +To use FIPS-approved cryptography with rustls, you should +utilize a FIPS-approved `CryptoProvider`. +rustls ships with one using `aws-lc-rs`, take these actions to make use of it: ## 1. Enable the `fips` crate feature for rustls. diff --git a/rustls/src/server/builder.rs b/rustls/src/server/builder.rs index b1dc00b3da8..daf6e094ecf 100644 --- a/rustls/src/server/builder.rs +++ b/rustls/src/server/builder.rs @@ -100,6 +100,9 @@ impl ConfigBuilder { /// Sets a custom [`ResolvesServerCert`]. pub fn with_cert_resolver(self, cert_resolver: Arc) -> ServerConfig { + #[cfg(feature = "tls12")] + let require_ems = self.provider.fips(); + ServerConfig { provider: self.provider, verifier: self.state.verifier, @@ -119,7 +122,7 @@ impl ConfigBuilder { send_half_rtt_data: false, send_tls13_tickets: 2, #[cfg(feature = "tls12")] - require_ems: cfg!(feature = "fips"), + require_ems, time_provider: self.time_provider, cert_compressors: compress::default_cert_compressors().to_vec(), cert_compression_cache: Arc::new(compress::CompressionCache::default()), diff --git a/rustls/src/server/server_conn.rs b/rustls/src/server/server_conn.rs index 29dda6fedbc..77f03e484da 100644 --- a/rustls/src/server/server_conn.rs +++ b/rustls/src/server/server_conn.rs @@ -401,7 +401,8 @@ pub struct ServerConfig { /// 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, + /// The default is `true` if the configured [`CryptoProvider`] is + /// FIPS-compliant (i.e., [`CryptoProvider::fips()`] returns `true`), /// `false` otherwise. /// /// It must be set to `true` to meet FIPS requirement mentioned in section From 9088004a0835b462a634b9866e27c46967ebce95 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Sun, 26 Apr 2026 09:21:21 +0100 Subject: [PATCH 395/403] ech: expand `maximum_name_length` to usize ASAP --- rustls/src/client/ech.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index ad5298c1b76..5df70c23c43 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -680,23 +680,19 @@ impl EchState { // Calculate padding // max_name_len = L - let max_name_len = self.maximum_name_length; + let max_name_len = usize::from(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, - ) + core::cmp::max(0, max_name_len.saturating_sub(name.as_ref().len())) } _ => { // 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 + max_name_len + 9 } }; From 8bf935cebc6eacf4847753755466efa293e76f45 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Sun, 26 Apr 2026 09:27:18 +0100 Subject: [PATCH 396/403] ech: pop comment from match arm --- rustls/src/client/ech.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index 5df70c23c43..0e4bcdda3a4 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -689,11 +689,9 @@ impl EchState { // max(0, L - D) core::cmp::max(0, max_name_len.saturating_sub(name.as_ref().len())) } - _ => { - // L + 9 - // "This is the length of a "server_name" extension with an L-byte name." - max_name_len + 9 - } + // L + 9 + // "This is the length of a "server_name" extension with an L-byte name." + _ => max_name_len + 9, }; // Let L be the length of the EncodedClientHelloInner with all the padding computed so far From c574ffd5d655fc73ab34c0cb6f62fa915cf54dee Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Sun, 26 Apr 2026 15:02:50 +0100 Subject: [PATCH 397/403] ech: avoid short-lived allocation for padding --- rustls/src/client/ech.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index 0e4bcdda3a4..a25c81f870f 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -1,6 +1,7 @@ use alloc::boxed::Box; use alloc::vec; use alloc::vec::Vec; +use core::iter; use pki_types::{DnsName, EchConfigListBytes, ServerName}; use subtle::ConstantTimeEq; @@ -697,7 +698,7 @@ impl EchState { // 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]); + encoded_hello.extend(iter::repeat(0).take(padding_len)); // Construct the inner hello message that will be used for the transcript. let inner_hello_msg = Message { From 3e06ef1063d2378bbfc395d6232b11e137a09e4f Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Sun, 26 Apr 2026 09:24:38 +0100 Subject: [PATCH 398/403] ech: add both name and "gross" padding --- rustls/src/client/ech.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index a25c81f870f..cc8e69cbbdc 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -684,7 +684,7 @@ impl EchState { let max_name_len = usize::from(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 { + let name_padding_len = match &self.inner_name { ServerName::DnsName(name) => { // name.len() = D // max(0, L - D) @@ -694,10 +694,11 @@ impl EchState { // "This is the length of a "server_name" extension with an L-byte name." _ => max_name_len + 9, }; + encoded_hello.extend(iter::repeat(0).take(name_padding_len)); // 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); + let padding_len = 31 - ((encoded_hello.len() - 1) % 32); encoded_hello.extend(iter::repeat(0).take(padding_len)); // Construct the inner hello message that will be used for the transcript. From 4e4952946db97ebe05fe9a80683d95f40a6406b9 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Sun, 26 Apr 2026 09:25:26 +0100 Subject: [PATCH 399/403] ech: test inner name padding --- rustls/src/client/ech.rs | 170 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 169 insertions(+), 1 deletion(-) diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index cc8e69cbbdc..2c6d074512b 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -834,8 +834,11 @@ pub(crate) fn fatal_alert_required( #[cfg(test)] mod tests { + use std::string::String; + use super::*; use crate::enums::CipherSuite; + use crate::msgs::enums::{Compression, HpkeAead, HpkeKdf}; use crate::msgs::handshake::{Random, ServerExtensions, SessionId}; #[test] @@ -845,7 +848,7 @@ mod tests { random: Random([0xffu8; 32]), session_id: SessionId::empty(), cipher_suite: CipherSuite::TLS13_AES_256_GCM_SHA384, - compression_method: crate::msgs::enums::Compression::Null, + compression_method: Compression::Null, extensions: Box::new(ServerExtensions::default()), }; let message = Message { @@ -891,4 +894,169 @@ mod tests { " afterwards those bytes are zeroed ^^^^^^^^^^^^^^^^ " ); } + + #[test] + fn inner_client_hello_length_conceals_inner_name_length() { + let base_inner_len = inner_hello_encoding_for_name(dns_name_of_len(1), true).len(); + assert!( + base_inner_len % 32 == 0, + "inner hello length must be 32-byte padded" + ); + assert!( + base_inner_len >= 256, + "inner hello must include inner name and its padding" + ); + + for inner_name_len in 1..251 { + assert_eq!( + inner_hello_encoding_for_name(dns_name_of_len(inner_name_len), true).len(), + base_inner_len, + "all inner hello lengths must be invariant wrt inner name length" + ); + } + } + + fn inner_hello_encoding_for_name(name: DnsName<'static>, enable_sni: bool) -> Vec { + let config = EchConfig { + config: EchConfigPayload::V18(EchConfigContents { + key_config: HpkeKeyConfig { + config_id: 0, + kem_id: MockHpke::SUITE.kem, + public_key: PayloadU16::new(vec![0; 32]), + symmetric_cipher_suites: vec![], + }, + maximum_name_length: 255, + public_name: DnsName::try_from("public").unwrap(), + extensions: vec![], + }), + suite: &MockHpke, + }; + + EchState::new( + &config, + ServerName::from(name.clone()), + false, + &FixedRandom, + enable_sni, + ) + .unwrap() + .encode_inner_hello( + &ClientHelloPayload { + client_version: ProtocolVersion::TLSv1_3, + random: Random([0u8; 32]), + session_id: SessionId::empty(), + cipher_suites: vec![], + compression_methods: vec![Compression::Null], + extensions: Box::new(ClientExtensions { + server_name: Some(ServerNamePayload::from(&name)), + ..Default::default() + }), + }, + None, + &None, + ) + } + + fn dns_name_of_len(mut len: usize) -> DnsName<'static> { + let mut s = String::new(); + let labels = len.div_ceil(63); + for _ in 0..labels { + let chars = Ord::min(len, 63); + len -= chars; + for _ in 0..chars { + s.push('a'); + } + if len != 0 { + s.push('.'); + } + } + DnsName::try_from(s).unwrap() + } + + #[derive(Debug)] + struct MockHpke; + + impl MockHpke { + const SUITE: HpkeSuite = HpkeSuite { + kem: HpkeKem::DHKEM_P256_HKDF_SHA256, + sym: HpkeSymmetricCipherSuite { + kdf_id: HpkeKdf::HKDF_SHA256, + aead_id: HpkeAead::AES_128_GCM, + }, + }; + } + + impl Hpke for MockHpke { + #[cfg_attr(coverage_nightly, coverage(off))] + fn seal( + &self, + _info: &[u8], + _aad: &[u8], + _plaintext: &[u8], + _pub_key: &HpkePublicKey, + ) -> Result<(EncapsulatedSecret, Vec), Error> { + todo!() + } + + fn setup_sealer( + &self, + _info: &[u8], + _pub_key: &HpkePublicKey, + ) -> Result<(EncapsulatedSecret, Box), Error> { + Ok((EncapsulatedSecret(vec![]), Box::new(MockHpkeSealer))) + } + + #[cfg_attr(coverage_nightly, coverage(off))] + fn open( + &self, + _enc: &EncapsulatedSecret, + _info: &[u8], + _aad: &[u8], + _ciphertext: &[u8], + _secret_key: &crate::crypto::hpke::HpkePrivateKey, + ) -> Result, Error> { + todo!() + } + + #[cfg_attr(coverage_nightly, coverage(off))] + fn setup_opener( + &self, + _enc: &EncapsulatedSecret, + _info: &[u8], + _secret_key: &crate::crypto::hpke::HpkePrivateKey, + ) -> Result, Error> { + todo!() + } + + #[cfg_attr(coverage_nightly, coverage(off))] + fn generate_key_pair( + &self, + ) -> Result<(HpkePublicKey, crate::crypto::hpke::HpkePrivateKey), Error> { + todo!() + } + + fn suite(&self) -> HpkeSuite { + Self::SUITE + } + } + + #[derive(Debug)] + struct MockHpkeSealer; + + impl HpkeSealer for MockHpkeSealer { + #[cfg_attr(coverage_nightly, coverage(off))] + fn seal(&mut self, _aad: &[u8], _plaintext: &[u8]) -> Result, Error> { + todo!() + } + } + + #[derive(Debug)] + struct FixedRandom; + + impl SecureRandom for FixedRandom { + fn fill(&self, buf: &mut [u8]) -> Result<(), crate::rand::GetRandomFailed> { + buf.fill(0x55); + Ok(()) + } + } } From c0005beed87c5067be215fb45a119843b99eb2f1 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Sun, 26 Apr 2026 09:34:26 +0100 Subject: [PATCH 400/403] ech: base inner name padding on actual extension In the case where SNI is disabled, `inner_sni` falls out of sync with `self.inner_name`. `inner_sni` is used to alter the inner hello's `server_name`, but `self.inner_name` was used as a basis for padding. This means padding would be added even if the extension wasn't, which ironically leaks the length of the inner name. --- rustls/src/client/ech.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index 2c6d074512b..e41d551b729 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -684,8 +684,8 @@ impl EchState { let max_name_len = usize::from(self.maximum_name_length); let max_name_len = if max_name_len > 0 { max_name_len } else { 255 }; - let name_padding_len = match &self.inner_name { - ServerName::DnsName(name) => { + let name_padding_len = match &inner_hello.server_name { + Some(ServerNamePayload::SingleDnsName(name)) => { // name.len() = D // max(0, L - D) core::cmp::max(0, max_name_len.saturating_sub(name.as_ref().len())) @@ -916,6 +916,27 @@ mod tests { } } + #[test] + fn inner_client_hello_length_does_not_leak_length_of_omitted_inner_name() { + let base_inner_len = inner_hello_encoding_for_name(dns_name_of_len(1), false).len(); + assert!( + base_inner_len % 32 == 0, + "inner hello length must be 32-byte padded" + ); + assert!( + base_inner_len >= 256, + "inner hello must include maximum_name_length bytes of padding" + ); + + for inner_name_len in 1..251 { + assert_eq!( + inner_hello_encoding_for_name(dns_name_of_len(inner_name_len), false).len(), + base_inner_len, + "all inner hello lengths must be invariant wrt inner name length" + ); + } + } + fn inner_hello_encoding_for_name(name: DnsName<'static>, enable_sni: bool) -> Vec { let config = EchConfig { config: EchConfigPayload::V18(EchConfigContents { From e7a555f9e8f1c0260c2dea0ef1f08419bde4b085 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Sun, 26 Apr 2026 15:08:26 +0100 Subject: [PATCH 401/403] Prefer `Ord::max` to `core::cmp` --- rustls/src/client/ech.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustls/src/client/ech.rs b/rustls/src/client/ech.rs index e41d551b729..5675e71d092 100644 --- a/rustls/src/client/ech.rs +++ b/rustls/src/client/ech.rs @@ -688,7 +688,7 @@ impl EchState { Some(ServerNamePayload::SingleDnsName(name)) => { // name.len() = D // max(0, L - D) - core::cmp::max(0, max_name_len.saturating_sub(name.as_ref().len())) + Ord::max(0, max_name_len.saturating_sub(name.as_ref().len())) } // L + 9 // "This is the length of a "server_name" extension with an L-byte name." From b44c09fbca5172b3f5e5ed6ba2ffe6fcd934e07a Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 28 Apr 2026 09:40:05 +0100 Subject: [PATCH 402/403] Prepare 0.23.40 --- Cargo.lock | 2 +- fuzz/Cargo.lock | 2 +- rustls/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0fa8510190e..3a697acb1e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2512,7 +2512,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.39" +version = "0.23.40" dependencies = [ "aws-lc-rs", "base64", diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index babe2dada18..10807ff9d56 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.39" +version = "0.23.40" dependencies = [ "log", "once_cell", diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml index c0b7675ef7b..131279701a2 100644 --- a/rustls/Cargo.toml +++ b/rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls" -version = "0.23.39" +version = "0.23.40" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" From 71016a0f13bbbfaf0e9296addc37ab44a24c570d Mon Sep 17 00:00:00 2001 From: Yuwei B Date: Mon, 11 May 2026 06:49:20 -0700 Subject: [PATCH 403/403] fix: skip session_id_generator when Reality is active Reality computes a cryptographic session_id (encrypted auth data tied to the server's public key). If a session_id_generator was also provided, it would overwrite Reality's value, silently breaking the handshake. Guard the session_id_generator block to only run when Reality is not active, and add a test that verifies Reality's session_id is preserved. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- rustls/src/client/hs.rs | 42 +++++++++++---------- rustls/src/client/test.rs | 77 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 19 deletions(-) diff --git a/rustls/src/client/hs.rs b/rustls/src/client/hs.rs index dcd4bd4160f..cd3439abe0e 100644 --- a/rustls/src/client/hs.rs +++ b/rustls/src/client/hs.rs @@ -526,27 +526,31 @@ where }; // ref: https://github.com/shadow-tls/rustls/blob/c033c22cdbb6b08adf8b35571ee8427c70512d13/rustls/src/client/hs.rs#L365 - if let Some(generator) = session_id_generator { - let mut buffer = Vec::new(); - match &mut chp.0 { - HandshakePayload::ClientHello(c) => { - c.session_id = SessionId { - len: 32, - data: [0; 32], - }; + // Skip session_id_generator when Reality is active — Reality computes its own + // cryptographic session_id above, and overwriting it would break the handshake. + if reality_state.is_none() { + if let Some(generator) = session_id_generator { + let mut buffer = Vec::new(); + match &mut chp.0 { + HandshakePayload::ClientHello(c) => { + c.session_id = SessionId { + len: 32, + data: [0; 32], + }; + } + _ => unreachable!(), } - _ => unreachable!(), - } - chp.encode(&mut buffer); - let session_id = SessionId { - len: 32, - data: generator(&buffer), - }; - match &mut chp.0 { - HandshakePayload::ClientHello(c) => { - c.session_id = session_id; + chp.encode(&mut buffer); + let session_id = SessionId { + len: 32, + data: generator(&buffer), + }; + match &mut chp.0 { + HandshakePayload::ClientHello(c) => { + c.session_id = session_id; + } + _ => unreachable!(), } - _ => unreachable!(), } } diff --git a/rustls/src/client/test.rs b/rustls/src/client/test.rs index e4051d61b67..69043c7c672 100644 --- a/rustls/src/client/test.rs +++ b/rustls/src/client/test.rs @@ -703,6 +703,35 @@ fn client_hello_sent_for_config(config: ClientConfig) -> Result [u8; 32], +) -> Result { + let mut conn = ClientConnection::new_with_session_id_generator( + config.into(), + ServerName::try_from("localhost").unwrap(), + Some(generator), + )?; + 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!( @@ -711,3 +740,51 @@ fn roots() -> RootCertStore { .unwrap(); r } + +/// Tests that when Reality is configured, the session_id_generator does not +/// overwrite Reality's cryptographically-computed session_id. +#[cfg(any(feature = "ring", feature = "aws_lc_rs"))] +#[test] +fn test_reality_session_id_not_overwritten_by_session_id_generator() { + use super::reality::RealityConfig; + + #[cfg(feature = "ring")] + let provider = crate::crypto::ring::default_provider(); + #[cfg(all(not(feature = "ring"), feature = "aws_lc_rs"))] + let provider = crate::crypto::aws_lc_rs::default_provider(); + + let server_pk = [1u8; 32]; + let short_id = vec![0x12, 0x34]; + let reality = RealityConfig::new(server_pk, short_id).unwrap(); + + let config = ClientConfig::builder_with_provider(provider.into()) + .with_protocol_versions(&[&crate::version::TLS13]) + .unwrap() + .with_root_certificates(roots()) + .with_reality(reality) + .with_no_client_auth(); + + // Get ClientHello with Reality only (no session_id_generator) + let ch_reality_only = client_hello_sent_for_config(config.clone()).unwrap(); + + // Get ClientHello with Reality + a session_id_generator that would produce all-0xFF + let ch_reality_with_generator = client_hello_sent_with_session_id_generator( + config, + |_| [0xFF; 32], + ) + .unwrap(); + + // Reality session_id should NOT be all zeros (it's encrypted data) + assert_ne!(ch_reality_only.session_id.data, [0u8; 32]); + + // With both Reality and session_id_generator, the session_id should come from + // Reality (not the generator's all-0xFF value) + assert_ne!( + ch_reality_with_generator.session_id.data, + [0xFF; 32], + "session_id_generator should not overwrite Reality's session_id" + ); + + // The session_id should still be non-zero (Reality-computed) + assert_ne!(ch_reality_with_generator.session_id.data, [0u8; 32]); +}