Rustls is a modern TLS library written in Rust

ring for cryptography and rustls-pemfile crate

. It uses ring for cryptography and libwebpki for certificate verification.

Status

Rustls is ready for use. There are no major breaking interface changes envisioned after the set included in the 0.20 release.

If you'd like to help out, please see CONTRIBUTING.md.

Release history:

  • Next release:
    • Planned: removal of unused signature verification schemes at link-time.
  • 0.20.0-beta3 (2021-xx-xx)
    • Unclean TCP closure is now tracked by the library. This means a new error is possible when reading plaintext: ErrorKind::UnexpectedEof will be returned in this case.
    • Breaking change: insulate the rustls public API from webpki API changes:
      • PKI errors are now reported using rustls-specific errors.
      • There is now a rustls-specific root trust anchor type.
    • Breaking change: the following types are no longer exposed in the crate root, and can instead be imported through the client module exposed in the crate root: ResolvesClientCert, StoresClientSessions, WriteEarlyData, ClientSessionMemoryCache, NoClientSessionStorage, HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier, WebPkiVerifier and DangerousClientConfig.
    • Breaking change: the following types are no longer exposed in the crate root, and can instead be imported through the server module exposed in the crate root: AllowAnonymousOrAuthenticatedClient, AllowAnyAuthenticatedClient, NoClientAuth, ResolvesServerCertUsingSni, NoServerSessionStorage, ServerSessionMemoryCache, StoresServerSessions, ClientHello, ProducesTickets, ResolvesServerCert, ClientCertVerified and ClientCertVerifier.
    • Breaking API change: QuicExt::write_hs() now returns a KeyChange type that returns handshake or 1-RTT keys. In the case of 1-RTT keys, a KeyChange also includes a Secrets type that must be used to derive further key updates, independent from the rustls Connection. The QuicExt::next_1rtt_keys() method has been removed.
    • Breaking API change: QUIC header protection keys now use a new type that directly exposes a masking/unmasking operation.
  • 0.20.0-beta2 (2021-07-04)
    • Breaking change: internal buffers are now limited to 64 kB by default. Use Connection::set_buffer_limit to change the buffer limits to suit your application.
    • Breaking API change: PEM parsing now lives in the rustls-pemfile crate. This means rustls::internals::pemfile and rustls::RootCertStore::add_pem_file no longer exist.
    • Breaking API change: ServerCertVerifier::verify_server_cert and ClientCertVerifier::verify_client_cert pass the end-entity and intermediate certificates separately. This means rustls deals with the case where the certificate chain is empty, rather than leaving that to ServerCertVerifier/ClientCertVerifier implementation.
    • Breaking API change: SupportedCipherSuite is now an enum with TLS 1.2 and TLS 1.3 variants. Some of its methods have moved to the inner Tls12CipherSuite and Tls13CipherSuite types. Instead of usable_for_version(), it now has a version() method. get_hash() has been renamed to hash_algorithm() and usable_for_sigalg() to usable_for_signature_algorithm().
    • There are now 80% fewer unreachable unwraps in the core crate thanks to large refactoring efforts.
    • Breaking API change: the WebPkiError variant of rustls::Error now includes which operation failed.
    • Breaking API changes: These public API items have been renamed to meet naming guidelines:
      • rustls::TLSError to rustls::Error.
      • rustls::ResolvesServerCertUsingSNI to rustls::ResolvesServerCertUsingSni.
      • rustls::WebPKIVerifier to rustls::WebPkiVerifier.
      • rustls::ciphersuites to rustls::cipher_suites.
      • rustls::ALL_CIPHERSUITES to ALL_CIPHER_SUITES; rustls::DEFAULT_CIPHERSUITES to DEFAULT_CIPHER_SUITES.
      • rustls::ClientHello::sigschemes to rustls::ClientHello::signature_schemes.
      • rustls::RootCertStore::get_subjects to rustls::RootCertStore::subjects.
      • rustls::ServerSession to rustls::ServerConnection.
      • rustls::ClientSession to rustls::ClientConnection.
      • rustls::ServerSession::get_sni_hostname to rustls::ServerConnection::sni_hostname.
      • rustls::ClientConfig::ciphersuites to rustls::ClientConfig::cipher_suites.
      • rustls::ServerConfig::ciphersuites to rustls::ServerConfig::cipher_suites.
      • rustls::ProducesTickets::get_lifetime to rustls::ProducesTickets::lifetime.
      • rustls::Session: get_peer_certificates to peer_certificates, get_alpn_protocol to alpn_protocol, get_protocol_version to protocol_version, get_negotiated_ciphersuite to negotiated_cipher_suite.
    • Breaking API change: ResolvesServerCert::resolve and ResolvesClientCert::resolve now return Option<Arc<CertifiedKey>> instead of Option<CertifiedKey>. CertifiedKey is now an immutable type.
    • Breaking API change: peer_certificates returns a borrow rather than a copy on the internally stored certificate chain.
    • Breaking API change: ClientConnection's DNS name parameter is now a new enum, ServerName, to allow future support for ECH and servers named by IP address.
  • 0.19.1 (2021-04-17):
    • Backport: fix security issue: there was a reachable panic in servers if a client sent an invalid ClientECDiffieHellmanPublic encoding, due to an errant unwrap() when parsing the encoding.
  • 0.19.0 (2020-11-22):
    • Ensured that get_peer_certificates is both better documented, and works uniformly for both full-handshake and resumed sessions.
    • Fix bug: fully qualified hostnames should have had their trailing dot stripped when quoted in the SNI extension.
  • 0.18.1 (2020-08-16):
    • Fix DoS vulnerability in TLS1.3 "Middlebox Compatibility Mode" CCS handling. This is thought to be quite minor -- see this commit message for a full discussion.
  • 0.18.0 (2020-07-04):
    • Allow custom certificate validation implementations to also handle handshake signature computation. This allows uses in non-web contexts, where webpki is not likely to process the certificates in use. Thanks to @DemiMarie-parity.
    • Performance improvements. Thanks to @nviennot.
    • Fixed client authentication being unduly rejected by client when server uses the superseded certificate_types field of CertificateRequest.
    • Breaking API change: The writev_tls API has been removed, in favour of using vectored IO support now offered by std::io::Write.
    • Added ed25519 support for authentication; thanks to @potatosalad.
    • Support removal of unused ciphersuites at link-time. To use this, call ClientConfig::with_ciphersuites instead of ClientConfig::new.

See OLDCHANGES.md for further change history.

Documentation

Lives here: https://docs.rs/rustls/

Approach

Rustls is a TLS library that aims to provide a good level of cryptographic security, requires no configuration to achieve that security, and provides no unsafe features or obsolete cryptography.

Current features

  • TLS1.2 and TLS1.3.
  • ECDSA, Ed25519 or RSA server authentication by clients.
  • ECDSA, Ed25519 or RSA server authentication by servers.
  • Forward secrecy using ECDHE; with curve25519, nistp256 or nistp384 curves.
  • AES128-GCM and AES256-GCM bulk encryption, with safe nonces.
  • ChaCha20-Poly1305 bulk encryption (RFC7905).
  • ALPN support.
  • SNI support.
  • Tunable fragment size to make TLS messages match size of underlying transport.
  • Optional use of vectored IO to minimise system calls.
  • TLS1.2 session resumption.
  • TLS1.2 resumption via tickets (RFC5077).
  • TLS1.3 resumption via tickets or session storage.
  • TLS1.3 0-RTT data for clients.
  • Client authentication by clients.
  • Client authentication by servers.
  • Extended master secret support (RFC7627).
  • Exporters (RFC5705).
  • OCSP stapling by servers.
  • SCT stapling by servers.
  • SCT verification by clients.

Possible future features

  • PSK support.
  • OCSP verification by clients.
  • Certificate pinning.

Non-features

For reasons explained in the manual, rustls does not and will not support:

  • SSL1, SSL2, SSL3, TLS1 or TLS1.1.
  • RC4.
  • DES or triple DES.
  • EXPORT ciphersuites.
  • MAC-then-encrypt ciphersuites.
  • Ciphersuites without forward secrecy.
  • Renegotiation.
  • Kerberos.
  • Compression.
  • Discrete-log Diffie-Hellman.
  • Automatic protocol version downgrade.

There are plenty of other libraries that provide these features should you need them.

Platform support

Rustls uses ring for implementing the cryptography in TLS. As a result, rustls only runs on platforms supported by ring. At the time of writing this means x86, x86-64, armv7, and aarch64.

Example code

There are two example programs which use mio to do asynchronous IO.

Client example program

The client example program is named tlsclient. The interface looks like:

Connects to the TLS server at hostname:PORT.  The default PORT
is 443.  By default, this reads a request from stdin (to EOF)
before making the connection.  --http replaces this with a
basic HTTP GET request for /.

If --cafile is not supplied, a built-in set of CA certificates
are used from the webpki-roots crate.

Usage:
  tlsclient [options] [--suite SUITE ...] [--proto PROTO ...] <hostname>
  tlsclient (--version | -v)
  tlsclient (--help | -h)

Options:
    -p, --port PORT     Connect to PORT [default: 443].
    --http              Send a basic HTTP GET request for /.
    --cafile CAFILE     Read root certificates from CAFILE.
    --auth-key KEY      Read client authentication key from KEY.
    --auth-certs CERTS  Read client authentication certificates from CERTS.
                        CERTS must match up with KEY.
    --protover VERSION  Disable default TLS version list, and use
                        VERSION instead.  May be used multiple times.
    --suite SUITE       Disable default cipher suite list, and use
                        SUITE instead.  May be used multiple times.
    --proto PROTOCOL    Send ALPN extension containing PROTOCOL.
                        May be used multiple times to offer several protocols.
    --cache CACHE       Save session cache to file CACHE.
    --no-tickets        Disable session ticket support.
    --no-sni            Disable server name indication support.
    --insecure          Disable certificate verification.
    --verbose           Emit log output.
    --max-frag-size M   Limit outgoing messages to M bytes.
    --version, -v       Show tool version.
    --help, -h          Show this screen.

Some sample runs:

$ cargo run --example tlsclient -- --http mozilla-modern.badssl.com
HTTP/1.1 200 OK
Server: nginx/1.6.2 (Ubuntu)
Date: Wed, 01 Jun 2016 18:44:00 GMT
Content-Type: text/html
Content-Length: 644
(...)

or

$ cargo run --example tlsclient -- --http expired.badssl.com
TLS error: WebPkiError(CertExpired, ValidateServerCert)
Connection closed

Server example program

The server example program is named tlsserver. The interface looks like:

Runs a TLS server on :PORT.  The default PORT is 443.

`echo' mode means the server echoes received data on each connection.

`http' mode means the server blindly sends a HTTP response on each
connection.

`forward' means the server forwards plaintext to a connection made to
localhost:fport.

`--certs' names the full certificate chain, `--key' provides the
RSA private key.

Usage:
  tlsserver --certs CERTFILE --key KEYFILE [--suite SUITE ...] [--proto PROTO ...] [options] echo
  tlsserver --certs CERTFILE --key KEYFILE [--suite SUITE ...] [--proto PROTO ...] [options] http
  tlsserver --certs CERTFILE --key KEYFILE [--suite SUITE ...] [--proto PROTO ...] [options] forward <fport>
  tlsserver (--version | -v)
  tlsserver (--help | -h)

Options:
    -p, --port PORT     Listen on PORT [default: 443].
    --certs CERTFILE    Read server certificates from CERTFILE.
                        This should contain PEM-format certificates
                        in the right order (the first certificate should
                        certify KEYFILE, the last should be a root CA).
    --key KEYFILE       Read private key from KEYFILE.  This should be a RSA
                        private key or PKCS8-encoded private key, in PEM format.
    --ocsp OCSPFILE     Read DER-encoded OCSP response from OCSPFILE and staple
                        to certificate.  Optional.
    --auth CERTFILE     Enable client authentication, and accept certificates
                        signed by those roots provided in CERTFILE.
    --require-auth      Send a fatal alert if the client does not complete client
                        authentication.
    --resumption        Support session resumption.
    --tickets           Support tickets.
    --protover VERSION  Disable default TLS version list, and use
                        VERSION instead.  May be used multiple times.
    --suite SUITE       Disable default cipher suite list, and use
                        SUITE instead.  May be used multiple times.
    --proto PROTOCOL    Negotiate PROTOCOL using ALPN.
                        May be used multiple times.
    --verbose           Emit log output.
    --version, -v       Show tool version.
    --help, -h          Show this screen.

Here's a sample run; we start a TLS echo server, then connect to it with openssl and tlsclient:

$ cargo run --example tlsserver -- --certs test-ca/rsa/end.fullchain --key test-ca/rsa/end.rsa -p 8443 echo &
$ echo hello world | openssl s_client -ign_eof -quiet -connect localhost:8443
depth=2 CN = ponytown RSA CA
verify error:num=19:self signed certificate in certificate chain
hello world
^C
$ echo hello world | cargo run --example tlsclient -- --cafile test-ca/rsa/ca.cert -p 8443 localhost
hello world
^C

License

Rustls is distributed under the following three licenses:

  • Apache License version 2.0.
  • MIT license.
  • ISC license.

These are included as LICENSE-APACHE, LICENSE-MIT and LICENSE-ISC respectively. You may use this software under the terms of any of these licenses, at your option.

Issues

Collection of the latest Issues

jsha

jsha

1

At https://docs.rs/rustls/latest/rustls/server/struct.ClientHello.html#method.signature_schemes, the SignatureScheme type links to rustls::internal::msgs::enums::SignatureScheme. This is the same type as rustls::SignatureScheme, but exported under a different name.

The internals version of this name is exported here: https://github.com/rustls/rustls/blob/093e88e7e180d44eb94b6f2c30b92a89f9f0cdbe/rustls/src/lib.rs#L347-L358

In practice, even though the comment says the internals paths are not part of the public API, they become so by being linked from the public API.

One simple and effective fix would be: We could remove pub mod internal entirely. Then all links to SignatureScheme would go to the public API path, rustls::SignatureScheme.

jadamcrain

jadamcrain

1

I'm implementing IEEE 2030.5 - 2018. The spec requires the CCM bulk encryption AEAD with truncated MAC:

The spec doesn't explicitly state why a less commonly supported mode is required, but I've pieced together that perhaps it's for embedded devices with AES acceleration but not GHASH:

https://crypto.stackexchange.com/questions/63796/why-does-tls-1-3-support-two-ccm-variants

It appears from this thread that rustls doesn't support them because ring lacks support.

We've successfully used rustls to implement two other M2M standards in electric power, but this will unfortunately mean that we have to use native-tls for this project.

My question at this point in time:

Would rustls support these bulk modes in 1.2 and 1.3 if ring implemented them? Is there any concern with adding them beyond the lack of support currently?

Perhaps this can just be a tracking issue in case anyone else runs into this as well. I didn't see any other open issues in the tracker.

complexspaces

complexspaces

0

We've received a few user reports where rustls fails to setup a TLS session when a TLS proxy is in-use (we aren't sure which brand, etc). After asking for some more logging, we've narrowed down the code section throwing an error to here.

Our best assumption so far is that the middlebox is returning some badly formatted data that causes buf_contains_message to reject it.

zh-jq

zh-jq

6

from tokio-rs/tls/issues/103

there are two streams in the following pcap files, the first to appleid.apple.com, the second to api.devicecheck.apple.com, both use session_ticket extension. out.pcap.gz

The second failed while the first succeeded. The main difference seems to be, in stream one, packet 6 contains Server Hello + Change Cipher Spec + Encrypted Handshake Message, but in stream two, packet 23 only contains Server Hello + Change Cipher Spec, the missing Encrypted Handshake Message is later in packet 27, which seems to be ignored by rustls as it reply alert message and close the connection before packet 27.

tokio-rustls version 0.23.2, rustls version 0.20.4

The error returned by rustls is CorruptMessagePayload(Handshake), I'm trying to test it locally with master version of rustls to get more info.

briansmith

briansmith

2

How can we test the QUIC API, especially for cases where the peer is doing something wrong/bad?

We use BoringSSL's BoGo test framework to test many aspects of Rustls. In particular, buggy/malicious behavior pretty much is tested exclusively via BoGo since it's the only implementation of TLS we have that allows us to (intentionally) do the wrong thing.

I looked into how Bogo tests QUIC. BoringSSL apparently implements an API very similar to the one that Rustls implements. One difference is that it requires the QUIC implementation to do the actual record encryption/decryption, whereas Rustls encapsulates the encryption/decryption. Thus the Bogo "mock_quic_transport.{go,c,h}" used in its QUIC tests, which doesn't even encrypt anything, seems impractical to implement on top of Rustls's public QUIC API.

It seems like if we wanted to adapt the Bogo tests for QUIC to work for Rustls, we'd need to implement a mock "real" QUIC transport that encrypts/decrypts. Perhaps BoringSSL people would help us maintain that if we were to contribute it?

Or, if Bogo is a nonstarter then what is the alternative?

briansmith

briansmith

2

In server/tls13.rs we have this: https://github.com/rustls/rustls/blob/5bda754ac18f37eb39132f89fb5522494b6202eb/rustls/src/server/tls13.rs#L530-L544

I find this code confusing for a few reasons:

  1. The comment "If 0-RTT should be rejected, this will be clobbered by ExtensionProcessing before the application can see." seems to only apply to QUIC because it's scoped in the QUIC-only block, but I think it also applies to the set_message_decrypter call that is above the QUIC block? Should we move the comment up?
  2. Perhaps the QUIC block should be inside the if let Some(key) = &early_data_client_key { to make it clearer that this is all one thing?
  3. The QUIC block is guarded by #[cfg(feature = "quic")] but it never checks that the current connection's protocol is QUIC; see PR #1008.

Besides the difficulty in understanding the code, it seems inefficient to derive and construct these keys in the case where we will not accept 0-RTT data. Maybe error-prone too. Maybe the solution is to move this key handling code out of emit_server_hello and inline it its caller, and then refactor it so that we don't configure the 0-RTT state if we're going to immediately overwrite it?

dequbed

dequbed

2

Hello!

Authentication frameworks such as GSSAPI and SASL implement a concept called "channel binding" in which they cryptographically verify in the authentication exchange that both parties are seeing the same cryptographic channel, thus binding the authentication to the underlying transport security layer and preventing a few attacks.

To be able to do this the authentication frameworks include data from the underlying encryption layer in the secrets used for the authentication itself.

In the case of TLS there are two common kinds of channel bindings, standardized in RFC5929: tls-server-end-point which uses the first Certificate provided by the server, and tls-unique which uses the first "Finished" Message sent in the connection. Getting to the first certificate sent by the server is already possible via ClientConnection::peer_certificates as the client or … well … keeping it around as the server. However, I don't see any way to get to the (contents of the) Finished message as either server or client.

Am I missing something or is there no way currently? And if the latter, is this something that the rustls team would be willing to add or to merge a PR adding it?

ctz

ctz

0

If we set ServerConfig::max_fragment_size or ClientConfig::max_fragment_size it is expected that all the TLS messages are no larger than this. However, this is only true if the messages are unencrypted: after that the sizes are larger by the encryption overhead.

This means, setting max_fragment_size to Some(64), the message sizes are:

briansmith

briansmith

3

We currently have this documentation:

Note in particular we say "securely half-close." However, prior to authenticating the handshake, the close_notify is not secure.

self.peer_has_closed is set to the value of has_received_close_notify. We set has_received_close_notify whenever we receive a close_notify alert, regardless of the state of the handshake.

Probably instead we must treat close_notify before the handshake has completed the same as the peer non-securely closing the connection. We should make sure we always return an error in this situation.

One way to do this is to use a type like this:

briansmith

briansmith

5

I was reading the code and was struck by this:

Consider the unusual case where we receive in the same TCP packet a valid close_notify Alert followed by an ApplicationData record. Then has_received_close_notify will be true but self.message_deframer.has_pending() may be true. Then peer_cleanly_closed will be false, right?

Now consider this logic later:

My thinking is that we may hit the (false, false) case and return Err(io::ErrorKind::WouldBlock.into()). Is that true?

If so, I am not sure that Err(io::ErrorKind::WouldBlock.into()) would be the right thing to return. I think instead when we receive a close_notify alert then we should discard any remaining already-read data after the alert and ensure we never try to read any more (act like we've seen EOF). And, in particular, we should ensure that any subsequent attempt to read data will return EOF instead of returning any data after close_notify.

We should document that it is possible that there might have been data received that wasn't processed after the close_notify, and give advice on what the application should do.

Regardless, I think instead of combining has_received_close_notify && !self.message_deframer.has_pending() into a single peer_cleanly_closed variable, it would be clearer to instead have the match above handle the triple (has_received_close_notify, deframer_has_pending, has_seen_eof).

If everything is the way we want it to be, then at the very least we should add some comments to explain this.

briansmith

briansmith

1
  • In TLS 1.2, we accept unlimited renegotiation requests from the peer. For each one, we send/queue an alert and keep going. This could cause us to allocate memory without bound. We should implement anti-DoS countermeasures that limit the number of renegotiation requests we process.
  • We do not verify that the HelloRequest or ClientHello we receive during a renegotiation request is well-formed. We should implement some form of well-formedness check. This should be trivial for HelloRequest. For ClientHello, we probably don't want to use our current ClientHello parser though. Perhaps we should just sanity check that it isn't huge? [edit: we do parse it into a HandshakePayload, and that does validate it sufficiently.]
briansmith

briansmith

2

In rustls-mio/tests/common/mod.rs we have:

I'm a bit alarmed that our CI/CD infrastructure doesn't complain us using Rust < 1.58.1.

This usage is in test-only code and we don't meet the prerequisites (AFAICT) for it to actually be a security problem. However, I would expect that by default we'd get a warning for using the MSRV version that we'd have to explicitly override. It seems like CI/CD isn't set up to do this, but it should be, especially for the case where a security issue in the the Rust toolchain might impact the security/validity of the build.

briansmith

briansmith

0

An application might know that it won't be sending application data for a while, and/or it won't be expecting data for a while, and it might want to roll the traffic key(s) forward. We should have a way for the application to make this happen.

Note that issue #755 tracks doing automatic key updates when "enough" data has been sent.

There are a lot of details to decide on w.r.t. the API design and functionality to implement. I don't think this is a high priority yet. I'm mostly filing this so that I can reference this issue from other issues.

briansmith

briansmith

next-major-release
4

The TLS 1.3 spec says in https://datatracker.ietf.org/doc/html/rfc8446#appendix-E.1.4:

[B]ecause these secrets can be used to compute any exporter value, they SHOULD be erased as soon as possible. If the total set of exporter labels is known, then implementations SHOULD pre-compute the inner Derive-Secret stage of the exporter computation for all those labels, then erase the [early_]exporter_master_secret, followed by each inner value as soon as it is known that it will not be needed again.

However, the design of the export_keying_material() API makes this erasure recommendation impossible to implement, because we currently support calling export_keying_material() at any time after the handshake completes, and so we have to retain the exporter key.

Note that TLS doesn't provide any way to rotate the exporter key; the KeyUpdate mechanism only applies to traffic keys. This design pretty much forces us to implement the erasure recommendation above, if we want to have long-lived connections that minimize their ability to expose secrets.

I propose:

  • We remove export_keying_material() from the public API.

  • Add a "handshake" callback. (Note that this suggested interface is intended to be easily extensible in a way that maintains SemVer compatibility):

  • When the handshake completes, call this callback.

  • Move current_exporter_secret out of KeyScheduleTraffic to the implementation(s) of HandshakeData. (It should probably be lazily constructed the first time export_keying_material is called, since most applications don't need it.)

  • The new export_keying_material() API should implement additional validation of its parameters as suggested in the TLS 1.3 specification and the and common sense (e.g. that the label and other parameters that should be non-empty aren't empty)..

  • Since HandshakeData is moved into the callback, its contents (in particular, the exporter key) will be destroyed automatically, implementing the semantics that the TLS 1.3 spec recommends.

Besides being safer, this would also:

  • Slightly reduce the memory requirements for each connection
  • Make it easier to split the KeySchedule into read and write parts, which I think is probably useful for full-duplex mode.
briansmith

briansmith

0

The default behavior of Rustls (any crate) must not change based on whether or not a feature flag is enabled. In response to a feature flag being enabled, we may only make additional APIs to enable different/additional functionality if that API is used. In particular, a library using Rustls has no control over whether a different library or the application using the library has enabled a feature or not.

This has come up a few times:

  • People have asked for SSLKEYLOGFILE functionality to be enabled by default if a feature flag is enabled.
  • #709 asks for webpki-roots to be enabled by default if a feature flag is enabled.

We should document this in our design documentation so we can easily refer to it in one place, instead of debating it over and over.

briansmith

briansmith

0

The ExpectTraffic state has a field want_write_key_update that remembers whether we received a key update message where the peer requested we update our write key. IIUC, the want_write_key_update field is not read until the next time we try to encrypt some data and send it. If it is a long time before we attempt to send data, then the old write key will live for a long time. This is counter to the goal of the key update feature.

Instead, as I mentioned in https://github.com/rustls/rustls/issues/288#issuecomment-1014093501, we should instead do something like this rough sketch:

  • Replace want_write_key_update: bool with enqueued_key_update_message: Vec<u8>.
  • When we receive a request to update our write key, and enqueued_key_update_message is non-empty, then do nothing.
  • When we receive a request to update our write key, and enqueued_key_update_message is empty, immediately format and encrypt the key update message we'd need to send, and store it in enqueued_key_update_message. Then immediately update the write key and the key schedule.
  • When sending data, where we check want_write_key_update, instead check if enqueued_key_update_message is non-empty. If it is non-empty, then send that enqueued message and reset it to empty, before trying to send any more data.
  • When the application checks whether we have anything to send, consider enqueued_key_update_message. We need to send the key update message eagerly so that the peer can update its receive key in a timely fashion.

Additionally, when sending an alert (whether close_notify or an error), we should either update or throw away the write key and write part of the key schedule, as they are no longer needed, and having them around is bad. Similarly, when we receive a close_notify from the peer, we should throw away the receive key and read part of the key schedule. We might consider doing these in follow-ups.

briansmith

briansmith

next-major-release
2

Currently we have these error variants intended to be used for certificate errors:

When implementing custom certificate verifiers we've found that we're often just returning InvalidCertificateData or else we're doing wasted work to return one of the other variants.

It seems like the distinction between these five variants is primarily driven by the desire of BOGO to differentiate between different types of errors. But, if that is the case then it would be good to find a way to limit this classification to just BogoShim and not require every implementation to do this classification. In some implementations it isn't clear that we even can accurately classify the errors returned by the underlying certificate verification library into the above.

If we implement my suggestion in #930, then we can have BogoShim do the mapping from webpki::Error to the five categories above, and save other implementations the trouble.

Information - Updated May 14, 2022

Stars: 3.4K
Forks: 368
Issues: 129

Repositories & Extras

A (mostly) pure-Rust implementation of various common cryptographic algorithms

Rust-Crypto seeks to create practical, auditable, pure-Rust implementations of common cryptographic

A (mostly) pure-Rust implementation of various common cryptographic algorithms

Orion is a cryptography library written in pure Rust

It aims to provide easy and usable crypto while trying to minimize the use of unsafe code

Orion is a cryptography library written in pure Rust

Rustls is a modern TLS library written in Rust

ring for cryptography and rustls-pemfile crate

Rustls is a modern TLS library written in Rust

Mundane is a Rust cryptography library backed by BoringSSL that is difficult

to misuse, ergonomic, and performant (in that order)

Mundane is a Rust cryptography library backed by BoringSSL that is difficult

A (mostly) pure-Rust implementation of various common cryptographic algorithms

Rust-Crypto seeks to create practical, auditable, pure-Rust implementations of common cryptographic

A (mostly) pure-Rust implementation of various common cryptographic algorithms

This repository holds a Rust port of Google's Tink cryptography library

This repository holds a Rust port of Google's RustCrypto crates – this repo focuses on making

This repository holds a Rust port of Google's Tink cryptography library

A cryptography library that is mainly implemented in Rust

I aim to implement bindings to other languages such as C/C++ and Python

A cryptography library that is mainly implemented in Rust

Libsm is an open source pure rust library of China Cryptographic Algorithm Standards

It is completed by a collaborative effort between the Cryptape Technology LLC

Libsm is an open source pure rust library of China Cryptographic Algorithm Standards

Cryptographic algorithms in pure Rust

The main interface to these crates is the RustCrypto traits

Cryptographic algorithms in pure Rust

A collection of cryptography functions written in Rust

rustup -- curl --proto '=https' --tlsv1

A collection of cryptography functions written in Rust
Facebook Instagram Twitter GitHub Dribbble
Privacy