> Cons: I'm not aware of any actual usage during the last few decades
> of ssh.
True. But is that a failing of the mechanism, or is it a virtue of the
original design?
A bit of both, perhaps, but I think the point is that if it hasn't been used much, perhaps that mechanism is unimportant.
> It could have been used for MSG_EXT_INFO, but for reasons I'm
> don't remember (or maybe never was familiar with), RFC 8308
> defines magic symbols for the key exchange methods list
> instead.
I don't recall the reasoning, if indeed I ever saw it. My best guess
at the moment is that that was done so that its the presence or absence
would be signed over by kex - that is, it's a workaround for kex
signing over only some of the cleartext packets, rather than all of
them. More on this below.
That's certainly a benefit, but IIRC the pattern of using magic kex method symbols was at least in part to avoid interop issues with older implementations that failed to handle unknown messages correctly. I know you're a proponent of telling broken implementations to go pound salt, but backward compatibility with existing software that can't be easily replaced can be important, and some folks here have placed a value on interop that is unusually high even for the IETF.
As for kex signing over only some of the cleartext, it's been so long I
don't recall any discussion that might have taken place on that. But
it does occur to me that there is some difficulty defining the range of
bytes to be signed over. If one party can send packets not strictly
necessary for kex, the other party must guess where the "end of
cleartext" point is.
I would say the best way to handle this would be to have a packet which
is sent by each party when it has sent everything it's going to before
NEWKEYS. The kex hash then hashes everything before - or perhaps
before-and-including - this packet. Any traffic whatever sent after it
and before NEWKEYS is specified to cause immediate disconnection.
A separate message is not needed for this. The NEWKEYS message itself is the end of cleartext, always. It can even be included in the hash, if desired.
This does open up a possible DoS, in that it means the implementation
must buffer all cleartext in both directions, so injecting an
unreasonable flood of IGNOREs can run the implementation out of RAM.
This could be as simple as adding a note that an unreasonably long
cleartext conversation, as well as excessively large single packets, is
grounds for disconnecting.
No, you don't need to buffer everything; hash state is normally built incrementally in a way that uses a constant amount of storage regardless of the amount of data to be hashed. You do need to buffer everything in both directions until you've seen the peer's KEXINIT so you know what hash to use.
The hash could be defined to hash over not the cleartext conversations
but instead over hashes of them, meaning that an implementation doesn't
need to buffer all the text, instead just keeping two
hashes-in-progress and feeding the cleartext into them. But I'm not
sure whether that would be cryptographically suitable.
That doesn't buy anything, since you still can't start computing such a hash until you know the algorithm to be used.
-- Jeff