IETF-SSH archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Terrapin



Peter Gutmann wrote:
>> 3. The long-term fix is to create an IETF-standardised EtM mechanism
>>    to replace the third-party one.

Mouse wrote:
> Again, I disagree.  Anything that leads to sending packet lengths in
> the clear will make prefix truncation trivially easy.

I don't think Peter intended to imply that the IETF version of EtM would
make the same mistakes! Indeed, surely the point of replacing it would
be to _fix_ all the mistakes we can.

I certainly agree that it would be nice not to send packet lengths in
the clear. (Although I've argued before in favour of decoupling the
semantic SSH messages from the unit of encrypted data, so that you could
have multiple short messages in a single encrypted block, split a long
messages across block boundaries, or randomly straddle an IGNORE across
each boundary just to confuse attackers. In that situation I'd be less
worried about sending _block_ lengths in clear, since practically
speaking they'd be inferrable from the TCP headers anyway.)

For my money, the big problem with the Terrapin-vulnerable modes is that
they reinitialise the cipher and/or MAC per packet, based only on the
sequence number. That's the real reason why you can delete the first
encrypted packet from a ChaCha20+Poly1305 stream and nobody notices: the
packet you deleted says (with cryptographic attestation) "packet number
4 is EXT_INFO(...)" and the one you kept says "packet number 5 is
SERVICE_ACCEPT(...)", and the two claims are independent, so the latter
doesn't become invalid when it doesn't have the former to follow.

This reinitialisation strategy is vitally _necessary_ in a datagram-
based crypto protocol, such as a VPN that encapsulates individual IP
fragments in encrypted UDP wrappers. In that situation you _have_ to be
able to lose a packet and not get the stream out of sync. But in a
stream-based protocol like SSH, it's the other way round: what was a
necessary feature becomes a potential problem.

I think that a redesign of the BPP ought to ensure it explicitly ties
the packets together into an unbreakable stream.

Something like: every packet ought to be (implicitly) making a claim
which is EITHER

  I am the first encrypted packet, and the MAC of all the cleartext data
  I sent during initial kex was XXXXXX

OR

  I expect to directly follow another encrypted packet, whose MAC is
  XXXXXX

and enough associated data should be baked into the new packet's MAC to
verify whichever of those claims it makes.

This also ensures that the first encrypted packet sent in each direction
can be used to verify the integrity of all the cleartext data
beforehand. Then there's no need for the strict-kex bodge of
_forbidding_ extraneous things like SSH_MSG_IGNORE during key exchange;
instead, you permit them, but expect that once crypto is established,
the verified peer confirms that it really did send them.

Cheers,
Simon

-- 
import hashlib; print((lambda p,q,g,y,r,s,m: (lambda w:(pow(g,int(hashlib.sha1(
m.encode('ascii')).hexdigest(),16)*w%q,p)*pow(y,r*w%q,p)%p)%q)(pow(s,q-2,q))==r
and s%q!=0 and m)(12342649995480866419, 2278082317364501, 1670428356600652640,
5398151833726432125, 645223105888478, 1916678356240619, "<anakin%pobox.com@localhost>"))



Home | Main Index | Thread Index | Old Index