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