[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 18:16:37 BST 2017
Ian Jackson <ijackson at chiark.greenend.org.uk> writes:
> 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.
Oh. Well, in that case, I'll take that version, because it's rather
simpler.
> 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.
Fair enough. Well, we're making progress now, I think. In particular,
I think we've established that, in fact, sorting out the semantics of
capabilities is something we can do as a (logically at least) different
project. To that end, I've floated my `make the early caps set be
dynamic' patch to the top my stack.
> > 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
OK. In that case, do we need to actually remember whether MSG1 had any
caps in? Is there a semantic difference here between MSG1 without caps,
and MSG1 with zero caps?
> 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.
Are they? Honestly, I think currently defined caps are MSG(inf, 2). I
stared at the code: the responder currently does /nothing at all/ with
capabilities declared by the initiator, other than verifying a
tautology. Searching for `remote_capabilities' in master brings me:
* `struct site' has a structure member used to record the peer's caps;
* `struct msg' has a structure member used to hold the caps in an
incoming message;
* `set_new_transform' prints them in a log message;
* `unpick_msg' extracts the caps word from an incoming message and
stashes it in `m->remote_capabilities';
* `check_msg' makes sure `m->remote_capabilities' matches
`st->remote_capabilities' when receiving MSG4, so this is the
initiator checking;
* `process_msg1' and `process_msg2' copy `m->remote_capabilities' into
`st->remote_capabilities';
* `process_msg2' furthermore uses `st->remote_capabilities' to decide
on a transform to use, but this is the initiator again;
* `generate_msg3' inspects `st->remote_capabilities' to decide what
kind of MSG3 to send, but this is the initiator again;
* `process_msg3' checks that
m.remote_capabilities & ~st->remote_capabilities & CAPAB_EARLY
is zero, but `CAPAB_EARLY' is zero, so this is always true; it then
augments `st->remote_capabilities' with `r->remote_capabilities';
and
* `site_apply' initializes `st->remote_capabilities' to zero.
The responder basically just shuffles the things about for a bit and
then throws them away. Nothing would be different if the initiator
never bothered with the things. (I tested this. OK, it's necessary
that MSG3 say /something/ there, otherwise the `mtu_target' ends up in
the wrong place.) My branch changes this analysis not at all.
> 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.
Apart from that, errr, small observation, the description above seems
precise and sensible. Thanks.
> 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.
Fair enough. I'm having trouble thinkind what such a thing might look
like, but I'm happy to agree that it's sensible to allow for the
possibility.
> 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.
I was having trouble thinking of a plausible meaning such a `bad cap'
would have. I originally had a couple of extra paragraphs which sort of
petered out.
> Probably we should add a plain assignment, after the signature check.
That would be sufficient, certainly. Is it plausible that an
implementation might withdraw a capability having observed some fact
about its peer? If so, then a plain assignment would be necessary, too,
for the withdrawal to be effective.
-- [mdw]
More information about the sgo-software-discuss
mailing list