rustls / rustls-openssl-compat

OpenSSL compatibility layers
32 stars 2 forks source link

Client session caching support is minimal #18

Open ctz opened 2 months ago

ctz commented 2 months ago

At the moment client-side session caching only respects SSL_CTX_sess_set_cache_size, but not the cache mode, callbacks, SSL_get_session etc.

Meaningfully implementing SSL_get_session would mean rustls client sessions would need to become serialisable -- they currently are not.

cpu commented 3 weeks ago

I was looking at adding Ubuntu 24.04 to the CI matrix now that runner images are available (see https://github.com/rustls/rustls-openssl-compat/pull/20 for some discussion) and noticed the runner.rs nginx test fails on 24.40 with Nginx 1.24.0 because the /ssl-was-reused endpoint always returns ..

Here are some notes on the root cause - the TL;DR (and why I'm commenting here) is that I believe we need to implement the session ticket callback functionality to make 1.24.0 have working session resumption.

Reproducing locally it's pretty obvious why the resumption test is failing as nginx 1.24.0 logs this at startup:

2024/06/11 14:24:46 [warn] 2922744#2922744: nginx was built with Session Tickets support, however, now it is linked dynamically to an OpenSSL library which has no tlsext support, therefore Session Tickets are not available

That in turn seems to be emitted in ngx_event_openssl.c when SSL_CTX_set_tlsext_ticket_key_cb fails. Both that function (deprecated) and the replacement SSL_CTX_set_tlsext_ticket_key_evp_cb are #define's that expand to calls to SSL_CTX_callback_ctrl with cmd == SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB.

In both cases the callback has the signature:

    int (*cb)(SSL *s, unsigned char key_name[16],
              unsigned char iv[EVP_MAX_IV_LENGTH],
              EVP_CIPHER_CTX *ctx, EVP_MAC_CTX *hctx, int enc))

We have some experience implementing cmd's off of the SSL_CTX_callback_ctrl entry point (presently just SslCtrl::SetTlsExtServerNameCallback) but this callback also needs initialized EVP_CIPHER_CTX and EVP_MAC_CTX arguments. Should these be modeled similar to EVP_PKEY?

ctz commented 2 weeks ago

I think this issue is mostly about client-side session caching, so probably shouldn't have much bearing on nginx.

I wonder what happens if we accept the SSL_CTX_set_tlsext_ticket_key_cb but never call the callback?

To get this fully working we'd need to implement the rustls ProducesTickets trait in terms of calling the callback, then using the returned cipher and mac keys to implement the RFC5077 "recommended" construction which AIUI the openssl API is tightly coupled to.

cpu commented 2 weeks ago

I think this issue is mostly about client-side session caching, so probably shouldn't have much bearing on nginx.

Oops yes, you're right :-) I will pull the relevant comments into a new issue.

I wonder what happens if we accept the SSL_CTX_set_tlsext_ticket_key_cb but never call the callback?

I actually went down this rabbit hole a bit yesterday. I think it's workable after re-reading the SSL_CTX_set_tlsext_ticket_key_cb man page (and fixing some broken english in it...) and the nginx callback. It feels like the correct route is to use our own fully-fledged ticketer instead of trying to do it the OpenSSL way.

I tried this and I expected this to Just Work but found that for some reason the ticketer I constructed with the provider and stuck in the server config was always failing to decrypt the ticket curl was giving back. I took a pcap and also added some logging and the issued ticket ciphertext exactly matched the to-be-decrypted ciphertext read back from the client. It looked like the unseal-in-place operation was producing an opaque Unspecified error. I'm not sure what the root issue is.

I'm going to finish up the config surface and then I will return to this rabbit hole. Theories+advice welcome!

cpu commented 2 weeks ago

I will pull the relevant comments into a new issue.

https://github.com/rustls/rustls-openssl-compat/issues/30