]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libcharon/sa/ikev2/tasks/ike_init.c
wip: ike-init: Indicate support for IKE_INTERMEDIATE
[thirdparty/strongswan.git] / src / libcharon / sa / ikev2 / tasks / ike_init.c
1 /*
2 * Copyright (C) 2008-2020 Tobias Brunner
3 * Copyright (C) 2005-2008 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 *
6 * Copyright (C) secunet Security Networks 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 "ike_init.h"
20
21 #include <string.h>
22
23 #include <daemon.h>
24 #include <bio/bio_reader.h>
25 #include <bio/bio_writer.h>
26 #include <sa/ikev2/keymat_v2.h>
27 #include <crypto/key_exchange.h>
28 #include <crypto/hashers/hash_algorithm_set.h>
29 #include <encoding/payloads/sa_payload.h>
30 #include <encoding/payloads/ke_payload.h>
31 #include <encoding/payloads/nonce_payload.h>
32
33 /** maximum retries to do with cookies/other dh groups */
34 #define MAX_RETRIES 5
35
36 /** maximum number of key exchanges (including the initial one) */
37 #define MAX_KEY_EXCHANGES (ADDITIONAL_KEY_EXCHANGE_7 - \
38 ADDITIONAL_KEY_EXCHANGE_1 + 2)
39
40 typedef struct private_ike_init_t private_ike_init_t;
41
42 /**
43 * Private members of a ike_init_t task.
44 */
45 struct private_ike_init_t {
46
47 /**
48 * Public methods and task_t interface.
49 */
50 ike_init_t public;
51
52 /**
53 * Assigned IKE_SA.
54 */
55 ike_sa_t *ike_sa;
56
57 /**
58 * Are we the initiator?
59 */
60 bool initiator;
61
62 /**
63 * Key exchanges to perform
64 */
65 struct {
66 transform_type_t type;
67 key_exchange_method_t method;
68 bool done;
69 bool derived;
70 } key_exchanges[MAX_KEY_EXCHANGES];
71
72 /**
73 * Current key exchange
74 */
75 int ke_index;
76
77 /**
78 * Key exchange method from the parsed or sent KE payload
79 */
80 key_exchange_method_t ke_method;
81
82 /**
83 * Current key exchange object
84 */
85 key_exchange_t *ke;
86
87 /**
88 * All key exchanges performed during rekeying (key_exchange_t)
89 */
90 array_t *kes;
91
92 /**
93 * Applying KE public key failed?
94 */
95 bool ke_failed;
96
97 /**
98 * Keymat derivation (from IKE_SA)
99 */
100 keymat_v2_t *keymat;
101
102 /**
103 * Nonce chosen by us
104 */
105 chunk_t my_nonce;
106
107 /**
108 * Nonce chosen by peer
109 */
110 chunk_t other_nonce;
111
112 /**
113 * Nonce generator
114 */
115 nonce_gen_t *nonceg;
116
117 /**
118 * Negotiated proposal used for IKE_SA
119 */
120 proposal_t *proposal;
121
122 /**
123 * Old IKE_SA that gets rekeyed
124 */
125 ike_sa_t *old_sa;
126
127 /**
128 * Cookie received from responder
129 */
130 chunk_t cookie;
131
132 /**
133 * Retries done so far after failure (cookie or bad DH group)
134 */
135 u_int retry;
136
137 /**
138 * Whether to use Signature Authentication as per RFC 7427
139 */
140 bool signature_authentication;
141
142 /**
143 * Whether to follow IKEv2 redirects as per RFC 5685
144 */
145 bool follow_redirects;
146 };
147
148 /**
149 * Returns the exchange type for additional exchanges when using multiple key
150 * exchanges, depending on whether this happens initially or during a rekeying
151 */
152 static exchange_type_t exchange_type_multi_ke(private_ike_init_t *this)
153 {
154 return this->old_sa ? IKE_FOLLOWUP_KE : IKE_INTERMEDIATE;
155 }
156
157 /**
158 * Allocate our own nonce value
159 */
160 static bool generate_nonce(private_ike_init_t *this)
161 {
162 if (!this->nonceg)
163 {
164 DBG1(DBG_IKE, "no nonce generator found to create nonce");
165 return FALSE;
166 }
167 if (!this->nonceg->allocate_nonce(this->nonceg, NONCE_SIZE,
168 &this->my_nonce))
169 {
170 DBG1(DBG_IKE, "nonce allocation failed");
171 return FALSE;
172 }
173 return TRUE;
174 }
175
176 /**
177 * Notify the peer about the hash algorithms we support or expect,
178 * as per RFC 7427
179 */
180 static void send_supported_hash_algorithms(private_ike_init_t *this,
181 message_t *message)
182 {
183 hash_algorithm_set_t *algos;
184 enumerator_t *enumerator, *rounds;
185 bio_writer_t *writer;
186 hash_algorithm_t hash;
187 peer_cfg_t *peer;
188 auth_cfg_t *auth;
189 auth_rule_t rule;
190 signature_params_t *config;
191 int written;
192 size_t len = BUF_LEN;
193 char buf[len];
194 char *pos = buf;
195 char *plugin_name;
196
197 algos = hash_algorithm_set_create();
198 peer = this->ike_sa->get_peer_cfg(this->ike_sa);
199 if (peer)
200 {
201 rounds = peer->create_auth_cfg_enumerator(peer, FALSE);
202 while (rounds->enumerate(rounds, &auth))
203 {
204 enumerator = auth->create_enumerator(auth);
205 while (enumerator->enumerate(enumerator, &rule, &config))
206 {
207 if (rule == AUTH_RULE_IKE_SIGNATURE_SCHEME)
208 {
209 hash = hasher_from_signature_scheme(config->scheme,
210 config->params);
211 if (hasher_algorithm_for_ikev2(hash))
212 {
213 algos->add(algos, hash);
214 }
215 }
216 }
217 enumerator->destroy(enumerator);
218 }
219 rounds->destroy(rounds);
220 }
221
222 if (!algos->count(algos))
223 {
224 enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
225 while (enumerator->enumerate(enumerator, &hash, &plugin_name))
226 {
227 if (hasher_algorithm_for_ikev2(hash))
228 {
229 algos->add(algos, hash);
230 }
231 }
232 enumerator->destroy(enumerator);
233 }
234
235 if (algos->count(algos))
236 {
237 writer = bio_writer_create(0);
238 enumerator = algos->create_enumerator(algos);
239 while (enumerator->enumerate(enumerator, &hash))
240 {
241 writer->write_uint16(writer, hash);
242
243 /* generate debug output */
244 written = snprintf(pos, len, " %N", hash_algorithm_short_names,
245 hash);
246 if (written > 0 && written < len)
247 {
248 pos += written;
249 len -= written;
250 }
251 }
252 enumerator->destroy(enumerator);
253 message->add_notify(message, FALSE, SIGNATURE_HASH_ALGORITHMS,
254 writer->get_buf(writer));
255 writer->destroy(writer);
256
257 *pos = '\0';
258 DBG2(DBG_CFG, "sending supported signature hash algorithms:%s", buf);
259 }
260 algos->destroy(algos);
261 }
262
263 /**
264 * Store algorithms supported by other peer
265 */
266 static void handle_supported_hash_algorithms(private_ike_init_t *this,
267 notify_payload_t *notify)
268 {
269 bio_reader_t *reader;
270 uint16_t algo;
271 int written;
272 size_t len = BUF_LEN;
273 char buf[len];
274 char *pos = buf;
275 bool added = FALSE;
276
277 reader = bio_reader_create(notify->get_notification_data(notify));
278 while (reader->remaining(reader) >= 2 && reader->read_uint16(reader, &algo))
279 {
280 if (hasher_algorithm_for_ikev2(algo))
281 {
282 this->keymat->add_hash_algorithm(this->keymat, algo);
283 added = TRUE;
284
285 /* generate debug output */
286 written = snprintf(pos, len, " %N", hash_algorithm_short_names,
287 algo);
288 if (written > 0 && written < len)
289 {
290 pos += written;
291 len -= written;
292 }
293 }
294 }
295 reader->destroy(reader);
296
297 *pos = '\0';
298 DBG2(DBG_CFG, "received supported signature hash algorithms:%s", buf);
299
300 if (added)
301 {
302 this->ike_sa->enable_extension(this->ike_sa, EXT_SIGNATURE_AUTH);
303 }
304 }
305
306 /**
307 * Check whether to send a USE_PPK notify
308 */
309 static bool send_use_ppk(private_ike_init_t *this)
310 {
311 peer_cfg_t *peer;
312 enumerator_t *keys;
313 shared_key_t *key;
314 bool use_ppk = FALSE;
315
316 if (this->initiator)
317 {
318 peer = this->ike_sa->get_peer_cfg(this->ike_sa);
319 if (peer->get_ppk_id(peer))
320 {
321 use_ppk = TRUE;
322 }
323 }
324 else if (this->ike_sa->supports_extension(this->ike_sa, EXT_PPK))
325 {
326 /* check if we have at least one PPK available */
327 keys = lib->credmgr->create_shared_enumerator(lib->credmgr, SHARED_PPK,
328 NULL, NULL);
329 if (keys->enumerate(keys, &key, NULL, NULL))
330 {
331 use_ppk = TRUE;
332 }
333 keys->destroy(keys);
334 }
335 return use_ppk;
336 }
337
338 /**
339 * build the payloads for the message
340 */
341 static bool build_payloads(private_ike_init_t *this, message_t *message)
342 {
343 sa_payload_t *sa_payload;
344 ke_payload_t *ke_payload;
345 nonce_payload_t *nonce_payload;
346 linked_list_t *proposal_list, *other_dh_groups;
347 ike_sa_id_t *id;
348 proposal_t *proposal;
349 enumerator_t *enumerator;
350 ike_cfg_t *ike_cfg;
351 bool additional_ke = FALSE;
352
353 id = this->ike_sa->get_id(this->ike_sa);
354
355 ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
356
357 if (this->initiator)
358 {
359 proposal_list = ike_cfg->get_proposals(ike_cfg);
360 other_dh_groups = linked_list_create();
361 enumerator = proposal_list->create_enumerator(proposal_list);
362 while (enumerator->enumerate(enumerator, (void**)&proposal))
363 {
364 /* include SPI of new IKE_SA when we are rekeying */
365 if (this->old_sa)
366 {
367 proposal->set_spi(proposal, id->get_initiator_spi(id));
368 }
369 /* move the selected DH group to the front of the proposal */
370 if (!proposal->promote_transform(proposal, KEY_EXCHANGE_METHOD,
371 this->ke_method))
372 { /* the proposal does not include the group, move to the back */
373 proposal_list->remove_at(proposal_list, enumerator);
374 other_dh_groups->insert_last(other_dh_groups, proposal);
375 }
376 additional_ke = additional_ke ||
377 proposal_has_additional_ke(proposal);
378 }
379 enumerator->destroy(enumerator);
380 /* add proposals that don't contain the selected group */
381 enumerator = other_dh_groups->create_enumerator(other_dh_groups);
382 while (enumerator->enumerate(enumerator, (void**)&proposal))
383 { /* no need to remove from the list as we destroy it anyway*/
384 proposal_list->insert_last(proposal_list, proposal);
385 }
386 enumerator->destroy(enumerator);
387 other_dh_groups->destroy(other_dh_groups);
388
389 sa_payload = sa_payload_create_from_proposals_v2(proposal_list);
390 proposal_list->destroy_offset(proposal_list, offsetof(proposal_t, destroy));
391 }
392 else
393 {
394 if (this->old_sa)
395 {
396 /* include SPI of new IKE_SA when we are rekeying */
397 this->proposal->set_spi(this->proposal, id->get_responder_spi(id));
398 }
399 sa_payload = sa_payload_create_from_proposal_v2(this->proposal);
400 additional_ke = proposal_has_additional_ke(this->proposal);
401 }
402 message->add_payload(message, (payload_t*)sa_payload);
403
404 ke_payload = ke_payload_create_from_key_exchange(PLV2_KEY_EXCHANGE,
405 this->ke);
406 if (!ke_payload)
407 {
408 DBG1(DBG_IKE, "creating KE payload failed");
409 return FALSE;
410 }
411 message->add_payload(message, (payload_t*)ke_payload);
412
413 nonce_payload = nonce_payload_create(PLV2_NONCE);
414 nonce_payload->set_nonce(nonce_payload, this->my_nonce);
415 message->add_payload(message, (payload_t*)nonce_payload);
416
417 /* negotiate fragmentation if we are not rekeying */
418 if (!this->old_sa &&
419 ike_cfg->fragmentation(ike_cfg) != FRAGMENTATION_NO)
420 {
421 if (this->initiator ||
422 this->ike_sa->supports_extension(this->ike_sa,
423 EXT_IKE_FRAGMENTATION))
424 {
425 message->add_notify(message, FALSE, FRAGMENTATION_SUPPORTED,
426 chunk_empty);
427 }
428 }
429 /* submit supported hash algorithms for signature authentication */
430 if (!this->old_sa && this->signature_authentication)
431 {
432 if (this->initiator ||
433 this->ike_sa->supports_extension(this->ike_sa,
434 EXT_SIGNATURE_AUTH))
435 {
436 send_supported_hash_algorithms(this, message);
437 }
438 }
439 /* notify other peer if we support redirection */
440 if (!this->old_sa && this->initiator && this->follow_redirects)
441 {
442 identification_t *gateway;
443 host_t *from;
444 chunk_t data;
445
446 from = this->ike_sa->get_redirected_from(this->ike_sa);
447 if (from)
448 {
449 gateway = identification_create_from_sockaddr(
450 from->get_sockaddr(from));
451 data = redirect_data_create(gateway, chunk_empty);
452 message->add_notify(message, FALSE, REDIRECTED_FROM, data);
453 chunk_free(&data);
454 gateway->destroy(gateway);
455 }
456 else
457 {
458 message->add_notify(message, FALSE, REDIRECT_SUPPORTED,
459 chunk_empty);
460 }
461 }
462 /* notify the peer if we want to use/support PPK */
463 if (!this->old_sa && send_use_ppk(this))
464 {
465 message->add_notify(message, FALSE, USE_PPK, chunk_empty);
466 }
467 /* notify the peer if we accept childless IKE_SAs */
468 if (!this->old_sa && !this->initiator &&
469 ike_cfg->childless(ike_cfg) != CHILDLESS_NEVER)
470 {
471 message->add_notify(message, FALSE, CHILDLESS_IKEV2_SUPPORTED,
472 chunk_empty);
473 }
474 if (!this->old_sa && additional_ke)
475 {
476 if (this->initiator ||
477 this->ike_sa->supports_extension(this->ike_sa,
478 EXT_IKE_INTERMEDIATE))
479 {
480 message->add_notify(message, FALSE, INTERMEDIATE_EXCHANGE_SUPPORTED,
481 chunk_empty);
482 }
483 }
484 return TRUE;
485 }
486
487 /**
488 * Process the SA payload and select a proposal
489 */
490 static void process_sa_payload(private_ike_init_t *this, message_t *message,
491 sa_payload_t *sa_payload)
492 {
493 ike_cfg_t *ike_cfg, *cfg, *alt_cfg = NULL;
494 enumerator_t *enumerator;
495 linked_list_t *proposal_list;
496 host_t *me, *other;
497 proposal_selection_flag_t flags = 0;
498
499 ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
500
501 proposal_list = sa_payload->get_proposals(sa_payload);
502 if (!this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN) &&
503 !lib->settings->get_bool(lib->settings, "%s.accept_private_algs",
504 FALSE, lib->ns))
505 {
506 flags |= PROPOSAL_SKIP_PRIVATE;
507 }
508 if (!lib->settings->get_bool(lib->settings,
509 "%s.prefer_configured_proposals", TRUE, lib->ns))
510 {
511 flags |= PROPOSAL_PREFER_SUPPLIED;
512 }
513 this->proposal = ike_cfg->select_proposal(ike_cfg, proposal_list, flags);
514 if (!this->proposal)
515 {
516 if (!this->initiator && !this->old_sa)
517 {
518 me = message->get_destination(message);
519 other = message->get_source(message);
520 enumerator = charon->backends->create_ike_cfg_enumerator(
521 charon->backends, me, other, IKEV2);
522 while (enumerator->enumerate(enumerator, &cfg))
523 {
524 if (ike_cfg == cfg)
525 { /* already tried and failed */
526 continue;
527 }
528 DBG1(DBG_IKE, "no matching proposal found, trying alternative "
529 "config");
530 this->proposal = cfg->select_proposal(cfg, proposal_list,
531 flags);
532 if (this->proposal)
533 {
534 alt_cfg = cfg->get_ref(cfg);
535 break;
536 }
537 }
538 enumerator->destroy(enumerator);
539 }
540 if (alt_cfg)
541 {
542 this->ike_sa->set_ike_cfg(this->ike_sa, alt_cfg);
543 alt_cfg->destroy(alt_cfg);
544 }
545 else
546 {
547 charon->bus->alert(charon->bus, ALERT_PROPOSAL_MISMATCH_IKE,
548 proposal_list);
549 }
550 }
551 proposal_list->destroy_offset(proposal_list,
552 offsetof(proposal_t, destroy));
553 }
554
555 /**
556 * Collect all key exchanges from the proposal
557 */
558 static void determine_key_exchanges(private_ike_init_t *this)
559 {
560 transform_type_t t = KEY_EXCHANGE_METHOD;
561 uint16_t alg;
562 int i = 1;
563
564 this->proposal->get_algorithm(this->proposal, t, &alg, NULL);
565 this->key_exchanges[0].type = t;
566 this->key_exchanges[0].method = alg;
567
568 for (t = ADDITIONAL_KEY_EXCHANGE_1; t <= ADDITIONAL_KEY_EXCHANGE_7; t++)
569 {
570 if (this->proposal->get_algorithm(this->proposal, t, &alg, NULL))
571 {
572 this->key_exchanges[i].type = t;
573 this->key_exchanges[i].method = alg;
574 i++;
575 }
576 }
577 }
578
579 /**
580 * Check if additional key exchanges are required
581 */
582 static bool additional_key_exchange_required(private_ike_init_t *this)
583 {
584 int i;
585
586 for (i = this->ke_index; i < MAX_KEY_EXCHANGES; i++)
587 {
588 if (this->key_exchanges[i].type && !this->key_exchanges[i].done)
589 {
590 return TRUE;
591 }
592 }
593 return FALSE;
594 }
595
596 /**
597 * Clear data on key exchanges
598 */
599 static void clear_key_exchanges(private_ike_init_t *this)
600 {
601 int i;
602
603 for (i = 0; i < MAX_KEY_EXCHANGES; i++)
604 {
605 this->key_exchanges[i].type = 0;
606 this->key_exchanges[i].method = 0;
607 this->key_exchanges[i].done = FALSE;
608 }
609 this->ke_index = 0;
610
611 array_destroy_offset(this->kes, offsetof(key_exchange_t, destroy));
612 this->kes = NULL;
613 }
614
615 /**
616 * Process a KE payload
617 */
618 static void process_ke_payload(private_ike_init_t *this, ke_payload_t *ke)
619 {
620 key_exchange_method_t method = this->key_exchanges[this->ke_index].method;
621 key_exchange_method_t received = ke->get_key_exchange_method(ke);
622
623 if (method != received)
624 {
625 DBG1(DBG_IKE, "key exchange method in received payload %N doesn't "
626 "match negotiated %N", key_exchange_method_names, received,
627 key_exchange_method_names, method);
628 this->ke_failed = TRUE;
629 return;
630 }
631
632 if (!this->initiator)
633 {
634 DESTROY_IF(this->ke);
635 this->ke = this->keymat->keymat.create_ke(&this->keymat->keymat,
636 method);
637 if (!this->ke)
638 {
639 DBG1(DBG_IKE, "negotiated key exchange method %N not supported",
640 key_exchange_method_names, method);
641 }
642 }
643 else if (this->ke)
644 {
645 this->ke_failed = this->ke->get_method(this->ke) != received;
646 }
647
648 if (this->ke && !this->ke_failed)
649 {
650 this->ke_failed = !this->ke->set_public_key(this->ke,
651 ke->get_key_exchange_data(ke));
652 }
653 }
654
655 /**
656 * Read payloads from message
657 */
658 static void process_payloads(private_ike_init_t *this, message_t *message)
659 {
660 enumerator_t *enumerator;
661 payload_t *payload;
662 ike_sa_id_t *id;
663 ke_payload_t *ke_pld = NULL;
664
665 enumerator = message->create_payload_enumerator(message);
666 while (enumerator->enumerate(enumerator, &payload))
667 {
668 switch (payload->get_type(payload))
669 {
670 case PLV2_SECURITY_ASSOCIATION:
671 {
672 process_sa_payload(this, message, (sa_payload_t*)payload);
673 break;
674 }
675 case PLV2_KEY_EXCHANGE:
676 {
677 ke_pld = (ke_payload_t*)payload;
678
679 this->ke_method = ke_pld->get_key_exchange_method(ke_pld);
680 break;
681 }
682 case PLV2_NONCE:
683 {
684 nonce_payload_t *nonce_payload = (nonce_payload_t*)payload;
685
686 this->other_nonce = nonce_payload->get_nonce(nonce_payload);
687 break;
688 }
689 case PLV2_NOTIFY:
690 {
691 notify_payload_t *notify = (notify_payload_t*)payload;
692
693 switch (notify->get_notify_type(notify))
694 {
695 case FRAGMENTATION_SUPPORTED:
696 this->ike_sa->enable_extension(this->ike_sa,
697 EXT_IKE_FRAGMENTATION);
698 break;
699 case SIGNATURE_HASH_ALGORITHMS:
700 if (this->signature_authentication)
701 {
702 handle_supported_hash_algorithms(this, notify);
703 }
704 break;
705 case USE_PPK:
706 if (!this->old_sa)
707 {
708 this->ike_sa->enable_extension(this->ike_sa,
709 EXT_PPK);
710 }
711 break;
712 case REDIRECTED_FROM:
713 {
714 identification_t *gateway;
715 chunk_t data;
716
717 data = notify->get_notification_data(notify);
718 gateway = redirect_data_parse(data, NULL);
719 if (!gateway)
720 {
721 DBG1(DBG_IKE, "received invalid REDIRECTED_FROM "
722 "notify, ignored");
723 break;
724 }
725 DBG1(DBG_IKE, "client got redirected from %Y", gateway);
726 gateway->destroy(gateway);
727 /* fall-through */
728 }
729 case REDIRECT_SUPPORTED:
730 if (!this->old_sa)
731 {
732 this->ike_sa->enable_extension(this->ike_sa,
733 EXT_IKE_REDIRECTION);
734 }
735 break;
736 case CHILDLESS_IKEV2_SUPPORTED:
737 if (this->initiator && !this->old_sa)
738 {
739 this->ike_sa->enable_extension(this->ike_sa,
740 EXT_IKE_CHILDLESS);
741 }
742 break;
743 case INTERMEDIATE_EXCHANGE_SUPPORTED:
744 if (!this->old_sa)
745 {
746 this->ike_sa->enable_extension(this->ike_sa,
747 EXT_IKE_INTERMEDIATE);
748 }
749 break;
750 default:
751 /* other notifies are handled elsewhere */
752 break;
753 }
754
755 }
756 default:
757 break;
758 }
759 }
760 enumerator->destroy(enumerator);
761
762 if (this->proposal)
763 {
764 this->ike_sa->set_proposal(this->ike_sa, this->proposal);
765
766 if (this->old_sa)
767 { /* retrieve SPI of new IKE_SA when rekeying */
768 id = this->ike_sa->get_id(this->ike_sa);
769 if (this->initiator)
770 {
771 id->set_responder_spi(id,
772 this->proposal->get_spi(this->proposal));
773 }
774 else
775 {
776 id->set_initiator_spi(id,
777 this->proposal->get_spi(this->proposal));
778 }
779 }
780
781 determine_key_exchanges(this);
782 if (ke_pld)
783 {
784 process_ke_payload(this, ke_pld);
785 }
786 }
787 }
788
789 /**
790 * Build payloads in additional exchanges when using multiple key exchanges
791 */
792 static bool build_payloads_multi_ke(private_ike_init_t *this,
793 message_t *message)
794 {
795 ke_payload_t *ke;
796
797 ke = ke_payload_create_from_key_exchange(PLV2_KEY_EXCHANGE, this->ke);
798 if (!ke)
799 {
800 DBG1(DBG_IKE, "creating KE payload failed");
801 return FALSE;
802 }
803 message->add_payload(message, (payload_t*)ke);
804 return TRUE;
805 }
806
807 METHOD(task_t, build_i_multi_ke, status_t,
808 private_ike_init_t *this, message_t *message)
809 {
810 key_exchange_method_t method;
811
812 message->set_exchange_type(message, exchange_type_multi_ke(this));
813
814 DESTROY_IF(this->ke);
815 method = this->key_exchanges[this->ke_index].method;
816 this->ke = this->keymat->keymat.create_ke(&this->keymat->keymat,
817 method);
818 if (!this->ke)
819 {
820 DBG1(DBG_IKE, "negotiated key exchange method %N not supported",
821 key_exchange_method_names, method);
822 return FAILED;
823 }
824 if (!build_payloads_multi_ke(this, message))
825 {
826 return FAILED;
827 }
828 return NEED_MORE;
829 }
830
831 METHOD(task_t, build_i, status_t,
832 private_ike_init_t *this, message_t *message)
833 {
834 ike_cfg_t *ike_cfg;
835
836 ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
837
838 DBG0(DBG_IKE, "initiating IKE_SA %s[%d] to %H",
839 this->ike_sa->get_name(this->ike_sa),
840 this->ike_sa->get_unique_id(this->ike_sa),
841 this->ike_sa->get_other_host(this->ike_sa));
842 this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
843
844 if (this->retry >= MAX_RETRIES)
845 {
846 DBG1(DBG_IKE, "giving up after %d retries", MAX_RETRIES);
847 return FAILED;
848 }
849
850 /* if we are retrying after an INVALID_KE_PAYLOAD we already have one */
851 if (!this->ke)
852 {
853 if (this->old_sa &&
854 lib->settings->get_bool(lib->settings,
855 "%s.prefer_previous_dh_group", TRUE, lib->ns))
856 { /* reuse the DH group we used for the old IKE_SA when rekeying */
857 proposal_t *proposal;
858 uint16_t dh_group;
859
860 proposal = this->old_sa->get_proposal(this->old_sa);
861 if (proposal->get_algorithm(proposal, KEY_EXCHANGE_METHOD,
862 &dh_group, NULL))
863 {
864 this->ke_method = dh_group;
865 }
866 else
867 { /* this shouldn't happen, but let's be safe */
868 this->ke_method = ike_cfg->get_algorithm(ike_cfg,
869 KEY_EXCHANGE_METHOD);
870 }
871 }
872 else
873 {
874 this->ke_method = ike_cfg->get_algorithm(ike_cfg,
875 KEY_EXCHANGE_METHOD);
876 }
877 this->ke = this->keymat->keymat.create_ke(&this->keymat->keymat,
878 this->ke_method);
879 if (!this->ke)
880 {
881 DBG1(DBG_IKE, "configured DH group %N not supported",
882 key_exchange_method_names, this->ke_method);
883 return FAILED;
884 }
885 }
886 else if (this->ke->get_method(this->ke) != this->ke_method)
887 { /* reset DH instance if group changed (INVALID_KE_PAYLOAD) */
888 this->ke->destroy(this->ke);
889 this->ke = this->keymat->keymat.create_ke(&this->keymat->keymat,
890 this->ke_method);
891 if (!this->ke)
892 {
893 DBG1(DBG_IKE, "requested DH group %N not supported",
894 key_exchange_method_names, this->ke_method);
895 return FAILED;
896 }
897 }
898
899 /* generate nonce only when we are trying the first time */
900 if (this->my_nonce.ptr == NULL)
901 {
902 if (!generate_nonce(this))
903 {
904 return FAILED;
905 }
906 }
907
908 if (this->cookie.ptr)
909 {
910 message->add_notify(message, FALSE, COOKIE, this->cookie);
911 }
912
913 if (!build_payloads(this, message))
914 {
915 return FAILED;
916 }
917
918 #ifdef ME
919 {
920 chunk_t connect_id = this->ike_sa->get_connect_id(this->ike_sa);
921 if (connect_id.ptr)
922 {
923 message->add_notify(message, FALSE, ME_CONNECTID, connect_id);
924 }
925 }
926 #endif /* ME */
927
928 return NEED_MORE;
929 }
930
931 /**
932 * Process payloads in additional exchanges when using multiple key exchanges
933 */
934 static void process_payloads_multi_ke(private_ike_init_t *this,
935 message_t *message)
936 {
937 ke_payload_t *ke;
938
939 ke = (ke_payload_t*)message->get_payload(message, PLV2_KEY_EXCHANGE);
940 if (ke)
941 {
942 process_ke_payload(this, ke);
943 }
944 else
945 {
946 DBG1(DBG_IKE, "KE payload missing in message");
947 }
948 }
949
950 METHOD(task_t, process_r_multi_ke, status_t,
951 private_ike_init_t *this, message_t *message)
952 {
953 if (message->get_exchange_type(message) == exchange_type_multi_ke(this))
954 {
955 process_payloads_multi_ke(this, message);
956 }
957 return NEED_MORE;
958 }
959
960 METHOD(task_t, process_r, status_t,
961 private_ike_init_t *this, message_t *message)
962 {
963 DBG0(DBG_IKE, "%H is initiating an IKE_SA", message->get_source(message));
964 this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
965
966 if (!generate_nonce(this))
967 {
968 return FAILED;
969 }
970
971 #ifdef ME
972 {
973 notify_payload_t *notify = message->get_notify(message, ME_CONNECTID);
974 if (notify)
975 {
976 chunk_t connect_id = notify->get_notification_data(notify);
977 DBG2(DBG_IKE, "received ME_CONNECTID %#B", &connect_id);
978 charon->connect_manager->stop_checks(charon->connect_manager,
979 connect_id);
980 }
981 }
982 #endif /* ME */
983
984 process_payloads(this, message);
985
986 return NEED_MORE;
987 }
988
989 /**
990 * Derive the keymat for the IKE_SA
991 */
992 static bool derive_keys_internal(private_ike_init_t *this, chunk_t nonce_i,
993 chunk_t nonce_r)
994 {
995 ike_sa_t *old_sa;
996 keymat_v2_t *old_keymat;
997 pseudo_random_function_t prf_alg = PRF_UNDEFINED;
998 chunk_t skd = chunk_empty;
999 ike_sa_id_t *id;
1000 array_t *kes = this->kes;
1001 bool success;
1002
1003 if (this->old_sa)
1004 {
1005 if (additional_key_exchange_required(this))
1006 { /* when rekeying, we only derive keys once all exchanges are done */
1007 return FALSE;
1008 }
1009 old_sa = this->old_sa;
1010 }
1011 else
1012 { /* key derivation for additional key exchanges is like rekeying, so pass
1013 * our own SA as old SA to get SK_d */
1014 old_sa = this->ike_sa;
1015 }
1016
1017 id = this->ike_sa->get_id(this->ike_sa);
1018 if (!kes)
1019 {
1020 array_insert_create(&kes, ARRAY_HEAD, this->ke);
1021 }
1022
1023 old_keymat = (keymat_v2_t*)old_sa->get_keymat(old_sa);
1024 prf_alg = old_keymat->get_skd(old_keymat, &skd);
1025 success = this->keymat->derive_ike_keys(this->keymat, this->proposal, kes,
1026 nonce_i, nonce_r, id, prf_alg, skd);
1027 if (success)
1028 {
1029 charon->bus->ike_keys(charon->bus, this->ike_sa, kes, chunk_empty,
1030 nonce_i, nonce_r, skd.len ? old_sa : NULL, NULL,
1031 AUTH_NONE);
1032 }
1033 if (kes != this->kes)
1034 {
1035 array_destroy(kes);
1036 }
1037 return success;
1038 }
1039
1040 METHOD(ike_init_t, derive_keys, status_t,
1041 private_ike_init_t *this)
1042 {
1043 bool success;
1044
1045 if (!this->ke_index || this->key_exchanges[this->ke_index-1].derived)
1046 {
1047 return NEED_MORE;
1048 }
1049
1050 if (this->initiator)
1051 {
1052 success = derive_keys_internal(this, this->my_nonce, this->other_nonce);
1053 }
1054 else
1055 {
1056 success = derive_keys_internal(this, this->other_nonce, this->my_nonce);
1057 }
1058
1059 this->key_exchanges[this->ke_index-1].derived = TRUE;
1060
1061 if (!success)
1062 {
1063 DBG1(DBG_IKE, "key derivation failed");
1064 return FAILED;
1065 }
1066 return additional_key_exchange_required(this) ? NEED_MORE : SUCCESS;
1067 }
1068
1069 /**
1070 * Called when a key exchange is done
1071 */
1072 static status_t key_exchange_done(private_ike_init_t *this)
1073 {
1074 if (this->old_sa)
1075 {
1076 /* during rekeying, we store all the key exchanges performed */
1077 array_insert_create(&this->kes, ARRAY_TAIL, this->ke);
1078 this->ke = NULL;
1079 }
1080
1081 this->key_exchanges[this->ke_index++].done = TRUE;
1082
1083 return additional_key_exchange_required(this) ? NEED_MORE : SUCCESS;
1084 }
1085
1086 METHOD(task_t, build_r_multi_ke, status_t,
1087 private_ike_init_t *this, message_t *message)
1088 {
1089 if (!this->ke)
1090 {
1091 message->add_notify(message, FALSE, INVALID_SYNTAX, chunk_empty);
1092 return FAILED;
1093 }
1094 if (this->ke_failed)
1095 {
1096 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
1097 return FAILED;
1098 }
1099 if (!build_payloads_multi_ke(this, message))
1100 {
1101 return FAILED;
1102 }
1103
1104 if (key_exchange_done(this) != NEED_MORE && this->old_sa)
1105 {
1106 /* during rekeying, we derive keys once all exchanges are done */
1107 if (derive_keys(this) != SUCCESS)
1108 {
1109 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
1110 return FAILED;
1111 }
1112 return SUCCESS;
1113 }
1114 /* we derive keys after each IKE_INTERMEDIATE once we receive the next
1115 * message, otherwise, IntAuth would be based on the wrong keys */
1116 return NEED_MORE;
1117 }
1118
1119 METHOD(task_t, build_r, status_t,
1120 private_ike_init_t *this, message_t *message)
1121 {
1122 identification_t *gateway;
1123
1124 /* check if we have everything we need */
1125 if (this->proposal == NULL ||
1126 this->other_nonce.len == 0 || this->my_nonce.len == 0)
1127 {
1128 DBG1(DBG_IKE, "received proposals unacceptable");
1129 message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
1130 return FAILED;
1131 }
1132
1133 /* check if we'd have to redirect the client */
1134 if (!this->old_sa &&
1135 this->ike_sa->supports_extension(this->ike_sa, EXT_IKE_REDIRECTION) &&
1136 charon->redirect->redirect_on_init(charon->redirect, this->ike_sa,
1137 &gateway))
1138 {
1139 chunk_t data;
1140
1141 DBG1(DBG_IKE, "redirecting peer to %Y", gateway);
1142 data = redirect_data_create(gateway, this->other_nonce);
1143 message->add_notify(message, TRUE, REDIRECT, data);
1144 gateway->destroy(gateway);
1145 chunk_free(&data);
1146 return FAILED;
1147 }
1148
1149 if (!this->ke ||
1150 !this->proposal->has_transform(this->proposal, KEY_EXCHANGE_METHOD,
1151 this->ke_method))
1152 {
1153 uint16_t group;
1154
1155 if (this->proposal->get_algorithm(this->proposal, KEY_EXCHANGE_METHOD,
1156 &group, NULL) &&
1157 this->ke_method != group)
1158 {
1159 DBG1(DBG_IKE, "DH group %N unacceptable, requesting %N",
1160 key_exchange_method_names, this->ke_method,
1161 key_exchange_method_names, group);
1162 this->ke_method = group;
1163 group = htons(group);
1164 message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
1165 chunk_from_thing(group));
1166 }
1167 else
1168 {
1169 DBG1(DBG_IKE, "no acceptable proposal found");
1170 message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
1171 }
1172 return FAILED;
1173 }
1174
1175 if (this->ke_failed)
1176 {
1177 DBG1(DBG_IKE, "applying DH public value failed");
1178 message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
1179 return FAILED;
1180 }
1181
1182 if (!build_payloads(this, message))
1183 {
1184 message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
1185 return FAILED;
1186 }
1187
1188 if (key_exchange_done(this) == NEED_MORE)
1189 {
1190 /* use other exchange type for additional key exchanges */
1191 this->public.task.build = _build_r_multi_ke;
1192 this->public.task.process = _process_r_multi_ke;
1193 }
1194 else if (this->old_sa)
1195 {
1196 /* during rekeying, we derive keys here directly */
1197 if (derive_keys(this) != SUCCESS)
1198 {
1199 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
1200 return FAILED;
1201 }
1202 return SUCCESS;
1203 }
1204 /* key derivation is done before the next request is processed */
1205 return NEED_MORE;
1206 }
1207
1208 /**
1209 * Raise alerts for received notify errors
1210 */
1211 static void raise_alerts(private_ike_init_t *this, notify_type_t type)
1212 {
1213 ike_cfg_t *ike_cfg;
1214 linked_list_t *list;
1215
1216 switch (type)
1217 {
1218 case NO_PROPOSAL_CHOSEN:
1219 ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
1220 list = ike_cfg->get_proposals(ike_cfg);
1221 charon->bus->alert(charon->bus, ALERT_PROPOSAL_MISMATCH_IKE, list);
1222 list->destroy_offset(list, offsetof(proposal_t, destroy));
1223 break;
1224 default:
1225 break;
1226 }
1227 }
1228
1229 METHOD(task_t, pre_process_i, status_t,
1230 private_ike_init_t *this, message_t *message)
1231 {
1232 enumerator_t *enumerator;
1233 payload_t *payload;
1234
1235 /* check for erroneous notifies */
1236 enumerator = message->create_payload_enumerator(message);
1237 while (enumerator->enumerate(enumerator, &payload))
1238 {
1239 if (payload->get_type(payload) == PLV2_NOTIFY)
1240 {
1241 notify_payload_t *notify = (notify_payload_t*)payload;
1242 notify_type_t type = notify->get_notify_type(notify);
1243
1244 switch (type)
1245 {
1246 case COOKIE:
1247 {
1248 chunk_t cookie;
1249
1250 cookie = notify->get_notification_data(notify);
1251 if (chunk_equals(cookie, this->cookie))
1252 {
1253 DBG1(DBG_IKE, "ignore response with duplicate COOKIE "
1254 "notify");
1255 enumerator->destroy(enumerator);
1256 return FAILED;
1257 }
1258 break;
1259 }
1260 case REDIRECT:
1261 {
1262 identification_t *gateway;
1263 chunk_t data, nonce = chunk_empty;
1264 status_t status = SUCCESS;
1265
1266 if (this->old_sa)
1267 {
1268 break;
1269 }
1270 data = notify->get_notification_data(notify);
1271 gateway = redirect_data_parse(data, &nonce);
1272 if (!gateway || !chunk_equals(nonce, this->my_nonce))
1273 {
1274 DBG1(DBG_IKE, "received invalid REDIRECT notify");
1275 status = FAILED;
1276 }
1277 DESTROY_IF(gateway);
1278 chunk_free(&nonce);
1279 enumerator->destroy(enumerator);
1280 return status;
1281 }
1282 default:
1283 break;
1284 }
1285 }
1286 }
1287 enumerator->destroy(enumerator);
1288 return SUCCESS;
1289 }
1290
1291 METHOD(task_t, process_i_multi_ke, status_t,
1292 private_ike_init_t *this, message_t *message)
1293 {
1294 process_payloads_multi_ke(this, message);
1295
1296 if (this->ke_failed)
1297 {
1298 return FAILED;
1299 }
1300
1301 if (key_exchange_done(this) != NEED_MORE && this->old_sa)
1302 {
1303 /* during rekeying, we derive keys once all exchanges are done */
1304 return derive_keys(this);
1305 }
1306 /* we derive keys after each IKE_INTERMEDIATE once we send the next
1307 * message, otherwise, IntAuth would be based on the wrong keys */
1308 return NEED_MORE;
1309 }
1310
1311 METHOD(task_t, process_i, status_t,
1312 private_ike_init_t *this, message_t *message)
1313 {
1314 enumerator_t *enumerator;
1315 payload_t *payload;
1316
1317 /* check for erroneous notifies */
1318 enumerator = message->create_payload_enumerator(message);
1319 while (enumerator->enumerate(enumerator, &payload))
1320 {
1321 if (payload->get_type(payload) == PLV2_NOTIFY)
1322 {
1323 notify_payload_t *notify = (notify_payload_t*)payload;
1324 notify_type_t type = notify->get_notify_type(notify);
1325
1326 switch (type)
1327 {
1328 case INVALID_KE_PAYLOAD:
1329 {
1330 chunk_t data;
1331 key_exchange_method_t bad_group;
1332
1333 bad_group = this->ke_method;
1334 data = notify->get_notification_data(notify);
1335 this->ke_method = ntohs(*((uint16_t*)data.ptr));
1336 DBG1(DBG_IKE, "peer didn't accept DH group %N, "
1337 "it requested %N", key_exchange_method_names,
1338 bad_group, key_exchange_method_names, this->ke_method);
1339
1340 if (!this->old_sa)
1341 { /* reset the IKE_SA if we are not rekeying */
1342 this->ike_sa->reset(this->ike_sa, FALSE);
1343 }
1344
1345 enumerator->destroy(enumerator);
1346 this->retry++;
1347 return NEED_MORE;
1348 }
1349 case NAT_DETECTION_SOURCE_IP:
1350 case NAT_DETECTION_DESTINATION_IP:
1351 /* skip, handled in ike_natd_t */
1352 break;
1353 case MULTIPLE_AUTH_SUPPORTED:
1354 /* handled in ike_auth_t */
1355 break;
1356 case COOKIE:
1357 {
1358 if (this->old_sa)
1359 {
1360 DBG1(DBG_IKE, "received COOKIE notify during rekeying"
1361 ", ignored");
1362 break;
1363 }
1364 chunk_free(&this->cookie);
1365 this->cookie = chunk_clone(notify->get_notification_data(notify));
1366 this->ike_sa->reset(this->ike_sa, FALSE);
1367 enumerator->destroy(enumerator);
1368 DBG2(DBG_IKE, "received %N notify", notify_type_names, type);
1369 this->retry++;
1370 return NEED_MORE;
1371 }
1372 case REDIRECT:
1373 {
1374 identification_t *gateway;
1375 chunk_t data, nonce = chunk_empty;
1376 status_t status = FAILED;
1377
1378 if (this->old_sa)
1379 {
1380 DBG1(DBG_IKE, "received REDIRECT notify during rekeying"
1381 ", ignored");
1382 break;
1383 }
1384 data = notify->get_notification_data(notify);
1385 gateway = redirect_data_parse(data, &nonce);
1386 if (this->ike_sa->handle_redirect(this->ike_sa, gateway))
1387 {
1388 status = NEED_MORE;
1389 }
1390 DESTROY_IF(gateway);
1391 chunk_free(&nonce);
1392 enumerator->destroy(enumerator);
1393 return status;
1394 }
1395 default:
1396 {
1397 if (type <= 16383)
1398 {
1399 DBG1(DBG_IKE, "received %N notify error",
1400 notify_type_names, type);
1401 enumerator->destroy(enumerator);
1402 raise_alerts(this, type);
1403 return FAILED;
1404 }
1405 DBG2(DBG_IKE, "received %N notify",
1406 notify_type_names, type);
1407 break;
1408 }
1409 }
1410 }
1411 }
1412 enumerator->destroy(enumerator);
1413
1414 process_payloads(this, message);
1415
1416 /* check if we have everything */
1417 if (this->proposal == NULL ||
1418 this->other_nonce.len == 0 || this->my_nonce.len == 0)
1419 {
1420 DBG1(DBG_IKE, "peer's proposal selection invalid");
1421 return FAILED;
1422 }
1423
1424 if (!this->proposal->has_transform(this->proposal, KEY_EXCHANGE_METHOD,
1425 this->ke_method))
1426 {
1427 DBG1(DBG_IKE, "peer's DH group selection invalid");
1428 return FAILED;
1429 }
1430
1431 if (this->ke_failed)
1432 {
1433 DBG1(DBG_IKE, "applying DH public value failed");
1434 return FAILED;
1435 }
1436
1437 if (key_exchange_done(this) == NEED_MORE)
1438 {
1439 /* use other exchange type for additional key exchanges */
1440 this->public.task.build = _build_i_multi_ke;
1441 this->public.task.process = _process_i_multi_ke;
1442 }
1443 else if (this->old_sa)
1444 {
1445 /* during rekeying, we derive keys here directly */
1446 return derive_keys(this);
1447 }
1448 /* key derivation is done before we send the next message */
1449 return NEED_MORE;
1450 }
1451
1452 METHOD(task_t, get_type, task_type_t,
1453 private_ike_init_t *this)
1454 {
1455 return TASK_IKE_INIT;
1456 }
1457
1458 METHOD(task_t, migrate, void,
1459 private_ike_init_t *this, ike_sa_t *ike_sa)
1460 {
1461 DESTROY_IF(this->proposal);
1462 chunk_free(&this->other_nonce);
1463 clear_key_exchanges(this);
1464
1465 this->ike_sa = ike_sa;
1466 this->keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
1467 this->proposal = NULL;
1468 this->ke_failed = FALSE;
1469 this->public.task.build = _build_i;
1470 this->public.task.process = _process_i;
1471 }
1472
1473 METHOD(task_t, destroy, void,
1474 private_ike_init_t *this)
1475 {
1476 DESTROY_IF(this->ke);
1477 DESTROY_IF(this->proposal);
1478 DESTROY_IF(this->nonceg);
1479 chunk_free(&this->my_nonce);
1480 chunk_free(&this->other_nonce);
1481 chunk_free(&this->cookie);
1482 clear_key_exchanges(this);
1483 free(this);
1484 }
1485
1486 METHOD(ike_init_t, get_lower_nonce, chunk_t,
1487 private_ike_init_t *this)
1488 {
1489 if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr,
1490 min(this->my_nonce.len, this->other_nonce.len)) < 0)
1491 {
1492 return this->my_nonce;
1493 }
1494 else
1495 {
1496 return this->other_nonce;
1497 }
1498 }
1499
1500 /*
1501 * Described in header.
1502 */
1503 ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa)
1504 {
1505 private_ike_init_t *this;
1506
1507 INIT(this,
1508 .public = {
1509 .task = {
1510 .get_type = _get_type,
1511 .migrate = _migrate,
1512 .destroy = _destroy,
1513 },
1514 .derive_keys = _derive_keys,
1515 .get_lower_nonce = _get_lower_nonce,
1516 },
1517 .ike_sa = ike_sa,
1518 .initiator = initiator,
1519 .ke_method = KE_NONE,
1520 .keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa),
1521 .old_sa = old_sa,
1522 .signature_authentication = lib->settings->get_bool(lib->settings,
1523 "%s.signature_authentication", TRUE, lib->ns),
1524 .follow_redirects = lib->settings->get_bool(lib->settings,
1525 "%s.follow_redirects", TRUE, lib->ns),
1526 );
1527 this->nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
1528
1529 if (initiator)
1530 {
1531 this->public.task.build = _build_i;
1532 this->public.task.process = _process_i;
1533 this->public.task.pre_process = _pre_process_i;
1534 }
1535 else
1536 {
1537 this->public.task.build = _build_r;
1538 this->public.task.process = _process_r;
1539 }
1540 return &this->public;
1541 }