IETF-SSH archive

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

Re: Terrapin



>> I certainly agree that it would be nice not to send packet lengths in
>> the clear.  [...]
>
> As I understand it (which even more than usual may be wrong!), this
> happened largely in respose to the SandP attack, which used peer
> behaviour in response to invalid packet lengths as an oracle for
> attacking the crypto; combined with certain crypto modes, it leads to a
> plaintext-revealing attack.

Yes. I think ChaCha20+Poly1305's protocol (despite its recently
discovered other flaw) has a reasonable defence here, which is simply to
use a _separate_ instance of the stream cipher for encrypting packet
lengths. That way, the only thing you get an oracle on is the cipher
instance that tells you nothing other than lengths; it doesn't let you
into anything else, because that's all encrypted with a different
cipher.

I agree with someone else's comment elsethread (Niels?) that the
_robust_ way to handle this would be to AEAD some fixed initial amount
of a packet / encrypted block, including the length, and only once that
MAC was validated, to trust the length field enough to read the
remaining data, and then check a second MAC on it. But of course this is
costly in time and space, especially for small packets. If you don't
have SHA-256 acceleration, two HMAC-SHA-256 per tiny packet is a lot
more painful than one!

(Perhaps if we were combining small packets into larger cipher+MAC
blocks that overhead might be reduced?)

Another reasonably cheap defence might be to follow the encrypted packet
length field with a second 32-bit field, whose value is the true packet
length times a constant k. k would be derived from the shared secret at
KEX time (and coerced to be an odd number, so that it's invertible mod
2^32, so that multiplying by it is injective), and fixed throughout the
session. Then an attacker trying to implement an oracle by modifying the
cipher block containing the length field would have to ensure that they
modified the len and k*len words in a way that was consistent; if they
couldn't do that, that initial check would blow them out of the water
with probability 1 - 2^-32.

(Inspired by the general form of polynomial-based MACs. Ideally this
would use a random invertible element of GF(2^32), which would ensure
that successfully modifying both fields was equivalent to knowing k,
because (original block) xor (modified block) would have to contain a
pair of polynomials whose ratio was k. But the integer-multiplication
variant is much cheaper on typical CPUs!)

This approach is conveniently independent of the 'separate stream cipher
instance' defence, so one could do both at once, and then the attacker
will almost certainly explode the connection at the first attempt to
modify a length field, _and_ if they succeed it only tells them about
other length fields.

>> 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.
>
> Well, not really for the MAC version such as I sketched above, because
> the MAC is `none' during the initial exchange.

In my suggestion, the first encrypted packet - being the only one which
doesn't have a previous MAC to tie itself to - would instead tie itself
to a MAC computed post-hoc using the initial set of session keys,
covering all the cleartext data sent by the sending side prior to
NEWKEYS.

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>"))

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