Subject: [Hipsec] Issue 12: Birthday check badly defined

From: [email-masked] (Pekka Nikander)
Date: Mon May 3 01:57:01 2004

>> Finally, due to the desire to make it possible for Alice
>> to make a difference between a replayed and fresh R1s,
>> I think that we need to retain the birthday parameter
>> even if we remove resynchronization out of the base spec,
>> and even make it stronger.  Basically, it seems to me best
>> to increment birthday count whenever old R1s are not
>> accepted any more.  This is apparently a change to the
>> current draft.
>
> Originally, [...], Birthday was supposed to
> be incremented upon system reboot and SA time outs.
> As far as I can tell, the main reason for needing this
> R1 replay protection was because the system was using
> "unknown SPIs" as an implicit I1 packet.

Even though the current nor the old versions of the drafts
do not say much more, IIRC the issue was subtler.  I vaguely
remember one discussion with Bob M. where he described the
reasons behind the design of the birthday mechanism, and I
think that there was something more.  But my memory fails
with the details.  Anyway, I don't think that it matters
any more.  But maybe somebody else remembers?

> Now, we do not use unknown SPIs anymore as an implicit
> I1.  [...]  I only get an I2 from my peer
> if it decided it wanted to resync with me-- I can use
> the cookie rotation to assure that this is a current
> I2, and signature and other fields to validate.

In the light of your analysis below, I agree.

> Case i) (normal HIP exchange)
>   The only mischief that seems possible is that I1s or
>   R1s could be replayed, causing the initiator to get
>   more than one R1, while in state I1-SENT or I2-SENT.
>   ...  Birthday here
>   may be useful as an R1 freshness counter, if we
>   allow hosts in I2-SENT to start over only if they
>   receive an R1 with a higher count ...

Agreed.

> Case ii)
>   The host will send an I1, which will trigger an R1
>   from the peer, who is already ESTABLISHED.  If
>   the resulting I2 passes cookie checks and signature,
>   then it means that the peer must want to reestablish
>   the SAs (resync).  I do not see what additional
>   protection that birthday check affords-- seems
>   redundant with cookie rotation.

Yes, this seems to be the case.  OTOH, the case i) protection
for the host itself still applies, as you imply.

> Case iii)
>   Data will be sent on an SPI that will be unknown
>   to the peer.  In this case, either the peer will
>   drop it silently or send the HIP NOTIFY-- in either
>   case, the local host will eventually kill off its
>   local HIP state, start over, and we are back to
>   case i).

As I argued before, the peer should be very careful in
sending NOTIFYs.  If it sends a signed NOTIFY, it needs
to spend cycles in signing the NOTIFY, and that opens
a possible DoS attack.  Sure, we can counter the threat
with careful resource control, but that still leaves the
possibility of increasing the CPU load without actually
overloading.

Sending an unsigned NOTIFY is one possible option, and
might be good.  OTOH, at least in IPv6 case I would
rather send an ICMP Parameter Problem, Type 0, with the
pointer pointing to the SPI number.  That should also
work for IPv4, as the SPI number fits within the first
8 bytes of the ESP payload.  That would be pretty
generic, and potentially work both for HIP and IKE.
And even that rate limited, of course.

Then the host itself must be, of course, pretty careful
of not dropping its existing (incoming) SAs before it
has completed resynchronisation and got an R2.  We have
to remember that the ICMP may be spoofed, and in the IPv4
case where it may not contain the replay protection field,
it may even be sent out of the blue, without really being
able to see the original ESP packet.

But that all doesn't change the argument over the
birthday value.  In the light of operational concerns,
the idea of replying to an unknown SPI with and R1
seems like a nice optimisation that just doesn't work
well enough in real life.

> So in summary, it seems to me that birthday is really
> only useful as an R1 freshness counter so that the
> Initiator knows when to process an R1 when in state
> I2-SENT.

I concur.

> In essence, this R1 counter is only needed
> because R1s are precomputed and stateless with respect
> to the I1.  If my thinking is wrong, it would be useful
> to document the attack scenario clearly.  And if people
> agree with the above, then we need to make some changes
> to R1 processing, and to the I2 processing perhaps when
> in state R2-SENT (because a new I2 based on newer R1
> may be forthcoming).  "Birthday" may be the wrong term
> for this counter.

We seem to mostly agree.  I think that "R1 generation counter"
might be a better name for the value.  There seems to be
two rules governing it:

   - it must be strictly incremented (never decrease)
   - it must be incremented every time old R1s cease
     to be valid

Could you suggest modifications to the current text?

--Pekka