rustls/crypto/mod.rs
1use alloc::borrow::Cow;
2use alloc::boxed::Box;
3use alloc::vec::Vec;
4use core::borrow::Borrow;
5use core::fmt::Debug;
6use core::time::Duration;
7
8use pki_types::PrivateKeyDer;
9
10use crate::enums::ProtocolVersion;
11use crate::error::{ApiMisuse, Error};
12use crate::msgs::handshake::ALL_KEY_EXCHANGE_ALGORITHMS;
13use crate::sync::Arc;
14pub use crate::webpki::{
15 WebPkiSupportedAlgorithms, verify_tls12_signature, verify_tls13_signature,
16};
17#[cfg(doc)]
18use crate::{ClientConfig, ConfigBuilder, ServerConfig, client, crypto, server};
19use crate::{SupportedCipherSuite, Tls12CipherSuite, Tls13CipherSuite};
20
21/// aws-lc-rs-based CryptoProvider.
22#[cfg(feature = "aws-lc-rs")]
23pub mod aws_lc_rs;
24
25/// TLS message encryption/decryption interfaces.
26pub mod cipher;
27
28mod enums;
29pub use enums::{CipherSuite, HashAlgorithm, SignatureAlgorithm, SignatureScheme};
30
31/// Hashing interfaces.
32pub mod hash;
33
34/// HMAC interfaces.
35pub mod hmac;
36
37/// Key exchange interfaces.
38pub mod kx;
39use kx::{NamedGroup, SupportedKxGroup};
40
41/// Cryptography specific to TLS1.2.
42pub mod tls12;
43
44/// Cryptography specific to TLS1.3.
45pub mod tls13;
46
47/// Hybrid public key encryption (RFC 9180).
48pub mod hpke;
49
50// Message signing interfaces.
51mod signer;
52pub use signer::{
53 CertificateIdentity, Credentials, Identity, InconsistentKeys, SelectedCredential, Signer,
54 SigningKey, SingleCredential, public_key_to_spki,
55};
56
57pub use crate::suites::CipherSuiteCommon;
58
59/// Controls core cryptography used by rustls.
60///
61/// This crate comes with one built-in option, provided as
62/// `CryptoProvider` structures:
63///
64/// - [`crypto::aws_lc_rs::DEFAULT_PROVIDER`]: (behind the `aws-lc-rs` crate feature).
65/// 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///
68/// This structure provides defaults. Everything in it can be overridden at
69/// runtime by replacing field values as needed.
70///
71/// # Using the per-process default `CryptoProvider`
72///
73/// There is the concept of an implicit default provider, configured at run-time once in
74/// a given process.
75///
76/// It is used for functions like [`ClientConfig::builder()`] and [`ServerConfig::builder()`].
77///
78/// The intention is that an application can specify the [`CryptoProvider`] they wish to use
79/// once, and have that apply to the variety of places where their application does TLS
80/// (which may be wrapped inside other libraries).
81/// They should do this by calling [`CryptoProvider::install_default()`] early on.
82///
83/// To achieve this goal:
84///
85/// - _libraries_ should use [`ClientConfig::builder()`]/[`ServerConfig::builder()`]
86/// or otherwise rely on the [`CryptoProvider::get_default()`] provider.
87/// - _applications_ should call [`CryptoProvider::install_default()`] early
88/// in their `fn main()`. If _applications_ uses a custom provider based on the one built-in,
89/// they can activate the `custom-provider` feature to ensure its usage.
90///
91/// # Using a specific `CryptoProvider`
92///
93/// Supply the provider when constructing your [`ClientConfig`] or [`ServerConfig`]:
94///
95/// - [`ClientConfig::builder()`]
96/// - [`ServerConfig::builder()`]
97///
98/// When creating and configuring a webpki-backed client or server certificate verifier, a choice of
99/// provider is also needed to start the configuration process:
100///
101/// - [`client::WebPkiServerVerifier::builder()`]
102/// - [`server::WebPkiClientVerifier::builder()`]
103///
104/// If you install a custom provider and want to avoid any accidental use of a built-in provider, the feature
105/// `custom-provider` can be activated to ensure your custom provider is used everywhere
106/// and not a built-in one. This will disable any implicit use of a built-in provider.
107///
108/// # Making a custom `CryptoProvider`
109///
110/// Your goal will be to populate an instance of this `CryptoProvider` struct.
111///
112/// ## Which elements are required?
113///
114/// There is no requirement that the individual elements ([`SupportedCipherSuite`], [`SupportedKxGroup`],
115/// [`SigningKey`], etc.) come from the same crate. It is allowed and expected that uninteresting
116/// elements would be delegated back to one of the default providers (statically) or a parent
117/// provider (dynamically).
118///
119/// For example, if we want to make a provider that just overrides key loading in the config builder
120/// API (with [`ConfigBuilder::with_single_cert`], etc.), it might look like this:
121///
122/// ```
123/// # #[cfg(feature = "aws-lc-rs")] {
124/// # use std::sync::Arc;
125/// # mod fictitious_hsm_api { pub fn load_private_key(key_der: pki_types::PrivateKeyDer<'static>) -> ! { unreachable!(); } }
126/// use rustls::crypto::aws_lc_rs;
127///
128/// pub fn provider() -> rustls::crypto::CryptoProvider {
129/// rustls::crypto::CryptoProvider{
130/// key_provider: &HsmKeyLoader,
131/// ..aws_lc_rs::DEFAULT_PROVIDER
132/// }
133/// }
134///
135/// #[derive(Debug)]
136/// struct HsmKeyLoader;
137///
138/// impl rustls::crypto::KeyProvider for HsmKeyLoader {
139/// fn load_private_key(&self, key_der: pki_types::PrivateKeyDer<'static>) -> Result<Box<dyn rustls::crypto::SigningKey>, rustls::Error> {
140/// fictitious_hsm_api::load_private_key(key_der)
141/// }
142/// }
143/// # }
144/// ```
145///
146/// ## References to the individual elements
147///
148/// The elements are documented separately:
149///
150/// - **Random** - see [`SecureRandom::fill()`].
151/// - **Cipher suites** - see [`SupportedCipherSuite`], [`Tls12CipherSuite`], and
152/// [`Tls13CipherSuite`].
153/// - **Key exchange groups** - see [`SupportedKxGroup`].
154/// - **Signature verification algorithms** - see [`WebPkiSupportedAlgorithms`].
155/// - **Authentication key loading** - see [`KeyProvider::load_private_key()`] and
156/// [`SigningKey`].
157///
158/// # Example code
159///
160/// See custom [`provider-example/`] for a full client and server example that uses
161/// cryptography from the [`RustCrypto`] and [`dalek-cryptography`] projects.
162///
163/// ```shell
164/// $ cargo run --example client | head -3
165/// Current ciphersuite: TLS13_CHACHA20_POLY1305_SHA256
166/// HTTP/1.1 200 OK
167/// Content-Type: text/html; charset=utf-8
168/// Content-Length: 19899
169/// ```
170///
171/// [`provider-example/`]: https://github.com/rustls/rustls/tree/main/provider-example/
172/// [`RustCrypto`]: https://github.com/RustCrypto
173/// [`dalek-cryptography`]: https://github.com/dalek-cryptography
174///
175/// # FIPS-approved cryptography
176/// The `fips` crate feature enables use of the `aws-lc-rs` crate in FIPS mode.
177///
178/// You can verify the configuration at runtime by checking
179/// [`ServerConfig::fips()`]/[`ClientConfig::fips()`] return `true`.
180#[expect(clippy::exhaustive_structs)]
181#[derive(Debug, Clone)]
182pub struct CryptoProvider {
183 /// List of supported TLS1.2 cipher suites, in preference order -- the first element
184 /// is the highest priority.
185 ///
186 /// Note that the protocol version is negotiated before the cipher suite.
187 ///
188 /// The `Tls12CipherSuite` 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 tls12_cipher_suites: Cow<'static, [&'static Tls12CipherSuite]>,
193
194 /// List of supported TLS1.3 cipher suites, in preference order -- the first element
195 /// is the highest priority.
196 ///
197 /// Note that the protocol version is negotiated before the cipher suite.
198 ///
199 /// The `Tls13CipherSuite` type carries both configuration and implementation.
200 pub tls13_cipher_suites: Cow<'static, [&'static Tls13CipherSuite]>,
201
202 /// List of supported key exchange groups, in preference order -- the
203 /// first element is the highest priority.
204 ///
205 /// The first element in this list is the _default key share algorithm_,
206 /// and in TLS1.3 a key share for it is sent in the client hello.
207 ///
208 /// The `SupportedKxGroup` type carries both configuration and implementation.
209 pub kx_groups: Cow<'static, [&'static dyn SupportedKxGroup]>,
210
211 /// List of signature verification algorithms for use with webpki.
212 ///
213 /// These are used for both certificate chain verification and handshake signature verification.
214 ///
215 /// This is called by [`ConfigBuilder::with_root_certificates()`],
216 /// [`server::WebPkiClientVerifier::builder()`] and
217 /// [`client::WebPkiServerVerifier::builder()`].
218 pub signature_verification_algorithms: WebPkiSupportedAlgorithms,
219
220 /// Source of cryptographically secure random numbers.
221 pub secure_random: &'static dyn SecureRandom,
222
223 /// Provider for loading private [`SigningKey`]s from [`PrivateKeyDer`].
224 pub key_provider: &'static dyn KeyProvider,
225
226 /// Provider for creating [`TicketProducer`]s for stateless session resumption.
227 pub ticketer_factory: &'static dyn TicketerFactory,
228}
229
230impl CryptoProvider {
231 /// Sets this `CryptoProvider` as the default for this process.
232 ///
233 /// This can be called successfully at most once in any process execution.
234 ///
235 /// Call this early in your process to configure which provider is used for
236 /// the provider. The configuration should happen before any use of
237 /// [`ClientConfig::builder()`] or [`ServerConfig::builder()`].
238 pub fn install_default(self) -> Result<(), Arc<Self>> {
239 static_default::install_default(self)
240 }
241}
242
243impl CryptoProvider {
244 /// Returns the default `CryptoProvider` for this process.
245 ///
246 /// This will be `None` if no default has been set yet.
247 pub fn get_default() -> Option<&'static Arc<Self>> {
248 static_default::get_default()
249 }
250
251 /// Returns `true` if this `CryptoProvider` is operating in FIPS mode.
252 ///
253 /// This covers only the cryptographic parts of FIPS approval. There are
254 /// also TLS protocol-level recommendations made by NIST. You should
255 /// prefer to call [`ClientConfig::fips()`] or [`ServerConfig::fips()`]
256 /// which take these into account.
257 pub fn fips(&self) -> bool {
258 let Self {
259 tls12_cipher_suites,
260 tls13_cipher_suites,
261 kx_groups,
262 signature_verification_algorithms,
263 secure_random,
264 key_provider,
265 ticketer_factory,
266 } = self;
267 tls12_cipher_suites
268 .iter()
269 .all(|cs| cs.fips())
270 && tls13_cipher_suites
271 .iter()
272 .all(|cs| cs.fips())
273 && kx_groups.iter().all(|kx| kx.fips())
274 && signature_verification_algorithms.fips()
275 && secure_random.fips()
276 && key_provider.fips()
277 && ticketer_factory.fips()
278 }
279
280 pub(crate) fn consistency_check(&self) -> Result<(), Error> {
281 if self.tls12_cipher_suites.is_empty() && self.tls13_cipher_suites.is_empty() {
282 return Err(ApiMisuse::NoCipherSuitesConfigured.into());
283 }
284
285 if self.kx_groups.is_empty() {
286 return Err(ApiMisuse::NoKeyExchangeGroupsConfigured.into());
287 }
288
289 // verifying cipher suites have matching kx groups
290 let mut supported_kx_algos = Vec::with_capacity(ALL_KEY_EXCHANGE_ALGORITHMS.len());
291 for group in self.kx_groups.iter() {
292 let kx = group.name().key_exchange_algorithm();
293 if !supported_kx_algos.contains(&kx) {
294 supported_kx_algos.push(kx);
295 }
296 // Small optimization. We don't need to go over other key exchange groups
297 // if we already cover all supported key exchange algorithms
298 if supported_kx_algos.len() == ALL_KEY_EXCHANGE_ALGORITHMS.len() {
299 break;
300 }
301 }
302
303 for cs in self.tls12_cipher_suites.iter() {
304 if supported_kx_algos.contains(&cs.kx) {
305 continue;
306 }
307 let suite_name = cs.common.suite;
308 return Err(Error::General(alloc::format!(
309 "TLS1.2 cipher suite {suite_name:?} requires {0:?} key exchange, but no {0:?}-compatible \
310 key exchange groups were present in `CryptoProvider`'s `kx_groups` field",
311 cs.kx,
312 )));
313 }
314
315 Ok(())
316 }
317
318 pub(crate) fn iter_cipher_suites(&self) -> impl Iterator<Item = SupportedCipherSuite> + '_ {
319 self.tls13_cipher_suites
320 .iter()
321 .copied()
322 .map(SupportedCipherSuite::Tls13)
323 .chain(
324 self.tls12_cipher_suites
325 .iter()
326 .copied()
327 .map(SupportedCipherSuite::Tls12),
328 )
329 }
330
331 /// We support a given TLS version if at least one ciphersuite for the version
332 /// is available.
333 pub(crate) fn supports_version(&self, v: ProtocolVersion) -> bool {
334 match v {
335 ProtocolVersion::TLSv1_2 => !self.tls12_cipher_suites.is_empty(),
336 ProtocolVersion::TLSv1_3 => !self.tls13_cipher_suites.is_empty(),
337 _ => false,
338 }
339 }
340
341 pub(crate) fn find_kx_group(
342 &self,
343 name: NamedGroup,
344 version: ProtocolVersion,
345 ) -> Option<&'static dyn SupportedKxGroup> {
346 if !name.usable_for_version(version) {
347 return None;
348 }
349 self.kx_groups
350 .iter()
351 .find(|skxg| skxg.name() == name)
352 .copied()
353 }
354}
355
356impl Borrow<[&'static Tls12CipherSuite]> for CryptoProvider {
357 fn borrow(&self) -> &[&'static Tls12CipherSuite] {
358 &self.tls12_cipher_suites
359 }
360}
361
362impl Borrow<[&'static Tls13CipherSuite]> for CryptoProvider {
363 fn borrow(&self) -> &[&'static Tls13CipherSuite] {
364 &self.tls13_cipher_suites
365 }
366}
367
368pub(crate) mod rand {
369 use super::{GetRandomFailed, SecureRandom};
370
371 /// Make an array of size `N` containing random material.
372 pub(crate) fn random_array<const N: usize>(
373 secure_random: &dyn SecureRandom,
374 ) -> Result<[u8; N], GetRandomFailed> {
375 let mut v = [0; N];
376 secure_random.fill(&mut v)?;
377 Ok(v)
378 }
379
380 /// Return a uniformly random [`u32`].
381 pub(crate) fn random_u32(secure_random: &dyn SecureRandom) -> Result<u32, GetRandomFailed> {
382 Ok(u32::from_be_bytes(random_array(secure_random)?))
383 }
384
385 /// Return a uniformly random [`u16`].
386 pub(crate) fn random_u16(secure_random: &dyn SecureRandom) -> Result<u16, GetRandomFailed> {
387 Ok(u16::from_be_bytes(random_array(secure_random)?))
388 }
389}
390
391/// Random material generation failed.
392#[expect(clippy::exhaustive_structs)]
393#[derive(Debug)]
394pub struct GetRandomFailed;
395
396/// A source of cryptographically secure randomness.
397pub trait SecureRandom: Send + Sync + Debug {
398 /// Fill the given buffer with random bytes.
399 ///
400 /// The bytes must be sourced from a cryptographically secure random number
401 /// generator seeded with good quality, secret entropy.
402 ///
403 /// This is used for all randomness required by rustls, but not necessarily
404 /// randomness required by the underlying cryptography library. For example:
405 /// [`SupportedKxGroup::start()`] requires random material to generate
406 /// an ephemeral key exchange key, but this is not included in the interface with
407 /// rustls: it is assumed that the cryptography library provides for this itself.
408 fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed>;
409
410 /// Return `true` if this is backed by a FIPS-approved implementation.
411 fn fips(&self) -> bool {
412 false
413 }
414}
415
416/// A mechanism for loading private [`SigningKey`]s from [`PrivateKeyDer`].
417///
418/// This trait is intended to be used with private key material that is sourced from DER,
419/// such as a private-key that may be present on-disk. It is not intended to be used with
420/// keys held in hardware security modules (HSMs) or physical tokens. For these use-cases
421/// see the Rustls manual section on [customizing private key usage].
422///
423/// [customizing private key usage]: <https://docs.rs/rustls/latest/rustls/manual/_03_howto/index.html#customising-private-key-usage>
424pub trait KeyProvider: Send + Sync + Debug {
425 /// Decode and validate a private signing key from `key_der`.
426 ///
427 /// This is used by [`ConfigBuilder::with_client_auth_cert()`], [`ConfigBuilder::with_single_cert()`],
428 /// and [`ConfigBuilder::with_single_cert_with_ocsp()`]. The key types and formats supported by this
429 /// function directly defines the key types and formats supported in those APIs.
430 ///
431 /// Return an error if the key type encoding is not supported, or if the key fails validation.
432 fn load_private_key(
433 &self,
434 key_der: PrivateKeyDer<'static>,
435 ) -> Result<Box<dyn SigningKey>, Error>;
436
437 /// Return `true` if this is backed by a FIPS-approved implementation.
438 ///
439 /// If this returns `true`, that must be the case for all possible key types
440 /// supported by [`KeyProvider::load_private_key()`].
441 fn fips(&self) -> bool {
442 false
443 }
444}
445
446/// A factory that builds [`TicketProducer`]s.
447///
448/// These can be used in [`ServerConfig::ticketer`] to enable stateless resumption.
449///
450/// [`ServerConfig::ticketer`]: crate::server::ServerConfig::ticketer
451pub trait TicketerFactory: Debug + Send + Sync {
452 /// Build a new `TicketProducer`.
453 fn ticketer(&self) -> Result<Arc<dyn TicketProducer>, Error>;
454
455 /// Return `true` if this is backed by a FIPS-approved implementation.
456 fn fips(&self) -> bool;
457}
458
459/// A trait for the ability to encrypt and decrypt tickets.
460pub trait TicketProducer: Debug + Send + Sync {
461 /// Encrypt and authenticate `plain`, returning the resulting
462 /// ticket. Return None if `plain` cannot be encrypted for
463 /// some reason: an empty ticket will be sent and the connection
464 /// will continue.
465 fn encrypt(&self, plain: &[u8]) -> Option<Vec<u8>>;
466
467 /// Decrypt `cipher`, validating its authenticity protection
468 /// and recovering the plaintext. `cipher` is fully attacker
469 /// controlled, so this decryption must be side-channel free,
470 /// panic-proof, and otherwise bullet-proof. If the decryption
471 /// fails, return None.
472 fn decrypt(&self, cipher: &[u8]) -> Option<Vec<u8>>;
473
474 /// Returns the lifetime of tickets produced now.
475 /// The lifetime is provided as a hint to clients that the
476 /// ticket will not be useful after the given time.
477 ///
478 /// This lifetime must be implemented by key rolling and
479 /// erasure, *not* by storing a lifetime in the ticket.
480 ///
481 /// The objective is to limit damage to forward secrecy caused
482 /// by tickets, not just limiting their lifetime.
483 fn lifetime(&self) -> Duration;
484}
485
486/// This function returns a [`CryptoProvider`] that uses
487/// FIPS140-3-approved cryptography.
488///
489/// Using this function expresses in your code that you require
490/// FIPS-approved cryptography, and will not compile if you make
491/// a mistake with cargo features.
492///
493/// See our [FIPS documentation](crate::manual::_06_fips) for
494/// more detail.
495///
496/// Install this as the process-default provider, like:
497///
498/// ```rust
499/// # #[cfg(feature = "fips")] {
500/// rustls::crypto::default_fips_provider().install_default()
501/// .expect("default provider already set elsewhere");
502/// # }
503/// ```
504///
505/// You can also use this explicitly, like:
506///
507/// ```rust
508/// # #[cfg(feature = "fips")] {
509/// # let root_store = rustls::RootCertStore::empty();
510/// let config = rustls::ClientConfig::builder(
511/// rustls::crypto::default_fips_provider().into()
512/// )
513/// .with_root_certificates(root_store)
514/// .with_no_client_auth()
515/// .unwrap();
516/// # }
517/// ```
518#[cfg(all(feature = "aws-lc-rs", any(feature = "fips", rustls_docsrs)))]
519#[cfg_attr(rustls_docsrs, doc(cfg(feature = "fips")))]
520pub fn default_fips_provider() -> CryptoProvider {
521 aws_lc_rs::DEFAULT_PROVIDER
522}
523
524mod static_default {
525 #[cfg(not(feature = "std"))]
526 use alloc::boxed::Box;
527 #[cfg(feature = "std")]
528 use std::sync::OnceLock;
529
530 #[cfg(not(feature = "std"))]
531 use once_cell::race::OnceBox;
532
533 use super::CryptoProvider;
534 use crate::sync::Arc;
535
536 #[cfg(feature = "std")]
537 pub(crate) fn install_default(
538 default_provider: CryptoProvider,
539 ) -> Result<(), Arc<CryptoProvider>> {
540 PROCESS_DEFAULT_PROVIDER.set(Arc::new(default_provider))
541 }
542
543 #[cfg(not(feature = "std"))]
544 pub(crate) fn install_default(
545 default_provider: CryptoProvider,
546 ) -> Result<(), Arc<CryptoProvider>> {
547 PROCESS_DEFAULT_PROVIDER
548 .set(Box::new(Arc::new(default_provider)))
549 .map_err(|e| *e)
550 }
551
552 pub(crate) fn get_default() -> Option<&'static Arc<CryptoProvider>> {
553 PROCESS_DEFAULT_PROVIDER.get()
554 }
555
556 #[cfg(feature = "std")]
557 static PROCESS_DEFAULT_PROVIDER: OnceLock<Arc<CryptoProvider>> = OnceLock::new();
558 #[cfg(not(feature = "std"))]
559 static PROCESS_DEFAULT_PROVIDER: OnceBox<Arc<CryptoProvider>> = OnceBox::new();
560}
561
562#[cfg(test)]
563pub(crate) fn tls13_suite(
564 suite: CipherSuite,
565 provider: &CryptoProvider,
566) -> &'static Tls13CipherSuite {
567 provider
568 .tls13_cipher_suites
569 .iter()
570 .find(|cs| cs.common.suite == suite)
571 .unwrap()
572}
573
574#[cfg(test)]
575pub(crate) fn tls12_suite(
576 suite: CipherSuite,
577 provider: &CryptoProvider,
578) -> &'static Tls12CipherSuite {
579 provider
580 .tls12_cipher_suites
581 .iter()
582 .find(|cs| cs.common.suite == suite)
583 .unwrap()
584}
585
586#[cfg(test)]
587pub(crate) fn tls13_only(provider: CryptoProvider) -> CryptoProvider {
588 CryptoProvider {
589 tls12_cipher_suites: Cow::default(),
590 ..provider
591 }
592}
593
594#[cfg(test)]
595pub(crate) fn tls12_only(provider: CryptoProvider) -> CryptoProvider {
596 CryptoProvider {
597 tls13_cipher_suites: Cow::default(),
598 ..provider
599 }
600}