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

Ian Jackson ijackson at chiark.greenend.org.uk
Mon May 1 16:30:56 BST 2017

Mark Wooding writes ("Re: [PATCH 38/43] secnet.8: Describe capability negotiation in its own section. [and 1 more messages] [and 2 more messages]"):
> But hold on a moment: what goes wrong if we /don't/ send DH groups in
> MSG1?  The way I see it:
> 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?

Nothing.  I think you are right.  Probably the notion that these DH
groups need to be early was a conclusion I jumped to, or a
half-remembered previous misunderstanding.

> 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.


I should have been more explicit that I was departing from the
documented protocol in a way that is forward-compatible with the
actual old code.

> 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

Include caps if any are (locally) considered early.  If including
caps, include all of them.

>   * 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.

Reject MSG3 unless either:
  - MSG1 did not contain a cap bitmap, and no cap in MSG3 is
    considered early by us
  - MSG3 did contains a cap bitmap, and any known cap is present
    in MSG1 but not MSG3

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

Let me have a proper stab at this:

  In the fully general case:

  Informally, each capability assignment defines the point in the
  protocol by which it must be advertised.

  We speak of a MSG(i,j)-cap, for a cap that must be advertised by the
  initiator in MSGi (i odd) at the latest and by the responder in MSGj
  (j even) at the latest.  And we'll write MSG(i)-cap for
  "MSG(i,*)-cap if i is odd, or MSG(*,i)-cap if i is even".
  MSG(1)-caps are divided into forcing and relaxed.

  Caps are categorised by each end according to their own knowledge of
  the semantics.  Unknown capabilities are treated as
  MSG(inf,inf)-caps.  All currently defined caps are MSG(1,2)-relaxed.

  MSG1 is sent with a cap bitmap if the initiator supports any
  MSG(1)-forcing caps.  MSG2-4 are always sent with a bitmap.  By the
  rules above, the bitmap for MSGk contains all MSG(i)-caps for i<=k.

  MSG(k+2) is rejected if it advertises any MSG(i)-caps i<=k (and
  i=k mod 2), which were not advertised in MSGk.  (For now this is
  true for 3<=k+2<=4, but if in future we add very late caps to MSG5,6
  or something, it might become true for larger k.)

  Special case: if MSG1 had no caps bitap, MSG3 is rejected only if it
  advertises any MSG(1)-forcing caps.

  Specialisation to "early" vs "normal" caps: early caps are
  MSG(1,2)-forcing.  Normal caps are MSG(1,2)-relaxed.  Consequently:

  MSG1 is sent with caps if the initiator supports any early caps.
  MSG2-4 are always sent with a bitmap.  When constructing the
  bitmaps, every bitmap mentions all supported caps.

  MSG3/MSG4 is rejected if it advertises any known caps which were not
  in MSG1/MSG2.

  Special case: if MSG1 had no caps bitmap, MSG3 is rejected only if
  it advertises any early caps.

If this doesn't sound mad I will write it up as a docs patch, mostly
as a guideline to our future selves.

> 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.

This is true but we would like to be able to later invent capabilities
which can for some reason not be advertised until MSG3/MSG4.

> 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.

I think this is a potential future landmine if anyone adds
capabilities which degrade security but do not break compatibility.
Eg, a cap bit meaning "please leak the secret key for debugging, or
some similar nonsense.

Probably we should add a plain assignment, after the signature check.


Ian Jackson <ijackson at chiark.greenend.org.uk>   These opinions are my own.

If I emailed you from an address @fyvzl.net or @evade.org.uk, that is
a private address which bypasses my fierce spamfilter.

More information about the sgo-software-discuss mailing list