QUIC Crypto and simple state machines
posted 2 weeks ago
If you don't know about QUIC, go read the excellent Cloudflare post about it. If you're lazy, just think about it as:
- Google wanted to improve TCP (2.0™️)
- but TCP can't really be changed
- so they built it on top of UDP (which is just IP with ports, check the 2 page RFC for UDP if you don't believe me)
- they made it with encryption by default
- and they called it QUIC, because it's quick, you know
There is more to it, it makes HTTP blazing fast with multiplexed streams and all, but I'm only interested about the crypto here.
Google QUIC's (or gQUIC) default encryption was provided by a home-made crypto protocol called QUIC Crypto. The thing is documented in a 14-page doc file and is more or less up-to-date. It was at some point agreed that things needed to get standardized, and thus the process of making QUIC an RFC (or RFCs) began.
Unfortunately QUIC Crypto did not make it and the IETF decided to replace it with TLS 1.3 for diverse reasons.
Why "Unfortunately" do you ask?
Well, as Adam Langley puts it in some of his slides. The protocol was dead simple:
While the protocol had some flaws, in the end, it was still a beautiful and elegant protocol. At its core was an extremely straight forward and linear state machine summed up by this diagram:
A few things to help you read it:
- a server config is just a blob that contains the server current semi-ephemeral keys. The server config is rotated every X days.
- an inchoate client hello is just an empty client hello, which prompts the server to send a REJ(ect) message containing its latest config (after that the client can try again with a full client hello)
- SHLO is a (encrypted) server hello which contains ephemeral keys
As you can see there isn't much going on, if you know the keys of the server you can do some 0-RTT magic, if you don't then request the keys and start the handshake again.
Compare that to the state machine of TLS 1.3:
In the end, TLS 1.3 is a solid protocol, but I'd like to see more experimentation here instead of just relying on TLS. version 1.3 is built on top of numerous previous failed versions which means a great amount of complexity due to legacy and a multitude of use cases and extensions it needs to support. Simpler protocols should be better, simple state machines make for better analysis and more secure implementations. Just look at the Noise protocol framework and its 1k LOC implementations and its symbolic proofs done with ProVerif and Tamarin. Actually, why haven't we started using Noise for everything?