This is complex because the choice of usable cipher suites depends
on selected protocol version, and the set of mutually supported
key exchange groups. Then, the usable set of key exchange groups
depends on the actually-selected cipher suite.
One can be installed with `CryptoProvider::install_default`.
First call wins.
The current value can be retrieved with `CryptoProvider::get_default()`.
This can be set from the crate features, if and only if they are unambigious,
by installing the result of `CryptoProvider::from_crate_features()`.
Use this for `ClientConfig::builder` and `ServerConfig::builder` et al.
Naturally, `ClientConfig::builder_with_provider` and co. continue to exist.
Change default for `require_ems` based on `fips` crate feature,
generalising the existing tests for `require_ems` to verify this too.
Include `require_ems` in `fips()` determination.
This means a `ClientConfig` and `ServerConfig` can be asked whether it
is in fips mode, and it answers by asking the same of all its
constituent cryptography.
Take new rustls-webpki and pki-types to ask the same of
`SignatureVerificationAlgorithm`.
The `KeyProvider` trait associted with the `CryptoProvider` struct is
specific to private key material that can be loaded from a DER
representation. For users that want to use private keys used through
a handle, or PKCS11 style interface an alternative integration approach
is needed.
This commit adds a doc string update to the `KeyProvider` to guide such
users to look at the Rustls manual's section on customizing private key
usage.
The top level of the crate is meant for "paved path" exports.
In 0.21.x, this type was in `cipher_suites`, along with a few other
types that got moved to specific crypto providers. Moving this to
`crypto` instead of re-exporting under its old name in `cipher_suites`
seems acceptable, because it will mainly be used in implementing crypto
providers. Also, its internals have changed significantly so there is
already churn for this type.
This commit replaces the existing `CryptoProvider` trait with
a `CryptoProvider` struct. This has several advantages:
* it consolidates all of the cryptography related settings into one API
surface, the `CryptoProvider` struct members. Previously the provider
had methods to suggest default ciphersuites, key exchanges etc, but
the builder API methods could override them in confusing ways.
* it allows removing the `WantsCipherSuites` and `WantsKxGroups` builder
states - the "safe defaults" are automatically supplied by the choice
of a crypto provider. Customization is achieved by overriding the
provider's struct fields. Having fewer builder states makes the API
easier to understand and document.
* it makes customization easier: the end user can rely on "struct update
syntax"[0] to only specify fields values for the required
customization, and defer the rest to an existing `CryptoProvider`.
Achieving this requires a couple of additional changes:
* The cipher suite and key exchange groups are now expressed as `Vec`
elements. This avoids imposing a `&'static` lifetime that would
preclude runtime customization (e.g. the tls*-mio examples that
build the list of ciphersuites at runtime based on command line
flags).
* As a result of the `Vec` members we can no longer offer the concrete
`CryptoProvider`s as `static` members of their respective modules.
Instead we add `pub fn default_provider() -> CryptoProvider` methods
to the `ring` and `aws-lc-rs` module that construct the `CryptoProvider`
with the safe defaults, ready for further customization.
[0]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax
In preparation for moving to a struct based model where
a `CryptoProvider` has a `&'static dyn KeyProvider` field, this commit
splits the `KeyProvider` trait from the `CryptoProvider` trait. In its
place `CryptoProvider` gets a `key_provider(&self)` fn that acts as
a stand-in for what will be a field in the struct based approach.
We're working towards making `CryptoProvider` a struct holding distinct
elements to be used for cryptography. To support this the
`load_private_key` fn needs to be lifted to a new trait, `KeyProvider`.
We can hold a `&dyn KeyProvider` in the to-be-added struct to invoke
as required for `load_private_key`.
This commit adds the new trait, includes `KeyProvider` in the existing
`CryptoProvider` trait bounds, and updates the *ring*, aws-lc-rs, and
provider example crypto providers to implement `KeyProvider`.
In preparation for moving to a struct based model where
a `CryptoProvider` has a `&'static dyn SecureRandom` field, this commit
splits the `SecureRandom` trait from the `CryptoProvider` trait. In its
place `CryptoProvider` gets a `secure_random(&self)` fn that acts as
a stand-in for what will be a field in the struct based approach.
We're working towards making `CryptoProvider` a struct holding distinct
elements to be used for cryptography. To support this the `fill_random`
fn needs to be lifted to a new trait, `SecureRandom`. We can hold
a `&dyn SecureRandom` in the to-be-added struct to invoke as required
for `fill_random`. Since the trait now provides additional context, the
fn is renamed from `fill_random` to `fill`.
This commit adds the new trait, includes `SecureRandom` in the existing
`CryptoProvider` trait bounds, and updates the *ring*, aws-lc-rs, and
provider example crypto providers to implement `SecureRandom`.
The `verify_tls12_signature` and `verify_tls13_signature` helpers from
the `webpki::verify` module can be useful when implementing a custom
client/server certificate verifier. This commit exports them under the
`crypto` mod alongside the `WebPkiSupportedAlgorithms` type they rely
on.
The top level of the crate is meant for "paved path" exports.
This newly exported type is used for cryptographic provider
customization, so it properly belongs in the `crypto` module.
When implementing a `CryptoProvider` external to this crate, one needs to be able to access the underlying `secret_bytes` after a key exchange when performing the TLS 1.2 PRF.
This change ensures that the bytes can be safely accessed.
It was surprising to me that builder_with_provider could set a
CryptoProvider, and then with_cipher_suites could choose implementations
from a different CryptoProvider. I've tried to document things to make
that a little less surprising.
Historically the types that now live in `rustls::crypto::signer` were
present in `rustls::sign`. When the crypto provider work refactored them
into their new home, we also added a `lib.rs` re-export under
`rustls::sign`. This left two import paths for accessing the same types.
To avoid duplicated import paths without causing more downstream
churn from moving the types this commit makes the
`rustls::crypto::signer` module `pub(crate)`, leaving `rustls::sign` as
the sole way to access the contained types externally.
The bits and pieces we're landing for HPKE support aren't ready for
broad use yet. To avoid confusion before the 0.22 release this commit
adds a `#[doc(hidden)]` attribute to the `crypto/hpke.rs` mod.
This commit introduces a trait for a hybrid public key encryption (HPKE)
provider. HPKE is specified in RFC 9180[0], and is a pre-requisite for
implementing encrypted client hello (ECH).
Implementations of this trait can use the cryptographic provider of
their choice to provide HPKE using existing primitives from the crypto
provider.
We've tailored the HPKE trait in Rustls to just what is required for
ECH, e.g. it doesn't support modes other than the unauthenticated 'base'
mode, and it only offers the "single-shot" APIs.
[0]: https://www.rfc-editor.org/rfc/rfc9180
Provide shims for limited number of places where ring 0.17 and
aws-lc-rs (ring 0.16-era) APIs have diverged. This is a
short-term fix, as they are likely to diverge more over time.
Eventually we'll have to stop sharing the code like this.
For unit-like tests, export a `test_provider` alias that resolves
to a provider module, for use in these tests.
This resolves to:
- *ring* if cfg(feature = "ring"), else
- aws-lc-rs if cfg(feature = "aws_lc_rs"), else
- is absent
This drastically simplifies `provider-example`. But the
primary goal is ensuring a client configured `with_provider(AWS_LC_RS)`
only uses algorithms from aws-lc-rs, irrespective of crate features.
Use `Error` instead of `GetRandomFailed` in trait `SupportedKxGroup`,
so that underlying crypto provider could throw errors other than RNG
related errors.
Instead of the type `rustls::crypto:💍:Ring`, the value
`rustls::crypto:💍:RING` implements this, and is more
entertaining to write.
`ServerConfig::builder()` references this by default, and
is equivalent to `ServerConfig::builder_with_provider(crypto:💍:RING)`.
This turns `SupportedKxGroup` into a trait, which can tell you
which `NamedGroup` it is, and `start()` an `ActiveKeyExchange`.
An `ActiveKeyExchange` represents the need for the peer's public key
which can be passed to `ActiveKeyExchange::complete`.
Unfortunately we can't be generic at compile-time over the various uses
of the resulting shared secret, so define a further type
which encapsulates the resulting shared secret.
Predefined key exchange algorithms (eg `rustls::kx_group::X25519`)
are now `&'static dyn rustls::SupportedKxGroup`.
The remainder of this commit is noise as much code ceased needing
to be generic of CryptoProvider (for its `KeyExchange` associated type).
Using the crate without this feature means something external
needs to provide all the cryptography, and (eg) convenient integrated
key loading APIs disappear.
This is how a TLS1.2 ciphersuite specifies how to decode a {Client,Server}KeyExchange
message.
This previously had a bunch of unused values: make it non_exhaustive so we can
extend it in the future, but otherwise remove all the unused items that could
mislead people as to what is actually implemented.
This needs to be public so a `rustls::Tls12CipherSuite` can be constructed outside
the core crate.