Subject: [Hipsec] keymat / state machine problem with packet retransmission

From: Miika Komu <[email-masked]>
Date: Fri, 29 Jul 2005 14:17:45 +0300 (EEST)

I discovered a problem in the state machine that may be worthy of noting
the draft. I discovered a hint for the problem during interops, and later
I could confirm it by running base exchange with the HIPL implementation
so that each HIP control packet sent was repeated always N x times.

The problem is caused by the following things:
a) i and j were added to the keymaterial (draft 02 -> 03)
b) both the initiator and responder must take care of detecting
   properly retransmitted packets, or otherwise they can generate new
   keymaterial different from the other, especially if the initiator
   does not save the cookie j
c) (the initiator and responder must take care of creating new SPI values
    if the packet was a retransmission - may be this is already include in
    the draft text somewhere)

The solution to the problem is scetched in pseudo C code below because I
am preparing to go for a holiday and I don't have the time to provide
text. I will leave it for the reader to analyze the problem; is it the
state machine specification that needs some fine tuning or is it just our
code that was buggy?)

hip_handle_r1(struct hip_control_msg *r1,
              struct hip_host_association *entry) {
	if (state == HIP_STATE_I2_SENT)
		retransmission = 1;
	else
		retransmission = 0;

  	/* solve puzzle: if this is a retransmission, we have to preserve
	   the old solution */
	if (!retransmission) {
		struct hip_puzzle *pz = NULL;

		pz = hip_get_param(r1, HIP_PARAM_PUZZLE);
		solved_puzzle = hip_solve_puzzle(pz, r1,
                                                 HIP_SOLVE_PUZZLE);
		I = pz->I;
		entry->puzzle_solution = solved_puzzle;
		entry->puzzle_i = pz->I;
	} else {
		I = entry->puzzle_i;
		solved_puzzle = entry->puzzle_solution;
	}

        /* keymaterial producing can be skipped if retransmission */
	hip_produce_keying_material(I, solved_puzzle, etc);

        // do rest of the stuff, send i2
}

hip_handle_i2(struct hip_control_msg *i2,
              struct hip_host_association *entry) {

	if (entry && (entry->state == HIP_STATE_R2_SENT ||
		    entry->state == HIP_STATE_ESTABLISHED)) {
		/* If the I2 packet is a retransmission, we need reuse the
 		   the SPI/keymat that was setup already when the first I2
                   was received. */
		retransmission = 1;
	} else {
		retransmission = 0;
        }

        /* keymaterial producing can be skipped if retransmission */
	hip_produce_keying_material(I, J, etc);

        // do rest of the stuff

        hip_add_SAs(); /* reuse SPI if retransmission! */

        // do rest of the stuff, send r2

}

hip_handle_r2(struct hip_control_msg *r2,
              struct hip_host_association *entry) {

	if (entry->state == HIP_STATE_ESTABLISHED) {
		retransmission = 1;
		HIP_DEBUG("Retransmission\n");
	} else {
		retransmission = 0;
        }

        // do rest of the stuff

        hip_add_SAs(); /* reuse SPI if retransmission! */

        // do rest of the stuff, transition to established
}

I tested above code in our HIPL implementation. It worked fine with and
without retransmission.

-- 
Miika Komu              [email-masked]          http://www.iki.fi/miika/

_______________________________________________
Hipsec mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/hipsec

---

From: Miika Komu <[email-masked]>
Date: Fri, 29 Jul 2005 16:21:49 +0300 (EEST)

> so that each HIP control packet sent was repeated always N x times.

Let me elaborate more with two examples:

Example A: C and D happen simultaneously:

a) ---->  I1
b) <----  R1
c) -----> I2
d) <----  R1  reflection of R1 (exactly the same as in b): initiator
              processes again!
e) ------> I2 the cookie solution must be same as in c, otherwise
              end-up with mismatching keymat
e) <---- R2

Example B: d and e happen simultaneously:

  init   resp

a) ----> I1
b) <---- R1
c) -----> I2
d) <---- R2
e) -----> I2 the cookie solution must be same as c, otherwise
             end-up with mismatching keymat

Unless my thinking is incorrect, some text should be added that the
initiator must remember the cookie solution it sent in I2 (and not to
calculate a new one) upon retransmissions. The same applies for the SPI
value.