We currently allow 0-RTT with Semi-static DH, with PSK resumption, and with pure PSK. Whether or not we keep all of these, it would be good to clean up the protocol design so that both the client and server have a uniform way of signaling their preferences.
After implementing and analyzing TLS 1.3, here are a few suggestions for discussion. 1) Early Data Extension The current early-data extension is too DH-specific. When using PSK, we now have to look at both early_data and pre_shared extensions. I suggest reusing the same extension for both, with the following interpretation: struct { select (Role) { case client: opaque id<1..2^16-1>; opaque context<0..255>; CipherSuite cipher_suite; Extension extensions<0..2^16-1>; case server: struct {}; } } EarlyDataIndication; In the semi-static DH case: - id is the configuration id - context is the hash of the ServerConfiguration + Server Certificate + CertificateRequest In the PSK resumption case: - id is the session ticket - context is a *public* value unique to the derived session. For example, it could be defined as the session hash of the original handshake, or it could be derived by the client as HKDF(RMS, “early data context”) In the pure PSK case - id is the PSK identifier - context is unique to the PSK and its allowed use. For example, it can be generated (out-of-band) as HKDF(PSK, “early data context”) 2) New Session Ticket The NewSessionTicket message needs to indicate whether the server will accept 0-RTT, and what ciphersuites it is willing to accept (e.g. pure PSK resumption vs only PSK-ECDHE). I suggest the following modification to this message: struct { uint32 ticket_lifetime; opaque ticket<0..2^16-1>; CipherSuite cipher_suites<2..2^16-2>; EarlyDataType early_data_type } NewSessionTicket; enum { no_early_data_allowed(0), replayable_early_data_allowed (1), all_early_data_allowed(2), (65535) } EarlyDataType; The interpretation of the early_data_type field is that the server is either: (a) unwilling to accept 0-RTT (no_early_data_allowed), (b) willing to accept 0-RTT, but it has no replay cache (replayable_early_data_allowed), (c) willing to accept 0-RTT and has a replay cache that it uses to prevent replay (all_early_data_allowed) The client’s response to this ticket message should be to store it in its session along with the “context” (session hash or derived from RMS), the allowed cipher suites, and the early_data_indication. When resuming with this ticket: - the client should not send any 0-RTT data if no_early_data_allowed - the client should only send replayable data if replayable_early_data_allowed (e.g. GET requests) - the client can send any 0-RTT data if all_early_data_allowed, trusting the server to do the right thing. A note on replay ---------------------- There has been much discussion on 0-RTT replay and here’s a quick summary of my understanding. We already knew that an active attacker, or a lossy network, or an overzealous web browser could and would cause 0-RTT (and even 1-RTT) data to be replayed to the server. This can already happen in TLS 1.2, in QUIC, and so we accepted it as a given in TLS 1.3. The new concerns on the mailing list (and in my TRON talk which was based on a ProVerif model) are that unlike TLS 1.2: (a) even a passive attacker could replay 0-RTT data, long after the client has gone away, (b) replaying authenticated 0-RTT data can be more damaging (whether authenticated with client cert or with a cookie), and (c) by replaying 0-RTT data, the attacker can obtain encrypted 0.5-RTT data which opens up new attack vectors. As a result of these new concerns, I would say that TLS 1.3 should recommend that all servers SHOULD implement a replay cache, and those that cannot should clearly signal this to the client, so that the client can adjust its 0-RTT use case and its expectations accordingly. A note on authenticating the 0-RTT “context” ---------------------------------------------------------- When trying to figure out how to authenticate 0-RTT DH mode in an earlier draft, we came upon the design of signing the Handshake Context that consists of the ClientHello + additional information from the previous handshake. This construction prevents 0-RTT authentication from unknown key share attacks. Even if we eliminate client certificate authentication from 0-RTT, this notion of “context" is still useful for two reasons: (a) the application may use TokenBinding or some such protocol to authenticate 0-RTT data, and we need to understand what “channel binding” to provide for this case, (b) in PSK resumption mode, since the handshake log does not contain much information that is specific to the previous connection, it would be more robust to add an explicit context. If we accept the definition of “context” in the EarlyDataIndication extension, then we can use the hash of the ClientHello uniformly in all 0-RTT modes for deriving keys, and for deriving a channel binding for the application. Furthermore, we can safely introduce a PSK_ECDHE mode where the server sends its Certificate and CertificateVerify and its signature is correctly bound to the PSK (via the “context” field). Best regards, Karthik _______________________________________________ TLS mailing list TLS@ietf.org https://www.ietf.org/mailman/listinfo/tls