Original text:
A small allowance for errors in clocks and variations in measurements is advisable.  However, any allowance also increases the opportunity <del> for replay.  In this case, it is better to reject early data than to risk greater exposure to replay attacks. </del>  4.2.7.

Reviewer comments:
Just saying "small allowance" is not very clear, so supply some concrete text with an arbitrarily selected value for discussion. Some (but not much) previous discussion in the vicinity of URL
See also issue
Not sure that tens of seconds is good advice. It's certainly larger than I had imagined for a general purpose server. If we accept that clock drift is in the order of seconds per day, then single-digit seconds is probably OK. You don't need to have a high rate of 0-RTT success toward the end of the ticket validity period (1 week), you only need to ensure that most users get 0-RTT if they come back a short time (measured in hours) after the initial session.
The reference point was the 15 seconds that Ilari had used (but still seemed large to me). It is still unclear to me what metric we actually want to use to bound the replay window (i.e., whether it is guided by clock rate skew, RTT, absolute time, or something else), so this text is mostly just a discussion starter. Is one second too small?
I updated the text some (and rebased); hopefully it is an improvement.
Copying here so they don't get lost. On Mon, Jul 11, 2016 at 12:08:00PM -0700, Eric Rescorla wrote: Did a readthrough, here's a bunch of comments (didn't check the issues list): One should note that it is not clear what sort of continuity properties should be provoded: Certificate valid for hostname The same key as in last time The same certificate as in last time The last choice obviously limits lifetime of derived PSK to the parent certificate. Also, extension matching is quite different between those three (and the last two are rather different from the current rules, tuned for 0-RTT only being used with PSK. Well, I think the DH parameters are gone, but DH public keys are still there, and those AFAIK are padded with zeroes. Should the "ServerHello" be "HelloRetryRequest"? Also, adding cookie extension if that was present in HRR? BTW, with the earlydata context and cross-connection cookies gone, I have figured out how to delta-compress the first clienthello and its rejection against to-be-sent second client hello plus connection parameters server selected into 6 bytes(!) of space (not including return-reachability check or MAC). Isn't this the true ciphersuite used on this connection, "resumption" or not? Otherwise you can get into all sorts of crazy situations that WILL be sources of implementation bugs. The idea that it isn't true ciphersuite brings me bad flashbacks about TLS 1.2 ticket "maybe resume" craziness (except this would be even worse). Hasn't earlydata just moved to EncryptedExtensions? What is written into this field if server selects pure-PSK ciphersuite and then decides to reject the ClientHello? Or connections that use pure-PSK just plain can't be rejected for any reason (including IP address verification in DTLS?) Currently assuming pure-PSK rejections are possible, ciphersuite is needed to tell if the next group field contains anything sane or not... What about cookie? IIRC, it is allowed to be in HRR even without being in CH... Again, rejections with cookie aren't spurious, and the cookie needs to be added. Cookie in HRR might not follow that.... I would say that it is a bad idea for any extension to do anything special with "resumption" without very good reasons. In fact, the only non-connection-control extension that is relevant for PSK I know is servername. Now, ALPN (connection-control by definition!) behaves specially with earlydata for darn good reasons (the ALP is locked). This is made worse by the fact that what consistutes "resumption" is not clearly defined (the ALPN rules are related to earlydata, not choosing PSK !). Also, for interoperability, any legal TLS 1.3 meaning of these algorithms must be extended to apply to TLS 1.2, even for TLS 1.2 ClientHello. Anything else would be pointless trap. This impiles that RSA PSS and EdDSA work in TLS 1.2 and also how those work. Also, even if meaning of the ECDSA codepoints changed, those would not break that rule, since new definition is strict subset of old. Are those supposed to be filtered to be subset of ones client advertised or not? E.g. if client didn't indicate support for x448, can the server still send x448? Doesn't seem to consistent with the other descriptions of this and presharedkey (those are just "MUST NOT select covered ciphersuite if missing"). Of course, in practice, it might be more this (at least that's how I would implement it)... Bit crazy algorithm: If you haven't heard of this server before, pick smallest you support, if you have, pick the one it selected the last time. The temporal ordering in messages is actually selecting different PSK and then rejecting 0-RTT. And the addition also prevents correlating session with its parent, even in case of reuse (this was the reason for switching to addition from XOR). Good luck with that... Also, requirement that the server MUST proceed with the handshake and reject 0-RTT if that validation fails would be good here... This does not talk about if endofearlydata alert is encrypted or not (obviously encrypted one won't work if server rejected 0-RTT, unless server trial-decrypts). Oh, still trial decryption... Got it. I think there was some proposal to dump the Finished. Would simplify implementation. In TLS, there is at least one appdata record with its MAC to be deprotected. That's not true in DTLS. However, even in DTLS, any wrong keys almost certainly cause handshake to immediately blow up as handshake keys won't match up... I don't think variations in clocks are minimal... I wonder what 95% timeskew interval per day is... (Oh, and have fun with leap seconds!) This seems inconsistent. In implementation, I would write explicit disjoint whitelists of extensions for both (and non-whitelisted one is a fatal error). Explicit whitelisting is safe even on client side, since the extensions are bounded by client-supported ones. How are multiple OIDs represented? Multiple EKU OID/value pairs? I think the certificate should be REQUIRED to match (as in, not be inconsistent with it) servername, even if not ACK'd. The exception on not having valid value can not work at all. With certificates, even if the EE cert is signed with unknown algorithm, there is a small chance things will work. In contrast, there is absolutely no chance of success if either endpoint tries ot use this fallback. Does this apply to in-handshake or post-handshake auth? I thought in-handshake auth with PSK is not possible. If it is intended to be possible, that's certainly going to be surprising to implementers, and there are probably going to be multiple implementations that outright choke if one tries to send CertificateRequest in (DHE-)PSK mode Later the document seems to imply that the limit for for content+type+ padding is in fact 16385 bytes. Maybe add requirement that record with sequence number of 2^64-1 MUST be either fatal alert or KeyUpdate. I would expand that 2^24.5 to some rough number ("about 24 million"?). And also "will wrap" -> "would wrap". Because such wrapping can't happen (even if endpoint delays KeyUpdate to RSN 2^64-1). This might cause fun with future key exchange types... I think this needs to be in ServerHello on server-side, given how low- level it is. These darn things use Supplemental Data messages, would need to define where the data goes. And one can't stick it to extension for usermapping and client_authz, because those are sent by the client, not the server. Isn't that "Client/HelloRetryRequest"? I don't think EncryptedExtensions can have Cookie... Should the two registeries shadowed by this closed? Isn't the RFC already published, so the codepoints are stable? This seems really obsolete. The timers have not been 18.2Hz for years, and applications running on operating systems damn better use OS services for random numbers, given that anything else is fraught with peril. Better to just nuke the code entierely for all versions. "Disabled" code has nasty tendency of coming back to life. The extensions field can't be omitted in TLS 1.3. And I would consider TLS 1.2 client implementations that send such messages as quite pathological. Also, ECDSA signing operations do have problems with timing attacks. Also, the lengths need to be correct (not verifying this leads to an attack). Best just to treat first length bytes >0x82 or >0x83 as malformed. There is no way to send legimate message with first length byte >0x83 in TLS. I think properties of the exporter should be covered as well: Is it intended to generate secret data (yes) Is it intended to generate connection-unique data (yes) Are values for different labels/contexts intended to be computationally independent (yes) (The TLS 1.2 exporter without EMS failed the middle requirement, creating security issues in applications that assumed the data was connection-unique. -Ilari Dave Garrett 10:52 PM (6 hours ago) to tls, Ilari, me Just replying to a few points. On Tuesday, July 12, 2016 12:16:24 am Ilari Liusvaara wrote: The HelloRetryRequest message is not applicable to pure-PSK, which does not use the KeyShare extension at all. PSK has its own separate extension. ((EC)DHE-PSK uses both together) The purpose of HelloRetryRequest is to allow for clients to not send full keys for every single algorithm they support, yet allow the server to still pick from that entire list if it needs to. PSK has no equivalent system; pre-shared keys are first-flight or bust. If an (EC)DHE-PSK suite is selected, and a valid PSK identity is selected, the server can use HelloRetryRequest to reject a group in favor of another supported by the client, but it can't reject the suite or identity in this manner. The response to no acceptable PSK identity is either to negotiate another suite or to abort with a fatal alert. See draft 14 section 4.2.5: URL xiaoyinl fixed the second one of those notes, but that was merged after the checkpoint for draft 14. I'll fix this one to just note for ECDHE PSK AES. Emphatically agreed, however I worded it this way to be slightly more general. If I said that all that code should be universally gutted, I'd risk more people ignoring it due to the severe status quo bias that is very common. In lieu of modernizing fully and dropping it completely, having these old features disabled via the same compile-time option that enables building of TLS 1.3 would be acceptable, IMO (though, more trouble than it should be worth, and still not ideal at all). Bikeshedding better wordings in this section would not be unwelcome, if you think anything here can be made better. Implementations should be expected to handle pathological cases gracefully, even if only to recognize and reject. ;) Ilari Liusvaara 2:00 AM (3 hours ago) to Dave, tls, me On Tue, Jul 12, 2016 at 01:52:57AM -0400, Dave Garrett wrote: Yes, rejection because of group mismatch can't occur. However, I don't see any requirement not to reject pure-PSK for cookie check (might be feasible, if the computational and network load is determined "small enough"). IIRC, there was merged patch that changed the reference, but not the text. Just checked, seems to still be there in Editor's Copy.
NAME I think I have dealt with most of these. You should raise the topic of the CertificateRequest.extensions on list. You say "Later the document seems to imply that the limit for for content+type+ padding is in fact 16385 bytes." If you point out where I will fix it. I don't think maxfragmentlength should go in ServerHello because the client doesn't need it to interpret messages from the server. If you want to provide a PR about RSA in S 8.5 that would be useful.
On Sat, Sep 03, 2016 at 12:49:39PM -0700, ekr wrote: Probably just me misreading the 255 byte limit for expansion from protection and the 16384+1+255 formula for the 16384+256 byte limit. Also, what's the protected limit if maxfragmentlength is in effect? 256 bytes above the plaintext limit (so e.g. 768 bytes for 512 byte plaintext limit)? Actually, probably OK to keep it until EE if included at all because the strictest limit one can apply is 512 octets, and the maximum size of ServerHello is (there is protection change afterwards, so one can't combine the mesage): 4 bytes for message header 2 bytes for version 32 bytes for random 2 bytes for protection/prf 2 bytes for extension length 6 bytes for PSK ACK (might be reduced to 4) 8 bytes for KeyShare header + dhf id + share len ? bytes for key share data This is 56 bytes, plus key share data, leaving at least 456 bytes for the key share. Now, the only DHFs that exceed that are FFDH4k, FFDH6k and FFDH8k (and possible PQ exchanges). And any device that is puny enough to want 512-byte fragments is very unlikely to support any of those. The first length byte thing? Actually, that's a special case of doing RSA PKCS v1.5 (CA certs) verification by doing RSA op and then decoding the result, instead of the proper way, which is to do RSA op, encode the expected result and then compare. -Ilari
Closing this as Ilari did a new review. NAME please let me know if there's anything that got missed. On Tue, Jul 12, 2016 at 03:31:21PM -0500, Benjamin Kaduk wrote: If the field is allowed to contain some ciphersuite with wrong key exchange type, it takes sniffing extensions from ServerHello and EncryptedExtensions to figure out what the actual ciphersuite is. And knowing the key exchange type is rather important in not getting hit by SMACK. AFAIK, the ciphersuite with the same protection and PRF, but some PSK or GDHE-PSK key exchange type. There is well-defined function from (kextype,protection,prfhash) into ciphersuite (or that no such ciphersuite exists). What would the client do with unknown groups anyway? Dump a message to log? Well, what client accepts is separate question to its speculative guesses for performance improvement. And for the first, there is supportedgroups. keyshare is not meant to be xmas tree! In one piece of code I wrote, I pulled +-15s maximum (config can have tighter limits) out of thin air... And, actually, since failing 0-RTT time check is just 1-RTT delay (since in proper implementations it is not a fatal error). I thought they had switched to something else, but apparently not... Correct. I should check the computers I have for what the tickrate approximately is (one curious observation: rebooting computer changes the tickrate(!)). I think I estimated 140ms/day drift for one of those (the others can be way worse). However, the rate of change of the rate (2nd derivate of time reported relative to "true time" (one can for all practical purposes ignore SR and GR here)) should be small. IIRC, maximum ticket validity is 7 days (but for some crappier clocks, that can be lots of drift). But likely TCP delays and such can cause bigger errors than slightly- bad clocks. The opposite way: I would have client choke if server sends it extension outside those lists (TLS 1.3 clients are already supposed to choke if server sends them extension they don't know about, this is only extending it to per-messages lists). I think "SHOULD" would be suitable. Oh, and stick that it stays constant for the duration of the connection as well... -Ilari

Revised text:
A small allowance for errors in clocks and variations in measurements is advisable.  However, any allowance also increases the opportunity  <ins> for replay.  In this case, it is better to reject early data and fall back to a full 1-RTT handshake than to risk greater exposure to replay attacks.  In common network topologies for browser clients, small allowances on the order of ten seconds are reasonable.  Clock skew distributions are not symmetric, so the optimal tradeoff may involve an asymmetric replay window. </ins> 4.2.7.