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

From: [email-masked] (Henderson, Thomas R)
Date: Thu Apr 29 14:49:00 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, and therefore probably requires opening
> a new issue.  [Petri, please.]

(note, this also pertains to issue 22 resync)

I am trying to reason through the current definition of
birthday. =20

Originally, birthday was used in the following context:

Initiator        Responder
                  (reboot)
------> data on SPI    ! unknown SPI (have I rebooted?)
          <---- (send R1 with birthday count)
** here, initiator checks birthday count-- if larger, then
   drop existing SA and process R1-- otherwise ignore R1

Birthday was used in this context to protect against=20
R1 replay, since R1 was a packet that could be used to
reset an existing SA-- therefore, a mischievous host
could replay an R1 and get the two hosts to restart
their HIP exchange.

Additionally, Birthday was used when restarting state if
SAs timed out.  Therefore, Birthday was supposed to=20
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=20
"unknown SPIs" as an implicit I1 packet.

Now, we do not use unknown SPIs anymore as an implicit
I1.  So the original case does not apply anymore,=20
because the initiator will be in I1-SENT state if
it legitimately receives an R1.  If I get an R1 but am=20
not in I1-SENT, then I ignore it.  If I think that I=20
have an established SA, I only resync it if I get a=20
new I2 from my peer.  I only get an I2 from my peer=20
if it decided it wanted to resync with me-- I can use=20
the cookie rotation to assure that this is a current=20
I2, and signature and other fields to validate.

Let's look at three cases when a host has data
to send and the two hosts either have no state or=20
inconsistent state (e.g., one side rebooted or hard
timeout of its SA) =20
i) neither party has HIP state
ii) a system has no HIP state but its peer thinks that
it does
iii) a system has HIP state but its peer does not

Assume also that we are also dealing with someone
who can eavesdrop on the packets and potentially
replay some of them, but not mangle, drop, or
reorder them (in which case, all bets for a successful
exchange are off)

Case i) (normal HIP exchange)
  The only mischief that seems possible is that I1s or=20
  R1s could be replayed, causing the initiator to get
  more than one R1, while in state I1-SENT or I2-SENT.
  Note that right now, as things are defined, a system
  only processes the first R1 and discards all later
  ones; this seems to be a problem.  Birthday here=20
  may be useful as an R1 freshness counter, if we
  allow hosts in I2-SENT to start over only if they=20
  receive an R1 with a higher count-- this would protect
  against someone who sniffs the I1 and sends a replayed
  stale R1 to the initiator before the legitimate R1
  can arrive.

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

Case iii)=20
  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).

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.  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=20
may be forthcoming).  "Birthday" may be the wrong term
for this counter.

Thoughts?

Tom