Subject: [TLS] Extensions "supported_groups" and "key_share" in TLS 1.3

From: Xuelei Fan <[email-masked]>
Date: Thu, 26 Nov 2015 21:52:37 +0800

Hi,

Per the latest draft of TLS 1.3, both "supported_groups" and "key_share"
extensions are REQUIRED for DHE or ECDHE cipher suites (Section 8.2).  Both
extension need to provide the supported named groups in preference order.
Looks like the functions are overlapped.  I was wondering, it may be nice
to obsolete the "supported_groups" extension, and use "key_share" extension
for both the supported named groups and the key exchange information for
each group.

For the "supported_groups" extension, the description is (Section 6.3.2.2):
   ---------------
   Clients which offer one or more (EC)DHE cipher suites MUST send at
   least one supported NamedGroup value and servers MUST NOT negotiate
   any of these cipher suites unless a supported value was provided.  If
   this extension is not provided and no alternative cipher suite is
   available, the server MUST close the connection with a fatal
   "missing_extension" alert.  (see Section 8.2) If the extension is
   provided, but no compatible group is offered, the server MUST NOT
   negotiate a cipher suite of the relevant type.  For instance, if a
   client supplies only ECDHE groups, the server MUST NOT negotiate
   finite field Diffie-Hellman.  If no acceptable group can be selected
   across all cipher suites, then the server MUST generate a fatal
   "handshake_failure" alert.
   ---------------

For the "key_share" extension, the description is (Section 6.3.2.3):
   ---------------
   Clients which offer one or more (EC)DHE cipher suites MUST send at
   least one supported KeyShare value and servers MUST NOT negotiate any
   of these cipher suites unless a supported value was provided.  If
   this extension is not provided in a ServerHello or retried
   ClientHello, and the peer is offering (EC)DHE cipher suites, then the
   endpoint MUST close the connection with a fatal "missing_extension"
   alert.
   ---------------

The "supported_groups" extension defines the groups, while the "key_share"
extension defines both the groups and the key exchange information.  Both
extension has its own preferences for the supported named groups.  It's
easy to get conflicted if the two preferences are not consistent.  The
"key_share" extension contains the information of the supported named
groups.  So, the information can be used to indicate the client supported
named groups.  Maybe, for TLS 1.3, it is not necessary to use the
"supported_groups" extension any more.

Cheers,
Xuelei

---

From: Ilari Liusvaara <[email-masked]>
Date: Thu, 26 Nov 2015 16:26:32 +0200

> for both the supported named groups and the key exchange information for

This wouldn't work if one had to downnegotiate TLS 1.2. That is going to
happen A LOT.

Also, one can support curve, but not prefer to send share on it (the
server can call for it, at cost of extra RTT).

Plus, some of the curves are of special purpose and won't ever have
shares.

Also, IIRC, if client has no shares, it omits key_share. If server wants
FS cipher suite, it then has to signal retry.

> "supported_groups" extension any more.

The only way to be conflicted would be to send key share for group not in
supported_groups. Sending supported_group for group not in key_shares is
not a conflict[1].

[1] In fact, I expect many clients to send shares for P-256 and X25519,
plus offer P-384 and X448 (without shares unless requested).

-Ilari

---

From: Xuelei Fan <[email-masked]>
Date: Thu, 26 Nov 2015 23:37:12 +0800

Thanks for the quick feedback.  You answered some questions puzzled me for
a while.

On Thu, Nov 26, 2015 at 10:26 PM, Ilari Liusvaara <[email-masked]>
wrote:

> I think, "supported_groups" extension still can be sent for TLS 1.2, but
can be ignored for TLS 1.3.  And "key_share" extension can be extended to
support TLS 1.2 and previous versions.

> The scenarios may be not effective because of the extra RTT.  As if the
client want to negotiate the curve, it may be more effective to provide the
key information in the beginning.  Or, maybe the generation of the key
exchange information is more expensive?

> I missed this point.  Is it possible to update the shares to tolerate the
special purpose?  For example, allowing empty shares.

> That's may be the point I missed, too.  Where and when the shares come
from?  Looks like there are two cases:
1. client generate the shares and wrap them in the initial ClientHello
message.
2. client omits the key_share, but still request for (EC)DHE cipher suites.
If server want to negotiate (EC)DHE cipher suite, need an extra RTT.
Client generate the shares on server request.

I think the cases answer my confusing of the two extensions.  Suppose, if
the shares can be optional, maybe it is easier to use key_share only.  If
client has no shares, using key_share with no shares (function as
supported_groups); if client has shares, using key_share with shares.

> The preferences may be not consistent, too.  For example, the
supported_groups prefer ffdhe2048, but the key_share prefer ffdhe4096.
Using two preferences would make the implementation inconsistent between
vendors if no clearly specification about the preference of the two.

> I like this scenarios more.  It might be more clear if TLS 1.3 support
this scenarios, but not the scenarios that sending shares before
requested.  For the TLS vendors, client implementation may only consider
one option. While a server implementation need to consider both, the effort
doubles.

Thanks,
Xuelei

---

From: Ilari Liusvaara <[email-masked]>
Date: Thu, 26 Nov 2015 21:15:25 +0200

> support TLS 1.2 and previous versions.

Given the slowness even _security_ _fix_ extensions get deployed,
planning any sort of transition is not IMO a good idea.

> exchange information is more expensive?

Yes, generating key exchanges can be expensive (even if it is cheaper
for each group then performing the actual key exchange). Especially for
P-384, P-521 and larger DH groups.

Also, the shares can get large if many are sent. "Xmas tree" client
keyshare is 3384 bytes by quick calculation (whereas the one containing
P-256 and X25519 is just 109). That's many times the rest of the
ClientHello, and might already cause problems.

Better plan might be to guess, as the cost of wrong guess is mostly
just 1 RTT.

> special purpose?  For example, allowing empty shares.

The current grammar does not allow empty value, so it is free. But
considering one needs supported_groups for backward compat., one can
just rely on that to signal that group is supported but no share is
given.

> Client generate the shares on server request.

I actually looked at the Editors's Copy. The description is a mess: It
seemingly first requires key_share extension, even for the first
ClientHello... Now, that extension can't be empty... And then proceeds
to say to omit it if client has no shares to send... Which looks like
it is mutually contradictionary.

> supported_groups); if client has shares, using key_share with shares.

I think two extensions are needed for backward compatiblity: One needs
to use supported_groups, but one can't extend it, so two extension it
is.

TLS 1.3 (without 0-RTT) is supposed to be possible to downnegotiate at
least to TLS 1.2.
 
> vendors if no clearly specification about the preference of the two.

Only supported_groups are perference-ordered. Key_shares is unordered,
with special exception for retry (the added group always goes last).
 
> one option. While a server implementation need to consider both, the effort

Basically, with some groups, sending on request is the only workable
option, given how slow or large some shares are.

Now, if PQ key exchanges were added, things would get worse, because
those methods tend to either have large keys or slow key exchange/
generation.

-Ilari

---

From: Dave Garrett <[email-masked]>
Date: Thu, 26 Nov 2015 17:50:11 -0500

> it is mutually contradictionary.

We went back and forth on whether to omit or require an empty extension. It looks like we have a mix of the two left in there that need fixing. (I think something got merged weird) Thanks for pointing this out.

I think it might be easier if we just required the extension for all cases where (EC)DHE suites are offered, and have it empty to request a server choice, instead of an omitted extension. If I remember correctly, that's what I had originally. One way or another, it needs to be fixed to be consistent.

Dave

---

From: Eric Rescorla <[email-masked]>
Date: Thu, 26 Nov 2015 15:02:09 -0800

On Thu, Nov 26, 2015 at 2:50 PM, Dave Garrett <[email-masked]>
wrote:

> We went back and forth on whether to omit or require an empty extension.
> It looks like we have a mix of the two left in there that need fixing. (I
> think something got merged weird) Thanks for pointing this out.
>
> I think it might be easier if we just required the extension for all cases
> where (EC)DHE suites are offered, and have it empty to request a server
> choice, instead of an omitted extension.

Yes, we should either have that or have empty be forbidden. It's a matter
of taste
but on balance, let's go with "empty". If you want to submit a PR that
cleans
this up, I'll merge that.

-Ekr

If I remember correctly, that's what I had originally. One way or another,
> it needs to be fixed to be consistent.
>
>
> Dave
>

---

From: Dave Garrett <[email-masked]>
Date: Thu, 26 Nov 2015 18:36:54 -0500

On Thursday, November 26, 2015 06:02:09 pm Eric Rescorla wrote:
> Yes, we should either have that or have empty be forbidden. It's a matter of taste
> but on balance, let's go with "empty". If you want to submit a PR that cleans

->  https://github.com/tlswg/tls13-spec/pull/349

There's one last decision, though: does "empty" mean empty client_shares vector or empty "extension_data" to save 2 bytes? I think it's cleaner to just keep the same extension structure for all cases and have an empty shares vector, which is what I have in the current PR.

Dave

---

From: Eric Rescorla <[email-masked]>
Date: Thu, 26 Nov 2015 15:47:19 -0800

On Thu, Nov 26, 2015 at 3:36 PM, Dave Garrett <[email-masked]>
wrote:

> There's one last decision, though: does "empty" mean empty client_shares
> vector or empty "extension_data" to save 2 bytes? I think it's cleaner to
> just keep the same extension structure for all cases and have an empty
> shares vector, which is what I have in the current PR.

Empty vector seems dominant.

-Ekr

---

From: Xuelei Fan <[email-masked]>
Date: Fri, 27 Nov 2015 08:59:38 +0800

If empty key_share vector is used to indicate to request a server choice, I
think it is not necessary to have  "supported_groups" extension as
mandatory any more.  key_share extension can be used for the supported
named groups.   "supported_groups" extension can be used for backward
compatibility (if TLS 1.2 fade out in the future, need no "supported_groups"
extension any more).

Or, if both are needed as mandatory, may be better to separate functions
that "supported_groups" extension defines the supported named groups and
preference, and key_share defines the shares only (no supported groups, no
preference, the groups must be defined in  "supported_groups" extension).

Xuelei

---

From: Eric Rescorla <[email-masked]>
Date: Thu, 26 Nov 2015 17:12:23 -0800

On Thu, Nov 26, 2015 at 4:59 PM, Xuelei Fan <[email-masked]> wrote:

> If empty key_share vector is used to indicate to request a server choice,
>

That's not what it means. It means "I have no idea what your preferences
are, so tell
me which of the groups I support you prefer". Thus, you still need
supported_groups
to indicate the groups you support.

-Ekr

I think it is not necessary to have  "supported_groups" extension as

---

From: Xuelei Fan <[email-masked]>
Date: Fri, 27 Nov 2015 09:28:35 +0800

On Fri, Nov 27, 2015 at 3:15 AM, Ilari Liusvaara <[email-masked]>
wrote:

> Agreed.

If  "supported_groups" extension is only for compatibility, it can be
not-mandatory.  However, if it is defined to define the supported groups
and preferences (see bellow), it can be mandatory.

> Agreed.

> Version down-negotiation is OK, but define "supported_groups" extension as
mandatory may be too strong, unless there are other considerations (See
bellow).

> with special exception for retry (the added group always goes last).
In section 6.3.2.3:
    client_shares
         A list of offered KeyShareEntry values in descending order of
client preference.

I think, key_share is ordered too.  If considering both key_share and
supported_groups together, looks like there are two options:
1. key_share defines the preferences and supported named groups, which is
overlap with supported_groups. supported_groups is used for version
down-negotiation purpose. Don't define supported_groups as mandatory any
more.

For this case, empty key_share vector can be used to indicate to request
server choice shares.

2. key_share won't defines the preferences any more.  The named groups in
key_share MUST exist in supported_groups extensions.  supported_groups is
used to define the supported named groups and preference, and key_share is
used to define the shares.  Both are mandatory.

For this case, key_share can be omitted to indicate to request server
choice shares.

> Agreed.

Thanks,
Xuelei

---

From: Xuelei Fan <[email-masked]>
Date: Fri, 27 Nov 2015 09:34:12 +0800

On Fri, Nov 27, 2015 at 9:12 AM, Eric Rescorla <[email-masked]> wrote:

> Make sense to me.

Thanks,
Xuelei

>>>> > On Thu, Nov 26, 2015 at 2:50 PM, Dave Garrett <[email-masked]
>>>> >
>>>> > wrote:
>>>> There's one last decision, though: does "empty" mean empty
>>>> client_shares vector or empty "extension_data" to save 2 bytes? I think
>>>> it's cleaner to just keep the same extension structure for all cases and
>>>> have an empty shares vector, which is what I have in the current PR.
>>>
>>>

---

From: Xuelei Fan <[email-masked]>
Date: Fri, 27 Nov 2015 09:37:29 +0800

> For this case, key_share can be omitted to indicate to request server
Update: key_share can be omitted, or the client_shares vector can be empty to
indicate to request server choice shares.

Xuelei

---

From: Dave Garrett <[email-masked]>
Date: Thu, 26 Nov 2015 20:39:00 -0500

> and preferences (see bellow), it can be mandatory.

If it weren't for the fact that we're retrofitting the elliptic_curves extension from RFC 4492 into the supported_groups extension via draft-ietf-tls-negotiated-ff-dhe & the TLS 1.3 draft, then yes, we'd probably have the key sharing and group support enumeration in the same extension. We are recycling the old extension for backwards compatibility, however, so we're having these two things be separate. A 20 year old protocol is just going to have kludgey stuff like this, whether we like it or not. ;)

> supported_groups together, looks like there are two options
[...]

Yes, I addressed the conflict of priorities in one of my PRs, but it's on my todo list to rewrite it as ekr noted a few parts that needed changing. We agreed on simply making the two orders be required to be the same, though at "SHOULD"-level requirement. Those that have them differ will be dealt with at the implementations' discretion.

> For this case, key_share can be omitted to indicate to request server

I dislike special cases; people screw them up. Life is easier if all (EC)DHE suites need a fixed set of accompanying extensions. Less complicated and simpler to describe clearly. (as pointed out, omitting it left us with garbled text, though that was also just due to us flip-flopping on how to handle it)

Dave

---

From: Xuelei Fan <[email-masked]>
Date: Fri, 27 Nov 2015 09:48:14 +0800

> Yes, I addressed the conflict of priorities in one of my PRs, but it's on
> my todo list to rewrite it as ekr noted a few parts that needed changing.
> We agreed on simply making the two orders be required to be the same,
> though at "SHOULD"-level requirement. Those that have them differ will be
> dealt with at the implementations' discretion.
>
> Requiring the two order the same would triage order checking.  It may be
easier that the key_share does not define the order.

> I dislike special cases; people screw them up. Life is easier if all
> (EC)DHE suites need a fixed set of accompanying extensions. Less
> complicated and simpler to describe clearly. (as pointed out, omitting it
> left us with garbled text, though that was also just due to us
> flip-flopping on how to handle it)

I meant that the proposal uses one of the options for the final version,
not both.  It may be more simple, I think.

Thanks,
Xuelei

---

From: Xuelei Fan <[email-masked]>
Date: Fri, 27 Nov 2015 10:12:14 +0800

> easier that the key_share does not define the order.
I may miss something.  Can key_share offers two shares for the same group?
For example, two DH public values (dh_Y) for the ffdhe2048?  If yes, the
key_share order is necessary.  Otherwise, I think it is more simple to
remove the order requirement of shares.

Thanks,
Xuelei

---

From: Dave Garrett <[email-masked]>
Date: Thu, 26 Nov 2015 21:39:32 -0500

On Thursday, November 26, 2015 09:12:14 pm Xuelei Fan wrote:
> Can key_share offers two shares for the same group?

It's currently worded "Clients MUST NOT offer multiple KeyShareEntry values for the same parameters", which is a little ambiguous, but I interpret this as one share per group. I don't know why you'd need to offer more than one, anyway.

Dave

---

From: Xuelei Fan <[email-masked]>
Date: Fri, 27 Nov 2015 10:50:40 +0800

> It's currently worded "Clients MUST NOT offer multiple KeyShareEntry
> values for the same parameters", which is a little ambiguous, but I
> interpret this as one share per group. I don't know why you'd need to offer
> more than one, anyway.
>
> Need no more than one.  Then, it may be more simple that key_share does
not define the preference order. The preference order is covered by
supported_groups.

Thanks,
Xuelei

---

From: Hubert Kario <[email-masked]>
Date: Fri, 27 Nov 2015 13:12:35 +0100

On Friday 27 November 2015 10:50:40 Xuelei Fan wrote:
> > interpret this as one share per group. I don't know why you'd need
> > to offer more than one, anyway.
> > 

What would then be the expected behaviour of the server if the first 
group in the supported_groups does not have a associated key share?

that is, I advertise support for secp384r1, secp256r1 or ffdhe2048, but 
I provide only secp256r1 key share as it's the one that's most widely 
supported

Should the server ask me to provide a secp384r1 key share or should it 
just proceed with secp256r1?

I think that specifying *both* in preference order, and recommending the 
servers to first inspect key shares and then supported_groups (if no 
intersect between what server supports and what key shares client 
provided) would end up with more predictable behaviour and cleaner code.

That being said, we probably should say that clients MUST advertise 
support for all groups for which they send key shares and servers MUST 
abort connection with something like illegal_parameter if that happens
-- 
Regards,
Hubert Kario
Senior Quality Engineer, QE BaseOS Security team
Web: www.cz.redhat.com
Red Hat Czech s.r.o., Purkyňova 99/71, 612 45, Brno, Czech Republic

---

From: Xuelei Fan <[email-masked]>
Date: Fri, 27 Nov 2015 20:33:46 +0800

On Fri, Nov 27, 2015 at 8:12 PM, Hubert Kario <[email-masked]> wrote:

> Try the next  group in the supported_groups until find an associated key
share.

> I think, it would be better to proceed with secp256r1.

> But if the orders are not consistent, the logic get annoyed.  It's a good
practice to keep the order consistent, but it would be better if the
preference order is unique and specified in one place.

> abort connection with something like illegal_parameter if that happens
This adds additional checking on both client and server.  Personally, I
would prefer to use one preference order in order to avoid any order
conflict.

Thanks & Regards,
Xuelei

---

From: Hubert Kario <[email-masked]>
Date: Fri, 27 Nov 2015 13:44:21 +0100

On Friday 27 November 2015 20:33:46 Xuelei Fan wrote:
> > I think that specifying *both* in preference order, and recommending
> > the servers to first inspect key shares and then supported_groups
> > (if no intersect between what server supports and what key shares
> > client provided) would end up with more predictable behaviour and
> > cleaner code.
> > 

that means that the code needs to keep references to two arrays at the 
same time and either create a hash table for lookups in key shares or 
iterate over key shares for every try - this makes code and logic more 
complex, not less

> > support for all groups for which they send key shares and servers
> > MUST abort connection with something like illegal_parameter if that
> > happens
> This adds additional checking on both client and server.  Personally,
> I would prefer to use one preference order in order to avoid any
> order conflict.

not the first, and certainly not the last checks that need to be done to 
implement TLS securely...
-- 
Regards,
Hubert Kario
Senior Quality Engineer, QE BaseOS Security team
Web: www.cz.redhat.com
Red Hat Czech s.r.o., Purkyňova 99/71, 612 45, Brno, Czech Republic

---

From: Xuelei Fan <[email-masked]>
Date: Fri, 27 Nov 2015 21:20:24 +0800

> iterate over key shares for every try - this makes code and logic more
I did not get the idea, can the complex above be avoided if keeping both?
Does one preference order just get ignored?

If the orders are not consistent, if I can choose from two options:
continue or alter, I would choose the continue option.  Alert message is
expensive in practice.

Anyway, minor question, not a big concern to me.

Thanks & Regards,
Xuelei

---

From: Hubert Kario <[email-masked]>
Date: Fri, 27 Nov 2015 14:28:22 +0100

On Friday 27 November 2015 21:20:24 Xuelei Fan wrote:
> > > But if the orders are not consistent, the logic get annoyed.  It's
> > > a
> > > good
> > that means that the code needs to keep references to two arrays at
> > the same time and either create a hash table for lookups in key
> > shares or iterate over key shares for every try - this makes code
> > and logic more complex, not less
> 
> I did not get the idea, can the complex above be avoided if keeping
> both? Does one preference order just get ignored?

the idea is that if there is a key share acceptable for the server, the 
supported_groups can be ignored

but to make sure that clients don't start putting complete garbage 
there, we need to tell servers to check key shares against 
supported_groups

> continue or alter, I would choose the continue option.

alter what?

> Alert message
> is expensive in practice.

Note that this alert will never be sent to a client that is behaving 
according to specification unless the packets were modified by the 
network. It's a sanity check.

---

From: Xuelei Fan <[email-masked]>
Date: Fri, 27 Nov 2015 21:55:34 +0800

On Fri, Nov 27, 2015 at 9:28 PM, Hubert Kario <[email-masked]> wrote:

> As the check needs additional effort,  and the client code also needs
additional effort to keep the order consistent, I think the logic may be
more complex.

Anyway, not a big concern to me.  Personally, I prefer one logic one place.

> If the preference orders in key_share and supported_groups are not
consistent, I think an alert message is expected.

> Sure, if both peer strict follow the spec.  But implementation may be not
correct.  Conner case, of course.

Thanks & Regards,
Xuelei