Support for session resumption using RFC5077 session ticket (TlsClient only)
Obtaining a Session Ticket
C -> S: Client Hello (empty SessionTicket ext) C <- S: Server Hello (empty SessionTicket ext) C <- S: Certificate C <- S: Server Hello Done C -> S: Client Key Exchange C -> S: ChangeCipherSpec C -> S: Finished C <- S: NewSessionTicket //client should store this ticket as ticketA C <- S: ChangeCipherSpec C <- S: Finished
Using a session ticket
C -> S: Client Hello (SessionTicket ext = ticketA; session id not set) C <- S: Server Hello (empty SessionTicket ext) C <- S: ChangeCipherSpec C <- S: Finished C -> S: ChangeCipherSpec C -> S: Finished
For session resumption using session ids (i.e., without using session tickets), there are two methods in TlsClient and AbstractTlsPeer to allow you to store and reuse TLSSession: notifyHandshakeComplete() and getSessionToResume(). In contrast, for session resumption using session tickets, there is only one method in TLSClient called notifyNewSessionTicket(NewSessionTicket newSessionTicket) to store the session ticket given by the server. I don't see a method to use the session ticket for session resumption.
To resume a TLS session with a ticket, the RFC says:
"The client caches this ticket along with the master secret and other parameters associated with the current session. When the client wishes to resume the session, it includes the ticket in the SessionTicket extension within the ClientHello message."
Summary of changes
All class references below are in package org.bouncycastle.crypto.tls.
- TlsClient
- added 2 new abstract methods: NewSessionTicket getNewSessionTicket() and SecurityParameters getSecurityParameters()
- modified notifyNewSessionTicket() method and added a parameter to pass in SecurityParameters. Note that this breaks backwards compatibility but I assume there aren't many implementations of the TLSClient interface given that BC didn't fully support session tickets. Perhaps we could refractor the session resumption stuff out in to an interface called "SessionResumable" or something like that. Need some guidance here.
- AbstractTlsClient
- updated to implement the new TlsClient
- NewSessionTicket
- added a new method to encode the ticket without the lifetime. This was added when resuming a session using a session ticket from server (I was using nginx/openssl for testing).
- SecurityParameters
- added a new method to copy parameters safely (to pass to the TlsClient)
- TlsClientProtocol
- this is where most of important changes are!
- resume session if the TlsClient has a session ticket (in client hello)
- notify TlsClient if the server sends a session ticket so that the client can store for later use
- DTlsClientProtocol
- I don't know much about DTLS. I took an initial stab at making it support session resumption but I need someone to take over.
- TlsExtensionUtils
- new session ticket extension
- MockTlsClient
- reference implementation of TlsClient that can resume sessions using tickets
- TlsClientTest
- shows how to use the MockTlsClient
I did system testing with nginx. No special config needed. This is what I have:
server { listen 1443 ssl; server_name _;
ssl_certificate cert.pem;
ssl_certificate_key keyNoPassphrase.pem;
ssl_session_cache shared:SSL:10m;
...
}
I didn't write any unit tests because I need a TLS server that can issue session resumption. Please do let me know if you can think of ways to unit-test my changes.
I do have pcaps but I can't attach them here without masking the IPs.
Please note that I've never contributed to BC so I don't know what the process is. Please feel free to educate me. :)
Hi. This PR has been open for almost a year. Is there something I can do to get this PR accepted? Thank you, Parthy
I would like to see this one making it into the bouncycastle provider Why is it stuck? Rgds Lars