github: Run charon-tkm tests
[strongswan.git] / src / libcharon / sa / ikev1 / phase1.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2012 Martin Willi
6 * Copyright (C) 2012 revosec AG
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #include "phase1.h"
20
21 #include <daemon.h>
22 #include <sa/ikev1/keymat_v1.h>
23 #include <encoding/payloads/ke_payload.h>
24 #include <encoding/payloads/nonce_payload.h>
25 #include <collections/linked_list.h>
26
27 typedef struct private_phase1_t private_phase1_t;
28
29 /**
30 * Private data of an phase1_t object.
31 */
32 struct private_phase1_t {
33
34 /**
35 * Public phase1_t interface.
36 */
37 phase1_t public;
38
39 /**
40 * IKE_SA we negotiate
41 */
42 ike_sa_t *ike_sa;
43
44 /**
45 * Currently selected peer config
46 */
47 peer_cfg_t *peer_cfg;
48
49 /**
50 * Other possible peer config candidates
51 */
52 linked_list_t *candidates;
53
54 /**
55 * Acting as initiator
56 */
57 bool initiator;
58
59 /**
60 * Extracted SA payload bytes
61 */
62 chunk_t sa_payload;
63
64 /**
65 * DH exchange
66 */
67 diffie_hellman_t *dh;
68
69 /**
70 * Keymat derivation (from SA)
71 */
72 keymat_v1_t *keymat;
73
74 /**
75 * Received public DH value from peer
76 */
77 chunk_t dh_value;
78
79 /**
80 * Initiators nonce
81 */
82 chunk_t nonce_i;
83
84 /**
85 * Responder nonce
86 */
87 chunk_t nonce_r;
88 };
89
90 /**
91 * Get the first authentcation config from peer config
92 */
93 static auth_cfg_t *get_auth_cfg(peer_cfg_t *peer_cfg, bool local)
94 {
95 enumerator_t *enumerator;
96 auth_cfg_t *cfg = NULL;
97
98 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
99 enumerator->enumerate(enumerator, &cfg);
100 enumerator->destroy(enumerator);
101 return cfg;
102 }
103
104 /**
105 * Lookup a shared secret for this IKE_SA
106 */
107 static shared_key_t *lookup_shared_key(private_phase1_t *this,
108 peer_cfg_t *peer_cfg)
109 {
110 host_t *me, *other;
111 identification_t *my_id, *other_id;
112 shared_key_t *shared_key = NULL;
113 auth_cfg_t *my_auth, *other_auth;
114 enumerator_t *enumerator;
115
116 me = this->ike_sa->get_my_host(this->ike_sa);
117 other = this->ike_sa->get_other_host(this->ike_sa);
118
119 if (peer_cfg)
120 { /* as initiator or aggressive responder, use identities */
121 my_auth = get_auth_cfg(peer_cfg, TRUE);
122 other_auth = get_auth_cfg(peer_cfg, FALSE);
123 if (my_auth && other_auth)
124 {
125 my_id = my_auth->get(my_auth, AUTH_RULE_IDENTITY);
126 if (peer_cfg->use_aggressive(peer_cfg))
127 {
128 other_id = this->ike_sa->get_other_id(this->ike_sa);
129 }
130 else
131 {
132 other_id = other_auth->get(other_auth, AUTH_RULE_IDENTITY);
133 }
134 if (my_id && other_id)
135 {
136 shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
137 my_id, other_id);
138 if (!shared_key)
139 {
140 DBG1(DBG_IKE, "no shared key found for '%Y'[%H] - '%Y'[%H]",
141 my_id, me, other_id, other);
142 }
143 }
144 }
145 }
146 else
147 { /* as responder, we try to find a config by IP addresses and use the
148 * configured identities to find the PSK */
149 enumerator = charon->backends->create_peer_cfg_enumerator(
150 charon->backends, me, other, NULL, NULL, IKEV1);
151 while (enumerator->enumerate(enumerator, &peer_cfg))
152 {
153 my_auth = get_auth_cfg(peer_cfg, TRUE);
154 other_auth = get_auth_cfg(peer_cfg, FALSE);
155 if (my_auth && other_auth)
156 {
157 my_id = my_auth->get(my_auth, AUTH_RULE_IDENTITY);
158 other_id = other_auth->get(other_auth, AUTH_RULE_IDENTITY);
159 if (my_id)
160 {
161 shared_key = lib->credmgr->get_shared(lib->credmgr,
162 SHARED_IKE, my_id, other_id);
163 if (shared_key)
164 {
165 break;
166 }
167 DBG1(DBG_IKE, "no shared key found for '%Y'[%H] - '%Y'[%H]",
168 my_id, me, other_id, other);
169 }
170 }
171 }
172 enumerator->destroy(enumerator);
173 }
174 if (!shared_key)
175 { /* try to get a PSK for IP addresses */
176 my_id = identification_create_from_sockaddr(me->get_sockaddr(me));
177 other_id = identification_create_from_sockaddr(
178 other->get_sockaddr(other));
179 if (my_id && other_id)
180 {
181 shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
182 my_id, other_id);
183 }
184 DESTROY_IF(my_id);
185 DESTROY_IF(other_id);
186 if (!shared_key)
187 {
188 DBG1(DBG_IKE, "no shared key found for %H - %H", me, other);
189 }
190 }
191 return shared_key;
192 }
193
194 METHOD(phase1_t, create_hasher, bool,
195 private_phase1_t *this)
196 {
197 return this->keymat->create_hasher(this->keymat,
198 this->ike_sa->get_proposal(this->ike_sa));
199 }
200
201 METHOD(phase1_t, create_dh, bool,
202 private_phase1_t *this, diffie_hellman_group_t group)
203 {
204 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat, group);
205 return this->dh != NULL;
206 }
207
208 METHOD(phase1_t, derive_keys, bool,
209 private_phase1_t *this, peer_cfg_t *peer_cfg, auth_method_t method)
210 {
211 shared_key_t *shared_key = NULL;
212
213 switch (method)
214 {
215 case AUTH_PSK:
216 case AUTH_XAUTH_INIT_PSK:
217 case AUTH_XAUTH_RESP_PSK:
218 shared_key = lookup_shared_key(this, peer_cfg);
219 if (!shared_key)
220 {
221 return FALSE;
222 }
223 break;
224 default:
225 break;
226 }
227
228 if (!this->keymat->derive_ike_keys(this->keymat,
229 this->ike_sa->get_proposal(this->ike_sa),
230 this->dh, this->dh_value, this->nonce_i, this->nonce_r,
231 this->ike_sa->get_id(this->ike_sa), method, shared_key))
232 {
233 DESTROY_IF(shared_key);
234 DBG1(DBG_IKE, "key derivation for %N failed", auth_method_names, method);
235 return FALSE;
236 }
237 charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh, this->dh_value,
238 this->nonce_i, this->nonce_r, NULL, shared_key);
239 DESTROY_IF(shared_key);
240 return TRUE;
241 }
242
243 /**
244 * Check if a peer skipped authentication by using Hybrid authentication
245 */
246 static bool skipped_auth(private_phase1_t *this,
247 auth_method_t method, bool local)
248 {
249 bool initiator;
250
251 initiator = local == this->initiator;
252 if (initiator && method == AUTH_HYBRID_INIT_RSA)
253 {
254 return TRUE;
255 }
256 if (!initiator && method == AUTH_HYBRID_RESP_RSA)
257 {
258 return TRUE;
259 }
260 return FALSE;
261 }
262
263 /**
264 * Check if remote authentication constraints fulfilled
265 */
266 static bool check_constraints(private_phase1_t *this, auth_method_t method)
267 {
268 identification_t *id;
269 auth_cfg_t *auth, *cfg;
270 peer_cfg_t *peer_cfg;
271
272 auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
273 /* auth identity to comply */
274 id = this->ike_sa->get_other_id(this->ike_sa);
275 auth->add(auth, AUTH_RULE_IDENTITY, id->clone(id));
276 if (skipped_auth(this, method, FALSE))
277 {
278 return TRUE;
279 }
280 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
281 cfg = get_auth_cfg(peer_cfg, FALSE);
282 return cfg && auth->complies(auth, cfg, TRUE);
283 }
284
285 /**
286 * Save authentication information after authentication succeeded
287 */
288 static void save_auth_cfg(private_phase1_t *this,
289 auth_method_t method, bool local)
290 {
291 auth_cfg_t *auth;
292
293 if (skipped_auth(this, method, local))
294 {
295 return;
296 }
297 auth = auth_cfg_create();
298 /* for local config, we _copy_ entires from the config, as it contains
299 * certificates we must send later. */
300 auth->merge(auth, this->ike_sa->get_auth_cfg(this->ike_sa, local), local);
301 this->ike_sa->add_auth_cfg(this->ike_sa, local, auth);
302 }
303
304 /**
305 * Create an authenticator instance
306 */
307 static authenticator_t* create_authenticator(private_phase1_t *this,
308 auth_method_t method, chunk_t id)
309 {
310 authenticator_t *authenticator;
311
312 authenticator = authenticator_create_v1(this->ike_sa, this->initiator,
313 method, this->dh, this->dh_value, this->sa_payload, id);
314 if (!authenticator)
315 {
316 DBG1(DBG_IKE, "negotiated authentication method %N not supported",
317 auth_method_names, method);
318 }
319 return authenticator;
320 }
321
322 METHOD(phase1_t, verify_auth, bool,
323 private_phase1_t *this, auth_method_t method, message_t *message,
324 chunk_t id_data)
325 {
326 authenticator_t *authenticator;
327 status_t status;
328
329 authenticator = create_authenticator(this, method, id_data);
330 if (authenticator)
331 {
332 status = authenticator->process(authenticator, message);
333 authenticator->destroy(authenticator);
334 if (status == SUCCESS && check_constraints(this, method))
335 {
336 save_auth_cfg(this, method, FALSE);
337 return TRUE;
338 }
339 }
340 return FALSE;
341 }
342
343 METHOD(phase1_t, build_auth, bool,
344 private_phase1_t *this, auth_method_t method, message_t *message,
345 chunk_t id_data)
346 {
347 authenticator_t *authenticator;
348 status_t status;
349
350 authenticator = create_authenticator(this, method, id_data);
351 if (authenticator)
352 {
353 status = authenticator->build(authenticator, message);
354 authenticator->destroy(authenticator);
355 if (status == SUCCESS)
356 {
357 save_auth_cfg(this, method, TRUE);
358 return TRUE;
359 }
360 }
361 return FALSE;
362 }
363
364 /**
365 * Get the two auth classes from local or remote config
366 */
367 static void get_auth_class(peer_cfg_t *peer_cfg, bool local,
368 auth_class_t *c1, auth_class_t *c2)
369 {
370 enumerator_t *enumerator;
371 auth_cfg_t *auth;
372
373 *c1 = *c2 = AUTH_CLASS_ANY;
374
375 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
376 while (enumerator->enumerate(enumerator, &auth))
377 {
378 if (*c1 == AUTH_CLASS_ANY)
379 {
380 *c1 = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
381 }
382 else
383 {
384 *c2 = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
385 break;
386 }
387 }
388 enumerator->destroy(enumerator);
389 }
390
391 /**
392 * Select an auth method to use by checking what key we have
393 */
394 static auth_method_t get_pubkey_method(private_phase1_t *this, auth_cfg_t *auth)
395 {
396 auth_method_t method = AUTH_NONE;
397 identification_t *id;
398 private_key_t *private;
399
400 if (auth)
401 {
402 id = (identification_t*)auth->get(auth, AUTH_RULE_IDENTITY);
403 if (id)
404 {
405 private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, id, NULL);
406 if (private)
407 {
408 switch (private->get_type(private))
409 {
410 case KEY_RSA:
411 method = AUTH_RSA;
412 break;
413 case KEY_ECDSA:
414 switch (private->get_keysize(private))
415 {
416 case 256:
417 method = AUTH_ECDSA_256;
418 break;
419 case 384:
420 method = AUTH_ECDSA_384;
421 break;
422 case 521:
423 method = AUTH_ECDSA_521;
424 break;
425 default:
426 DBG1(DBG_IKE, "%d bit ECDSA private key size not "
427 "supported", private->get_keysize(private));
428 break;
429 }
430 break;
431 default:
432 DBG1(DBG_IKE, "private key of type %N not supported",
433 key_type_names, private->get_type(private));
434 break;
435 }
436 private->destroy(private);
437 }
438 else
439 {
440 DBG1(DBG_IKE, "no private key found for '%Y'", id);
441 }
442 }
443 }
444 return method;
445 }
446
447 /**
448 * Calculate authentication method from a peer config
449 */
450 static auth_method_t calc_auth_method(private_phase1_t *this,
451 peer_cfg_t *peer_cfg)
452 {
453 auth_class_t i1, i2, r1, r2;
454
455 get_auth_class(peer_cfg, this->initiator, &i1, &i2);
456 get_auth_class(peer_cfg, !this->initiator, &r1, &r2);
457
458 if (i1 == AUTH_CLASS_PUBKEY && r1 == AUTH_CLASS_PUBKEY)
459 {
460 if (i2 == AUTH_CLASS_ANY && r2 == AUTH_CLASS_ANY)
461 {
462 /* for any pubkey method, return RSA */
463 return AUTH_RSA;
464 }
465 if (i2 == AUTH_CLASS_XAUTH)
466 {
467 return AUTH_XAUTH_INIT_RSA;
468 }
469 if (r2 == AUTH_CLASS_XAUTH)
470 {
471 return AUTH_XAUTH_RESP_RSA;
472 }
473 }
474 if (i1 == AUTH_CLASS_PSK && r1 == AUTH_CLASS_PSK)
475 {
476 if (i2 == AUTH_CLASS_ANY && r2 == AUTH_CLASS_ANY)
477 {
478 return AUTH_PSK;
479 }
480 if (i2 == AUTH_CLASS_XAUTH)
481 {
482 return AUTH_XAUTH_INIT_PSK;
483 }
484 if (r2 == AUTH_CLASS_XAUTH)
485 {
486 return AUTH_XAUTH_RESP_PSK;
487 }
488 }
489 if (i1 == AUTH_CLASS_XAUTH && r1 == AUTH_CLASS_PUBKEY &&
490 i2 == AUTH_CLASS_ANY && r2 == AUTH_CLASS_ANY)
491 {
492 return AUTH_HYBRID_INIT_RSA;
493 }
494 return AUTH_NONE;
495 }
496
497 METHOD(phase1_t, get_auth_method, auth_method_t,
498 private_phase1_t *this, peer_cfg_t *peer_cfg)
499 {
500 auth_method_t method;
501
502 method = calc_auth_method(this, peer_cfg);
503 if (method == AUTH_RSA)
504 {
505 return get_pubkey_method(this, get_auth_cfg(peer_cfg, TRUE));
506 }
507 return method;
508 }
509
510 /**
511 * Check if a peer config can be used with a given auth method
512 */
513 static bool check_auth_method(private_phase1_t *this, peer_cfg_t *peer_cfg,
514 auth_method_t given)
515 {
516 auth_method_t method;
517
518 method = calc_auth_method(this, peer_cfg);
519 switch (given)
520 {
521 case AUTH_ECDSA_256:
522 case AUTH_ECDSA_384:
523 case AUTH_ECDSA_521:
524 return method == AUTH_RSA;
525 default:
526 return method == given;
527 }
528 }
529
530 METHOD(phase1_t, select_config, peer_cfg_t*,
531 private_phase1_t *this, auth_method_t method, bool aggressive,
532 identification_t *id)
533 {
534 enumerator_t *enumerator;
535 peer_cfg_t *current;
536 host_t *me, *other;
537 int unusable = 0;
538
539 if (this->peer_cfg)
540 { /* try to find an alternative config */
541 if (this->candidates->remove_first(this->candidates,
542 (void**)&current) != SUCCESS)
543 {
544 DBG1(DBG_CFG, "no alternative config found");
545 return NULL;
546 }
547 DBG1(DBG_CFG, "switching to peer config '%s'",
548 current->get_name(current));
549 return current;
550 }
551
552 me = this->ike_sa->get_my_host(this->ike_sa);
553 other = this->ike_sa->get_other_host(this->ike_sa);
554 DBG1(DBG_CFG, "looking for %N peer configs matching %H...%H[%Y]",
555 auth_method_names, method, me, other, id);
556 enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
557 me, other, NULL, id, IKEV1);
558 while (enumerator->enumerate(enumerator, &current))
559 {
560 if (check_auth_method(this, current, method) &&
561 current->use_aggressive(current) == aggressive)
562 {
563 current->get_ref(current);
564 if (!this->peer_cfg)
565 {
566 this->peer_cfg = current;
567 }
568 else
569 {
570 this->candidates->insert_last(this->candidates, current);
571 }
572 }
573 else
574 {
575 unusable++;
576 }
577 }
578 enumerator->destroy(enumerator);
579
580 if (this->peer_cfg)
581 {
582 DBG1(DBG_CFG, "selected peer config \"%s\"",
583 this->peer_cfg->get_name(this->peer_cfg));
584 return this->peer_cfg->get_ref(this->peer_cfg);
585 }
586 if (unusable)
587 {
588 DBG1(DBG_IKE, "found %d matching config%s, but none allows %N "
589 "authentication using %s Mode", unusable, unusable > 1 ? "s" : "",
590 auth_method_names, method, aggressive ? "Aggressive" : "Main");
591 return NULL;
592 }
593 DBG1(DBG_IKE, "no peer config found");
594 return NULL;
595 }
596
597 METHOD(phase1_t, get_id, identification_t*,
598 private_phase1_t *this, peer_cfg_t *peer_cfg, bool local)
599 {
600 identification_t *id = NULL;
601 auth_cfg_t *auth;
602
603 auth = get_auth_cfg(peer_cfg, local);
604 if (auth)
605 {
606 id = auth->get(auth, AUTH_RULE_IDENTITY);
607 if (local && (!id || id->get_type(id) == ID_ANY))
608 { /* no ID configured, use local IP address */
609 host_t *me;
610
611 me = this->ike_sa->get_my_host(this->ike_sa);
612 if (!me->is_anyaddr(me))
613 {
614 id = identification_create_from_sockaddr(me->get_sockaddr(me));
615 auth->add(auth, AUTH_RULE_IDENTITY, id);
616 }
617 }
618 }
619 return id;
620 }
621
622 METHOD(phase1_t, has_virtual_ip, bool,
623 private_phase1_t *this, peer_cfg_t *peer_cfg)
624 {
625 enumerator_t *enumerator;
626 bool found = FALSE;
627 host_t *host;
628
629 enumerator = peer_cfg->create_virtual_ip_enumerator(peer_cfg);
630 found = enumerator->enumerate(enumerator, &host);
631 enumerator->destroy(enumerator);
632
633 return found;
634 }
635
636 METHOD(phase1_t, has_pool, bool,
637 private_phase1_t *this, peer_cfg_t *peer_cfg)
638 {
639 enumerator_t *enumerator;
640 bool found = FALSE;
641 char *pool;
642
643 enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
644 found = enumerator->enumerate(enumerator, &pool);
645 enumerator->destroy(enumerator);
646
647 return found;
648 }
649
650 METHOD(phase1_t, save_sa_payload, bool,
651 private_phase1_t *this, message_t *message)
652 {
653 enumerator_t *enumerator;
654 payload_t *payload, *sa = NULL;
655 chunk_t data;
656 size_t offset = IKE_HEADER_LENGTH;
657
658 enumerator = message->create_payload_enumerator(message);
659 while (enumerator->enumerate(enumerator, &payload))
660 {
661 if (payload->get_type(payload) == PLV1_SECURITY_ASSOCIATION)
662 {
663 sa = payload;
664 break;
665 }
666 else
667 {
668 offset += payload->get_length(payload);
669 }
670 }
671 enumerator->destroy(enumerator);
672
673 data = message->get_packet_data(message);
674 if (sa && data.len >= offset + sa->get_length(sa))
675 {
676 /* Get SA payload without 4 byte fixed header */
677 data = chunk_skip(data, offset);
678 data.len = sa->get_length(sa);
679 data = chunk_skip(data, 4);
680 this->sa_payload = chunk_clone(data);
681 return TRUE;
682 }
683 DBG1(DBG_IKE, "unable to extract SA payload encoding");
684 return FALSE;
685 }
686
687 METHOD(phase1_t, add_nonce_ke, bool,
688 private_phase1_t *this, message_t *message)
689 {
690 nonce_payload_t *nonce_payload;
691 ke_payload_t *ke_payload;
692 nonce_gen_t *nonceg;
693 chunk_t nonce;
694
695 ke_payload = ke_payload_create_from_diffie_hellman(PLV1_KEY_EXCHANGE,
696 this->dh);
697 if (!ke_payload)
698 {
699 DBG1(DBG_IKE, "creating KE payload failed");
700 return FALSE;
701 }
702 message->add_payload(message, &ke_payload->payload_interface);
703
704 nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
705 if (!nonceg)
706 {
707 DBG1(DBG_IKE, "no nonce generator found to create nonce");
708 return FALSE;
709 }
710 if (!nonceg->allocate_nonce(nonceg, NONCE_SIZE, &nonce))
711 {
712 DBG1(DBG_IKE, "nonce allocation failed");
713 nonceg->destroy(nonceg);
714 return FALSE;
715 }
716 nonceg->destroy(nonceg);
717
718 nonce_payload = nonce_payload_create(PLV1_NONCE);
719 nonce_payload->set_nonce(nonce_payload, nonce);
720 message->add_payload(message, &nonce_payload->payload_interface);
721
722 if (this->initiator)
723 {
724 this->nonce_i = nonce;
725 }
726 else
727 {
728 this->nonce_r = nonce;
729 }
730 return TRUE;
731 }
732
733 METHOD(phase1_t, get_nonce_ke, bool,
734 private_phase1_t *this, message_t *message)
735 {
736 nonce_payload_t *nonce_payload;
737 ke_payload_t *ke_payload;
738
739 ke_payload = (ke_payload_t*)message->get_payload(message, PLV1_KEY_EXCHANGE);
740 if (!ke_payload)
741 {
742 DBG1(DBG_IKE, "KE payload missing in message");
743 return FALSE;
744 }
745 this->dh_value = chunk_clone(ke_payload->get_key_exchange_data(ke_payload));
746 if (!this->dh->set_other_public_value(this->dh, this->dh_value))
747 {
748 DBG1(DBG_IKE, "unable to apply received KE value");
749 return FALSE;
750 }
751
752 nonce_payload = (nonce_payload_t*)message->get_payload(message, PLV1_NONCE);
753 if (!nonce_payload)
754 {
755 DBG1(DBG_IKE, "NONCE payload missing in message");
756 return FALSE;
757 }
758
759 if (this->initiator)
760 {
761 this->nonce_r = nonce_payload->get_nonce(nonce_payload);
762 }
763 else
764 {
765 this->nonce_i = nonce_payload->get_nonce(nonce_payload);
766 }
767 return TRUE;
768 }
769
770 METHOD(phase1_t, destroy, void,
771 private_phase1_t *this)
772 {
773 DESTROY_IF(this->peer_cfg);
774 this->candidates->destroy_offset(this->candidates,
775 offsetof(peer_cfg_t, destroy));
776 chunk_free(&this->sa_payload);
777 DESTROY_IF(this->dh);
778 free(this->dh_value.ptr);
779 free(this->nonce_i.ptr);
780 free(this->nonce_r.ptr);
781 free(this);
782 }
783
784 /**
785 * See header
786 */
787 phase1_t *phase1_create(ike_sa_t *ike_sa, bool initiator)
788 {
789 private_phase1_t *this;
790
791 INIT(this,
792 .public = {
793 .create_hasher = _create_hasher,
794 .create_dh = _create_dh,
795 .derive_keys = _derive_keys,
796 .get_auth_method = _get_auth_method,
797 .get_id = _get_id,
798 .select_config = _select_config,
799 .has_virtual_ip = _has_virtual_ip,
800 .has_pool = _has_pool,
801 .verify_auth = _verify_auth,
802 .build_auth = _build_auth,
803 .save_sa_payload = _save_sa_payload,
804 .add_nonce_ke = _add_nonce_ke,
805 .get_nonce_ke = _get_nonce_ke,
806 .destroy = _destroy,
807 },
808 .candidates = linked_list_create(),
809 .ike_sa = ike_sa,
810 .initiator = initiator,
811 .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
812 );
813
814 return &this->public;
815 }