On Thu, Jul 9, 2026 at 12:45 AM Viktor Dukhovni <[email protected]> wrote:
> On Wed, Jul 08, 2026 at 04:21:22PM -0400, David Benjamin wrote: > > > I think you're interpreting it right. If the cipher suite does not > exactly > > match what you end up negotiating, you cannot accept early data. > > > > > With the 0-RTT keys independent of the 1-RTT keys, why must the full > > > 0-RTT cipher suite match the 1-RTT cipher suite that comes into effect > > > only later? > > > > The unhelpful answer is "because the spec said so". But that is > unhelpful. > > :-) > > Thanks. Given recent discussion around SSLKEYLOGFILE, I guess I might > note that if the early data algorithm (not just the key) could be > different from the 1-RTT algorithm, then the SSLKEYLOGFILE would fail to > record that information... > > > More helpfully, I think the spec's choice is the right one. You're right > > that we *could* have defined it so that the cipher suite changes across > > 0-RTT and 1-RTT and it would (I think?) have been well-defined > > self-consistent at the TLS layer. > > Yes, that's the motivation for the question. > > > Likewise, we also *could* have said that ALPNs change at this > > transition or whatever else. The question is whether > > these are good semantics to present to the application layer. > > Well, the ALPN changing is a very different sort of problem. > Oh yeah, changing ALPN is definitely much, much more dire. This was mostly to illustrate that the main concern is how you expose it to the application, not its impact on TLS's consistency. That is, looking *just* at TLS, there's no actual *problem* if ALPN changes. It's just some random byte string we stash alongside the connection. Of course, it's a nightmare for the application layer. But that means the considerations for ALPN and cipher suite changes are similar in kind, though not in degree. Horrifyingly, ALPN actually *was* originally defined to change in TLS 1.2! RFC 7301 specifically allows ALPN to change on renegotiation. https://www.rfc-editor.org/rfc/rfc7301.html#:~:text=until%0A%20%20%20renegotiated (This seems completely insane to me and I doubt any application actually handles an ALPN changing like that. Looks like our implementation opts to not offer ALPN on renegotiation handshakes and just treats ALPN as a first-handshake-only property. Fortunately this is largely moot because ALPN is primarily used for H2 and H2 forbids renegotiation.) > > *If* we said that the cipher suite changes, it would mean that the > > connection properties change partway through the lifetime of the > > connection. > > > > This breaks an invariant[*] of a TLS connection's lifecycle: > > 1. First you set up the connection. > > 2. Now connection properties are set and you can query ALPN, version, > > cipher suite, certificate, whatever else. > > 3. Read and write data as you wish. > > Or the library could simply hide the 0-RTT cipher from the application > and report the 1-RTT cipher consistently, but I guess that's not the > sort of thing that folks would be comfortable with, and in any case the > specification requires the cipher to not change. > It actually can't easily be hidden on the client side. Consider a client that has sent out a 0-RTT ClientHello but has yet to get the ServerHello. The connection is now in state where it is writable, but the 1-RTT cipher is not known yet. That means your choices are: - Break an invariant: Previously, once the connection is writable, connection properties are established. Now the cipher suite is unavailable. - Break a different invariant: Previously, once a connection property was established, it wouldn't change. Now it might change from the 0-RTT cipher to the 1-RTT cipher. - Constrain the protocol: Lock the 0-RTT and 1-RTT ciphers to match[*], limiting the kinds of flows that are possible, but preserving some invariants application developers may be relying on. [*] On 0-RTT accept. 0-RTT reject is a very different beast, but kinda of unavoidably so because all the application data is unwritten anyway. IMO the right way to model 0-RTT reject is that your initial logical connection got terminated and you have a new logical connection... which happens to share the same underlying transport. It's a thorny thing to juggle regardless, but it helps with this invariants situation, and also helps answer questions like "what happens if you 0-RTT an h2 connection, multiplex three requests in early data, but 0-RTT reject turns it into an h1 connection which now cannot multiplex"... > > The cipher suite, sure, is less dire. But maybe your protocol has the > > client send something cipher-suite-dependent and then the server responds > > with something cipher-suite-dependent. > > Well, the 0-RTT cipher is not nearly as important as the subsequent > 1-RTT cipher, it is for low-value data that might be subject to replay, > say a DNS query, with the response in a propertly secured 1-RTT payload. > > So the "more relevant" cipher to report is the 1-RTT cipher, and the > 0-RTT cipher is rather secondary. Speaking hypothetically, of course. > Since I won't actually ignore the specification. > > > Since you already have to make predictions on other fields like ALPN, > doing > > that for cipher suites seems not much of a price to pay for this sanity. > > Well, the ALPN is much less likely to be mispredicted. Especially when > it isn't one of multiple HTTP flavours, but something else entirely. > That's true. TLS version is perhaps a better analog. That's also easier to predict than cipher suite, especially right now when TLS 1.4 doesn't exist, but it's again dipping into the TLS layer. > > Plus the prediction is easy for resumption: it's the cipher suite you got > > on the original connection. I recognize that's not true for PSKs, but > I'll > > note that if your PSKs are longer-lived and broader-scoped than > resumption > > secrets doing 0-RTT (no forward secrecy) with them is probably not the > best > > plan anyway. > > So in particular, I expect that "imported" RFC9258 PSKs, that are by > design cipher (and KDF) agnostic (polymorphic), should NOT be used > with 0-RTT. An RFC9258 PSK is not a prediction of the cipher, and > which imported KDF happens to land first on the wire is not even > something that the application providing the input external PSK > should depend on. > > Would you concur that an RFC9258 "ipsk" landing in slot 0 should not > be used for 0-RTT? Even if the client tries to send early data with > an "ipsk", I'm inclined to unconditionally decline that early data. > Yeah, our RFC 9258 implementation just doesn't do early data. I see RFC 9258 does actually allow it though: https://www.rfc-editor.org/rfc/rfc9258.html#section-5.1-13 I guess, *if* you wanted to allow it to do early data, you'd do something like: - Associate a predicted ALPN, version, cipher suite, etc., with an EPSK - That prediction determines an IPSK. Put that IPSK first. (I am still a little sad RFC 9258 ended up expanding each EPSK into multiple IPSKs. It's kind of a nuisance.) But I think it's reasonable for an implementation to say "nah, I'm not (yet) going to support it" and: - As a client, never offer 0-RTT with EPSKs - As a server, always decline 0-RTT with EPSKs This is perfectly interoperable because you're always allowed to decline 0-RTT. David
_______________________________________________ TLS mailing list -- [email protected] To unsubscribe send an email to [email protected]
