I was looking at the recent Internet drafts for the QUIC transport protocol (transport and TLS), and wondered how that could be implemented in Java (or another JVM language), assuming I don't want to reimplement TLS 1.3 at the same time.
TLS is usually based on TCP (or some other protocol with similar service), with two layers in TLS itself:
+--------------+--------------+--------------+
| Handshake | Alerts | Application |
| Layer | | Data |
| | | |
+--------------+--------------+--------------+
| |
| Record Layer |
| |
+--------------------------------------------+
| |
| TCP |
| |
+--------------------------------------------+
Diagram adapted from the internet draft, section 2.1
In Java, we can use the classes in javax.net.ssl to implement this, either using SSLEngine for just TLS without the I/O (application or a framework needs to plug in the networking, e.g. using NIO), or an SSLSocket (or SSLServerSocket) for TLS over TCP via usual InputStream/OutputStream blocking I/O.
QUIC uses only the handshake part of TLS 1.3 for negotiating the session keys, while using its own packet format and encryption ("Packet protection") instead of TLS' record layer (and the whole thing is based on UDP, not TCP):
+--------------+--------------+ +-------------+
| TLS | TLS | | QUIC |
| Handshake | Alerts | | Applications|
| | | | (h2q, etc.) |
+--------------+--------------+-+-------------+
| |
| QUIC Transport |
| (streams, reliability, congestion, etc.) |
| |
+---------------------------------------------+
| |
| QUIC Packet Protection |
| |
+---------------------------------------------+
| |
| UDP |
| |
+---------------------------------------------+
Diagram adapted from the internet draft, section 3
So now my problem: The given TLS implementations (from Java 11 we have TLS 1.3 included) have only TLS in a box, i.e. record + handshake + alerts together, not a handshake only version. SSLEngine seems to come nearest, but it still has just two wrap
and unwrap
methods which create/read ciphertext and read/produce plain text (though I might be able to do just the handshake without transferring any actual data).
Is there an easy way to strip off the record layer? Or is there a different implementation I could use?
I also would need to get the actual keys (or rather, the master secret) out of it.