ECDH, early capabilities, etc.
mdw at distorted.org.uk
Thu Apr 27 00:57:03 BST 2017
Ian Jackson <ijackson at chiark.greenend.org.uk> writes:
> The commit needed to cope with and ignore an unknown early capability
> is "site: fix site name checking leaving room for expansion"
> 1737eeef9bc4 from July 2013. That was released in secnet 0.3.0 in
> September 2013.
> Current advice from secnet release announcements is:
> (Everyone should be running at least version 0.3.4, as all previous
> versions have significant security bugs.)
> So I think deploying this with an early capability flag is fine.
Thanks for doing the archaeology on this. Your analysis seems sound.
> Each new group should have a capability flag. I don't see the need
> for a negotiation system for arbitrary user-defined groups. Instead,
> let's just hardcode a capability flag for each new group.
> (We don't need a capability flag for the existing Zp group (or
> manually-configured different Zp group), since that should always be
> the least-preferred option. We presume that everyone supports it if
> we do.)
I can see a use-case where someone wants to arrange a smooth upgrade
from some tiny trad-DH group to a big trad-DH group. If they end up
sharing a cap slot then the negotiation protocol won't be able to
distinguish between them.
Left to my own devices, I'd probably redesignate the existing `transport
number' cap bits as crypto algorithm cap bits, and add an optional
argument to `diffie-hellman' to override the default cap choice. But I
can't bring myself to be very concerned about this.
> As for configuration, we want each site administrator to be able to
> individually turn on and off each of:
> dh (normally with the conventional default secnet group,
> but theoretically in a specified group);
> and presumably to specify a preference order.
> I think we can do this by making the `dh' argument to site closures be
> a list.
Hmm. Introducing new cap bits is a little subtle. Currently 16 of the
bits are marked as being `transport number' bits (covered by
CAPAB_TRANSFORM_MASK) and the remaining bits are entirely unused.
These bits seem to have been intended for advertising actual bulk-crypto
transforms rather than any other kind of thing. Respecting this intent
would lead me to allocate an additional range of cap bits for DH groups:
I want at least two, and there should probably be at least some left
over for the future.
So: this will work as follows.
* I'll allocate cap bits 16 and 17 for X25519 and X448, respectively,
and mark these as early. I'll modify `site_apply' to set the
relevant bits for the DH groups. The existing capability handling
machinery will transmit the new caps in MSG1 and MSG2 as necessary.
* There can be at most one DH group with any given cap number. The
negotiation machinery can't distinguish between groups with the same
cap. In particular, then, you can't advertise more than one trad-DH
* At MSG2 time: we might as well advertise all our caps because it's
easier that way, but if MSG1 didn't advertise any DH caps then we'll
have to go with trad-DH.
* At MSG3 time: select MSG3BIS if the remote site sent either
transport or DH cap bits. If both our MSG1 and their MSG2
advertised DH caps then send an extra byte after the chosen
transform number naming the selected group, which is the first in
our list which is either trad-DH or which was explicitly advertised
in MSG2; we fail if no group was acceptable. The DH group byte may
end up as 0xff if we settled on trad-DH (e.g., I want X25519 or
trad, you want X448 or trad). The hex-encoded DH public value then
holds a public element from the stated group.
* At MSG4 time: We know to expect the extra DH-group byte because
their MSG1 and our MSG2 both declared DH-group caps. If the
selected group turns out to be unacceptable (e.g., they chose
trad-DH and we don't actually allow it) then we fail.
I don't like the MSG3BIS plan. In particular, including extra bytes
based on context from other packets makes protocol dissector writers
sad. On the other hand:
* The extra information needs to go somewhere. The responder has no
way of discerning the initiator's DH group preference order.
* I don't want to add another MSG3 variant because that doesn't seem
to be heading in a good direction.
* I could squirrel the selection away behind the local-name field, but
that doesn't seem to help much. The compatibility break is actually
in the different DH group.
Better suggestions are welcome. I'm setting a low bar here.
> * Change the dh closure interface to move any Zp-specific parts from
> site.c into dh.c (and perhaps rename the dh closure to
> `key_agreement' or something in the code and the README).
The current `dh_if' interface seems pretty clean, actually. I hadn't
planned on messing with it. The new curves have well-defined interfaces
in terms of fixed-length byte strings, which I intend to use (so
there'll be a little tedious messing about with hex strings), but I
think it'll fit in just fine.
I've noticed that the old CBCMAC transform will be incompatible with
these new groups: it requires 76 bytes of key material, and they'll
provide 32 or 56 bytes unless I apply expansion. I don't propose to do
much about this other than shrugging my shoulders.
> * Change the site closure to look for `key-agreement', rather
> than `dh'; and provide a default definition of key-agreement
> which is simply a list containing only `dh'.
There's currently no default. If no DH closure named `dh' can be found
in the arguments to `site' then a fatal error is reported and you lose.
(While investigating this, I noticed that `find_cl_if' (`conffile.c'
line 657) can't possibly work if its `fail_if_invalid' argument is
false -- which it never actually is.)
I don't propose to change this. Administrators who want to define a
selection of DH groups can write a list; the others can leave their
configuration with the explicit DH group it already must have.
> * Add a field to the key_agreement closure declaring its
> capability index (-1 for the existing closure), and the
> negotiation/selection algorithm.
> * Add the new algorithms.
Hmm. I'd originally planned to do this first, so that the new
negotiation machinery actually had some extra DH groups to talk about.
But then the post-negotiation version won't be able to communicate with
the pre-negotiation version if both are configured to use the same new
group (the newer version will assume the older one wants to use trad
I'll probably do this anyway, make the thing work, and then reorder the
patches so that the finished history doesn't contain a compatibility
This morning I finished the work I wanted to do on factoring out the
common portions of X25519 and X448, and both are working well in a
branch of my library. They have few tendrils other than the testing
machinery, but I can hack those off easily enough. The test handling
will take a bit more effort.
More information about the sgo-software-discuss