Coverage Report

Created: 2026-06-28 08:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.40/src/crypto/mod.rs
Line
Count
Source
1
use alloc::boxed::Box;
2
use alloc::vec::Vec;
3
use core::fmt::Debug;
4
5
use pki_types::PrivateKeyDer;
6
use zeroize::Zeroize;
7
8
#[cfg(all(doc, feature = "tls12"))]
9
use crate::Tls12CipherSuite;
10
use crate::msgs::ffdhe_groups::FfdheGroup;
11
use crate::sign::SigningKey;
12
use crate::sync::Arc;
13
pub use crate::webpki::{
14
    WebPkiSupportedAlgorithms, verify_tls12_signature, verify_tls13_signature,
15
    verify_tls13_signature_with_raw_key,
16
};
17
#[cfg(doc)]
18
use crate::{
19
    ClientConfig, ConfigBuilder, ServerConfig, SupportedCipherSuite, Tls13CipherSuite, client,
20
    crypto, server, sign,
21
};
22
use crate::{Error, NamedGroup, ProtocolVersion, SupportedProtocolVersion, suites};
23
24
/// *ring* based CryptoProvider.
25
#[cfg(feature = "ring")]
26
pub mod ring;
27
28
/// aws-lc-rs-based CryptoProvider.
29
#[cfg(feature = "aws_lc_rs")]
30
pub mod aws_lc_rs;
31
32
/// TLS message encryption/decryption interfaces.
33
pub mod cipher;
34
35
/// Hashing interfaces.
36
pub mod hash;
37
38
/// HMAC interfaces.
39
pub mod hmac;
40
41
#[cfg(feature = "tls12")]
42
/// Cryptography specific to TLS1.2.
43
pub mod tls12;
44
45
/// Cryptography specific to TLS1.3.
46
pub mod tls13;
47
48
/// Hybrid public key encryption (RFC 9180).
49
pub mod hpke;
50
51
// Message signing interfaces. Re-exported under rustls::sign. Kept crate-internal here to
52
// avoid having two import paths to the same types.
53
pub(crate) mod signer;
54
55
pub use crate::msgs::handshake::KeyExchangeAlgorithm;
56
pub use crate::rand::GetRandomFailed;
57
pub use crate::suites::CipherSuiteCommon;
58
59
/// Controls core cryptography used by rustls.
60
///
61
/// This crate comes with two built-in options, provided as
62
/// `CryptoProvider` structures:
63
///
64
/// - [`crypto::aws_lc_rs::default_provider`]: (behind the `aws_lc_rs` crate feature,
65
///   which is enabled by default).  This provider uses the [aws-lc-rs](https://github.com/aws/aws-lc-rs)
66
///   crate.  The `fips` crate feature makes this option use FIPS140-3-approved cryptography.
67
/// - [`crypto::ring::default_provider`]: (behind the `ring` crate feature, which
68
///   is optional).  This provider uses the [*ring*](https://github.com/briansmith/ring)
69
///   crate.
70
///
71
/// This structure provides defaults. Everything in it can be overridden at
72
/// runtime by replacing field values as needed.
73
///
74
/// # Using the per-process default `CryptoProvider`
75
///
76
/// There is the concept of an implicit default provider, configured at run-time once in
77
/// a given process.
78
///
79
/// It is used for functions like [`ClientConfig::builder()`] and [`ServerConfig::builder()`].
80
///
81
/// The intention is that an application can specify the [`CryptoProvider`] they wish to use
82
/// once, and have that apply to the variety of places where their application does TLS
83
/// (which may be wrapped inside other libraries).
84
/// They should do this by calling [`CryptoProvider::install_default()`] early on.
85
///
86
/// To achieve this goal:
87
///
88
/// - _libraries_ should use [`ClientConfig::builder()`]/[`ServerConfig::builder()`]
89
///   or otherwise rely on the [`CryptoProvider::get_default()`] provider.
90
/// - _applications_ should call [`CryptoProvider::install_default()`] early
91
///   in their `fn main()`. If _applications_ uses a custom provider based on the one built-in,
92
///   they can activate the `custom-provider` feature to ensure its usage.
93
///
94
/// # Using a specific `CryptoProvider`
95
///
96
/// Supply the provider when constructing your [`ClientConfig`] or [`ServerConfig`]:
97
///
98
/// - [`ClientConfig::builder_with_provider()`]
99
/// - [`ServerConfig::builder_with_provider()`]
100
///
101
/// When creating and configuring a webpki-backed client or server certificate verifier, a choice of
102
/// provider is also needed to start the configuration process:
103
///
104
/// - [`client::WebPkiServerVerifier::builder_with_provider()`]
105
/// - [`server::WebPkiClientVerifier::builder_with_provider()`]
106
///
107
/// If you install a custom provider and want to avoid any accidental use of a built-in provider, the feature
108
/// `custom-provider` can be activated to ensure your custom provider is used everywhere
109
/// and not a built-in one. This will disable any implicit use of a built-in provider.
110
///
111
/// # Making a custom `CryptoProvider`
112
///
113
/// Your goal will be to populate an instance of this `CryptoProvider` struct.
114
///
115
/// ## Which elements are required?
116
///
117
/// There is no requirement that the individual elements ([`SupportedCipherSuite`], [`SupportedKxGroup`],
118
/// [`SigningKey`], etc.) come from the same crate.  It is allowed and expected that uninteresting
119
/// elements would be delegated back to one of the default providers (statically) or a parent
120
/// provider (dynamically).
121
///
122
/// For example, if we want to make a provider that just overrides key loading in the config builder
123
/// API (with [`ConfigBuilder::with_single_cert`], etc.), it might look like this:
124
///
125
/// ```
126
/// # #[cfg(feature = "aws_lc_rs")] {
127
/// # use std::sync::Arc;
128
/// # mod fictious_hsm_api { pub fn load_private_key(key_der: pki_types::PrivateKeyDer<'static>) -> ! { unreachable!(); } }
129
/// use rustls::crypto::aws_lc_rs;
130
///
131
/// pub fn provider() -> rustls::crypto::CryptoProvider {
132
///   rustls::crypto::CryptoProvider{
133
///     key_provider: &HsmKeyLoader,
134
///     ..aws_lc_rs::default_provider()
135
///   }
136
/// }
137
///
138
/// #[derive(Debug)]
139
/// struct HsmKeyLoader;
140
///
141
/// impl rustls::crypto::KeyProvider for HsmKeyLoader {
142
///     fn load_private_key(&self, key_der: pki_types::PrivateKeyDer<'static>) -> Result<Arc<dyn rustls::sign::SigningKey>, rustls::Error> {
143
///          fictious_hsm_api::load_private_key(key_der)
144
///     }
145
/// }
146
/// # }
147
/// ```
148
///
149
/// ## References to the individual elements
150
///
151
/// The elements are documented separately:
152
///
153
/// - **Random** - see [`crypto::SecureRandom::fill()`].
154
/// - **Cipher suites** - see [`SupportedCipherSuite`], [`Tls12CipherSuite`], and
155
///   [`Tls13CipherSuite`].
156
/// - **Key exchange groups** - see [`crypto::SupportedKxGroup`].
157
/// - **Signature verification algorithms** - see [`crypto::WebPkiSupportedAlgorithms`].
158
/// - **Authentication key loading** - see [`crypto::KeyProvider::load_private_key()`] and
159
///   [`sign::SigningKey`].
160
///
161
/// # Example code
162
///
163
/// See custom [`provider-example/`] for a full client and server example that uses
164
/// cryptography from the [`RustCrypto`] and [`dalek-cryptography`] projects.
165
///
166
/// ```shell
167
/// $ cargo run --example client | head -3
168
/// Current ciphersuite: TLS13_CHACHA20_POLY1305_SHA256
169
/// HTTP/1.1 200 OK
170
/// Content-Type: text/html; charset=utf-8
171
/// Content-Length: 19899
172
/// ```
173
///
174
/// [`provider-example/`]: https://github.com/rustls/rustls/tree/main/provider-example/
175
/// [`RustCrypto`]: https://github.com/RustCrypto
176
/// [`dalek-cryptography`]: https://github.com/dalek-cryptography
177
///
178
/// # FIPS-approved cryptography
179
/// The `fips` crate feature enables use of the `aws-lc-rs` crate in FIPS mode.
180
///
181
/// You can verify the configuration at runtime by checking
182
/// [`ServerConfig::fips()`]/[`ClientConfig::fips()`] return `true`.
183
#[derive(Debug, Clone)]
184
pub struct CryptoProvider {
185
    /// List of supported ciphersuites, in preference order -- the first element
186
    /// is the highest priority.
187
    ///
188
    /// The `SupportedCipherSuite` type carries both configuration and implementation.
189
    ///
190
    /// A valid `CryptoProvider` must ensure that all cipher suites are accompanied by at least
191
    /// one matching key exchange group in [`CryptoProvider::kx_groups`].
192
    pub cipher_suites: Vec<suites::SupportedCipherSuite>,
193
194
    /// List of supported key exchange groups, in preference order -- the
195
    /// first element is the highest priority.
196
    ///
197
    /// The first element in this list is the _default key share algorithm_,
198
    /// and in TLS1.3 a key share for it is sent in the client hello.
199
    ///
200
    /// The `SupportedKxGroup` type carries both configuration and implementation.
201
    pub kx_groups: Vec<&'static dyn SupportedKxGroup>,
202
203
    /// List of signature verification algorithms for use with webpki.
204
    ///
205
    /// These are used for both certificate chain verification and handshake signature verification.
206
    ///
207
    /// This is called by [`ConfigBuilder::with_root_certificates()`],
208
    /// [`server::WebPkiClientVerifier::builder_with_provider()`] and
209
    /// [`client::WebPkiServerVerifier::builder_with_provider()`].
210
    pub signature_verification_algorithms: WebPkiSupportedAlgorithms,
211
212
    /// Source of cryptographically secure random numbers.
213
    pub secure_random: &'static dyn SecureRandom,
214
215
    /// Provider for loading private [`SigningKey`]s from [`PrivateKeyDer`].
216
    pub key_provider: &'static dyn KeyProvider,
217
}
218
219
impl CryptoProvider {
220
    /// Sets this `CryptoProvider` as the default for this process.
221
    ///
222
    /// This can be called successfully at most once in any process execution.
223
    ///
224
    /// Call this early in your process to configure which provider is used for
225
    /// the provider.  The configuration should happen before any use of
226
    /// [`ClientConfig::builder()`] or [`ServerConfig::builder()`].
227
0
    pub fn install_default(self) -> Result<(), Arc<Self>> {
228
0
        static_default::install_default(self)
229
0
    }
230
231
    /// Returns the default `CryptoProvider` for this process.
232
    ///
233
    /// This will be `None` if no default has been set yet.
234
1
    pub fn get_default() -> Option<&'static Arc<Self>> {
235
1
        static_default::get_default()
236
1
    }
237
238
    /// An internal function that:
239
    ///
240
    /// - gets the pre-installed default, or
241
    /// - installs one `from_crate_features()`, or else
242
    /// - panics about the need to call [`CryptoProvider::install_default()`]
243
0
    pub(crate) fn get_default_or_install_from_crate_features() -> &'static Arc<Self> {
244
0
        if let Some(provider) = Self::get_default() {
245
0
            return provider;
246
0
        }
247
248
0
        let provider = Self::from_crate_features()
249
0
            .expect(r###"
250
0
Could not automatically determine the process-level CryptoProvider from Rustls crate features.
251
0
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.
252
0
See the documentation of the CryptoProvider type for more information.
253
0
            "###);
254
        // Ignore the error resulting from us losing a race, and accept the outcome.
255
0
        let _ = provider.install_default();
256
0
        Self::get_default().unwrap()
257
0
    }
258
259
    /// Returns a provider named unambiguously by rustls crate features.
260
    ///
261
    /// This function returns `None` if the crate features are ambiguous (ie, specify two
262
    /// providers), or specify no providers, or the feature `custom-provider` is activated.
263
    /// In all cases the application should explicitly specify the provider to use
264
    /// with [`CryptoProvider::install_default`].
265
0
    fn from_crate_features() -> Option<Self> {
266
        #[cfg(all(
267
            feature = "ring",
268
            not(feature = "aws_lc_rs"),
269
            not(feature = "custom-provider")
270
        ))]
271
        {
272
            return Some(ring::default_provider());
273
        }
274
275
        #[cfg(all(
276
            feature = "aws_lc_rs",
277
            not(feature = "ring"),
278
            not(feature = "custom-provider")
279
        ))]
280
        {
281
0
            return Some(aws_lc_rs::default_provider());
282
        }
283
284
        #[allow(unreachable_code)]
285
        None
286
0
    }
287
288
    /// Returns `true` if this `CryptoProvider` is operating in FIPS mode.
289
    ///
290
    /// This covers only the cryptographic parts of FIPS approval.  There are
291
    /// also TLS protocol-level recommendations made by NIST.  You should
292
    /// prefer to call [`ClientConfig::fips()`] or [`ServerConfig::fips()`]
293
    /// which take these into account.
294
1
    pub fn fips(&self) -> bool {
295
        let Self {
296
1
            cipher_suites,
297
1
            kx_groups,
298
1
            signature_verification_algorithms,
299
1
            secure_random,
300
1
            key_provider,
301
1
        } = self;
302
1
        cipher_suites.iter().all(|cs| cs.fips())
303
0
            && kx_groups.iter().all(|kx| kx.fips())
304
0
            && signature_verification_algorithms.fips()
305
0
            && secure_random.fips()
306
0
            && key_provider.fips()
307
1
    }
308
}
309
310
/// A source of cryptographically secure randomness.
311
pub trait SecureRandom: Send + Sync + Debug {
312
    /// Fill the given buffer with random bytes.
313
    ///
314
    /// The bytes must be sourced from a cryptographically secure random number
315
    /// generator seeded with good quality, secret entropy.
316
    ///
317
    /// This is used for all randomness required by rustls, but not necessarily
318
    /// randomness required by the underlying cryptography library.  For example:
319
    /// [`SupportedKxGroup::start()`] requires random material to generate
320
    /// an ephemeral key exchange key, but this is not included in the interface with
321
    /// rustls: it is assumed that the cryptography library provides for this itself.
322
    fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed>;
323
324
    /// Return `true` if this is backed by a FIPS-approved implementation.
325
0
    fn fips(&self) -> bool {
326
0
        false
327
0
    }
328
}
329
330
/// A mechanism for loading private [`SigningKey`]s from [`PrivateKeyDer`].
331
///
332
/// This trait is intended to be used with private key material that is sourced from DER,
333
/// such as a private-key that may be present on-disk. It is not intended to be used with
334
/// keys held in hardware security modules (HSMs) or physical tokens. For these use-cases
335
/// see the Rustls manual section on [customizing private key usage].
336
///
337
/// [customizing private key usage]: <https://docs.rs/rustls/latest/rustls/manual/_03_howto/index.html#customising-private-key-usage>
338
pub trait KeyProvider: Send + Sync + Debug {
339
    /// Decode and validate a private signing key from `key_der`.
340
    ///
341
    /// This is used by [`ConfigBuilder::with_client_auth_cert()`], [`ConfigBuilder::with_single_cert()`],
342
    /// and [`ConfigBuilder::with_single_cert_with_ocsp()`].  The key types and formats supported by this
343
    /// function directly defines the key types and formats supported in those APIs.
344
    ///
345
    /// Return an error if the key type encoding is not supported, or if the key fails validation.
346
    fn load_private_key(
347
        &self,
348
        key_der: PrivateKeyDer<'static>,
349
    ) -> Result<Arc<dyn SigningKey>, Error>;
350
351
    /// Return `true` if this is backed by a FIPS-approved implementation.
352
    ///
353
    /// If this returns `true`, that must be the case for all possible key types
354
    /// supported by [`KeyProvider::load_private_key()`].
355
0
    fn fips(&self) -> bool {
356
0
        false
357
0
    }
358
}
359
360
/// A supported key exchange group.
361
///
362
/// This type carries both configuration and implementation. Specifically,
363
/// it has a TLS-level name expressed using the [`NamedGroup`] enum, and
364
/// a function which produces a [`ActiveKeyExchange`].
365
///
366
/// Compare with [`NamedGroup`], which carries solely a protocol identifier.
367
pub trait SupportedKxGroup: Send + Sync + Debug {
368
    /// Start a key exchange.
369
    ///
370
    /// This will prepare an ephemeral secret key in the supported group, and a corresponding
371
    /// public key. The key exchange can be completed by calling [ActiveKeyExchange#complete]
372
    /// or discarded.
373
    ///
374
    /// # Errors
375
    ///
376
    /// This can fail if the random source fails during ephemeral key generation.
377
    fn start(&self) -> Result<Box<dyn ActiveKeyExchange>, Error>;
378
379
    /// Start and complete a key exchange, in one operation.
380
    ///
381
    /// The default implementation for this calls `start()` and then calls
382
    /// `complete()` on the result.  This is suitable for Diffie-Hellman-like
383
    /// key exchange algorithms, where there is not a data dependency between
384
    /// our key share (named "pub_key" in this API) and the peer's (`peer_pub_key`).
385
    ///
386
    /// If there is such a data dependency (like key encapsulation mechanisms), this
387
    /// function should be implemented.
388
0
    fn start_and_complete(&self, peer_pub_key: &[u8]) -> Result<CompletedKeyExchange, Error> {
389
0
        let kx = self.start()?;
390
391
        Ok(CompletedKeyExchange {
392
0
            group: kx.group(),
393
0
            pub_key: kx.pub_key().to_vec(),
394
0
            secret: kx.complete(peer_pub_key)?,
395
        })
396
0
    }
397
398
    /// FFDHE group the `SupportedKxGroup` operates in.
399
    ///
400
    /// Return `None` if this group is not a FFDHE one.
401
    ///
402
    /// The default implementation calls `FfdheGroup::from_named_group`: this function
403
    /// is extremely linker-unfriendly so it is recommended all key exchange implementers
404
    /// provide this function.
405
    ///
406
    /// `rustls::ffdhe_groups` contains suitable values to return from this,
407
    /// for example [`rustls::ffdhe_groups::FFDHE2048`][crate::ffdhe_groups::FFDHE2048].
408
0
    fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
409
        #[allow(deprecated)]
410
0
        FfdheGroup::from_named_group(self.name())
411
0
    }
412
413
    /// Named group the SupportedKxGroup operates in.
414
    ///
415
    /// If the `NamedGroup` enum does not have a name for the algorithm you are implementing,
416
    /// you can use [`NamedGroup::Unknown`].
417
    fn name(&self) -> NamedGroup;
418
419
    /// Return `true` if this is backed by a FIPS-approved implementation.
420
0
    fn fips(&self) -> bool {
421
0
        false
422
0
    }
423
424
    /// Return `true` if this should be offered/selected with the given version.
425
    ///
426
    /// The default implementation returns true for all versions.
427
0
    fn usable_for_version(&self, _version: ProtocolVersion) -> bool {
428
0
        true
429
0
    }
430
}
431
432
/// An in-progress key exchange originating from a [`SupportedKxGroup`].
433
pub trait ActiveKeyExchange: Send + Sync {
434
    /// Completes the key exchange, given the peer's public key.
435
    ///
436
    /// This method must return an error if `peer_pub_key` is invalid: either
437
    /// mis-encoded, or an invalid public key (such as, but not limited to, being
438
    /// in a small order subgroup).
439
    ///
440
    /// If the key exchange algorithm is FFDHE, the result must be left-padded with zeros,
441
    /// as required by [RFC 8446](https://www.rfc-editor.org/rfc/rfc8446#section-7.4.1)
442
    /// (see [`complete_for_tls_version()`](Self::complete_for_tls_version) for more details).
443
    ///
444
    /// The shared secret is returned as a [`SharedSecret`] which can be constructed
445
    /// from a `&[u8]`.
446
    ///
447
    /// This consumes and so terminates the [`ActiveKeyExchange`].
448
    fn complete(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, Error>;
449
450
    /// Completes the key exchange for the given TLS version, given the peer's public key.
451
    ///
452
    /// Note that finite-field Diffie–Hellman key exchange has different requirements for the derived
453
    /// shared secret in TLS 1.2 and TLS 1.3 (ECDHE key exchange is the same in TLS 1.2 and TLS 1.3):
454
    ///
455
    /// In TLS 1.2, the calculated secret is required to be stripped of leading zeros
456
    /// [(RFC 5246)](https://www.rfc-editor.org/rfc/rfc5246#section-8.1.2).
457
    ///
458
    /// In TLS 1.3, the calculated secret is required to be padded with leading zeros to be the same
459
    /// byte-length as the group modulus [(RFC 8446)](https://www.rfc-editor.org/rfc/rfc8446#section-7.4.1).
460
    ///
461
    /// The default implementation of this method delegates to [`complete()`](Self::complete) assuming it is
462
    /// implemented for TLS 1.3 (i.e., for FFDHE KX, removes padding as needed). Implementers of this trait
463
    /// are encouraged to just implement [`complete()`](Self::complete) assuming TLS 1.3, and let the default
464
    /// implementation of this method handle TLS 1.2-specific requirements.
465
    ///
466
    /// This method must return an error if `peer_pub_key` is invalid: either
467
    /// mis-encoded, or an invalid public key (such as, but not limited to, being
468
    /// in a small order subgroup).
469
    ///
470
    /// The shared secret is returned as a [`SharedSecret`] which can be constructed
471
    /// from a `&[u8]`.
472
    ///
473
    /// This consumes and so terminates the [`ActiveKeyExchange`].
474
0
    fn complete_for_tls_version(
475
0
        self: Box<Self>,
476
0
        peer_pub_key: &[u8],
477
0
        tls_version: &SupportedProtocolVersion,
478
0
    ) -> Result<SharedSecret, Error> {
479
0
        if tls_version.version != ProtocolVersion::TLSv1_2 {
480
0
            return self.complete(peer_pub_key);
481
0
        }
482
483
0
        let group = self.group();
484
0
        let mut complete_res = self.complete(peer_pub_key)?;
485
0
        if group.key_exchange_algorithm() == KeyExchangeAlgorithm::DHE {
486
0
            complete_res.strip_leading_zeros();
487
0
        }
488
0
        Ok(complete_res)
489
0
    }
Unexecuted instantiation: <rustls::crypto::aws_lc_rs::pq::mlkem::Active as rustls::crypto::ActiveKeyExchange>::complete_for_tls_version
Unexecuted instantiation: <rustls::crypto::aws_lc_rs::kx::KeyExchange as rustls::crypto::ActiveKeyExchange>::complete_for_tls_version
Unexecuted instantiation: <rustls::crypto::aws_lc_rs::pq::hybrid::ActiveHybrid as rustls::crypto::ActiveKeyExchange>::complete_for_tls_version
490
491
    /// For hybrid key exchanges, returns the [`NamedGroup`] and key share
492
    /// for the classical half of this key exchange.
493
    ///
494
    /// There is no requirement for a hybrid scheme (or any other!) to implement
495
    /// `hybrid_component()`. It only enables an optimization; described below.
496
    ///
497
    /// "Hybrid" means a key exchange algorithm which is constructed from two
498
    /// (or more) independent component algorithms. Usually one is post-quantum-secure,
499
    /// and the other is "classical".  See
500
    /// <https://datatracker.ietf.org/doc/draft-ietf-tls-hybrid-design/11/>
501
    ///
502
    /// # Background
503
    /// Rustls always sends a presumptive key share in its `ClientHello`, using
504
    /// (absent any other information) the first item in [`CryptoProvider::kx_groups`].
505
    /// If the server accepts the client's selection, it can complete the handshake
506
    /// using that key share.  If not, the server sends a `HelloRetryRequest` instructing
507
    /// the client to send a different key share instead.
508
    ///
509
    /// This request costs an extra round trip, and wastes the key exchange computation
510
    /// (in [`SupportedKxGroup::start()`]) the client already did.  We would
511
    /// like to avoid those wastes if possible.
512
    ///
513
    /// It is early days for post-quantum-secure hybrid key exchange deployment.
514
    /// This means (commonly) continuing to offer both the hybrid and classical
515
    /// key exchanges, so the handshake can be completed without a `HelloRetryRequest`
516
    /// for servers that support the offered hybrid or classical schemes.
517
    ///
518
    /// Implementing `hybrid_component()` enables two optimizations:
519
    ///
520
    /// 1. Sending both the hybrid and classical key shares in the `ClientHello`.
521
    ///
522
    /// 2. Performing the classical key exchange setup only once.  This is important
523
    ///    because the classical key exchange setup is relatively expensive.
524
    ///    This optimization is permitted and described in
525
    ///    <https://www.ietf.org/archive/id/draft-ietf-tls-hybrid-design-11.html#section-3.2>
526
    ///
527
    /// Both of these only happen if the classical algorithm appears separately in
528
    /// the client's [`CryptoProvider::kx_groups`], and if the hybrid algorithm appears
529
    /// first in that list.
530
    ///
531
    /// # How it works
532
    /// This function is only called by rustls for clients.  It is called when
533
    /// constructing the initial `ClientHello`.  rustls follows these steps:
534
    ///
535
    /// 1. If the return value is `None`, nothing further happens.
536
    /// 2. If the given [`NamedGroup`] does not appear in
537
    ///    [`CryptoProvider::kx_groups`], nothing further happens.
538
    /// 3. The given key share is added to the `ClientHello`, after the hybrid entry.
539
    ///
540
    /// Then, one of three things may happen when the server replies to the `ClientHello`:
541
    ///
542
    /// 1. The server sends a `HelloRetryRequest`.  Everything is thrown away and
543
    ///    we start again.
544
    /// 2. The server agrees to our hybrid key exchange: rustls calls
545
    ///    [`ActiveKeyExchange::complete()`] consuming `self`.
546
    /// 3. The server agrees to our classical key exchange: rustls calls
547
    ///    [`ActiveKeyExchange::complete_hybrid_component()`] which
548
    ///    discards the hybrid key data, and completes just the classical key exchange.
549
0
    fn hybrid_component(&self) -> Option<(NamedGroup, &[u8])> {
550
0
        None
551
0
    }
Unexecuted instantiation: <rustls::crypto::aws_lc_rs::pq::mlkem::Active as rustls::crypto::ActiveKeyExchange>::hybrid_component
Unexecuted instantiation: <rustls::crypto::aws_lc_rs::kx::KeyExchange as rustls::crypto::ActiveKeyExchange>::hybrid_component
552
553
    /// Completes the classical component of the key exchange, given the peer's public key.
554
    ///
555
    /// This is only called if `hybrid_component` returns `Some(_)`.
556
    ///
557
    /// This method must return an error if `peer_pub_key` is invalid: either
558
    /// mis-encoded, or an invalid public key (such as, but not limited to, being
559
    /// in a small order subgroup).
560
    ///
561
    /// The shared secret is returned as a [`SharedSecret`] which can be constructed
562
    /// from a `&[u8]`.
563
    ///
564
    /// See the documentation on [`Self::hybrid_component()`] for explanation.
565
0
    fn complete_hybrid_component(
566
0
        self: Box<Self>,
567
0
        _peer_pub_key: &[u8],
568
0
    ) -> Result<SharedSecret, Error> {
569
0
        unreachable!("only called if `hybrid_component()` implemented")
Unexecuted instantiation: <rustls::crypto::aws_lc_rs::pq::mlkem::Active as rustls::crypto::ActiveKeyExchange>::complete_hybrid_component
Unexecuted instantiation: <rustls::crypto::aws_lc_rs::kx::KeyExchange as rustls::crypto::ActiveKeyExchange>::complete_hybrid_component
570
    }
571
572
    /// Return the public key being used.
573
    ///
574
    /// For ECDHE, the encoding required is defined in
575
    /// [RFC8446 section 4.2.8.2](https://www.rfc-editor.org/rfc/rfc8446#section-4.2.8.2).
576
    ///
577
    /// For FFDHE, the encoding required is defined in
578
    /// [RFC8446 section 4.2.8.1](https://www.rfc-editor.org/rfc/rfc8446#section-4.2.8.1).
579
    fn pub_key(&self) -> &[u8];
580
581
    /// FFDHE group the `ActiveKeyExchange` is operating in.
582
    ///
583
    /// Return `None` if this group is not a FFDHE one.
584
    ///
585
    /// The default implementation calls `FfdheGroup::from_named_group`: this function
586
    /// is extremely linker-unfriendly so it is recommended all key exchange implementers
587
    /// provide this function.
588
    ///
589
    /// `rustls::ffdhe_groups` contains suitable values to return from this,
590
    /// for example [`rustls::ffdhe_groups::FFDHE2048`][crate::ffdhe_groups::FFDHE2048].
591
0
    fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
592
        #[allow(deprecated)]
593
0
        FfdheGroup::from_named_group(self.group())
594
0
    }
595
596
    /// Return the group being used.
597
    fn group(&self) -> NamedGroup;
598
}
599
600
/// The result from [`SupportedKxGroup::start_and_complete()`].
601
pub struct CompletedKeyExchange {
602
    /// Which group was used.
603
    pub group: NamedGroup,
604
605
    /// Our key share (sometimes a public key).
606
    pub pub_key: Vec<u8>,
607
608
    /// The computed shared secret.
609
    pub secret: SharedSecret,
610
}
611
612
/// The result from [`ActiveKeyExchange::complete`] or [`ActiveKeyExchange::complete_hybrid_component`].
613
pub struct SharedSecret {
614
    buf: Vec<u8>,
615
    offset: usize,
616
}
617
618
impl SharedSecret {
619
    /// Returns the shared secret as a slice of bytes.
620
0
    pub fn secret_bytes(&self) -> &[u8] {
621
0
        &self.buf[self.offset..]
622
0
    }
623
624
    /// Removes leading zeros from `secret_bytes()` by adjusting the `offset`.
625
    ///
626
    /// This function does not re-allocate.
627
0
    fn strip_leading_zeros(&mut self) {
628
0
        let start = self
629
0
            .secret_bytes()
630
0
            .iter()
631
0
            .enumerate()
632
0
            .find(|(_i, x)| **x != 0)
633
0
            .map(|(i, _x)| i)
634
0
            .unwrap_or(self.secret_bytes().len());
635
0
        self.offset += start;
636
0
    }
637
}
638
639
impl Drop for SharedSecret {
640
0
    fn drop(&mut self) {
641
0
        self.buf.zeroize();
642
0
    }
643
}
644
645
impl From<&[u8]> for SharedSecret {
646
0
    fn from(source: &[u8]) -> Self {
647
0
        Self {
648
0
            buf: source.to_vec(),
649
0
            offset: 0,
650
0
        }
651
0
    }
652
}
653
654
impl From<Vec<u8>> for SharedSecret {
655
0
    fn from(buf: Vec<u8>) -> Self {
656
0
        Self { buf, offset: 0 }
657
0
    }
658
}
659
660
/// This function returns a [`CryptoProvider`] that uses
661
/// FIPS140-3-approved cryptography.
662
///
663
/// Using this function expresses in your code that you require
664
/// FIPS-approved cryptography, and will not compile if you make
665
/// a mistake with cargo features.
666
///
667
/// See our [FIPS documentation](crate::manual::_06_fips) for
668
/// more detail.
669
///
670
/// Install this as the process-default provider, like:
671
///
672
/// ```rust
673
/// # #[cfg(feature = "fips")] {
674
/// rustls::crypto::default_fips_provider().install_default()
675
///     .expect("default provider already set elsewhere");
676
/// # }
677
/// ```
678
///
679
/// You can also use this explicitly, like:
680
///
681
/// ```rust
682
/// # #[cfg(feature = "fips")] {
683
/// # let root_store = rustls::RootCertStore::empty();
684
/// let config = rustls::ClientConfig::builder_with_provider(
685
///         rustls::crypto::default_fips_provider().into()
686
///     )
687
///     .with_safe_default_protocol_versions()
688
///     .unwrap()
689
///     .with_root_certificates(root_store)
690
///     .with_no_client_auth();
691
/// # }
692
/// ```
693
#[cfg(all(feature = "aws_lc_rs", any(feature = "fips", rustls_docsrs)))]
694
#[cfg_attr(rustls_docsrs, doc(cfg(feature = "fips")))]
695
pub fn default_fips_provider() -> CryptoProvider {
696
    aws_lc_rs::default_provider()
697
}
698
699
mod static_default {
700
    #[cfg(not(feature = "std"))]
701
    use alloc::boxed::Box;
702
    #[cfg(feature = "std")]
703
    use std::sync::OnceLock;
704
705
    #[cfg(not(feature = "std"))]
706
    use once_cell::race::OnceBox;
707
708
    use super::CryptoProvider;
709
    use crate::sync::Arc;
710
711
    #[cfg(feature = "std")]
712
0
    pub(crate) fn install_default(
713
0
        default_provider: CryptoProvider,
714
0
    ) -> Result<(), Arc<CryptoProvider>> {
715
0
        PROCESS_DEFAULT_PROVIDER.set(Arc::new(default_provider))
716
0
    }
717
718
    #[cfg(not(feature = "std"))]
719
    pub(crate) fn install_default(
720
        default_provider: CryptoProvider,
721
    ) -> Result<(), Arc<CryptoProvider>> {
722
        PROCESS_DEFAULT_PROVIDER
723
            .set(Box::new(Arc::new(default_provider)))
724
            .map_err(|e| *e)
725
    }
726
727
1
    pub(crate) fn get_default() -> Option<&'static Arc<CryptoProvider>> {
728
1
        PROCESS_DEFAULT_PROVIDER.get()
729
1
    }
730
731
    #[cfg(feature = "std")]
732
    static PROCESS_DEFAULT_PROVIDER: OnceLock<Arc<CryptoProvider>> = OnceLock::new();
733
    #[cfg(not(feature = "std"))]
734
    static PROCESS_DEFAULT_PROVIDER: OnceBox<Arc<CryptoProvider>> = OnceBox::new();
735
}
736
737
#[cfg(test)]
738
mod tests {
739
    use std::vec;
740
741
    use super::SharedSecret;
742
743
    #[test]
744
    fn test_shared_secret_strip_leading_zeros() {
745
        let test_cases = [
746
            (vec![0, 1], vec![1]),
747
            (vec![1], vec![1]),
748
            (vec![1, 0, 2], vec![1, 0, 2]),
749
            (vec![0, 0, 1, 2], vec![1, 2]),
750
            (vec![0, 0, 0], vec![]),
751
            (vec![], vec![]),
752
        ];
753
        for (buf, expected) in test_cases {
754
            let mut secret = SharedSecret::from(&buf[..]);
755
            assert_eq!(secret.secret_bytes(), buf);
756
            secret.strip_leading_zeros();
757
            assert_eq!(secret.secret_bytes(), expected);
758
        }
759
    }
760
}