rustls/crypto/mod.rs
1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::fmt::Debug;
4
5use pki_types::PrivateKeyDer;
6use zeroize::Zeroize;
7
8#[cfg(all(doc, feature = "tls12"))]
9use crate::Tls12CipherSuite;
10use crate::msgs::ffdhe_groups::FfdheGroup;
11use crate::sign::SigningKey;
12use crate::sync::Arc;
13pub use crate::webpki::{
14 WebPkiSupportedAlgorithms, verify_tls12_signature, verify_tls13_signature,
15 verify_tls13_signature_with_raw_key,
16};
17#[cfg(doc)]
18use crate::{
19 ClientConfig, ConfigBuilder, ServerConfig, SupportedCipherSuite, Tls13CipherSuite, client,
20 crypto, server, sign,
21};
22use crate::{Error, NamedGroup, ProtocolVersion, SupportedProtocolVersion, suites};
23
24/// *ring* based CryptoProvider.
25#[cfg(feature = "ring")]
26pub mod ring;
27
28/// aws-lc-rs-based CryptoProvider.
29#[cfg(feature = "aws_lc_rs")]
30pub mod aws_lc_rs;
31
32/// TLS message encryption/decryption interfaces.
33pub mod cipher;
34
35/// Hashing interfaces.
36pub mod hash;
37
38/// HMAC interfaces.
39pub mod hmac;
40
41#[cfg(feature = "tls12")]
42/// Cryptography specific to TLS1.2.
43pub mod tls12;
44
45/// Cryptography specific to TLS1.3.
46pub mod tls13;
47
48/// Hybrid public key encryption (RFC 9180).
49pub 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.
53pub(crate) mod signer;
54
55pub use crate::msgs::handshake::KeyExchangeAlgorithm;
56pub use crate::rand::GetRandomFailed;
57pub 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)]
184pub 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
219impl 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 pub fn install_default(self) -> Result<(), Arc<Self>> {
228 static_default::install_default(self)
229 }
230
231 /// Returns the default `CryptoProvider` for this process.
232 ///
233 /// This will be `None` if no default has been set yet.
234 pub fn get_default() -> Option<&'static Arc<Self>> {
235 static_default::get_default()
236 }
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 pub(crate) fn get_default_or_install_from_crate_features() -> &'static Arc<Self> {
244 if let Some(provider) = Self::get_default() {
245 return provider;
246 }
247
248 let provider = Self::from_crate_features()
249 .expect(r###"
250Could not automatically determine the process-level CryptoProvider from Rustls crate features.
251Call 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.
252See the documentation of the CryptoProvider type for more information.
253 "###);
254 // Ignore the error resulting from us losing a race, and accept the outcome.
255 let _ = provider.install_default();
256 Self::get_default().unwrap()
257 }
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 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 return Some(aws_lc_rs::default_provider());
282 }
283
284 #[allow(unreachable_code)]
285 None
286 }
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 pub fn fips(&self) -> bool {
295 let Self {
296 cipher_suites,
297 kx_groups,
298 signature_verification_algorithms,
299 secure_random,
300 key_provider,
301 } = self;
302 cipher_suites.iter().all(|cs| cs.fips())
303 && kx_groups.iter().all(|kx| kx.fips())
304 && signature_verification_algorithms.fips()
305 && secure_random.fips()
306 && key_provider.fips()
307 }
308}
309
310/// A source of cryptographically secure randomness.
311pub 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 fn fips(&self) -> bool {
326 false
327 }
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>
338pub 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 fn fips(&self) -> bool {
356 false
357 }
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.
367pub 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 fn start_and_complete(&self, peer_pub_key: &[u8]) -> Result<CompletedKeyExchange, Error> {
389 let kx = self.start()?;
390
391 Ok(CompletedKeyExchange {
392 group: kx.group(),
393 pub_key: kx.pub_key().to_vec(),
394 secret: kx.complete(peer_pub_key)?,
395 })
396 }
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 fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
409 #[allow(deprecated)]
410 FfdheGroup::from_named_group(self.name())
411 }
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 fn fips(&self) -> bool {
421 false
422 }
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 fn usable_for_version(&self, _version: ProtocolVersion) -> bool {
428 true
429 }
430}
431
432/// An in-progress key exchange originating from a [`SupportedKxGroup`].
433pub 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 fn complete_for_tls_version(
475 self: Box<Self>,
476 peer_pub_key: &[u8],
477 tls_version: &SupportedProtocolVersion,
478 ) -> Result<SharedSecret, Error> {
479 if tls_version.version != ProtocolVersion::TLSv1_2 {
480 return self.complete(peer_pub_key);
481 }
482
483 let group = self.group();
484 let mut complete_res = self.complete(peer_pub_key)?;
485 if group.key_exchange_algorithm() == KeyExchangeAlgorithm::DHE {
486 complete_res.strip_leading_zeros();
487 }
488 Ok(complete_res)
489 }
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 fn hybrid_component(&self) -> Option<(NamedGroup, &[u8])> {
550 None
551 }
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 fn complete_hybrid_component(
566 self: Box<Self>,
567 _peer_pub_key: &[u8],
568 ) -> Result<SharedSecret, Error> {
569 unreachable!("only called if `hybrid_component()` implemented")
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 fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
592 #[allow(deprecated)]
593 FfdheGroup::from_named_group(self.group())
594 }
595
596 /// Return the group being used.
597 fn group(&self) -> NamedGroup;
598}
599
600/// The result from [`SupportedKxGroup::start_and_complete()`].
601pub 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`].
613pub struct SharedSecret {
614 buf: Vec<u8>,
615 offset: usize,
616}
617
618impl SharedSecret {
619 /// Returns the shared secret as a slice of bytes.
620 pub fn secret_bytes(&self) -> &[u8] {
621 &self.buf[self.offset..]
622 }
623
624 /// Removes leading zeros from `secret_bytes()` by adjusting the `offset`.
625 ///
626 /// This function does not re-allocate.
627 fn strip_leading_zeros(&mut self) {
628 let start = self
629 .secret_bytes()
630 .iter()
631 .enumerate()
632 .find(|(_i, x)| **x != 0)
633 .map(|(i, _x)| i)
634 .unwrap_or(self.secret_bytes().len());
635 self.offset += start;
636 }
637}
638
639impl Drop for SharedSecret {
640 fn drop(&mut self) {
641 self.buf.zeroize();
642 }
643}
644
645impl From<&[u8]> for SharedSecret {
646 fn from(source: &[u8]) -> Self {
647 Self {
648 buf: source.to_vec(),
649 offset: 0,
650 }
651 }
652}
653
654impl From<Vec<u8>> for SharedSecret {
655 fn from(buf: Vec<u8>) -> Self {
656 Self { buf, offset: 0 }
657 }
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", docsrs)))]
694#[cfg_attr(docsrs, doc(cfg(feature = "fips")))]
695pub fn default_fips_provider() -> CryptoProvider {
696 aws_lc_rs::default_provider()
697}
698
699mod 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 pub(crate) fn install_default(
713 default_provider: CryptoProvider,
714 ) -> Result<(), Arc<CryptoProvider>> {
715 PROCESS_DEFAULT_PROVIDER.set(Arc::new(default_provider))
716 }
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 pub(crate) fn get_default() -> Option<&'static Arc<CryptoProvider>> {
728 PROCESS_DEFAULT_PROVIDER.get()
729 }
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)]
738mod 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}