Why does a full TLS 1.3 handshake cost one round trip where a full TLS 1.2 handshake costs two?
answer
- count the flights, not the messages
- 1.2 sets up, then exchanges
- 1.3 guesses in the first flight
- a wrong guess costs one retry
- the retried hello is folded into the transcript
basics
~20 sTLS 1.3 has the client send its key-exchange contribution with the ClientHello, so the server can derive keys and send its entire flight, identity and Finished included, in one response. TLS 1.2 needs a second exchange before either side can protect anything.
solid answer
~40 sIn TLS 1.2 the server's first flight — `ServerHello`, the certificate, `ServerKeyExchange` where the suite needs one, and `ServerHelloDone` — only *sets up* the exchange. The client must then answer with `ClientKeyExchange`, a `ChangeCipherSpec` record and `Finished`, and wait for the server's own `ChangeCipherSpec` and `Finished` before it may write a request: two round trips. TLS 1.3 moves the client's key-exchange contribution into the `ClientHello` itself, so the server can derive keys the moment it has chosen the parameters and send everything from `ServerHello` through its `Finished` in one flight. The client answers with `Finished` and application data together, so the first ticket request goes out after one round trip.
code
pseudocode · 15 linesTLS 1.2, full handshake
client -> server : ClientHello
server -> client : ServerHello, Certificate,
ServerKeyExchange, ServerHelloDone
client -> server : ClientKeyExchange, ChangeCipherSpec, Finished
server -> client : ChangeCipherSpec, Finished
client -> server : application data (2 round trips)
TLS 1.3, full handshake
client -> server : ClientHello
server -> client : ServerHello, {EncryptedExtensions},
{Certificate}, {CertificateVerify}, {Finished}
client -> server : {Finished}, application data (1 round trip)
{ } = protected under the handshake traffic keysgo deeper
Remember the headline: a fresh TLS 1.3 handshake costs one round trip and a fresh TLS 1.2 handshake costs two, and the reason is where in the exchange the client's key-exchange contribution is sent.
Walk both flights out loud, naming ServerHelloDone as the 1.2 flight terminator and the 1.3 server flight ending at Finished. Explain that the client predicts parameters in its first message, and what happens when that prediction misses.
Put numbers on it for a real path: one round trip saved on every new connection, multiplied by connection churn. Then note the diagnostic cost, because most of a 1.3 handshake is opaque in a capture in a way a 1.2 one was not.
Treat it as a latency budget question across the estate. Which clients reconnect constantly, what their path latency is, and what a retry rate above the expected floor would be telling you about a parameter mismatch between fleets.
## The two shapes, side by side The round-trip difference is not an optimisation of the same exchange; it is a different flight structure. What changed is **when the client commits to a key-exchange contribution**. **TLS 1.2, full handshake** 1. Client sends `ClientHello`. 2. Server sends `ServerHello`, its certificate, a `ServerKeyExchange` where the negotiated suite requires one, and `ServerHelloDone` to say its flight is finished. 3. Client sends `ClientKeyExchange`, then a `ChangeCipherSpec` record, then `Finished`. 4. Server sends its own `ChangeCipherSpec` and `Finished`. 5. Only now may the client send a request. That is two full round trips before the first application byte, on top of whatever the transport underneath already cost. **TLS 1.3, full handshake** 1. Client sends `ClientHello` **carrying its key-exchange contribution already**. 2. Server replies with `ServerHello`, then — protected — `EncryptedExtensions`, its certificate, a signature over the transcript, and `Finished`. 3. Client sends `Finished` and application data in the same flight. One round trip. ## Why the client can guess The client does not know which parameters the server will choose, so it *predicts*: it sends a contribution for the exchange it thinks the server will accept, alongside the lists it is offering. If the prediction is right — which it is for the overwhelming majority of connections, because clients predict the option servers overwhelmingly deploy — the server derives keys immediately on receipt and never has to ask for anything. If the prediction is wrong, the server answers with **`HelloRetryRequest`**, and the client sends a second `ClientHello`. That costs exactly one extra round trip, putting the handshake back at the two round trips TLS 1.2 always paid. It is not a restart: the transport connection stays up, and the retry is part of the same handshake. ## What a retry does to the transcript A retried handshake has to keep the property that both sides can prove they saw the same messages, including the first `ClientHello` that was rejected. TLS 1.3 handles this by replacing the first `ClientHello` in the transcript with a short synthetic message of type `message_hash(254)` whose body is the hash of that message. Both sides do this identically, so the transcript stays a single well-defined sequence and `Finished` still covers everything — including the fact that a retry happened at all, which is what stops an attacker from injecting or removing one. ## Comparison | | TLS 1.2 full | TLS 1.3 full | TLS 1.3 with retry | |---|---|---|---| | Round trips before client data | 2 | 1 | 2 | | Client key-exchange contribution sent | second flight | first flight | first and second flight | | Server flight ends with | `ServerHelloDone` | `Finished` | `HelloRetryRequest`, then `Finished` | | Handshake messages protected | only `Finished` | everything after `ServerHello` | everything after the second `ServerHello` | ## Why it matters operationally For a ticketing gateway whose clients are phone handsets on mobile networks, a round trip is not a rounding error: on a path with 80 ms of latency, removing one removes 80 ms from *every* new connection, and connections are created constantly as clients come and go. That is the practical reason the flight shape is worth knowing rather than a specification curiosity. It also changes what a packet trace looks like. In a 1.2 trace you can see the certificate, the selected extension answers and the whole negotiation. In a 1.3 trace the server's response after `ServerHello` is opaque, so "the handshake failed somewhere in the server's flight" is as far as an observer gets without the keys. When a gateway is upgraded from one to the other, the same failure produces visibly less evidence, and teams are often surprised by that. ## Version note Everything above describes handshakes that establish a fresh exchange. Handshakes that reuse previously established keying material have their own shorter shapes and their own costs, and are a separate mechanism from the flight structure described here.
- What does a TLS 1.3 HelloRetryRequest cost, and what happens to the first ClientHello?It costs one extra round trip: the client sends a second `ClientHello` and the server then sends its ordinary flight. The transport connection is not restarted. The first `ClientHello` is not simply forgotten either — it is replaced in the handshake transcript by a synthetic `message_hash(254)` message carrying its hash, so `Finished` still covers the fact that a retry happened.
- Which TLS 1.2 message tells the client the server has nothing further to send in its first flight?`ServerHelloDone`. TLS 1.2 flights are variable — a certificate request and a `ServerKeyExchange` may or may not be present — so the flight needs an explicit terminator. TLS 1.3 has no equivalent, because the server's flight always ends with its `Finished`.
- Does the server also wait a round trip before it can write application data in TLS 1.3?No. Once it has sent its own `Finished` it may write immediately, half a round trip before the client's `Finished` arrives. The trade is that it is writing before it has confirmed the client completed the exchange, so whether that is acceptable depends on what is being written.
saying these in an interview costs you the question
- Says TLS 1.3 is faster because it uses faster ciphers
- Thinks HelloRetryRequest restarts the whole connection
- Believes ServerHelloDone exists in TLS 1.3 as well
- Counts messages instead of flights when estimating cost
- Assumes the client's first flight cannot carry key-exchange material