rama::tls::rustls::dep::rustls::crypto

Struct CryptoProvider

pub struct CryptoProvider {
    pub cipher_suites: Vec<SupportedCipherSuite>,
    pub kx_groups: Vec<&'static dyn SupportedKxGroup>,
    pub signature_verification_algorithms: WebPkiSupportedAlgorithms,
    pub secure_random: &'static dyn SecureRandom,
    pub key_provider: &'static dyn KeyProvider,
}
Expand description

Controls core cryptography used by rustls.

This crate comes with two built-in options, provided as CryptoProvider structures:

  • [crypto::aws_lc_rs::default_provider]: (behind the aws_lc_rs feature, which is enabled by default). This provider uses the aws-lc-rs crate. The fips crate feature makes this option use FIPS140-3-approved cryptography.
  • [crypto::ring::default_provider]: (behind the ring crate feature, which is optional). This provider uses the ring crate.

This structure provides defaults. Everything in it can be overridden at runtime by replacing field values as needed.

§Using the per-process default CryptoProvider

There is the concept of an implicit default provider, configured at run-time once in a given process.

It is used for functions like [ClientConfig::builder()] and [ServerConfig::builder()].

The intention is that an application can specify the CryptoProvider they wish to use once, and have that apply to the variety of places where their application does TLS (which may be wrapped inside other libraries). They should do this by calling CryptoProvider::install_default() early on.

To achieve this goal:

  • libraries should use [ClientConfig::builder()]/[ServerConfig::builder()] or otherwise rely on the CryptoProvider::get_default() provider.
  • applications should call CryptoProvider::install_default() early in their fn main(). If applications uses a custom provider based on the one built-in, they can activate the custom-provider feature to ensure its usage.

§Using a specific CryptoProvider

Supply the provider when constructing your [ClientConfig] or [ServerConfig]:

  • [ClientConfig::builder_with_provider()]
  • [ServerConfig::builder_with_provider()]

When creating and configuring a webpki-backed client or server certificate verifier, a choice of provider is also needed to start the configuration process:

  • [client::WebPkiServerVerifier::builder_with_provider()]
  • [server::WebPkiClientVerifier::builder_with_provider()]

If you install a custom provider and want to avoid any accidental use of a built-in provider, the feature custom-provider can be activated to ensure your custom provider is used everywhere and not a built-in one. This will disable any implicit use of a built-in provider.

§Making a custom CryptoProvider

Your goal will be to populate a [crypto::CryptoProvider] struct instance.

§Which elements are required?

There is no requirement that the individual elements (SupportedCipherSuite, SupportedKxGroup, SigningKey, etc.) come from the same crate. It is allowed and expected that uninteresting elements would be delegated back to one of the default providers (statically) or a parent provider (dynamically).

For example, if we want to make a provider that just overrides key loading in the config builder API ([ConfigBuilder::with_single_cert] etc.), it might look like this:

use rustls::crypto::aws_lc_rs;

pub fn provider() -> rustls::crypto::CryptoProvider {
  rustls::crypto::CryptoProvider{
    key_provider: &HsmKeyLoader,
    ..aws_lc_rs::default_provider()
  }
}

#[derive(Debug)]
struct HsmKeyLoader;

impl rustls::crypto::KeyProvider for HsmKeyLoader {
    fn load_private_key(&self, key_der: pki_types::PrivateKeyDer<'static>) -> Result<Arc<dyn rustls::sign::SigningKey>, rustls::Error> {
         fictious_hsm_api::load_private_key(key_der)
    }
}

§References to the individual elements

The elements are documented separately:

  • Random - see [crypto::SecureRandom::fill()].
  • Cipher suites - see [SupportedCipherSuite], [Tls12CipherSuite], and [Tls13CipherSuite].
  • Key exchange groups - see [crypto::SupportedKxGroup].
  • Signature verification algorithms - see [crypto::WebPkiSupportedAlgorithms].
  • Authentication key loading - see [crypto::KeyProvider::load_private_key()] and [sign::SigningKey].

§Example code

See provider-example/ for a full client and server example that uses cryptography from the rust-crypto and dalek-cryptography projects.

$ cargo run --example client | head -3
Current ciphersuite: TLS13_CHACHA20_POLY1305_SHA256
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 19899

§FIPS-approved cryptography

The fips crate feature enables use of the aws-lc-rs crate in FIPS mode.

You can verify the configuration at runtime by checking [ServerConfig::fips()]/[ClientConfig::fips()] return true.

Fields§

§cipher_suites: Vec<SupportedCipherSuite>

List of supported ciphersuites, in preference order – the first element is the highest priority.

The SupportedCipherSuite type carries both configuration and implementation.

A valid CryptoProvider must ensure that all cipher suites are accompanied by at least one matching key exchange group in CryptoProvider::kx_groups.

§kx_groups: Vec<&'static dyn SupportedKxGroup>

List of supported key exchange groups, in preference order – the first element is the highest priority.

The first element in this list is the default key share algorithm, and in TLS1.3 a key share for it is sent in the client hello.

The SupportedKxGroup type carries both configuration and implementation.

§signature_verification_algorithms: WebPkiSupportedAlgorithms

List of signature verification algorithms for use with webpki.

These are used for both certificate chain verification and handshake signature verification.

This is called by [ConfigBuilder::with_root_certificates()], [server::WebPkiClientVerifier::builder_with_provider()] and [client::WebPkiServerVerifier::builder_with_provider()].

§secure_random: &'static dyn SecureRandom

Source of cryptographically secure random numbers.

§key_provider: &'static dyn KeyProvider

Provider for loading private SigningKeys from PrivateKeyDer.

Implementations§

§

impl CryptoProvider

pub fn install_default(self) -> Result<(), Arc<CryptoProvider>>

Sets this CryptoProvider as the default for this process.

This can be called successfully at most once in any process execution.

Call this early in your process to configure which provider is used for the provider. The configuration should happen before any use of [ClientConfig::builder()] or [ServerConfig::builder()].

pub fn get_default() -> Option<&'static Arc<CryptoProvider>>

Returns the default CryptoProvider for this process.

This will be None if no default has been set yet.

pub fn fips(&self) -> bool

Returns true if this CryptoProvider is operating in FIPS mode.

This covers only the cryptographic parts of FIPS approval. There are also TLS protocol-level recommendations made by NIST. You should prefer to call [ClientConfig::fips()] or [ServerConfig::fips()] which take these into account.

Trait Implementations§

§

impl Clone for CryptoProvider

§

fn clone(&self) -> CryptoProvider

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for CryptoProvider

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dst: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
§

impl<T> Conv for T

§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
§

impl<T> FmtForward for T

§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> FutureExt for T

§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pipe for T
where T: ?Sized,

§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<S, P, B, E>(self, other: P) -> And<T, P>
where T: Policy<S, B, E>, P: Policy<S, B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
§

fn or<S, P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<S, B, E>, P: Policy<S, B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T> Tap for T

§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
§

impl<T> TryConv for T

§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where T: 'static,

§

impl<T> MaybeSendSync for T