Replying to myself: We obviously don't *need* to do this. We have working implementations that use the current syntax, so we know it can be done, and "finished is a feature", so we have to balance against that whether this is a better syntax. OTOH, if you think this is a worse syntax, then it's easy. :)
-Ekr On Wed, Jul 13, 2016 at 10:12 AM, Eric Rescorla <e...@rtfm.com> wrote: > Hi folks, > > There have been a lot of discussions about whether we should try to > refactor cipher-suite negotiation to be less monolithic in the cipher > suite. I've generally been on the "no" side of that on cost/benefit > grounds as well as not quite seeing how it would fit into the rest > of the infrastructure. However, now that we're starting to get full > implementations, and it's becoming clearer how the new elements > (principally PSK-resumption and key_shares) interact with cipher > suites, I've started to think that in fact we may be able to clean > things up. One proposal for this is below [0]. I know this is > pretty late in the process, but if we do want this change it's > better to do it now. > > I'm sure we'll need to discuss this in Berlin, but in the meantime, > fire away. > > > The basic idea here is to factor out the TLS 1.3 negotiation into three > mostly orthogonal axes. > > - Symmetric cipher/PRF -- indicated by the cipher suite list as in TLS 1.2 > - Key exchange -- indicated by the key_shares and pre_shared_key extensions > - Authentication -- indicated the signature_algorithms and pre_shared_key > extensions > > A proposal for how to do this is below. See the end for other options, > caveats, etc. > > > If we take PSK out of the picture, this gives us a very simple structure: > > - The client offers a set of key_shares and the server picks one that it > likes [1]. > - The client offers a list of signature_algorithms and the server picks > a certificate/key that matches that list and signs with it. > > In other words, we just eliminate the redundancy with the cipher suite > indications. This leaves is with the question of how to handle the > existing TLS 1.2 cipher suites. We can either assign new cipher suites > or say that any cipher suite with *_aead_alg_hash means that we > support aead_alg_hash. Matter of taste. > > > PSK is handled by extending the concept of PSK flags that we already > have in NewSessionTicket to also include uses of PSKs where you > indicate the way in which you are using the PSK (or want it to be > used). There a bunch of ways to encode this. I'll give you the one I > mostly prefer below and then a one that's a smaller change but I think > a little less elegant at the end [note #4]. > > First, we replace the flags word of the different KE modes for the > ticket with lists of code points, as below: > > enum { > psk_ke(0), // PSK key exchange > psk_dhe_ke(1), // PSK + DHE key exchange > (255) > } PskKeModes; > > And then add new code points for being able to use the PSK with and > without signatures (from the server). We had pretty rough consensus in > B-A that we needed this mode and [draft-thomson-tls-0rtt-and-certs-01] > is part of the motivation for this idea. > > enum { > psk_auth(0), // PSK only > psk_sign_auth(1), // PSK + a signature (as in draft-thomson) [5] > (255) > } PskAuthModes; > > This gives us the following NewSessionTicket message where we have > replaced the flags word with two (potentially ordered) lists: > > struct { > uint32 ticket_lifetime; > PskAuthModes auth_modes<1..255>; > PskKeModes ke_modes<1..255>; > TicketExtension extensions<2..2^16-2>; > opaque ticket<0..2^16-1>; > } NewSessionTicket; > > We now need a way to indicate that the server will do 0-RTT (previously > in the flags word) so we add a new 0-RTT extension: > > struct { > uint32 ticket_age_add; > } TicketEarlyDataInfo; > > This has two nice properties: > > - You don't need to provide ticket_age_add when you don't do 0-RTT > (and it is silly if you don't). > - It exercises this extension mechanism, which is good for future-proofing. > > > PreSharedKeyExtension becomes: > > struct { > PskAuthMode auth_modes<1..255>; > PskKeModee ke_modes<1..255>; > opaque identity<0..2^16-1>; > } PskIdentity; > > struct { > select (Role) { > case client: > PskIdentity identities<2..2^16-1>; > case server: > PskAuthMode auth_mode; > PskKeMode ke_mode; > uint16 selected_identity; > } > } PreSharedKeyExtension; > > The way to interpret these is as follows: > > - With each identity, the client indicates to the server which modes > it can be used with. > - When the server responds with an identity, it tells you how it > used it. > > You might ask why you need the server to indicate what it did. The > reason is that we would like the client to know in advance (at the > time of the ServerHello) whether the server has sent > Certificate/CertificateVerify rather than having to figure it out from > what messages the server sends. The ke_mode field is redundant > (because you also infer it from the server key_shares) but I added it > for parity. > > I haven't implemented this yet (am going to try to take a crack at that > before Berlin) but I believe based on experience with the NSS > negotiation that it will be simpler. I know it removes a bunch of odd > edge cases which have accumulated over the years, but maybe it adds > others. > > -Ekr > > > BONUS MATERIAL > 0. I've discussed this with and/or borrowed ideas from Richard Barnes, > David Benjamin, Karthik Bhargavan, Dave Garrett, Nick Sullivan, Martin > Thomson, and others. Thanks to those guys, but blame me if you think > this is bad. > > 1. The other major encoding option here is to have dummy > group/signature_algorithm indicators that tell you whether you can use > a pure PSK. When I and others discussed this, the consensus was that > that was less clean. > > 2. One question that comes up at the same time is whether we should > allow multiple key shares to be used, which is a structure that this > makes pretty easy. Basically, the server would just supply as many > counter-shares as it wanted and then we'd need a defined order for how > they were inserted into the key schedule. This feature would be nice > for enabling post-quantum, but probably better to just define > <PQ-Algorithm + Curve> code points. > > 3. Note that because of this PSK-PRF interaction, PSK isn't totally > orthogonal with AEAD/PRF. I.e., you cannot use the same PSK with > HKDF-SHA256 and HKDF-SHA384 if you want to be on the cryptographic > fairway, but I think it should be easy enough to filter out the cipher > suites to make that work. > > 4. The other major alternative is just to use the flags bits. So we > would extend and generalize the flags as shown below. > > enum { > early_data(1), > dhe_psk_ke(2), > psk_ke(4), > psk_auth(8), // New (no server cert) > sig_psk_auth(16) // New (sign with server cert) > } PskUsageFlags; > > These new flags have the expected meaning, namely: > > psk_auth The server will do connections with just > PSK authentication (equivalent to PSK now) > > sig_psk_auth The server will do connections with PSK > plus signature (not currently specified). > > > Then we update the PreSharedKeyExtension as follows: > > struct { > uint32 usage_flags; > opaque identity<0..2^16-1>; > } PskIdentity; > > struct { > select (Role) { > case client: > PskIdentity identities<2..2^16-1>; > case server: > uint32 usage_flags; // New (one from each category) > uint16 selected_identity; > } > } PreSharedKeyExtension; > > The idea here is: > > - The client indicates how each PSK can be used (by flags, which > need to be a subset of the ticket flags). > - The server can pick a PSK and indicate how it was actually > used. > > For instance, if the client wants to do PSK w/ ECDHE it would indicate > dhe_psk_ke. If it only wants PSK it would indicate psk_ke. If it was > willing to do both, it would indicate the bitwise OR. > > Similarly, if the client wants PSK for auth, it would indicate > psk_auth. If it wants the server to sign, it indicates sig_psk_auth, > and so on (indicating neither is silly because it makes the key > unusable). > > By contrast, the server just sets the bits that it actually used. > I.e., if it sets psk_auth, that means it won't be signing and > there is no Certificate/CertificateVerify. OTOH if it sets > sign_psk_auth, that means it will be signing and there will > be a Certificate/CertificateVerify. > > This leaves early data. As above, the client uses the early_data > bit to indicate that the PSK was used to encrypt early data > (obviously, this can just be one key) and the server uses it to > indicate that it accepted early data. ticket_age needs to go in > its own extension, but that's easy enough. > > > 5. Note: this would allow for modes where the server signs over a PSK > handshake with no DHE at all. The resumption_ctx mechanism is intended > to ensure that that is OK, but we'd need to confirm with analysis. > >
_______________________________________________ TLS mailing list TLS@ietf.org https://www.ietf.org/mailman/listinfo/tls