Use a dedicated PRF for HASH/SIG payloads using ECDSA specific hasher
[strongswan.git] / src / libcharon / sa / ikev1 / tasks / quick_mode.c
1 /*
2 * Copyright (C) 2011 Martin Willi
3 * Copyright (C) 2011 revosec AG
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 "quick_mode.h"
17
18 #include <string.h>
19
20 #include <daemon.h>
21 #include <sa/ikev1/keymat_v1.h>
22 #include <encoding/payloads/sa_payload.h>
23 #include <encoding/payloads/nonce_payload.h>
24 #include <encoding/payloads/ke_payload.h>
25 #include <encoding/payloads/id_payload.h>
26 #include <encoding/payloads/payload.h>
27 #include <sa/ikev1/tasks/informational.h>
28 #include <sa/ikev1/tasks/quick_delete.h>
29
30 typedef struct private_quick_mode_t private_quick_mode_t;
31
32 /**
33 * Private members of a quick_mode_t task.
34 */
35 struct private_quick_mode_t {
36
37 /**
38 * Public methods and task_t interface.
39 */
40 quick_mode_t public;
41
42 /**
43 * Assigned IKE_SA.
44 */
45 ike_sa_t *ike_sa;
46
47 /**
48 * TRUE if we are initiating quick mode
49 */
50 bool initiator;
51
52 /**
53 * Traffic selector of initiator
54 */
55 traffic_selector_t *tsi;
56
57 /**
58 * Traffic selector of responder
59 */
60 traffic_selector_t *tsr;
61
62 /**
63 * Initiators nonce
64 */
65 chunk_t nonce_i;
66
67 /**
68 * Responder nonce
69 */
70 chunk_t nonce_r;
71
72 /**
73 * Initiators ESP SPI
74 */
75 u_int32_t spi_i;
76
77 /**
78 * Responder ESP SPI
79 */
80 u_int32_t spi_r;
81
82 /**
83 * selected CHILD_SA proposal
84 */
85 proposal_t *proposal;
86
87 /**
88 * Config of CHILD_SA to establish
89 */
90 child_cfg_t *config;
91
92 /**
93 * CHILD_SA we are about to establish
94 */
95 child_sa_t *child_sa;
96
97 /**
98 * IKEv1 keymat
99 */
100 keymat_v1_t *keymat;
101
102 /**
103 * DH exchange, when PFS is in use
104 */
105 diffie_hellman_t *dh;
106
107 /**
108 * Negotiated lifetime of new SA
109 */
110 u_int32_t lifetime;
111
112 /**
113 * Negotaited lifebytes of new SA
114 */
115 u_int64_t lifebytes;
116
117 /**
118 * Reqid to use, 0 for auto-allocate
119 */
120 u_int32_t reqid;
121
122 /**
123 * SPI of SA we rekey
124 */
125 u_int32_t rekey;
126
127 /**
128 * Negotiated mode, tunnel or transport
129 */
130 ipsec_mode_t mode;
131
132 /** states of quick mode */
133 enum {
134 QM_INIT,
135 QM_NEGOTIATED,
136 } state;
137 };
138
139 /**
140 * Install negotiated CHILD_SA
141 */
142 static bool install(private_quick_mode_t *this)
143 {
144 status_t status, status_i, status_o;
145 chunk_t encr_i, encr_r, integ_i, integ_r;
146 linked_list_t *tsi, *tsr;
147 child_sa_t *old = NULL;
148
149 this->child_sa->set_proposal(this->child_sa, this->proposal);
150 this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
151 this->child_sa->set_mode(this->child_sa, this->mode);
152 this->child_sa->set_protocol(this->child_sa,
153 this->proposal->get_protocol(this->proposal));
154
155 status_i = status_o = FAILED;
156 encr_i = encr_r = integ_i = integ_r = chunk_empty;
157 tsi = linked_list_create();
158 tsr = linked_list_create();
159 tsi->insert_last(tsi, this->tsi->clone(this->tsi));
160 tsr->insert_last(tsr, this->tsr->clone(this->tsr));
161 if (this->initiator)
162 {
163 charon->bus->narrow(charon->bus, this->child_sa,
164 NARROW_INITIATOR_POST_AUTH, tsi, tsr);
165 }
166 else
167 {
168 charon->bus->narrow(charon->bus, this->child_sa,
169 NARROW_RESPONDER, tsr, tsi);
170 }
171 if (tsi->get_count(tsi) == 0 || tsr->get_count(tsr) == 0)
172 {
173 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
174 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
175 DBG1(DBG_IKE, "no acceptable traffic selectors found");
176 return FALSE;
177 }
178
179 if (this->keymat->derive_child_keys(this->keymat, this->proposal, this->dh,
180 this->spi_i, this->spi_r, this->nonce_i, this->nonce_r,
181 &encr_i, &integ_i, &encr_r, &integ_r))
182 {
183 if (this->initiator)
184 {
185 status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
186 this->spi_i, 0, TRUE, FALSE, tsi, tsr);
187 status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
188 this->spi_r, 0, FALSE, FALSE, tsi, tsr);
189 }
190 else
191 {
192 status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
193 this->spi_r, 0, TRUE, FALSE, tsr, tsi);
194 status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
195 this->spi_i, 0, FALSE, FALSE, tsr, tsi);
196 }
197 }
198 chunk_clear(&integ_i);
199 chunk_clear(&integ_r);
200 chunk_clear(&encr_i);
201 chunk_clear(&encr_r);
202
203 if (status_i != SUCCESS || status_o != SUCCESS)
204 {
205 DBG1(DBG_IKE, "unable to install %s%s%sIPsec SA (SAD) in kernel",
206 (status_i != SUCCESS) ? "inbound " : "",
207 (status_i != SUCCESS && status_o != SUCCESS) ? "and ": "",
208 (status_o != SUCCESS) ? "outbound " : "");
209 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
210 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
211 return FALSE;
212 }
213
214 if (this->initiator)
215 {
216 status = this->child_sa->add_policies(this->child_sa, tsi, tsr);
217 }
218 else
219 {
220 status = this->child_sa->add_policies(this->child_sa, tsr, tsi);
221 }
222 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
223 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
224 if (status != SUCCESS)
225 {
226 DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
227 return FALSE;
228 }
229
230 charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
231 this->dh, this->nonce_i, this->nonce_r);
232
233 /* add to IKE_SA, and remove from task */
234 this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
235 this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
236
237 DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
238 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
239 this->child_sa->get_name(this->child_sa),
240 this->child_sa->get_reqid(this->child_sa),
241 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
242 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
243 this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
244 this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
245
246 if (this->rekey)
247 {
248 old = this->ike_sa->get_child_sa(this->ike_sa,
249 this->proposal->get_protocol(this->proposal),
250 this->rekey, TRUE);
251 }
252 if (old)
253 {
254 charon->bus->child_rekey(charon->bus, old, this->child_sa);
255 }
256 else
257 {
258 charon->bus->child_updown(charon->bus, this->child_sa, TRUE);
259 }
260 this->child_sa = NULL;
261
262 return TRUE;
263 }
264
265 /**
266 * Generate and add NONCE
267 */
268 static bool add_nonce(private_quick_mode_t *this, chunk_t *nonce,
269 message_t *message)
270 {
271 nonce_payload_t *nonce_payload;
272 rng_t *rng;
273
274 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
275 if (!rng)
276 {
277 DBG1(DBG_IKE, "no RNG found to create nonce");
278 return FALSE;
279 }
280 rng->allocate_bytes(rng, NONCE_SIZE, nonce);
281 rng->destroy(rng);
282
283 nonce_payload = nonce_payload_create(NONCE_V1);
284 nonce_payload->set_nonce(nonce_payload, *nonce);
285 message->add_payload(message, &nonce_payload->payload_interface);
286
287 return TRUE;
288 }
289
290 /**
291 * Extract nonce from NONCE payload
292 */
293 static bool get_nonce(private_quick_mode_t *this, chunk_t *nonce,
294 message_t *message)
295 {
296 nonce_payload_t *nonce_payload;
297
298 nonce_payload = (nonce_payload_t*)message->get_payload(message, NONCE_V1);
299 if (!nonce_payload)
300 {
301 DBG1(DBG_IKE, "NONCE payload missing in message");
302 return FALSE;
303 }
304 *nonce = nonce_payload->get_nonce(nonce_payload);
305
306 return TRUE;
307 }
308
309 /**
310 * Add KE payload to message
311 */
312 static void add_ke(private_quick_mode_t *this, message_t *message)
313 {
314 ke_payload_t *ke_payload;
315
316 ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE_V1, this->dh);
317 message->add_payload(message, &ke_payload->payload_interface);
318 }
319
320 /**
321 * Get DH value from a KE payload
322 */
323 static bool get_ke(private_quick_mode_t *this, message_t *message)
324 {
325 ke_payload_t *ke_payload;
326
327 ke_payload = (ke_payload_t*)message->get_payload(message, KEY_EXCHANGE_V1);
328 if (!ke_payload)
329 {
330 DBG1(DBG_IKE, "KE payload missing");
331 return FALSE;
332 }
333 this->dh->set_other_public_value(this->dh,
334 ke_payload->get_key_exchange_data(ke_payload));
335 return TRUE;
336 }
337
338 /**
339 * Select a traffic selector from configuration
340 */
341 static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local,
342 linked_list_t *supplied)
343 {
344 traffic_selector_t *ts;
345 linked_list_t *list;
346 host_t *host;
347
348 host = this->ike_sa->get_virtual_ip(this->ike_sa, local);
349 if (!host)
350 {
351 if (local)
352 {
353 host = this->ike_sa->get_my_host(this->ike_sa);
354 }
355 else
356 {
357 host = this->ike_sa->get_other_host(this->ike_sa);
358 }
359 }
360 list = this->config->get_traffic_selectors(this->config, local,
361 supplied, host);
362 if (list->get_first(list, (void**)&ts) == SUCCESS)
363 {
364 if (list->get_count(list) > 1)
365 {
366 DBG1(DBG_IKE, "configuration has more than one %s traffic selector,"
367 " using first only", local ? "local" : "remote");
368 }
369 ts = ts->clone(ts);
370 }
371 else
372 {
373 DBG1(DBG_IKE, "%s traffic selector missing in configuration",
374 local ? "local" : "local");
375 ts = NULL;
376 }
377 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
378 return ts;
379 }
380
381 /**
382 * Add selected traffic selectors to message
383 */
384 static void add_ts(private_quick_mode_t *this, message_t *message)
385 {
386 id_payload_t *id_payload;
387 host_t *hsi, *hsr;
388
389 if (this->initiator)
390 {
391 hsi = this->ike_sa->get_my_host(this->ike_sa);
392 hsr = this->ike_sa->get_other_host(this->ike_sa);
393 }
394 else
395 {
396 hsr = this->ike_sa->get_my_host(this->ike_sa);
397 hsi = this->ike_sa->get_other_host(this->ike_sa);
398 }
399 /* add ID payload only if negotiating non host2host tunnels */
400 if (!this->tsi->is_host(this->tsi, hsi) ||
401 !this->tsr->is_host(this->tsr, hsr) ||
402 this->tsi->get_protocol(this->tsi) ||
403 this->tsr->get_protocol(this->tsr) ||
404 this->tsi->get_from_port(this->tsi) ||
405 this->tsr->get_from_port(this->tsr) ||
406 this->tsi->get_to_port(this->tsi) != 65535 ||
407 this->tsr->get_to_port(this->tsr) != 65535)
408 {
409 id_payload = id_payload_create_from_ts(this->tsi);
410 message->add_payload(message, &id_payload->payload_interface);
411 id_payload = id_payload_create_from_ts(this->tsr);
412 message->add_payload(message, &id_payload->payload_interface);
413 }
414 }
415
416 /**
417 * Get traffic selectors from received message
418 */
419 static bool get_ts(private_quick_mode_t *this, message_t *message)
420 {
421 traffic_selector_t *tsi = NULL, *tsr = NULL;
422 enumerator_t *enumerator;
423 id_payload_t *id_payload;
424 payload_t *payload;
425 host_t *hsi, *hsr;
426 bool first = TRUE;
427
428 enumerator = message->create_payload_enumerator(message);
429 while (enumerator->enumerate(enumerator, &payload))
430 {
431 if (payload->get_type(payload) == ID_V1)
432 {
433 id_payload = (id_payload_t*)payload;
434
435 if (first)
436 {
437 tsi = id_payload->get_ts(id_payload);
438 first = FALSE;
439 }
440 else
441 {
442 tsr = id_payload->get_ts(id_payload);
443 break;
444 }
445 }
446 }
447 enumerator->destroy(enumerator);
448
449 /* create host2host selectors if ID payloads missing */
450 if (this->initiator)
451 {
452 hsi = this->ike_sa->get_my_host(this->ike_sa);
453 hsr = this->ike_sa->get_other_host(this->ike_sa);
454 }
455 else
456 {
457 hsr = this->ike_sa->get_my_host(this->ike_sa);
458 hsi = this->ike_sa->get_other_host(this->ike_sa);
459 }
460 if (!tsi)
461 {
462 tsi = traffic_selector_create_from_subnet(hsi->clone(hsi),
463 hsi->get_family(hsi) == AF_INET ? 32 : 128, 0, 0);
464 }
465 if (!tsr)
466 {
467 tsr = traffic_selector_create_from_subnet(hsr->clone(hsr),
468 hsr->get_family(hsr) == AF_INET ? 32 : 128, 0, 0);
469 }
470 if (this->initiator)
471 {
472 /* check if peer selection valid */
473 if (!tsr->is_contained_in(tsr, this->tsr) ||
474 !tsi->is_contained_in(tsi, this->tsi))
475 {
476 DBG1(DBG_IKE, "peer selected invalid traffic selectors: ",
477 "%R for %R, %R for %R", tsi, this->tsi, tsr, this->tsr);
478 tsi->destroy(tsi);
479 tsr->destroy(tsr);
480 return FALSE;
481 }
482 this->tsi->destroy(this->tsi);
483 this->tsr->destroy(this->tsr);
484 this->tsi = tsi;
485 this->tsr = tsr;
486 }
487 else
488 {
489 this->tsi = tsi;
490 this->tsr = tsr;
491 }
492 return TRUE;
493 }
494
495 /**
496 * Add NAT-OA payloads
497 */
498 static void add_nat_oa_payloads(private_quick_mode_t *this, message_t *message)
499 {
500 identification_t *id;
501 id_payload_t *nat_oa;
502 host_t *src, *dst;
503
504 src = message->get_source(message);
505 dst = message->get_destination(message);
506
507 src = this->initiator ? src : dst;
508 dst = this->initiator ? dst : src;
509
510 /* first NAT-OA is the initiator's address */
511 id = identification_create_from_sockaddr(src->get_sockaddr(src));
512 nat_oa = id_payload_create_from_identification(NAT_OA_V1, id);
513 message->add_payload(message, (payload_t*)nat_oa);
514 id->destroy(id);
515
516 /* second NAT-OA is that of the responder */
517 id = identification_create_from_sockaddr(dst->get_sockaddr(dst));
518 nat_oa = id_payload_create_from_identification(NAT_OA_V1, id);
519 message->add_payload(message, (payload_t*)nat_oa);
520 id->destroy(id);
521 }
522
523 /**
524 * Look up lifetimes
525 */
526 static void get_lifetimes(private_quick_mode_t *this)
527 {
528 lifetime_cfg_t *lft;
529
530 lft = this->config->get_lifetime(this->config);
531 if (lft->time.life)
532 {
533 this->lifetime = lft->time.life;
534 }
535 else if (lft->bytes.life)
536 {
537 this->lifebytes = lft->bytes.life;
538 }
539 free(lft);
540 }
541
542 /**
543 * Check and apply lifetimes
544 */
545 static void apply_lifetimes(private_quick_mode_t *this, sa_payload_t *sa_payload)
546 {
547 u_int32_t lifetime;
548 u_int64_t lifebytes;
549
550 lifetime = sa_payload->get_lifetime(sa_payload);
551 lifebytes = sa_payload->get_lifebytes(sa_payload);
552 if (this->lifetime != lifetime)
553 {
554 DBG1(DBG_IKE, "received %us lifetime, configured %us",
555 lifetime, this->lifetime);
556 this->lifetime = lifetime;
557 }
558 if (this->lifebytes != lifebytes)
559 {
560 DBG1(DBG_IKE, "received %llu lifebytes, configured %llu",
561 lifebytes, this->lifebytes);
562 this->lifebytes = lifebytes;
563 }
564 }
565
566 /**
567 * Set the task ready to build notify error message
568 */
569 static status_t send_notify(private_quick_mode_t *this, notify_type_t type)
570 {
571 notify_payload_t *notify;
572
573 notify = notify_payload_create_from_protocol_and_type(NOTIFY_V1,
574 PROTO_ESP, type);
575 notify->set_spi(notify, this->spi_i);
576
577 this->ike_sa->queue_task(this->ike_sa,
578 (task_t*)informational_create(this->ike_sa, notify));
579 /* cancel all active/passive tasks in favour of informational */
580 return ALREADY_DONE;
581 }
582
583 METHOD(task_t, build_i, status_t,
584 private_quick_mode_t *this, message_t *message)
585 {
586 switch (this->state)
587 {
588 case QM_INIT:
589 {
590 enumerator_t *enumerator;
591 sa_payload_t *sa_payload;
592 linked_list_t *list, *tsi, *tsr;
593 proposal_t *proposal;
594 diffie_hellman_group_t group;
595 bool udp;
596
597 udp = this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY);
598 this->child_sa = child_sa_create(
599 this->ike_sa->get_my_host(this->ike_sa),
600 this->ike_sa->get_other_host(this->ike_sa),
601 this->config, this->reqid, udp);
602
603 list = this->config->get_proposals(this->config, FALSE);
604
605 this->spi_i = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
606 if (!this->spi_i)
607 {
608 DBG1(DBG_IKE, "allocating SPI from kernel failed");
609 return FAILED;
610 }
611 enumerator = list->create_enumerator(list);
612 while (enumerator->enumerate(enumerator, &proposal))
613 {
614 proposal->set_spi(proposal, this->spi_i);
615 }
616 enumerator->destroy(enumerator);
617
618 this->mode = this->config->get_mode(this->config);
619 if (udp && this->mode == MODE_TRANSPORT)
620 {
621 /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
622 add_nat_oa_payloads(this, message);
623 }
624
625 get_lifetimes(this);
626 sa_payload = sa_payload_create_from_proposals_v1(list,
627 this->lifetime, this->lifebytes, AUTH_NONE,
628 this->mode, udp);
629 list->destroy_offset(list, offsetof(proposal_t, destroy));
630 message->add_payload(message, &sa_payload->payload_interface);
631
632 if (!add_nonce(this, &this->nonce_i, message))
633 {
634 return FAILED;
635 }
636
637 group = this->config->get_dh_group(this->config);
638 if (group != MODP_NONE)
639 {
640 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
641 group);
642 if (!this->dh)
643 {
644 DBG1(DBG_IKE, "configured DH group %N not supported",
645 diffie_hellman_group_names, group);
646 return FAILED;
647 }
648 add_ke(this, message);
649 }
650 this->tsi = select_ts(this, TRUE, NULL);
651 this->tsr = select_ts(this, FALSE, NULL);
652 tsi = linked_list_create();
653 tsr = linked_list_create();
654 tsi->insert_last(tsi, this->tsi);
655 tsr->insert_last(tsr, this->tsr);
656 this->tsi = this->tsr = NULL;
657 charon->bus->narrow(charon->bus, this->child_sa,
658 NARROW_INITIATOR_PRE_AUTH, tsi, tsr);
659 tsi->remove_first(tsi, (void**)&this->tsi);
660 tsr->remove_first(tsr, (void**)&this->tsr);
661 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
662 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
663 if (!this->tsi || !this->tsr)
664 {
665 return FAILED;
666 }
667 add_ts(this, message);
668 return NEED_MORE;
669 }
670 case QM_NEGOTIATED:
671 {
672 return SUCCESS;
673 }
674 default:
675 return FAILED;
676 }
677 }
678
679 /**
680 * Check for notify errors, return TRUE if error found
681 */
682 static bool has_notify_errors(private_quick_mode_t *this, message_t *message)
683 {
684 enumerator_t *enumerator;
685 payload_t *payload;
686 bool err = FALSE;
687
688 enumerator = message->create_payload_enumerator(message);
689 while (enumerator->enumerate(enumerator, &payload))
690 {
691 if (payload->get_type(payload) == NOTIFY_V1)
692 {
693 notify_payload_t *notify;
694 notify_type_t type;
695
696 notify = (notify_payload_t*)payload;
697 type = notify->get_notify_type(notify);
698 if (type < 16384)
699 {
700
701 DBG1(DBG_IKE, "received %N error notify",
702 notify_type_names, type);
703 err = TRUE;
704 }
705 else
706 {
707 DBG1(DBG_IKE, "received %N notify", notify_type_names, type);
708 }
709 }
710 }
711 enumerator->destroy(enumerator);
712
713 return err;
714 }
715
716 /**
717 * Check if this is a rekey for an existing CHILD_SA, reuse reqid if so
718 */
719 static void check_for_rekeyed_child(private_quick_mode_t *this)
720 {
721 enumerator_t *enumerator, *policies;
722 traffic_selector_t *local, *remote;
723 child_sa_t *child_sa;
724
725 enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
726 while (this->reqid == 0 && enumerator->enumerate(enumerator, &child_sa))
727 {
728 if (child_sa->get_state(child_sa) == CHILD_INSTALLED &&
729 streq(child_sa->get_name(child_sa),
730 this->config->get_name(this->config)))
731 {
732 policies = child_sa->create_policy_enumerator(child_sa);
733 if (policies->enumerate(policies, &local, &remote))
734 {
735 if (local->equals(local, this->tsr) &&
736 remote->equals(remote, this->tsi) &&
737 this->proposal->equals(this->proposal,
738 child_sa->get_proposal(child_sa)))
739 {
740 this->reqid = child_sa->get_reqid(child_sa);
741 this->rekey = child_sa->get_spi(child_sa, TRUE);
742 child_sa->set_state(child_sa, CHILD_REKEYING);
743 DBG1(DBG_IKE, "detected rekeying of CHILD_SA %s{%u}",
744 child_sa->get_name(child_sa), this->reqid);
745 }
746 }
747 policies->destroy(policies);
748 }
749 }
750 enumerator->destroy(enumerator);
751 }
752
753 METHOD(task_t, process_r, status_t,
754 private_quick_mode_t *this, message_t *message)
755 {
756 switch (this->state)
757 {
758 case QM_INIT:
759 {
760 sa_payload_t *sa_payload;
761 linked_list_t *tsi, *tsr, *list;
762 peer_cfg_t *peer_cfg;
763 host_t *me, *other;
764 u_int16_t group;
765 bool udp;
766
767 if (!get_ts(this, message))
768 {
769 return FAILED;
770 }
771 me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
772 if (!me)
773 {
774 me = this->ike_sa->get_my_host(this->ike_sa);
775 }
776 other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
777 if (!other)
778 {
779 other = this->ike_sa->get_other_host(this->ike_sa);
780 }
781 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
782 tsi = linked_list_create();
783 tsr = linked_list_create();
784 tsi->insert_last(tsi, this->tsi);
785 tsr->insert_last(tsr, this->tsr);
786 this->tsi = this->tsr = NULL;
787 this->config = peer_cfg->select_child_cfg(peer_cfg, tsr, tsi,
788 me, other);
789 if (this->config)
790 {
791 this->tsi = select_ts(this, FALSE, tsi);
792 this->tsr = select_ts(this, TRUE, tsr);
793 }
794 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
795 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
796 if (!this->config || !this->tsi || !this->tsr)
797 {
798 DBG1(DBG_IKE, "no matching CHILD_SA config found");
799 return send_notify(this, INVALID_ID_INFORMATION);
800 }
801
802 sa_payload = (sa_payload_t*)message->get_payload(message,
803 SECURITY_ASSOCIATION_V1);
804 if (!sa_payload)
805 {
806 DBG1(DBG_IKE, "sa payload missing");
807 return send_notify(this, INVALID_PAYLOAD_TYPE);
808 }
809 list = sa_payload->get_proposals(sa_payload);
810 this->proposal = this->config->select_proposal(this->config,
811 list, FALSE, FALSE);
812 list->destroy_offset(list, offsetof(proposal_t, destroy));
813
814 get_lifetimes(this);
815 apply_lifetimes(this, sa_payload);
816
817 if (!this->proposal)
818 {
819 DBG1(DBG_IKE, "no matching proposal found, sending %N",
820 notify_type_names, NO_PROPOSAL_CHOSEN);
821 return send_notify(this, NO_PROPOSAL_CHOSEN);
822 }
823 this->spi_i = this->proposal->get_spi(this->proposal);
824
825 if (!get_nonce(this, &this->nonce_i, message))
826 {
827 return send_notify(this, INVALID_PAYLOAD_TYPE);
828 }
829
830 if (this->proposal->get_algorithm(this->proposal,
831 DIFFIE_HELLMAN_GROUP, &group, NULL))
832 {
833 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
834 group);
835 if (!this->dh)
836 {
837 DBG1(DBG_IKE, "negotiated DH group %N not supported",
838 diffie_hellman_group_names, group);
839 return send_notify(this, INVALID_KEY_INFORMATION);
840 }
841 if (!get_ke(this, message))
842 {
843 return send_notify(this, INVALID_PAYLOAD_TYPE);
844 }
845 }
846
847 check_for_rekeyed_child(this);
848
849 udp = this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY);
850 this->child_sa = child_sa_create(
851 this->ike_sa->get_my_host(this->ike_sa),
852 this->ike_sa->get_other_host(this->ike_sa),
853 this->config, this->reqid, udp);
854 return NEED_MORE;
855 }
856 case QM_NEGOTIATED:
857 {
858 if (message->get_exchange_type(message) == INFORMATIONAL_V1 ||
859 has_notify_errors(this, message))
860 {
861 return SUCCESS;
862 }
863 if (!install(this))
864 {
865 this->ike_sa->queue_task(this->ike_sa,
866 (task_t*)quick_delete_create(this->ike_sa,
867 this->proposal->get_protocol(this->proposal),
868 this->spi_i, TRUE, TRUE));
869 return ALREADY_DONE;
870 }
871 return SUCCESS;
872 }
873 default:
874 return FAILED;
875 }
876 }
877
878 METHOD(task_t, build_r, status_t,
879 private_quick_mode_t *this, message_t *message)
880 {
881 switch (this->state)
882 {
883 case QM_INIT:
884 {
885 sa_payload_t *sa_payload;
886 bool udp;
887
888 this->spi_r = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
889 if (!this->spi_r)
890 {
891 DBG1(DBG_IKE, "allocating SPI from kernel failed");
892 return send_notify(this, NO_PROPOSAL_CHOSEN);
893 }
894 this->proposal->set_spi(this->proposal, this->spi_r);
895
896 udp = this->child_sa->has_encap(this->child_sa);
897 this->mode = this->config->get_mode(this->config);
898 if (udp && this->mode == MODE_TRANSPORT)
899 {
900 /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
901 add_nat_oa_payloads(this, message);
902 }
903
904 sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
905 this->lifetime, this->lifebytes, AUTH_NONE,
906 this->mode, udp);
907 message->add_payload(message, &sa_payload->payload_interface);
908
909 if (!add_nonce(this, &this->nonce_r, message))
910 {
911 return FAILED;
912 }
913 if (this->dh)
914 {
915 add_ke(this, message);
916 }
917
918 add_ts(this, message);
919
920 this->state = QM_NEGOTIATED;
921 return NEED_MORE;
922 }
923 default:
924 return FAILED;
925 }
926 }
927
928 METHOD(task_t, process_i, status_t,
929 private_quick_mode_t *this, message_t *message)
930 {
931 switch (this->state)
932 {
933 case QM_INIT:
934 {
935 sa_payload_t *sa_payload;
936 linked_list_t *list;
937
938 sa_payload = (sa_payload_t*)message->get_payload(message,
939 SECURITY_ASSOCIATION_V1);
940 if (!sa_payload)
941 {
942 DBG1(DBG_IKE, "sa payload missing");
943 return send_notify(this, NO_PROPOSAL_CHOSEN);
944 }
945 list = sa_payload->get_proposals(sa_payload);
946 this->proposal = this->config->select_proposal(this->config,
947 list, FALSE, FALSE);
948 list->destroy_offset(list, offsetof(proposal_t, destroy));
949 if (!this->proposal)
950 {
951 DBG1(DBG_IKE, "no matching proposal found");
952 return send_notify(this, NO_PROPOSAL_CHOSEN);
953 }
954 this->spi_r = this->proposal->get_spi(this->proposal);
955
956 apply_lifetimes(this, sa_payload);
957
958 if (!get_nonce(this, &this->nonce_r, message))
959 {
960 return send_notify(this, INVALID_PAYLOAD_TYPE);
961 }
962 if (this->dh && !get_ke(this, message))
963 {
964 return send_notify(this, INVALID_KEY_INFORMATION);
965 }
966 if (!get_ts(this, message))
967 {
968 return send_notify(this, INVALID_PAYLOAD_TYPE);
969 }
970 if (!install(this))
971 {
972 return send_notify(this, NO_PROPOSAL_CHOSEN);
973 }
974 this->state = QM_NEGOTIATED;
975 return NEED_MORE;
976 }
977 default:
978 return FAILED;
979 }
980 }
981
982 METHOD(task_t, get_type, task_type_t,
983 private_quick_mode_t *this)
984 {
985 return TASK_QUICK_MODE;
986 }
987
988 METHOD(quick_mode_t, use_reqid, void,
989 private_quick_mode_t *this, u_int32_t reqid)
990 {
991 this->reqid = reqid;
992 }
993
994 METHOD(quick_mode_t, rekey, void,
995 private_quick_mode_t *this, u_int32_t spi)
996 {
997 this->rekey = spi;
998 }
999
1000 METHOD(task_t, migrate, void,
1001 private_quick_mode_t *this, ike_sa_t *ike_sa)
1002 {
1003 chunk_free(&this->nonce_i);
1004 chunk_free(&this->nonce_r);
1005 DESTROY_IF(this->tsi);
1006 DESTROY_IF(this->tsr);
1007 DESTROY_IF(this->proposal);
1008 DESTROY_IF(this->child_sa);
1009 DESTROY_IF(this->dh);
1010
1011 this->ike_sa = ike_sa;
1012 this->keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
1013 this->state = QM_INIT;
1014 this->tsi = NULL;
1015 this->tsr = NULL;
1016 this->proposal = NULL;
1017 this->child_sa = NULL;
1018 this->dh = NULL;
1019 this->spi_i = 0;
1020 this->spi_r = 0;
1021
1022 if (!this->initiator)
1023 {
1024 DESTROY_IF(this->config);
1025 this->config = NULL;
1026 }
1027 }
1028
1029 METHOD(task_t, destroy, void,
1030 private_quick_mode_t *this)
1031 {
1032 chunk_free(&this->nonce_i);
1033 chunk_free(&this->nonce_r);
1034 DESTROY_IF(this->tsi);
1035 DESTROY_IF(this->tsr);
1036 DESTROY_IF(this->proposal);
1037 DESTROY_IF(this->child_sa);
1038 DESTROY_IF(this->config);
1039 DESTROY_IF(this->dh);
1040 free(this);
1041 }
1042
1043 /*
1044 * Described in header.
1045 */
1046 quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
1047 traffic_selector_t *tsi, traffic_selector_t *tsr)
1048 {
1049 private_quick_mode_t *this;
1050
1051 INIT(this,
1052 .public = {
1053 .task = {
1054 .get_type = _get_type,
1055 .migrate = _migrate,
1056 .destroy = _destroy,
1057 },
1058 .use_reqid = _use_reqid,
1059 .rekey = _rekey,
1060 },
1061 .ike_sa = ike_sa,
1062 .initiator = config != NULL,
1063 .config = config,
1064 .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
1065 .state = QM_INIT,
1066 );
1067
1068 if (config)
1069 {
1070 this->public.task.build = _build_i;
1071 this->public.task.process = _process_i;
1072 }
1073 else
1074 {
1075 this->public.task.build = _build_r;
1076 this->public.task.process = _process_r;
1077 }
1078
1079 return &this->public;
1080 }