[PATCH 38/43] secnet.8: Describe capability negotiation in its own section. [and 1 more messages] [and 2 more messages]

Mark Wooding mdw at distorted.org.uk
Mon May 1 14:41:56 BST 2017


Ian Jackson <ijackson at chiark.greenend.org.uk> writes:

> I still think my scheme works just fine.

Ahhh.  The NOTES file has

: 2. Late capability flags are advertised in MSG2 or MSG3, as
:    applicable.  They may also appear in MSG1, but this is not
                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:    guaranteed.  MSG4 must advertise the same set as MSG2.
     ~~~~~~~~~~~

The thing I was missing was that you had decided that this isn't true
any more, only without actually telling me.  So there I was, trying to
figure out how all of this fits together with the rules as they were
written.

> He will send 16 (CHACHA20POLY1305), 15 (EXPLICIT), 10 (TRADZP), 9, 8.

Traitorous fingers.  Yes.  That's why I left 10 out of that list.

> He will send 15 not because "he wants his peer to notice 16" but
> because he always sends 15.  Sending EXPLICIT is not dependent on
> configuration.

OK.

[...]

> Why do you think Bob's MSG3TER has 11 (X25519) set ? 

I don't, but my fingers betrayed me when I tried to type `10'.

> but the code sends all capability bits if there are any early ones.
> I'm proposing formalising this, at least for non-TRADZP DH groups.

OK.  Would you mind actually stating what you think the rules ought to
be, then?  I think I've wasted enough of my time trying to fit in with
the protocol-as-documented, so I'd rather not spend more time trying to
fit in with The Way Things Should Actually Be which, for added fun, I
have to guess at rather than being somewhere I can actually see it.

The things I want to know, specifically, are:

  * when I'm about to send MSG1, whether I need to include caps, and
    which caps they should be; and

  * when I've received MSG3, how to decide whether the caps it advertise
    are acceptable given the caps I received (or didn't) earlier in
    MSG1.

If a notion of `early capability' is useful in addressing these issues,
it should be clearly defined, /ab initio/.

But hold on a moment: what goes wrong if we /don't/ send DH groups in
MSG1?  The way I see it:

  * Alice sends MSG1, compatibly;

  * Bob sends back MSG2, bearing an exciting panoply of capabilities;

  * Alice looks at them and decides that a particular DH group and
    transform look shiny.  She knows, because Bob's caps have the
    EXPLICIT bit, that Bob understands DH group negotiation and
    MSG3TER.  So she sends off MSG3TER with her own (previously
    undisclosed) caps, and her pick of DH group and transform.

  * Bob sees Alice's picks and rolls with them.

  * Everyone wins.

The way I see it, then, `early' caps are specifically `what you need to
know in order to send MSG2 correctly'.  So maybe we can put these worms
back in their can for now, not worry, and be happy.

Of course, this seems too easy, so there must be a catch.  It's not that
it doesn't actually work because I just tested it: my current code can,
with the same configuration, negotiate X25519 with itself (with updated
configuration), and settle on trad DH with both master and
debian/0.3.0_beta1.

... so what am I missing?

With this view, then, a good answer to my query above might be

        MSG1 must include a capabilities word if they are necessary for
        the sender of MSG2 to decide what to do.  There are currently no
        defined circumstances under which this is the case.  If MSG1
        includes capabilities, then the following MSG3 must include
        exactly the same capabilities.  Similarly, MSG4 must include the
        same capabilities as MSG2.

        (Note that these matching requirements are necessary for
        security.  When an initiator is preparing MSG3, or a responder
        preparing MSG2, they have only unauthenticated messages upon
        which to base their decisions.  The following signed message
        MSG4 or MSG3 acts to confirm that the earlier decision was
        justified.)

Also, I now think the existing checking is /insufficient/.  From master,
`process_msg3':

    uint32_t capab_adv_late = m.remote_capabilities
	& ~st->remote_capabilities & CAPAB_EARLY;
    if (capab_adv_late) {
	slog(st,LOG_SEC,"msg3 impermissibly adds early capability flag(s)"
	     " %#"PRIx32" (was %#"PRIx32", now %#"PRIx32")",
	     capab_adv_late, st->remote_capabilities, m.remote_capabilities);
	return False;
    }

Here, we complain if MSG3 has any `early' caps that MSG1 logically
`should' have had.  And then...

    st->remote_capabilities|=m.remote_capabilities;

we don't care if MSG1 had /late/ caps which MSG3 presumably ought to
have.  But MSG1 is unauthenticated!  Currently, this causes a denial-of-
service opportunity, and there are plenty of them.  (The easiest is
spamming MSG1 with a made-up wrong nonce, which ties up the recipient
for retries*retry_interval.)  But I'd be happier if this were fixed.

-- [mdw]



More information about the sgo-software-discuss mailing list