unit-tests: Add tests for IKE_SA rekeying if collision is not detected by one peer
[strongswan.git] / src / libcharon / tests / suites / test_ike_rekey.c
1 /*
2 * Copyright (C) 2016 Tobias Brunner
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "test_suite.h"
17
18 #include <tests/utils/exchange_test_helper.h>
19 #include <tests/utils/exchange_test_asserts.h>
20 #include <tests/utils/job_asserts.h>
21 #include <tests/utils/sa_asserts.h>
22
23 /**
24 * Initiate rekeying the given IKE_SA.
25 */
26 #define initiate_rekey(sa) ({ \
27 assert_hook_not_called(ike_rekey); \
28 call_ikesa(sa, rekey); \
29 assert_ike_sa_state(a, IKE_REKEYING); \
30 assert_hook(); \
31 })
32
33 /**
34 * Regular IKE_SA rekeying either initiated by the original initiator or
35 * responder of the IKE_SA.
36 */
37 START_TEST(test_regular)
38 {
39 ike_sa_t *a, *b, *new_sa;
40 status_t s;
41
42 if (_i)
43 { /* responder rekeys the IKE_SA */
44 exchange_test_helper->establish_sa(exchange_test_helper,
45 &b, &a, NULL);
46 }
47 else
48 { /* initiator rekeys the IKE_SA */
49 exchange_test_helper->establish_sa(exchange_test_helper,
50 &a, &b, NULL);
51 }
52 /* these should never get called as this results in a successful rekeying */
53 assert_hook_not_called(ike_updown);
54 assert_hook_not_called(child_updown);
55
56 initiate_rekey(a);
57
58 /* CREATE_CHILD_SA { SA, Ni, KEi } --> */
59 assert_hook_rekey(ike_rekey, 1, 3);
60 assert_no_notify(IN, REKEY_SA);
61 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
62 assert_ike_sa_state(b, IKE_REKEYED);
63 assert_child_sa_count(b, 0);
64 new_sa = assert_ike_sa_checkout(3, 4, FALSE);
65 assert_ike_sa_state(new_sa, IKE_ESTABLISHED);
66 assert_child_sa_count(new_sa, 1);
67 assert_ike_sa_count(1);
68 assert_hook();
69
70 /* <-- CREATE_CHILD_SA { SA, Nr, KEr } */
71 assert_hook_rekey(ike_rekey, 1, 3);
72 assert_no_notify(IN, REKEY_SA);
73 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
74 assert_ike_sa_state(a, IKE_DELETING);
75 assert_child_sa_count(a, 0);
76 new_sa = assert_ike_sa_checkout(3, 4, TRUE);
77 assert_ike_sa_state(new_sa, IKE_ESTABLISHED);
78 assert_child_sa_count(new_sa, 1);
79 assert_ike_sa_count(2);
80 assert_hook();
81
82 /* we don't expect this hook to get called anymore */
83 assert_hook_not_called(ike_rekey);
84
85 /* INFORMATIONAL { D } --> */
86 assert_single_payload(IN, PLV2_DELETE);
87 s = exchange_test_helper->process_message(exchange_test_helper, b, NULL);
88 ck_assert_int_eq(DESTROY_ME, s);
89 call_ikesa(b, destroy);
90 /* <-- INFORMATIONAL { } */
91 assert_message_empty(IN);
92 s = exchange_test_helper->process_message(exchange_test_helper, a, NULL);
93 ck_assert_int_eq(DESTROY_ME, s);
94 call_ikesa(a, destroy);
95
96 /* ike_rekey/ike_updown/child_updown */
97 assert_hook();
98 assert_hook();
99 assert_hook();
100
101 charon->ike_sa_manager->flush(charon->ike_sa_manager);
102 }
103 END_TEST
104
105 /**
106 * Both peers initiate the IKE_SA rekeying concurrently and should handle the
107 * collision properly depending on the nonces.
108 */
109 START_TEST(test_collision)
110 {
111 ike_sa_t *a, *b, *sa;
112 status_t status;
113
114 exchange_test_helper->establish_sa(exchange_test_helper,
115 &a, &b, NULL);
116
117 /* When rekeyings collide we get two IKE_SAs with a total of four nonces.
118 * The IKE_SA with the lowest nonce SHOULD be deleted by the peer that
119 * created that IKE_SA. The replaced IKE_SA is deleted by the peer that
120 * initiated the surviving SA.
121 * Four nonces and SPIs are needed (SPI 1 and 2 are used for the initial
122 * IKE_SA):
123 * N1/3 -----\ /----- N2/4
124 * \--/-----> N3/5
125 * N4/6 <-------/ /----- ...
126 * ... -----\
127 * We test this four times, each time a different nonce is the lowest.
128 */
129 struct {
130 /* Nonces used at each point */
131 u_char nonces[4];
132 /* SPIs of the deleted IKE_SAs (either redundant or replaced) */
133 uint32_t del_a_i, del_a_r;
134 uint32_t del_b_i, del_b_r;
135 /* SPIs of the kept IKE_SA */
136 uint32_t spi_i, spi_r;
137 } data[] = {
138 { { 0x00, 0xFF, 0xFF, 0xFF }, 3, 5, 1, 2, 4, 6 },
139 { { 0xFF, 0x00, 0xFF, 0xFF }, 1, 2, 4, 6, 3, 5 },
140 { { 0xFF, 0xFF, 0x00, 0xFF }, 3, 5, 1, 2, 4, 6 },
141 { { 0xFF, 0xFF, 0xFF, 0x00 }, 1, 2, 4, 6, 3, 5 },
142 };
143 /* these should never get called as this results in a successful rekeying */
144 assert_hook_not_called(ike_updown);
145 assert_hook_not_called(child_updown);
146
147 exchange_test_helper->nonce_first_byte = data[_i].nonces[0];
148 initiate_rekey(a);
149 exchange_test_helper->nonce_first_byte = data[_i].nonces[1];
150 initiate_rekey(b);
151
152 /* CREATE_CHILD_SA { SA, Ni, KEi } --> */
153 exchange_test_helper->nonce_first_byte = data[_i].nonces[2];
154 assert_hook_not_called(ike_rekey);
155 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
156 assert_ike_sa_state(b, IKE_REKEYING);
157 assert_child_sa_count(b, 1);
158 assert_ike_sa_count(0);
159 assert_hook();
160
161 /* <-- CREATE_CHILD_SA { SA, Ni, KEi } */
162 exchange_test_helper->nonce_first_byte = data[_i].nonces[3];
163 assert_hook_not_called(ike_rekey);
164 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
165 assert_ike_sa_state(a, IKE_REKEYING);
166 assert_child_sa_count(a, 1);
167 assert_ike_sa_count(0);
168 assert_hook();
169
170 /* simplify next steps by checking in original IKE_SAs */
171 charon->ike_sa_manager->checkin(charon->ike_sa_manager, a);
172 charon->ike_sa_manager->checkin(charon->ike_sa_manager, b);
173 assert_ike_sa_count(2);
174
175 /* <-- CREATE_CHILD_SA { SA, Nr, KEr } */
176 assert_hook_rekey(ike_rekey, 1, data[_i].spi_i);
177 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
178 /* as original initiator a is initiator of both SAs it could delete */
179 sa = assert_ike_sa_checkout(data[_i].del_a_i, data[_i].del_a_r, TRUE);
180 assert_ike_sa_state(sa, IKE_DELETING);
181 assert_child_sa_count(sa, 0);
182 /* if b won it will delete the original SA a initiated */
183 sa = assert_ike_sa_checkout(data[_i].del_b_i, data[_i].del_b_r,
184 data[_i].del_b_i == 1);
185 assert_ike_sa_state(sa, IKE_REKEYED);
186 assert_child_sa_count(sa, 0);
187 sa = assert_ike_sa_checkout(data[_i].spi_i, data[_i].spi_r,
188 data[_i].del_a_i == 1);
189 assert_ike_sa_state(sa, IKE_ESTABLISHED);
190 assert_child_sa_count(sa, 1);
191 assert_ike_sa_count(4);
192 assert_hook();
193
194 /* CREATE_CHILD_SA { SA, Nr, KEr } --> */
195 assert_hook_rekey(ike_rekey, 1, data[_i].spi_i);
196 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
197 /* if b wins it deletes the SA originally initiated by a */
198 sa = assert_ike_sa_checkout(data[_i].del_b_i, data[_i].del_b_r,
199 data[_i].del_b_i != 1);
200 assert_ike_sa_state(sa, IKE_DELETING);
201 assert_child_sa_count(sa, 0);
202 /* a only deletes SAs for which b is responder */
203 sa = assert_ike_sa_checkout(data[_i].del_a_i, data[_i].del_a_r, FALSE);
204 assert_ike_sa_state(sa, IKE_REKEYED);
205 assert_child_sa_count(sa, 0);
206 sa = assert_ike_sa_checkout(data[_i].spi_i, data[_i].spi_r,
207 data[_i].del_b_i == 1);
208 assert_ike_sa_state(sa, IKE_ESTABLISHED);
209 assert_child_sa_count(sa, 1);
210 assert_ike_sa_count(6);
211 assert_hook();
212
213 /* we don't expect this hook to get called anymore */
214 assert_hook_not_called(ike_rekey);
215
216 /* INFORMATIONAL { D } --> */
217 assert_single_payload(IN, PLV2_DELETE);
218 sa = assert_ike_sa_checkout(data[_i].del_a_i, data[_i].del_a_r, FALSE);
219 status = exchange_test_helper->process_message(exchange_test_helper, sa,
220 NULL);
221 ck_assert_int_eq(DESTROY_ME, status);
222 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, sa);
223 assert_ike_sa_count(5);
224 /* <-- INFORMATIONAL { D } */
225 assert_single_payload(IN, PLV2_DELETE);
226 sa = assert_ike_sa_checkout(data[_i].del_b_i, data[_i].del_b_r,
227 data[_i].del_b_i == 1);
228 status = exchange_test_helper->process_message(exchange_test_helper, sa,
229 NULL);
230 ck_assert_int_eq(DESTROY_ME, status);
231 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, sa);
232 assert_ike_sa_count(4);
233 /* <-- INFORMATIONAL { } */
234 assert_message_empty(IN);
235 sa = assert_ike_sa_checkout(data[_i].del_a_i, data[_i].del_a_r, TRUE);
236 status = exchange_test_helper->process_message(exchange_test_helper, sa,
237 NULL);
238 ck_assert_int_eq(DESTROY_ME, status);
239 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, sa);
240 assert_ike_sa_count(3);
241 /* INFORMATIONAL { } --> */
242 assert_message_empty(IN);
243 sa = assert_ike_sa_checkout(data[_i].del_b_i, data[_i].del_b_r,
244 data[_i].del_b_i != 1);
245 status = exchange_test_helper->process_message(exchange_test_helper, sa,
246 NULL);
247 ck_assert_int_eq(DESTROY_ME, status);
248 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, sa);
249 assert_ike_sa_count(2);
250
251 /* ike_rekey/ike_updown/child_updown */
252 assert_hook();
253 assert_hook();
254 assert_hook();
255
256 charon->ike_sa_manager->flush(charon->ike_sa_manager);
257 }
258 END_TEST
259
260 /**
261 * In this scenario one of the peers does not notice that there is a rekey
262 * collision because the other request is dropped:
263 *
264 * rekey ----\ /---- rekey
265 * \ /
266 * detect collision <-----\---/
267 * -------\-------->
268 * detect collision <-------\-------- delete old SA
269 * delete ---------\------>
270 * rekey done \-----> SA not found (or it never arrives)
271 */
272 START_TEST(test_collision_dropped_request)
273 {
274 ike_sa_t *a, *b, *sa;
275 message_t *msg;
276 status_t s;
277
278 exchange_test_helper->establish_sa(exchange_test_helper,
279 &a, &b, NULL);
280
281 /* Three nonces and SPIs are needed (SPI 1 and 2 are used for the initial
282 * CHILD_SA):
283 * N1/3 -----\ /----- N2/4
284 * N3/5 <-----\--/
285 * ... -----\ \-------> ...
286 * We test this three times, each time a different nonce is the lowest.
287 */
288 struct {
289 /* Nonces used at each point */
290 u_char nonces[3];
291 /* SPIs of the deleted IKE_SAs (either redundant or replaced) */
292 uint32_t del_a_i, del_a_r;
293 uint32_t del_b_i, del_b_r;
294 /* SPIs of the kept IKE_SA */
295 uint32_t spi_i, spi_r;
296 } data[] = {
297 { { 0x00, 0xFF, 0xFF }, 3, 5, 1, 2, 4, 6 },
298 { { 0xFF, 0x00, 0xFF }, 1, 2, 4, 6, 3, 5 },
299 { { 0xFF, 0xFF, 0x00 }, 3, 5, 1, 2, 4, 6 },
300 { { 0xFF, 0xFF, 0xFF }, 1, 2, 4, 6, 3, 5 },
301 };
302 /* these should never get called as this results in a successful rekeying */
303 assert_hook_not_called(ike_updown);
304 assert_hook_not_called(child_updown);
305
306 exchange_test_helper->nonce_first_byte = data[_i].nonces[0];
307 initiate_rekey(a);
308 /* drop the CREATE_CHILD_SA request from a to b */
309 msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
310 msg->destroy(msg);
311 exchange_test_helper->nonce_first_byte = data[_i].nonces[1];
312 initiate_rekey(b);
313
314 /* <-- CREATE_CHILD_SA { SA, Ni, KEi } */
315 exchange_test_helper->nonce_first_byte = data[_i].nonces[2];
316 assert_hook_not_called(ike_rekey);
317 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
318 assert_ike_sa_state(a, IKE_REKEYING);
319 assert_child_sa_count(a, 1);
320 assert_ike_sa_count(0);
321 assert_hook();
322
323 /* CREATE_CHILD_SA { SA, Ni, KEi } --> */
324 assert_hook_rekey(ike_rekey, 1, 4);
325 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
326 assert_ike_sa_state(b, IKE_DELETING);
327 assert_child_sa_count(b, 0);
328 sa = assert_ike_sa_checkout(4, 5, TRUE);
329 assert_ike_sa_state(sa, IKE_ESTABLISHED);
330 assert_child_sa_count(sa, 1);
331 assert_ike_sa_count(1);
332 assert_hook();
333
334 /* <-- INFORMATIONAL { D } */
335 assert_hook_rekey(ike_rekey, 1, 4);
336 assert_single_payload(IN, PLV2_DELETE);
337 s = exchange_test_helper->process_message(exchange_test_helper, a, NULL);
338 ck_assert_int_eq(DESTROY_ME, s);
339 call_ikesa(a, destroy);
340 sa = assert_ike_sa_checkout(4, 5, FALSE);
341 assert_ike_sa_state(sa, IKE_ESTABLISHED);
342 assert_child_sa_count(sa, 1);
343 assert_ike_sa_count(2);
344 assert_hook();
345
346 /* INFORMATIONAL { } --> */
347 assert_hook_not_called(ike_rekey);
348 assert_message_empty(IN);
349 s = exchange_test_helper->process_message(exchange_test_helper, b, NULL);
350 ck_assert_int_eq(DESTROY_ME, s);
351 call_ikesa(b, destroy);
352 assert_hook();
353
354 /* ike_updown/child_updown */
355 assert_hook();
356 assert_hook();
357
358 charon->ike_sa_manager->flush(charon->ike_sa_manager);
359 }
360 END_TEST
361
362 /**
363 * In this scenario one of the peers does not notice that there is a rekey
364 * collision because the other request is delayed:
365 *
366 * rekey ----\ /---- rekey
367 * \ /
368 * detect collision <-----\---/
369 * -------\-------->
370 * \ /---- delete old SA
371 * \-/----> detect collision
372 * detect collision <---------/ /---- TEMP_FAIL
373 * delete -----------/---->
374 * rekey done /
375 * sa already gone <--------/
376 */
377 START_TEST(test_collision_delayed_request)
378 {
379 ike_sa_t *a, *b, *sa;
380 message_t *msg;
381 status_t s;
382
383 exchange_test_helper->establish_sa(exchange_test_helper,
384 &a, &b, NULL);
385
386 /* Three nonces and SPIs are needed (SPI 1 and 2 are used for the initial
387 * CHILD_SA):
388 * N1/3 -----\ /----- N2/4
389 * N3/5 <-----\--/
390 * ... -----\ \-------> ...
391 * We test this three times, each time a different nonce is the lowest.
392 */
393 struct {
394 /* Nonces used at each point */
395 u_char nonces[3];
396 /* SPIs of the deleted IKE_SAs (either redundant or replaced) */
397 uint32_t del_a_i, del_a_r;
398 uint32_t del_b_i, del_b_r;
399 /* SPIs of the kept IKE_SA */
400 uint32_t spi_i, spi_r;
401 } data[] = {
402 { { 0x00, 0xFF, 0xFF }, 3, 5, 1, 2, 4, 6 },
403 { { 0xFF, 0x00, 0xFF }, 1, 2, 4, 6, 3, 5 },
404 { { 0xFF, 0xFF, 0x00 }, 3, 5, 1, 2, 4, 6 },
405 { { 0xFF, 0xFF, 0xFF }, 1, 2, 4, 6, 3, 5 },
406 };
407 /* these should never get called as this results in a successful rekeying */
408 assert_hook_not_called(ike_updown);
409 assert_hook_not_called(child_updown);
410
411 exchange_test_helper->nonce_first_byte = data[_i].nonces[0];
412 initiate_rekey(a);
413 exchange_test_helper->nonce_first_byte = data[_i].nonces[1];
414 initiate_rekey(b);
415
416 /* delay the CREATE_CHILD_SA request from a to b */
417 msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
418
419 /* <-- CREATE_CHILD_SA { SA, Ni, KEi } */
420 exchange_test_helper->nonce_first_byte = data[_i].nonces[2];
421 assert_hook_not_called(ike_rekey);
422 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
423 assert_ike_sa_state(a, IKE_REKEYING);
424 assert_child_sa_count(a, 1);
425 assert_ike_sa_count(0);
426 assert_hook();
427
428 /* CREATE_CHILD_SA { SA, Ni, KEi } --> */
429 assert_hook_rekey(ike_rekey, 1, 4);
430 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
431 assert_ike_sa_state(b, IKE_DELETING);
432 assert_child_sa_count(b, 0);
433 sa = assert_ike_sa_checkout(4, 5, TRUE);
434 assert_ike_sa_state(sa, IKE_ESTABLISHED);
435 assert_child_sa_count(sa, 1);
436 assert_ike_sa_count(1);
437 assert_hook();
438
439 /* CREATE_CHILD_SA { SA, Ni, KEi } --> (delayed) */
440 assert_single_notify(OUT, TEMPORARY_FAILURE);
441 exchange_test_helper->process_message(exchange_test_helper, b, msg);
442 assert_ike_sa_state(b, IKE_DELETING);
443
444 /* <-- INFORMATIONAL { D } */
445 assert_hook_rekey(ike_rekey, 1, 4);
446 assert_single_payload(IN, PLV2_DELETE);
447 s = exchange_test_helper->process_message(exchange_test_helper, a, NULL);
448 ck_assert_int_eq(DESTROY_ME, s);
449 call_ikesa(a, destroy);
450 sa = assert_ike_sa_checkout(4, 5, FALSE);
451 assert_ike_sa_state(sa, IKE_ESTABLISHED);
452 assert_child_sa_count(sa, 1);
453 assert_ike_sa_count(2);
454 assert_hook();
455
456 /* <-- CREATE_CHILD_SA { N(TEMP_FAIL) } */
457 /* the SA is already gone */
458 msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
459 msg->destroy(msg);
460
461 /* INFORMATIONAL { } --> */
462 assert_hook_not_called(ike_rekey);
463 assert_message_empty(IN);
464 s = exchange_test_helper->process_message(exchange_test_helper, b, NULL);
465 ck_assert_int_eq(DESTROY_ME, s);
466 call_ikesa(b, destroy);
467 assert_hook();
468
469 /* ike_updown/child_updown */
470 assert_hook();
471 assert_hook();
472
473 charon->ike_sa_manager->flush(charon->ike_sa_manager);
474 }
475 END_TEST
476
477 /**
478 * In this scenario one of the peers does not notice that there is a rekey
479 * collision and the delete arrives after the TEMPORARY_FAILURE notify:
480 *
481 * rekey ----\ /---- rekey
482 * \ /
483 * detect collision <-----\---/
484 * -------\-------->
485 * \ /---- delete old SA
486 * \-/----> detect collision
487 * no reschedule <---------/------ TEMP_FAIL
488 * detect collision <--------/
489 * delete ---------------->
490 * rekey done
491 */
492 START_TEST(test_collision_delayed_request_and_delete)
493 {
494 ike_sa_t *a, *b, *sa;
495 message_t *msg;
496 status_t s;
497
498 exchange_test_helper->establish_sa(exchange_test_helper,
499 &a, &b, NULL);
500
501 /* Three nonces and SPIs are needed (SPI 1 and 2 are used for the initial
502 * CHILD_SA):
503 * N1/3 -----\ /----- N2/4
504 * N3/5 <-----\--/
505 * ... -----\ \-------> ...
506 * We test this three times, each time a different nonce is the lowest.
507 */
508 struct {
509 /* Nonces used at each point */
510 u_char nonces[3];
511 /* SPIs of the deleted IKE_SAs (either redundant or replaced) */
512 uint32_t del_a_i, del_a_r;
513 uint32_t del_b_i, del_b_r;
514 /* SPIs of the kept IKE_SA */
515 uint32_t spi_i, spi_r;
516 } data[] = {
517 { { 0x00, 0xFF, 0xFF }, 3, 5, 1, 2, 4, 6 },
518 { { 0xFF, 0x00, 0xFF }, 1, 2, 4, 6, 3, 5 },
519 { { 0xFF, 0xFF, 0x00 }, 3, 5, 1, 2, 4, 6 },
520 { { 0xFF, 0xFF, 0xFF }, 1, 2, 4, 6, 3, 5 },
521 };
522 /* these should never get called as this results in a successful rekeying */
523 assert_hook_not_called(ike_updown);
524 assert_hook_not_called(child_updown);
525
526 exchange_test_helper->nonce_first_byte = data[_i].nonces[0];
527 initiate_rekey(a);
528 exchange_test_helper->nonce_first_byte = data[_i].nonces[1];
529 initiate_rekey(b);
530
531 /* delay the CREATE_CHILD_SA request from a to b */
532 msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
533
534 /* <-- CREATE_CHILD_SA { SA, Ni, KEi } */
535 exchange_test_helper->nonce_first_byte = data[_i].nonces[2];
536 assert_hook_not_called(ike_rekey);
537 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
538 assert_ike_sa_state(a, IKE_REKEYING);
539 assert_child_sa_count(a, 1);
540 assert_ike_sa_count(0);
541 assert_hook();
542
543 /* CREATE_CHILD_SA { SA, Ni, KEi } --> */
544 assert_hook_rekey(ike_rekey, 1, 4);
545 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
546 assert_ike_sa_state(b, IKE_DELETING);
547 assert_child_sa_count(b, 0);
548 sa = assert_ike_sa_checkout(4, 5, TRUE);
549 assert_ike_sa_state(sa, IKE_ESTABLISHED);
550 assert_child_sa_count(sa, 1);
551 assert_ike_sa_count(1);
552 assert_hook();
553
554 /* CREATE_CHILD_SA { SA, Ni, KEi } --> (delayed) */
555 assert_single_notify(OUT, TEMPORARY_FAILURE);
556 exchange_test_helper->process_message(exchange_test_helper, b, msg);
557 assert_ike_sa_state(b, IKE_DELETING);
558
559 /* delay the INFORMATIONAL request from b to a */
560 msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
561
562 /* <-- CREATE_CHILD_SA { N(TEMP_FAIL) } */
563 assert_hook_rekey(ike_rekey, 1, 4);
564 assert_no_jobs_scheduled();
565 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
566 assert_ike_sa_state(a, IKE_REKEYED);
567 assert_child_sa_count(a, 0);
568 sa = assert_ike_sa_checkout(4, 5, FALSE);
569 assert_ike_sa_state(sa, IKE_ESTABLISHED);
570 assert_child_sa_count(sa, 1);
571 assert_ike_sa_count(2);
572 assert_scheduler();
573 assert_hook();
574
575 /* <-- INFORMATIONAL { D } (delayed) */
576 assert_single_payload(IN, PLV2_DELETE);
577 s = exchange_test_helper->process_message(exchange_test_helper, a, msg);
578 ck_assert_int_eq(DESTROY_ME, s);
579 call_ikesa(a, destroy);
580
581 /* INFORMATIONAL { } --> */
582 assert_hook_not_called(ike_rekey);
583 assert_message_empty(IN);
584 s = exchange_test_helper->process_message(exchange_test_helper, b, NULL);
585 ck_assert_int_eq(DESTROY_ME, s);
586 call_ikesa(b, destroy);
587 assert_hook();
588
589 /* ike_updown/child_updown */
590 assert_hook();
591 assert_hook();
592
593 charon->ike_sa_manager->flush(charon->ike_sa_manager);
594 }
595 END_TEST
596
597 /**
598 * One of the hosts initiates a DELETE of the IKE_SA the other peer is
599 * concurrently trying to rekey.
600 *
601 * rekey ----\ /---- delete
602 * \-----/----> detect collision
603 * detect collision <---------/ /---- TEMP_FAIL
604 * delete ----\ /
605 * \----/----->
606 * sa already gone <--------/
607 */
608 START_TEST(test_collision_delete)
609 {
610 ike_sa_t *a, *b;
611 message_t *msg;
612 status_t s;
613
614 if (_i)
615 { /* responder rekeys the IKE_SA */
616 exchange_test_helper->establish_sa(exchange_test_helper,
617 &b, &a, NULL);
618 }
619 else
620 { /* initiator rekeys the IKE_SA */
621 exchange_test_helper->establish_sa(exchange_test_helper,
622 &a, &b, NULL);
623 }
624 /* this should never get called as this does not result in a successful
625 * rekeying on either side */
626 assert_hook_not_called(ike_rekey);
627
628 initiate_rekey(a);
629 call_ikesa(b, delete);
630 assert_ike_sa_state(b, IKE_DELETING);
631
632 /* RFC 7296, 2.25.2: If a peer receives a request to rekey an IKE SA that
633 * it is currently trying to close, it SHOULD reply with TEMPORARY_FAILURE.
634 */
635
636 /* CREATE_CHILD_SA { SA, Ni, KEi } --> */
637 assert_hook_not_called(ike_updown);
638 assert_single_notify(OUT, TEMPORARY_FAILURE);
639 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
640 assert_ike_sa_state(b, IKE_DELETING);
641 assert_ike_sa_count(0);
642 assert_hook();
643
644 /* RFC 7296, 2.25.2: If a peer receives a request to close an IKE SA that
645 * it is currently rekeying, it SHOULD reply as usual, and forget its own
646 * rekeying request.
647 */
648
649 /* <-- INFORMATIONAL { D } */
650 assert_hook_updown(ike_updown, FALSE);
651 assert_hook_updown(child_updown, FALSE);
652 assert_single_payload(IN, PLV2_DELETE);
653 assert_message_empty(OUT);
654 s = exchange_test_helper->process_message(exchange_test_helper, a, NULL);
655 ck_assert_int_eq(DESTROY_ME, s);
656 call_ikesa(a, destroy);
657 assert_hook();
658 assert_hook();
659
660 /* <-- CREATE_CHILD_SA { N(TEMP_FAIL) } */
661 /* the SA is already gone */
662 msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
663 msg->destroy(msg);
664
665 /* INFORMATIONAL { } --> */
666 assert_hook_updown(ike_updown, FALSE);
667 assert_hook_updown(child_updown, FALSE);
668 s = exchange_test_helper->process_message(exchange_test_helper, b, NULL);
669 ck_assert_int_eq(DESTROY_ME, s);
670 call_ikesa(b, destroy);
671 assert_hook();
672 assert_hook();
673
674 /* ike_rekey */
675 assert_hook();
676 }
677 END_TEST
678
679 /**
680 * One of the hosts initiates a DELETE of the IKE_SA the other peer is
681 * concurrently trying to rekey. However, the delete request is delayed or
682 * dropped, so the peer doing the rekeying is unaware of the collision.
683 *
684 * rekey ----\ /---- delete
685 * \-----/----> detect collision
686 * reschedule <---------/------ TEMP_FAIL
687 * <--------/
688 * delete ---------------->
689 */
690 START_TEST(test_collision_delete_drop_delete)
691 {
692 ike_sa_t *a, *b;
693 message_t *msg;
694 status_t s;
695
696 if (_i)
697 { /* responder rekeys the IKE_SA */
698 exchange_test_helper->establish_sa(exchange_test_helper,
699 &b, &a, NULL);
700 }
701 else
702 { /* initiator rekeys the IKE_SA */
703 exchange_test_helper->establish_sa(exchange_test_helper,
704 &a, &b, NULL);
705 }
706 /* this should never get called as this does not result in a successful
707 * rekeying on either side */
708 assert_hook_not_called(ike_rekey);
709
710 initiate_rekey(a);
711 call_ikesa(b, delete);
712 assert_ike_sa_state(b, IKE_DELETING);
713
714 /* RFC 7296, 2.25.2: If a peer receives a request to rekey an IKE SA that
715 * it is currently trying to close, it SHOULD reply with TEMPORARY_FAILURE.
716 */
717
718 /* CREATE_CHILD_SA { SA, Ni, KEi } --> */
719 assert_hook_not_called(ike_updown);
720 assert_single_notify(OUT, TEMPORARY_FAILURE);
721 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
722 assert_ike_sa_state(b, IKE_DELETING);
723 assert_ike_sa_count(0);
724 assert_hook();
725
726 /* delay the DELETE request */
727 msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
728
729 /* <-- CREATE_CHILD_SA { N(TEMP_FAIL) } */
730 assert_hook_not_called(ike_updown);
731 assert_hook_not_called(child_updown);
732 /* we expect a job to retry the rekeying is scheduled */
733 assert_jobs_scheduled(1);
734 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
735 assert_ike_sa_state(a, IKE_ESTABLISHED);
736 assert_scheduler();
737 assert_hook();
738 assert_hook();
739
740 /* <-- INFORMATIONAL { D } (delayed) */
741 assert_hook_updown(ike_updown, FALSE);
742 assert_hook_updown(child_updown, FALSE);
743 assert_single_payload(IN, PLV2_DELETE);
744 assert_message_empty(OUT);
745 s = exchange_test_helper->process_message(exchange_test_helper, a, msg);
746 ck_assert_int_eq(DESTROY_ME, s);
747 call_ikesa(a, destroy);
748 assert_hook();
749 assert_hook();
750
751 /* INFORMATIONAL { } --> */
752 assert_hook_updown(ike_updown, FALSE);
753 assert_hook_updown(child_updown, FALSE);
754 s = exchange_test_helper->process_message(exchange_test_helper, b, NULL);
755 ck_assert_int_eq(DESTROY_ME, s);
756 call_ikesa(b, destroy);
757 assert_hook();
758 assert_hook();
759
760 /* ike_rekey */
761 assert_hook();
762 }
763 END_TEST
764
765 Suite *ike_rekey_suite_create()
766 {
767 Suite *s;
768 TCase *tc;
769
770 s = suite_create("ike rekey");
771
772 tc = tcase_create("regular");
773 tcase_add_loop_test(tc, test_regular, 0, 2);
774 suite_add_tcase(s, tc);
775
776 tc = tcase_create("collisions rekey");
777 tcase_add_loop_test(tc, test_collision, 0, 4);
778 tcase_add_loop_test(tc, test_collision_dropped_request, 0, 3);
779 tcase_add_loop_test(tc, test_collision_delayed_request, 0, 3);
780 tcase_add_loop_test(tc, test_collision_delayed_request_and_delete, 0, 3);
781 suite_add_tcase(s, tc);
782
783 tc = tcase_create("collisions delete");
784 tcase_add_loop_test(tc, test_collision_delete, 0, 2);
785 tcase_add_loop_test(tc, test_collision_delete_drop_delete, 0, 2);
786 suite_add_tcase(s, tc);
787
788 return s;
789 }