I have a very simple httpd-setup with SSLSessionCache directive set so that sessions are available also after a graceful restart (in shared memory).
I then connect to the server with openssl s_client and the -sess_out parameter so i have a sessionfile.
Next step is to gracefully restart apache.
Then after that, connect again with openssl s_client this time using the sessionfile with the -sess_in parameter.
This works perfectly with TLSv1.2.
But with TLSv1.3 mod_ssl somehow falls back to a full handshake. SSL_session_reused() returns false. If i do exactly the same test, but don't gracefully restart between the requests, it works and SSL_session_reused() returns true.
We can see this also if we trace ssl messages:
without a graceful restart (correct behavior)
CLT0-0 send: Version: TLS 1.3 (772) Length: 512 Content-Type: Handshake (22) Message-Type: ClientHello (1) CLT0-0 receive: Version: TLS 1.3 (772) Length: 128 Content-Type: Handshake (22) Message-Type: ServerHello (2) Server extension (43): supported versions Server extension (51): key share Server extension (41): pre shared key CLT0-0 receive: Version: TLS 1.3 (772) Length: 6 Content-Type: Handshake (22) Message-Type: EncryptedExtensions (8) CLT0-0 receive: Version: TLS 1.3 (772) Length: 52 Content-Type: Handshake (22) Message-Type: Finished (20) CLT0-0 send: Version: TLS 1.3 (772) Length: 1 Content-Type: ChangeCipherSpec (20) CLT0-0 send: Version: TLS 1.3 (772) Length: 52 Content-Type: Handshake (22) Message-Type: Finished (20)
Here we see the client sends the "pre shared key" extension in his ClientHello. The Server responds then with his ServerHello which also contains the pre shared key extension and continues directly with the EncryptedExtensions and a Finish message. No Certificate and CertificateVerify message...
with a graceful restart (wrong behavior)
CLT0-0 send: Version: TLS 1.3 (772) Length: 512 Content-Type: Handshake (22) Message-Type: ClientHello (1) CLT0-0 receive: Version: TLS 1.3 (772) Length: 122 Content-Type: Handshake (22) Message-Type: ServerHello (2) Server extension (43): supported versions Server extension (51): key share CLT0-0 receive: Version: TLS 1.3 (772) Length: 6 Content-Type: Handshake (22) Message-Type: EncryptedExtensions (8) CLT0-0 receive: Version: TLS 1.3 (772) Length: 1738 Content-Type: Handshake (22) Message-Type: Certificate (11) CLT0-0 receive: Version: TLS 1.3 (772) Length: 264 Content-Type: Handshake (22) Message-Type: CertificateVerify (15) CLT0-0 receive: Version: TLS 1.3 (772) Length: 52 Content-Type: Handshake (22) Message-Type: Finished (20) CLT0-0 send: Version: TLS 1.3 (772) Length: 1 Content-Type: ChangeCipherSpec (20) CLT0-0 send: Version: TLS 1.3 (772) Length: 52 Content-Type: Handshake (22) Message-Type: Finished (20)
The client sends the same. But the Server responds then with his ServerHello which does NOT contain the "pre shared key" extension. Then a Certificate and CertificateVerify message as in the initial 1st handshake...
Also i see strange behavior related to the OpenSSL callbacks that mod_ssl registers:
mod_ssl registers all callbacks for adding, removing and getting a session (https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_sess_set_get_cb.html). The ssl-options, so that openssl doesn't use its internal cache are correctly set as well. But now with TLSv1.3 i never ever fall into the "get session"-callback, but always into the "new session" callback, even in the scenarion where i leave the graceful restart and SSL_session_reused returns true. I've had a look at the openssl code and indeed, in TLSv1.3 this callback never gets invoked. so i wonder if this might be a cause of incorrect behavior...
I think this is a very common use-case ("Allow to resume ssl-sessions after graceful restart") and should work with TLSv1.3 as it does with 1.2.
Any help is much appreciated!
UPDATE
This seems to be related to the SSLSessionTickets directive. With "SSLSessionTickets off" resumption works. If SessionTickets are enabled it doesn't work.