<< | Thread Index | >> ]    [ << | Date Index | >> ]

Subject: Re: CIPE protocol crypto questions
From: Olaf Titz <olaf,AT,bigred,DOT,inka,DOT,de>
Date: Mon, 12 Feb 2001 13:30:40 +0100
In-reply-to: <966tfo$ckb$1@sana.furryterror.org>

>       Also:  How would TCP path MTU discovery work?  PMTUD requires
>       receiving an ICMP fragmentation-required message with the correct
>       MTU, but if the DF bit is set on CIPE's UDP carrier packet,
>       and a router on the Internet sends an ICMP fragmentation-required
>       message, then this ICMP message will be sent to the CIPE peer,
>       and _not_ to the TCP peer that needs the path MTU information.

There is some code in the tunnel driver which is not entirely clear to
me, which appears to address this issue. Linux 2.2 and later
apparently does PMTUD on the IP level and the tunnel driver should
process the ICMPs from the carrier, adjust the route cache, and notify
the sender itself. But it could also be that I'm off here.

Just re-checking I find that I have marked the section of code
responsible for notifying #if 0. If you know the Linux kernel
networking a bit, could you please check in cipe/output.c after the
dprintk(..., "adjusting PMTU") if it is correct to send an ICMP (or to
send _this_ ICMP) there? I don't have the necessary equipment to
really test it in practice.

With 2.0 I'm pretty sure it's broken, but its tunnel driver has other
problems too.

>       b.  It's a feature, because if you care enough about IP TOS=20
>       to set it for your application on the VPN, then you want routers
>       on the Internet carrying the UDP carrier packets to have the same
>       routing information.  This justifies TOS bits, but not DF.

IMHO this falls under the same category as the question "what to do
with the TTL". There are pros and cons for both copying and resetting,
which means I should make it configurable.

It's not easy to decide what to do with DF, because the driver can't
see for what purpose the DF was set. If it's for PMTUD then there is
at least some interaction with the kernel's internal PMTUD. If it's
for other purpose then I'm reluctant to drop it and let the carrier
fragment the packet despite the sender saying no.

>       c.  It's an accident, because most of the code for CIPE was
>       copied unaudited from the IPIP tunneling code...

That's the primary reason. I'm still struggling with understanding how
the PMTU thing works out and why the standard tunnel does what it
does. I know it's very likely that (a) something is wrong with this
aspect in CIPE and (b) everything which is broken here is broken in
the standard tunnel too.

> 2.  The current protocol uses two kinds of packets, encrypted with
> different keys.  These packets are distinguished by one bit of the IV
> of each packet.  This creates two kinds of problems:
>       a.  It's easy to isolate the key exchange, ping, etc. packets
>       from the IP-carrying data packets by checking this bit, and

Not quite. Usually the control packets are encrypted under the current
dynamic key, the static key is only used as a fallback when the
dynamic one is already expired. So it is likely that the _last_ "1"
(first bit) packet in a stream of "1" packets followed by a "0" packet
is a key exchange (because the sender invalidates its sending dynamic
key _after_ sending NK_IND). OTOH you can't deduce anything about the
type of "0" packets.

> Other postings on the CIPE list indicate that key exchange takes place
> using the current dynamic key, instead of the shared static key,=20
> if there is a valid one known to both peers.  If true, this would
> effectively turn this problem into a simple DOS (by preventing the
> dynamic key from ever being negotiated at all).  The documentation
> doesn't seem to mention this, though.

It does discuss this issue, in the protocol description under
"Security considerations". The recently discovered goof-up in the
control packet timestamps (until recently ciped did not process them
correctly) has also urged me to reconsider the measure described
there, namely, a protection in the driver against sending greater
amounts of data using the static key.

>       a.  Assume that 99%+ of the traffic is encrypted using the most
>       recently negotiated dynamic key, and always try the most recently
>       negotiated dynamic key, then the second most recently negotiated
>       dynamic key, then the static key, relying on the CRC of each
>       packet to identify when the decryption was successful.  This=20
>       would allow the 64th bit of the IV to be random again.

What I always wanted to avoid is trying more than one key on each
packet. Before I invented the "first bit of IV" kluge the
consideration was, decrypt each packet using the most recent dynamic
key and if that fails, using the static key.

The problem is, this makes it even easier to do DOS attacks by just
feeding the receiver junk, and efficiency was very high on the
priority list.

>       b.  Encrypt the IV using the static key and cipher in ECB mode.

This is too much data encrypted under the static key. The static key
was assumed to be very long-lived, and if an attacker has months of
remaining key lifetime to burn, you don't want to feed him megapackets
of ciphertext. Just to be sure. (After all, this is the reason to use
dynamic keys in the first place.)

> 3.  The CRC function for validating each packet is linear.  If some
> properties are known about the data and cipher used, it is easier to
> modify a packet and maintain a correct CRC than certain other hash
> functions.  This attack can theoretically be used against SSH, which uses
> CRC's for integrity checking as well.  WEP is completely vulnerable to
> this kind of attack, because it uses RC4 as a cipher.

Because CIPE uses a block cipher in CBC mode, you can't just modify a
packet and predict the influence on the CRC, as each changed bit in
the input (both for encryption and decryption) influences at least 64
bits in the output.

If I remember right this was the reason why the RC4 cipher was
withdrawn from SSH, precisely because it does not offer this kind of
protection. It is also a concern currently with PKCIPE, which has a
single checksum byte covering the packets and uses RC4 - this means
the checksum is a framing check only, _not_ any kind of signature.
(I'm just working on strengthening the parameter exchange process in
PKCIPE agaist this kind of attacks. I believe though that at this
stage the worst an attacker can do is DOS.)

> Using a CRC of an MD5 or SHA-1 hash comes to mind as a possible
> solution--the message integrity check data is the same length, but the
> function is no longer linear wrt the encrypted data.  If we are willing
> to accept a larger protocol overhead, an entire MD5 or SHA-1 hash can
> be used as well.

I've sometimes thought about that, too. Actually instead of running a
CRC over the SHA1 it _should_ suffice to take just the first 32 bits
of it (I'm not entirely certain about that, do you have any reference
which covers this?) Of course, the reason for the choice of CRC in the
original implementation was that I didn't want to burn too many
precious cycles of '386 processing power. With today's hardware this
isn't a concern any more, but the length of the packet still is.


<< | Thread Index | >> ]    [ << | Date Index | >> ]