2 * Copyright (C) 2011 Martin Willi
3 * Copyright (C) 2011 revosec AG
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>.
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
16 #include "quick_mode.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>
30 typedef struct private_quick_mode_t private_quick_mode_t
;
33 * Private members of a quick_mode_t task.
35 struct private_quick_mode_t
{
38 * Public methods and task_t interface.
48 * TRUE if we are initiating quick mode
53 * Traffic selector of initiator
55 traffic_selector_t
*tsi
;
58 * Traffic selector of responder
60 traffic_selector_t
*tsr
;
83 * selected CHILD_SA proposal
88 * Config of CHILD_SA to establish
93 * CHILD_SA we are about to establish
103 * DH exchange, when PFS is in use
105 diffie_hellman_t
*dh
;
108 * Negotiated lifetime of new SA
113 * Negotaited lifebytes of new SA
118 * Reqid to use, 0 for auto-allocate
122 /** states of quick mode */
130 * Install negotiated CHILD_SA
132 static bool install(private_quick_mode_t
*this)
134 status_t status
, status_i
, status_o
;
135 chunk_t encr_i
, encr_r
, integ_i
, integ_r
;
136 linked_list_t
*tsi
, *tsr
;
138 this->child_sa
->set_proposal(this->child_sa
, this->proposal
);
139 this->child_sa
->set_state(this->child_sa
, CHILD_INSTALLING
);
140 this->child_sa
->set_mode(this->child_sa
, MODE_TUNNEL
);
141 this->child_sa
->set_protocol(this->child_sa
,
142 this->proposal
->get_protocol(this->proposal
));
144 status_i
= status_o
= FAILED
;
145 encr_i
= encr_r
= integ_i
= integ_r
= chunk_empty
;
146 tsi
= linked_list_create();
147 tsr
= linked_list_create();
148 tsi
->insert_last(tsi
, this->tsi
);
149 tsr
->insert_last(tsr
, this->tsr
);
150 if (this->keymat
->derive_child_keys(this->keymat
, this->proposal
, this->dh
,
151 this->spi_i
, this->spi_r
, this->nonce_i
, this->nonce_r
,
152 &encr_i
, &integ_i
, &encr_r
, &integ_r
))
156 status_i
= this->child_sa
->install(this->child_sa
, encr_r
, integ_r
,
157 this->spi_i
, 0, TRUE
, FALSE
, tsi
, tsr
);
158 status_o
= this->child_sa
->install(this->child_sa
, encr_i
, integ_i
,
159 this->spi_r
, 0, FALSE
, FALSE
, tsi
, tsr
);
163 status_i
= this->child_sa
->install(this->child_sa
, encr_i
, integ_i
,
164 this->spi_r
, 0, TRUE
, FALSE
, tsr
, tsi
);
165 status_o
= this->child_sa
->install(this->child_sa
, encr_r
, integ_r
,
166 this->spi_i
, 0, FALSE
, FALSE
, tsr
, tsi
);
169 chunk_clear(&integ_i
);
170 chunk_clear(&integ_r
);
171 chunk_clear(&encr_i
);
172 chunk_clear(&encr_r
);
174 if (status_i
!= SUCCESS
|| status_o
!= SUCCESS
)
176 DBG1(DBG_IKE
, "unable to install %s%s%sIPsec SA (SAD) in kernel",
177 (status_i
!= SUCCESS
) ?
"inbound " : "",
178 (status_i
!= SUCCESS
&& status_o
!= SUCCESS
) ?
"and ": "",
179 (status_o
!= SUCCESS
) ?
"outbound " : "");
187 status
= this->child_sa
->add_policies(this->child_sa
, tsi
, tsr
);
191 status
= this->child_sa
->add_policies(this->child_sa
, tsr
, tsi
);
195 if (status
!= SUCCESS
)
197 DBG1(DBG_IKE
, "unable to install IPsec policies (SPD) in kernel");
201 charon
->bus
->child_keys(charon
->bus
, this->child_sa
, this->initiator
,
202 this->dh
, this->nonce_i
, this->nonce_r
);
204 /* add to IKE_SA, and remove from task */
205 this->child_sa
->set_state(this->child_sa
, CHILD_INSTALLED
);
206 this->ike_sa
->add_child_sa(this->ike_sa
, this->child_sa
);
208 DBG0(DBG_IKE
, "CHILD_SA %s{%d} established "
209 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
210 this->child_sa
->get_name(this->child_sa
),
211 this->child_sa
->get_reqid(this->child_sa
),
212 ntohl(this->child_sa
->get_spi(this->child_sa
, TRUE
)),
213 ntohl(this->child_sa
->get_spi(this->child_sa
, FALSE
)),
214 this->child_sa
->get_traffic_selectors(this->child_sa
, TRUE
),
215 this->child_sa
->get_traffic_selectors(this->child_sa
, FALSE
));
217 charon
->bus
->child_updown(charon
->bus
, this->child_sa
, TRUE
);
219 this->child_sa
= NULL
;
225 * Generate and add NONCE
227 static bool add_nonce(private_quick_mode_t
*this, chunk_t
*nonce
,
230 nonce_payload_t
*nonce_payload
;
233 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
236 DBG1(DBG_IKE
, "no RNG found to create nonce");
239 rng
->allocate_bytes(rng
, NONCE_SIZE
, nonce
);
242 nonce_payload
= nonce_payload_create(NONCE_V1
);
243 nonce_payload
->set_nonce(nonce_payload
, *nonce
);
244 message
->add_payload(message
, &nonce_payload
->payload_interface
);
250 * Extract nonce from NONCE payload
252 static bool get_nonce(private_quick_mode_t
*this, chunk_t
*nonce
,
255 nonce_payload_t
*nonce_payload
;
257 nonce_payload
= (nonce_payload_t
*)message
->get_payload(message
, NONCE_V1
);
260 DBG1(DBG_IKE
, "NONCE payload missing in message");
263 *nonce
= nonce_payload
->get_nonce(nonce_payload
);
269 * Add KE payload to message
271 static void add_ke(private_quick_mode_t
*this, message_t
*message
)
273 ke_payload_t
*ke_payload
;
275 ke_payload
= ke_payload_create_from_diffie_hellman(KEY_EXCHANGE_V1
, this->dh
);
276 message
->add_payload(message
, &ke_payload
->payload_interface
);
280 * Get DH value from a KE payload
282 static bool get_ke(private_quick_mode_t
*this, message_t
*message
)
284 ke_payload_t
*ke_payload
;
286 ke_payload
= (ke_payload_t
*)message
->get_payload(message
, KEY_EXCHANGE_V1
);
289 DBG1(DBG_IKE
, "KE payload missing");
292 this->dh
->set_other_public_value(this->dh
,
293 ke_payload
->get_key_exchange_data(ke_payload
));
298 * Select a traffic selector from configuration
300 static traffic_selector_t
* select_ts(private_quick_mode_t
*this, bool local
,
301 linked_list_t
*supplied
)
303 traffic_selector_t
*ts
;
307 host
= this->ike_sa
->get_virtual_ip(this->ike_sa
, local
);
312 host
= this->ike_sa
->get_my_host(this->ike_sa
);
316 host
= this->ike_sa
->get_other_host(this->ike_sa
);
319 list
= this->config
->get_traffic_selectors(this->config
, local
,
321 if (list
->get_first(list
, (void**)&ts
) == SUCCESS
)
323 if (list
->get_count(list
) > 1)
325 DBG1(DBG_IKE
, "configuration has more than one %s traffic selector,"
326 " using first only", local ?
"local" : "remote");
332 DBG1(DBG_IKE
, "%s traffic selector missing in configuration",
333 local ?
"local" : "local");
336 list
->destroy_offset(list
, offsetof(traffic_selector_t
, destroy
));
341 * Add selected traffic selectors to message
343 static void add_ts(private_quick_mode_t
*this, message_t
*message
)
345 id_payload_t
*id_payload
;
350 hsi
= this->ike_sa
->get_my_host(this->ike_sa
);
351 hsr
= this->ike_sa
->get_other_host(this->ike_sa
);
355 hsr
= this->ike_sa
->get_my_host(this->ike_sa
);
356 hsi
= this->ike_sa
->get_other_host(this->ike_sa
);
358 /* add ID payload only if negotiating non host2host tunnels */
359 if (!this->tsi
->is_host(this->tsi
, hsi
) ||
360 !this->tsr
->is_host(this->tsr
, hsr
) ||
361 this->tsi
->get_protocol(this->tsi
) ||
362 this->tsr
->get_protocol(this->tsr
) ||
363 this->tsi
->get_from_port(this->tsi
) ||
364 this->tsr
->get_from_port(this->tsr
) ||
365 this->tsi
->get_to_port(this->tsi
) != 65535 ||
366 this->tsr
->get_to_port(this->tsr
) != 65535)
368 id_payload
= id_payload_create_from_ts(this->tsi
);
369 message
->add_payload(message
, &id_payload
->payload_interface
);
370 id_payload
= id_payload_create_from_ts(this->tsr
);
371 message
->add_payload(message
, &id_payload
->payload_interface
);
376 * Get traffic selectors from received message
378 static bool get_ts(private_quick_mode_t
*this, message_t
*message
)
380 traffic_selector_t
*tsi
= NULL
, *tsr
= NULL
;
381 enumerator_t
*enumerator
;
382 id_payload_t
*id_payload
;
387 enumerator
= message
->create_payload_enumerator(message
);
388 while (enumerator
->enumerate(enumerator
, &payload
))
390 if (payload
->get_type(payload
) == ID_V1
)
392 id_payload
= (id_payload_t
*)payload
;
396 tsi
= id_payload
->get_ts(id_payload
);
401 tsr
= id_payload
->get_ts(id_payload
);
406 enumerator
->destroy(enumerator
);
408 /* create host2host selectors if ID payloads missing */
411 hsi
= this->ike_sa
->get_my_host(this->ike_sa
);
412 hsr
= this->ike_sa
->get_other_host(this->ike_sa
);
416 hsr
= this->ike_sa
->get_my_host(this->ike_sa
);
417 hsi
= this->ike_sa
->get_other_host(this->ike_sa
);
421 tsi
= traffic_selector_create_from_subnet(hsi
->clone(hsi
),
422 hsi
->get_family(hsi
) == AF_INET ?
32 : 128, 0, 0);
426 tsr
= traffic_selector_create_from_subnet(hsr
->clone(hsr
),
427 hsr
->get_family(hsr
) == AF_INET ?
32 : 128, 0, 0);
431 /* check if peer selection valid */
432 if (!tsr
->is_contained_in(tsr
, this->tsr
) ||
433 !tsi
->is_contained_in(tsi
, this->tsi
))
435 DBG1(DBG_IKE
, "peer selected invalid traffic selectors: ",
436 "%R for %R, %R for %R", tsi
, this->tsi
, tsr
, this->tsr
);
441 this->tsi
->destroy(this->tsi
);
442 this->tsr
->destroy(this->tsr
);
455 * Add NAT-OA payloads
457 static void add_nat_oa_payloads(private_quick_mode_t
*this, message_t
*message
)
459 identification_t
*id
;
460 id_payload_t
*nat_oa
;
463 src
= message
->get_source(message
);
464 dst
= message
->get_destination(message
);
466 src
= this->initiator ? src
: dst
;
467 dst
= this->initiator ? dst
: src
;
469 /* first NAT-OA is the initiator's address */
470 id
= identification_create_from_sockaddr(src
->get_sockaddr(src
));
471 nat_oa
= id_payload_create_from_identification(NAT_OA_V1
, id
);
472 message
->add_payload(message
, (payload_t
*)nat_oa
);
475 /* second NAT-OA is that of the responder */
476 id
= identification_create_from_sockaddr(dst
->get_sockaddr(dst
));
477 nat_oa
= id_payload_create_from_identification(NAT_OA_V1
, id
);
478 message
->add_payload(message
, (payload_t
*)nat_oa
);
485 static void get_lifetimes(private_quick_mode_t
*this)
489 lft
= this->config
->get_lifetime(this->config
);
492 this->lifetime
= lft
->time
.life
;
494 else if (lft
->bytes
.life
)
496 this->lifebytes
= lft
->bytes
.life
;
502 * Check and apply lifetimes
504 static void apply_lifetimes(private_quick_mode_t
*this, sa_payload_t
*sa_payload
)
509 lifetime
= sa_payload
->get_lifetime(sa_payload
);
510 lifebytes
= sa_payload
->get_lifebytes(sa_payload
);
511 if (this->lifetime
!= lifetime
)
513 DBG1(DBG_IKE
, "received %us lifetime, configured %us, using lower",
514 lifetime
, this->lifetime
);
515 this->lifetime
= min(this->lifetime
, lifetime
);
517 if (this->lifebytes
!= lifebytes
)
519 DBG1(DBG_IKE
, "received %llu lifebytes, configured %llu, using lower",
520 lifebytes
, this->lifebytes
);
521 this->lifebytes
= min(this->lifebytes
, lifebytes
);
526 * Set the task ready to build notify error message
528 static status_t
send_notify(private_quick_mode_t
*this, notify_type_t type
)
530 notify_payload_t
*notify
;
532 notify
= notify_payload_create_from_protocol_and_type(NOTIFY_V1
,
534 notify
->set_spi(notify
, this->spi_i
);
536 this->ike_sa
->queue_task(this->ike_sa
,
537 (task_t
*)informational_create(this->ike_sa
, notify
));
538 /* cancel all active/passive tasks in favour of informational */
542 METHOD(task_t
, build_i
, status_t
,
543 private_quick_mode_t
*this, message_t
*message
)
549 enumerator_t
*enumerator
;
550 sa_payload_t
*sa_payload
;
552 proposal_t
*proposal
;
554 diffie_hellman_group_t group
;
555 bool udp
= this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
);
557 this->child_sa
= child_sa_create(
558 this->ike_sa
->get_my_host(this->ike_sa
),
559 this->ike_sa
->get_other_host(this->ike_sa
),
560 this->config
, this->reqid
, udp
);
562 list
= this->config
->get_proposals(this->config
, FALSE
);
564 this->spi_i
= this->child_sa
->alloc_spi(this->child_sa
, PROTO_ESP
);
567 DBG1(DBG_IKE
, "allocating SPI from kernel failed");
570 enumerator
= list
->create_enumerator(list
);
571 while (enumerator
->enumerate(enumerator
, &proposal
))
573 proposal
->set_spi(proposal
, this->spi_i
);
575 enumerator
->destroy(enumerator
);
577 mode
= this->config
->get_mode(this->config
);
578 if (udp
&& mode
== MODE_TRANSPORT
)
580 /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
581 add_nat_oa_payloads(this, message
);
585 sa_payload
= sa_payload_create_from_proposals_v1(list
,
586 this->lifetime
, this->lifebytes
, AUTH_NONE
,
588 list
->destroy_offset(list
, offsetof(proposal_t
, destroy
));
589 message
->add_payload(message
, &sa_payload
->payload_interface
);
591 if (!add_nonce(this, &this->nonce_i
, message
))
596 group
= this->config
->get_dh_group(this->config
);
597 if (group
!= MODP_NONE
)
599 this->dh
= this->keymat
->keymat
.create_dh(&this->keymat
->keymat
,
603 DBG1(DBG_IKE
, "configured DH group %N not supported",
604 diffie_hellman_group_names
, group
);
607 add_ke(this, message
);
609 this->tsi
= select_ts(this, TRUE
, NULL
);
610 this->tsr
= select_ts(this, FALSE
, NULL
);
611 if (!this->tsi
|| !this->tsr
)
615 add_ts(this, message
);
628 * Check for notify errors, return TRUE if error found
630 static bool has_notify_errors(private_quick_mode_t
*this, message_t
*message
)
632 enumerator_t
*enumerator
;
636 enumerator
= message
->create_payload_enumerator(message
);
637 while (enumerator
->enumerate(enumerator
, &payload
))
639 if (payload
->get_type(payload
) == NOTIFY_V1
)
641 notify_payload_t
*notify
;
644 notify
= (notify_payload_t
*)payload
;
645 type
= notify
->get_notify_type(notify
);
649 DBG1(DBG_IKE
, "received %N error notify",
650 notify_type_names
, type
);
655 DBG1(DBG_IKE
, "received %N notify", notify_type_names
, type
);
659 enumerator
->destroy(enumerator
);
664 METHOD(task_t
, process_r
, status_t
,
665 private_quick_mode_t
*this, message_t
*message
)
671 sa_payload_t
*sa_payload
;
672 linked_list_t
*tsi
, *tsr
, *list
;
673 peer_cfg_t
*peer_cfg
;
676 bool udp
= this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
);
678 if (!get_ts(this, message
))
682 me
= this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
);
685 me
= this->ike_sa
->get_my_host(this->ike_sa
);
687 other
= this->ike_sa
->get_virtual_ip(this->ike_sa
, FALSE
);
690 other
= this->ike_sa
->get_other_host(this->ike_sa
);
692 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
693 tsi
= linked_list_create();
694 tsr
= linked_list_create();
695 tsi
->insert_last(tsi
, this->tsi
);
696 tsr
->insert_last(tsr
, this->tsr
);
697 this->tsi
= this->tsr
= NULL
;
698 this->config
= peer_cfg
->select_child_cfg(peer_cfg
, tsr
, tsi
,
702 this->tsi
= select_ts(this, FALSE
, tsi
);
703 this->tsr
= select_ts(this, TRUE
, tsr
);
705 tsi
->destroy_offset(tsi
, offsetof(traffic_selector_t
, destroy
));
706 tsr
->destroy_offset(tsr
, offsetof(traffic_selector_t
, destroy
));
707 if (!this->config
|| !this->tsi
|| !this->tsr
)
709 DBG1(DBG_IKE
, "no matching CHILD_SA config found");
710 return send_notify(this, INVALID_ID_INFORMATION
);
713 sa_payload
= (sa_payload_t
*)message
->get_payload(message
,
714 SECURITY_ASSOCIATION_V1
);
717 DBG1(DBG_IKE
, "sa payload missing");
718 return send_notify(this, INVALID_PAYLOAD_TYPE
);
720 list
= sa_payload
->get_proposals(sa_payload
);
721 this->proposal
= this->config
->select_proposal(this->config
,
723 list
->destroy_offset(list
, offsetof(proposal_t
, destroy
));
726 apply_lifetimes(this, sa_payload
);
730 DBG1(DBG_IKE
, "no matching proposal found, sending %N",
731 notify_type_names
, NO_PROPOSAL_CHOSEN
);
732 return send_notify(this, NO_PROPOSAL_CHOSEN
);
734 this->spi_i
= this->proposal
->get_spi(this->proposal
);
736 if (!get_nonce(this, &this->nonce_i
, message
))
738 return send_notify(this, INVALID_PAYLOAD_TYPE
);
741 if (this->proposal
->get_algorithm(this->proposal
,
742 DIFFIE_HELLMAN_GROUP
, &group
, NULL
))
744 this->dh
= this->keymat
->keymat
.create_dh(&this->keymat
->keymat
,
748 DBG1(DBG_IKE
, "negotiated DH group %N not supported",
749 diffie_hellman_group_names
, group
);
750 return send_notify(this, INVALID_KEY_INFORMATION
);
752 if (!get_ke(this, message
))
754 return send_notify(this, INVALID_PAYLOAD_TYPE
);
758 this->child_sa
= child_sa_create(
759 this->ike_sa
->get_my_host(this->ike_sa
),
760 this->ike_sa
->get_other_host(this->ike_sa
),
761 this->config
, this->reqid
, udp
);
766 if (message
->get_exchange_type(message
) == INFORMATIONAL_V1
||
767 has_notify_errors(this, message
))
773 this->ike_sa
->queue_task(this->ike_sa
,
774 (task_t
*)quick_delete_create(this->ike_sa
,
775 this->proposal
->get_protocol(this->proposal
),
776 this->spi_i
, TRUE
, TRUE
));
786 METHOD(task_t
, build_r
, status_t
,
787 private_quick_mode_t
*this, message_t
*message
)
793 sa_payload_t
*sa_payload
;
795 bool udp
= this->child_sa
->has_encap(this->child_sa
);
797 this->spi_r
= this->child_sa
->alloc_spi(this->child_sa
, PROTO_ESP
);
800 DBG1(DBG_IKE
, "allocating SPI from kernel failed");
801 return send_notify(this, NO_PROPOSAL_CHOSEN
);
803 this->proposal
->set_spi(this->proposal
, this->spi_r
);
805 mode
= this->config
->get_mode(this->config
);
806 if (udp
&& mode
== MODE_TRANSPORT
)
808 /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
809 add_nat_oa_payloads(this, message
);
812 sa_payload
= sa_payload_create_from_proposal_v1(this->proposal
,
813 this->lifetime
, this->lifebytes
, AUTH_NONE
,
815 message
->add_payload(message
, &sa_payload
->payload_interface
);
817 if (!add_nonce(this, &this->nonce_r
, message
))
823 add_ke(this, message
);
826 add_ts(this, message
);
828 this->state
= QM_NEGOTIATED
;
836 METHOD(task_t
, process_i
, status_t
,
837 private_quick_mode_t
*this, message_t
*message
)
843 sa_payload_t
*sa_payload
;
846 sa_payload
= (sa_payload_t
*)message
->get_payload(message
,
847 SECURITY_ASSOCIATION_V1
);
850 DBG1(DBG_IKE
, "sa payload missing");
851 return send_notify(this, NO_PROPOSAL_CHOSEN
);
853 list
= sa_payload
->get_proposals(sa_payload
);
854 this->proposal
= this->config
->select_proposal(this->config
,
856 list
->destroy_offset(list
, offsetof(proposal_t
, destroy
));
859 DBG1(DBG_IKE
, "no matching proposal found");
860 return send_notify(this, NO_PROPOSAL_CHOSEN
);
862 this->spi_r
= this->proposal
->get_spi(this->proposal
);
864 apply_lifetimes(this, sa_payload
);
866 if (!get_nonce(this, &this->nonce_r
, message
))
868 return send_notify(this, INVALID_PAYLOAD_TYPE
);
870 if (this->dh
&& !get_ke(this, message
))
872 return send_notify(this, INVALID_KEY_INFORMATION
);
874 if (!get_ts(this, message
))
876 return send_notify(this, INVALID_PAYLOAD_TYPE
);
880 return send_notify(this, NO_PROPOSAL_CHOSEN
);
882 this->state
= QM_NEGOTIATED
;
890 METHOD(task_t
, get_type
, task_type_t
,
891 private_quick_mode_t
*this)
893 return TASK_QUICK_MODE
;
896 METHOD(quick_mode_t
, use_reqid
, void,
897 private_quick_mode_t
*this, u_int32_t reqid
)
902 METHOD(task_t
, migrate
, void,
903 private_quick_mode_t
*this, ike_sa_t
*ike_sa
)
905 chunk_free(&this->nonce_i
);
906 chunk_free(&this->nonce_r
);
907 DESTROY_IF(this->tsi
);
908 DESTROY_IF(this->tsr
);
909 DESTROY_IF(this->proposal
);
910 DESTROY_IF(this->child_sa
);
911 DESTROY_IF(this->dh
);
913 this->ike_sa
= ike_sa
;
914 this->keymat
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
915 this->state
= QM_INIT
;
918 this->proposal
= NULL
;
919 this->child_sa
= NULL
;
924 if (!this->initiator
)
926 DESTROY_IF(this->config
);
931 METHOD(task_t
, destroy
, void,
932 private_quick_mode_t
*this)
934 chunk_free(&this->nonce_i
);
935 chunk_free(&this->nonce_r
);
936 DESTROY_IF(this->tsi
);
937 DESTROY_IF(this->tsr
);
938 DESTROY_IF(this->proposal
);
939 DESTROY_IF(this->child_sa
);
940 DESTROY_IF(this->config
);
941 DESTROY_IF(this->dh
);
946 * Described in header.
948 quick_mode_t
*quick_mode_create(ike_sa_t
*ike_sa
, child_cfg_t
*config
,
949 traffic_selector_t
*tsi
, traffic_selector_t
*tsr
)
951 private_quick_mode_t
*this;
956 .get_type
= _get_type
,
960 .use_reqid
= _use_reqid
,
963 .initiator
= config
!= NULL
,
965 .keymat
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
),
971 this->public.task
.build
= _build_i
;
972 this->public.task
.process
= _process_i
;
976 this->public.task
.build
= _build_r
;
977 this->public.task
.process
= _process_r
;
980 return &this->public;