2 * Copyright (C) 2008-2020 Tobias Brunner
3 * Copyright (C) 2005-2008 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
6 * Copyright (C) secunet Security Networks AG
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>.
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
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>
33 /** maximum retries to do with cookies/other dh groups */
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)
40 typedef struct private_ike_init_t private_ike_init_t
;
43 * Private members of a ike_init_t task.
45 struct private_ike_init_t
{
48 * Public methods and task_t interface.
58 * Are we the initiator?
63 * Key exchanges to perform
66 transform_type_t type
;
67 key_exchange_method_t method
;
70 } key_exchanges
[MAX_KEY_EXCHANGES
];
73 * Current key exchange
78 * Key exchange method from the parsed or sent KE payload
80 key_exchange_method_t ke_method
;
83 * Current key exchange object
88 * All key exchanges performed during rekeying (key_exchange_t)
93 * Applying KE public key failed?
98 * Keymat derivation (from IKE_SA)
108 * Nonce chosen by peer
118 * Negotiated proposal used for IKE_SA
120 proposal_t
*proposal
;
123 * Old IKE_SA that gets rekeyed
128 * Cookie received from responder
133 * Retries done so far after failure (cookie or bad DH group)
138 * Whether to use Signature Authentication as per RFC 7427
140 bool signature_authentication
;
143 * Whether to follow IKEv2 redirects as per RFC 5685
145 bool follow_redirects
;
149 * Returns the exchange type for additional exchanges when using multiple key
150 * exchanges, depending on whether this happens initially or during a rekeying
152 static exchange_type_t
exchange_type_multi_ke(private_ike_init_t
*this)
154 return this->old_sa
? IKE_FOLLOWUP_KE
: IKE_INTERMEDIATE
;
158 * Allocate our own nonce value
160 static bool generate_nonce(private_ike_init_t
*this)
164 DBG1(DBG_IKE
, "no nonce generator found to create nonce");
167 if (!this->nonceg
->allocate_nonce(this->nonceg
, NONCE_SIZE
,
170 DBG1(DBG_IKE
, "nonce allocation failed");
177 * Notify the peer about the hash algorithms we support or expect,
180 static void send_supported_hash_algorithms(private_ike_init_t
*this,
183 hash_algorithm_set_t
*algos
;
184 enumerator_t
*enumerator
, *rounds
;
185 bio_writer_t
*writer
;
186 hash_algorithm_t hash
;
190 signature_params_t
*config
;
192 size_t len
= BUF_LEN
;
197 algos
= hash_algorithm_set_create();
198 peer
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
201 rounds
= peer
->create_auth_cfg_enumerator(peer
, FALSE
);
202 while (rounds
->enumerate(rounds
, &auth
))
204 enumerator
= auth
->create_enumerator(auth
);
205 while (enumerator
->enumerate(enumerator
, &rule
, &config
))
207 if (rule
== AUTH_RULE_IKE_SIGNATURE_SCHEME
)
209 hash
= hasher_from_signature_scheme(config
->scheme
,
211 if (hasher_algorithm_for_ikev2(hash
))
213 algos
->add(algos
, hash
);
217 enumerator
->destroy(enumerator
);
219 rounds
->destroy(rounds
);
222 if (!algos
->count(algos
))
224 enumerator
= lib
->crypto
->create_hasher_enumerator(lib
->crypto
);
225 while (enumerator
->enumerate(enumerator
, &hash
, &plugin_name
))
227 if (hasher_algorithm_for_ikev2(hash
))
229 algos
->add(algos
, hash
);
232 enumerator
->destroy(enumerator
);
235 if (algos
->count(algos
))
237 writer
= bio_writer_create(0);
238 enumerator
= algos
->create_enumerator(algos
);
239 while (enumerator
->enumerate(enumerator
, &hash
))
241 writer
->write_uint16(writer
, hash
);
243 /* generate debug output */
244 written
= snprintf(pos
, len
, " %N", hash_algorithm_short_names
,
246 if (written
> 0 && written
< len
)
252 enumerator
->destroy(enumerator
);
253 message
->add_notify(message
, FALSE
, SIGNATURE_HASH_ALGORITHMS
,
254 writer
->get_buf(writer
));
255 writer
->destroy(writer
);
258 DBG2(DBG_CFG
, "sending supported signature hash algorithms:%s", buf
);
260 algos
->destroy(algos
);
264 * Store algorithms supported by other peer
266 static void handle_supported_hash_algorithms(private_ike_init_t
*this,
267 notify_payload_t
*notify
)
269 bio_reader_t
*reader
;
272 size_t len
= BUF_LEN
;
277 reader
= bio_reader_create(notify
->get_notification_data(notify
));
278 while (reader
->remaining(reader
) >= 2 && reader
->read_uint16(reader
, &algo
))
280 if (hasher_algorithm_for_ikev2(algo
))
282 this->keymat
->add_hash_algorithm(this->keymat
, algo
);
285 /* generate debug output */
286 written
= snprintf(pos
, len
, " %N", hash_algorithm_short_names
,
288 if (written
> 0 && written
< len
)
295 reader
->destroy(reader
);
298 DBG2(DBG_CFG
, "received supported signature hash algorithms:%s", buf
);
302 this->ike_sa
->enable_extension(this->ike_sa
, EXT_SIGNATURE_AUTH
);
307 * Check whether to send a USE_PPK notify
309 static bool send_use_ppk(private_ike_init_t
*this)
314 bool use_ppk
= FALSE
;
318 peer
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
319 if (peer
->get_ppk_id(peer
))
324 else if (this->ike_sa
->supports_extension(this->ike_sa
, EXT_PPK
))
326 /* check if we have at least one PPK available */
327 keys
= lib
->credmgr
->create_shared_enumerator(lib
->credmgr
, SHARED_PPK
,
329 if (keys
->enumerate(keys
, &key
, NULL
, NULL
))
339 * build the payloads for the message
341 static bool build_payloads(private_ike_init_t
*this, message_t
*message
)
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
;
348 proposal_t
*proposal
;
349 enumerator_t
*enumerator
;
351 bool additional_ke
= FALSE
;
353 id
= this->ike_sa
->get_id(this->ike_sa
);
355 ike_cfg
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
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
))
364 /* include SPI of new IKE_SA when we are rekeying */
367 proposal
->set_spi(proposal
, id
->get_initiator_spi(id
));
369 /* move the selected DH group to the front of the proposal */
370 if (!proposal
->promote_transform(proposal
, KEY_EXCHANGE_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
);
376 additional_ke
= additional_ke
||
377 proposal_has_additional_ke(proposal
);
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
);
386 enumerator
->destroy(enumerator
);
387 other_dh_groups
->destroy(other_dh_groups
);
389 sa_payload
= sa_payload_create_from_proposals_v2(proposal_list
);
390 proposal_list
->destroy_offset(proposal_list
, offsetof(proposal_t
, destroy
));
396 /* include SPI of new IKE_SA when we are rekeying */
397 this->proposal
->set_spi(this->proposal
, id
->get_responder_spi(id
));
399 sa_payload
= sa_payload_create_from_proposal_v2(this->proposal
);
400 additional_ke
= proposal_has_additional_ke(this->proposal
);
402 message
->add_payload(message
, (payload_t
*)sa_payload
);
404 ke_payload
= ke_payload_create_from_key_exchange(PLV2_KEY_EXCHANGE
,
408 DBG1(DBG_IKE
, "creating KE payload failed");
411 message
->add_payload(message
, (payload_t
*)ke_payload
);
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
);
417 /* negotiate fragmentation if we are not rekeying */
419 ike_cfg
->fragmentation(ike_cfg
) != FRAGMENTATION_NO
)
421 if (this->initiator
||
422 this->ike_sa
->supports_extension(this->ike_sa
,
423 EXT_IKE_FRAGMENTATION
))
425 message
->add_notify(message
, FALSE
, FRAGMENTATION_SUPPORTED
,
429 /* submit supported hash algorithms for signature authentication */
430 if (!this->old_sa
&& this->signature_authentication
)
432 if (this->initiator
||
433 this->ike_sa
->supports_extension(this->ike_sa
,
436 send_supported_hash_algorithms(this, message
);
439 /* notify other peer if we support redirection */
440 if (!this->old_sa
&& this->initiator
&& this->follow_redirects
)
442 identification_t
*gateway
;
446 from
= this->ike_sa
->get_redirected_from(this->ike_sa
);
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
);
454 gateway
->destroy(gateway
);
458 message
->add_notify(message
, FALSE
, REDIRECT_SUPPORTED
,
462 /* notify the peer if we want to use/support PPK */
463 if (!this->old_sa
&& send_use_ppk(this))
465 message
->add_notify(message
, FALSE
, USE_PPK
, chunk_empty
);
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
)
471 message
->add_notify(message
, FALSE
, CHILDLESS_IKEV2_SUPPORTED
,
474 if (!this->old_sa
&& additional_ke
)
476 if (this->initiator
||
477 this->ike_sa
->supports_extension(this->ike_sa
,
478 EXT_IKE_INTERMEDIATE
))
480 message
->add_notify(message
, FALSE
, INTERMEDIATE_EXCHANGE_SUPPORTED
,
488 * Process the SA payload and select a proposal
490 static void process_sa_payload(private_ike_init_t
*this, message_t
*message
,
491 sa_payload_t
*sa_payload
)
493 ike_cfg_t
*ike_cfg
, *cfg
, *alt_cfg
= NULL
;
494 enumerator_t
*enumerator
;
495 linked_list_t
*proposal_list
;
497 proposal_selection_flag_t flags
= 0;
499 ike_cfg
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
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",
506 flags
|= PROPOSAL_SKIP_PRIVATE
;
508 if (!lib
->settings
->get_bool(lib
->settings
,
509 "%s.prefer_configured_proposals", TRUE
, lib
->ns
))
511 flags
|= PROPOSAL_PREFER_SUPPLIED
;
513 this->proposal
= ike_cfg
->select_proposal(ike_cfg
, proposal_list
, flags
);
516 if (!this->initiator
&& !this->old_sa
)
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
))
525 { /* already tried and failed */
528 DBG1(DBG_IKE
, "no matching proposal found, trying alternative "
530 this->proposal
= cfg
->select_proposal(cfg
, proposal_list
,
534 alt_cfg
= cfg
->get_ref(cfg
);
538 enumerator
->destroy(enumerator
);
542 this->ike_sa
->set_ike_cfg(this->ike_sa
, alt_cfg
);
543 alt_cfg
->destroy(alt_cfg
);
547 charon
->bus
->alert(charon
->bus
, ALERT_PROPOSAL_MISMATCH_IKE
,
551 proposal_list
->destroy_offset(proposal_list
,
552 offsetof(proposal_t
, destroy
));
556 * Collect all key exchanges from the proposal
558 static void determine_key_exchanges(private_ike_init_t
*this)
560 transform_type_t t
= KEY_EXCHANGE_METHOD
;
564 this->proposal
->get_algorithm(this->proposal
, t
, &alg
, NULL
);
565 this->key_exchanges
[0].type
= t
;
566 this->key_exchanges
[0].method
= alg
;
568 for (t
= ADDITIONAL_KEY_EXCHANGE_1
; t
<= ADDITIONAL_KEY_EXCHANGE_7
; t
++)
570 if (this->proposal
->get_algorithm(this->proposal
, t
, &alg
, NULL
))
572 this->key_exchanges
[i
].type
= t
;
573 this->key_exchanges
[i
].method
= alg
;
580 * Check if additional key exchanges are required
582 static bool additional_key_exchange_required(private_ike_init_t
*this)
586 for (i
= this->ke_index
; i
< MAX_KEY_EXCHANGES
; i
++)
588 if (this->key_exchanges
[i
].type
&& !this->key_exchanges
[i
].done
)
597 * Clear data on key exchanges
599 static void clear_key_exchanges(private_ike_init_t
*this)
603 for (i
= 0; i
< MAX_KEY_EXCHANGES
; i
++)
605 this->key_exchanges
[i
].type
= 0;
606 this->key_exchanges
[i
].method
= 0;
607 this->key_exchanges
[i
].done
= FALSE
;
611 array_destroy_offset(this->kes
, offsetof(key_exchange_t
, destroy
));
616 * Process a KE payload
618 static void process_ke_payload(private_ike_init_t
*this, ke_payload_t
*ke
)
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
);
623 if (method
!= received
)
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
;
632 if (!this->initiator
)
634 DESTROY_IF(this->ke
);
635 this->ke
= this->keymat
->keymat
.create_ke(&this->keymat
->keymat
,
639 DBG1(DBG_IKE
, "negotiated key exchange method %N not supported",
640 key_exchange_method_names
, method
);
645 this->ke_failed
= this->ke
->get_method(this->ke
) != received
;
648 if (this->ke
&& !this->ke_failed
)
650 this->ke_failed
= !this->ke
->set_public_key(this->ke
,
651 ke
->get_key_exchange_data(ke
));
656 * Read payloads from message
658 static void process_payloads(private_ike_init_t
*this, message_t
*message
)
660 enumerator_t
*enumerator
;
663 ke_payload_t
*ke_pld
= NULL
;
665 enumerator
= message
->create_payload_enumerator(message
);
666 while (enumerator
->enumerate(enumerator
, &payload
))
668 switch (payload
->get_type(payload
))
670 case PLV2_SECURITY_ASSOCIATION
:
672 process_sa_payload(this, message
, (sa_payload_t
*)payload
);
675 case PLV2_KEY_EXCHANGE
:
677 ke_pld
= (ke_payload_t
*)payload
;
679 this->ke_method
= ke_pld
->get_key_exchange_method(ke_pld
);
684 nonce_payload_t
*nonce_payload
= (nonce_payload_t
*)payload
;
686 this->other_nonce
= nonce_payload
->get_nonce(nonce_payload
);
691 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
693 switch (notify
->get_notify_type(notify
))
695 case FRAGMENTATION_SUPPORTED
:
696 this->ike_sa
->enable_extension(this->ike_sa
,
697 EXT_IKE_FRAGMENTATION
);
699 case SIGNATURE_HASH_ALGORITHMS
:
700 if (this->signature_authentication
)
702 handle_supported_hash_algorithms(this, notify
);
708 this->ike_sa
->enable_extension(this->ike_sa
,
712 case REDIRECTED_FROM
:
714 identification_t
*gateway
;
717 data
= notify
->get_notification_data(notify
);
718 gateway
= redirect_data_parse(data
, NULL
);
721 DBG1(DBG_IKE
, "received invalid REDIRECTED_FROM "
725 DBG1(DBG_IKE
, "client got redirected from %Y", gateway
);
726 gateway
->destroy(gateway
);
729 case REDIRECT_SUPPORTED
:
732 this->ike_sa
->enable_extension(this->ike_sa
,
733 EXT_IKE_REDIRECTION
);
736 case CHILDLESS_IKEV2_SUPPORTED
:
737 if (this->initiator
&& !this->old_sa
)
739 this->ike_sa
->enable_extension(this->ike_sa
,
743 case INTERMEDIATE_EXCHANGE_SUPPORTED
:
746 this->ike_sa
->enable_extension(this->ike_sa
,
747 EXT_IKE_INTERMEDIATE
);
751 /* other notifies are handled elsewhere */
760 enumerator
->destroy(enumerator
);
764 this->ike_sa
->set_proposal(this->ike_sa
, this->proposal
);
767 { /* retrieve SPI of new IKE_SA when rekeying */
768 id
= this->ike_sa
->get_id(this->ike_sa
);
771 id
->set_responder_spi(id
,
772 this->proposal
->get_spi(this->proposal
));
776 id
->set_initiator_spi(id
,
777 this->proposal
->get_spi(this->proposal
));
781 determine_key_exchanges(this);
784 process_ke_payload(this, ke_pld
);
790 * Build payloads in additional exchanges when using multiple key exchanges
792 static bool build_payloads_multi_ke(private_ike_init_t
*this,
797 ke
= ke_payload_create_from_key_exchange(PLV2_KEY_EXCHANGE
, this->ke
);
800 DBG1(DBG_IKE
, "creating KE payload failed");
803 message
->add_payload(message
, (payload_t
*)ke
);
807 METHOD(task_t
, build_i_multi_ke
, status_t
,
808 private_ike_init_t
*this, message_t
*message
)
810 key_exchange_method_t method
;
812 message
->set_exchange_type(message
, exchange_type_multi_ke(this));
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
,
820 DBG1(DBG_IKE
, "negotiated key exchange method %N not supported",
821 key_exchange_method_names
, method
);
824 if (!build_payloads_multi_ke(this, message
))
831 METHOD(task_t
, build_i
, status_t
,
832 private_ike_init_t
*this, message_t
*message
)
836 ike_cfg
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
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
);
844 if (this->retry
>= MAX_RETRIES
)
846 DBG1(DBG_IKE
, "giving up after %d retries", MAX_RETRIES
);
850 /* if we are retrying after an INVALID_KE_PAYLOAD we already have one */
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
;
860 proposal
= this->old_sa
->get_proposal(this->old_sa
);
861 if (proposal
->get_algorithm(proposal
, KEY_EXCHANGE_METHOD
,
864 this->ke_method
= dh_group
;
867 { /* this shouldn't happen, but let's be safe */
868 this->ke_method
= ike_cfg
->get_algorithm(ike_cfg
,
869 KEY_EXCHANGE_METHOD
);
874 this->ke_method
= ike_cfg
->get_algorithm(ike_cfg
,
875 KEY_EXCHANGE_METHOD
);
877 this->ke
= this->keymat
->keymat
.create_ke(&this->keymat
->keymat
,
881 DBG1(DBG_IKE
, "configured DH group %N not supported",
882 key_exchange_method_names
, this->ke_method
);
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
,
893 DBG1(DBG_IKE
, "requested DH group %N not supported",
894 key_exchange_method_names
, this->ke_method
);
899 /* generate nonce only when we are trying the first time */
900 if (this->my_nonce
.ptr
== NULL
)
902 if (!generate_nonce(this))
908 if (this->cookie
.ptr
)
910 message
->add_notify(message
, FALSE
, COOKIE
, this->cookie
);
913 if (!build_payloads(this, message
))
920 chunk_t connect_id
= this->ike_sa
->get_connect_id(this->ike_sa
);
923 message
->add_notify(message
, FALSE
, ME_CONNECTID
, connect_id
);
932 * Process payloads in additional exchanges when using multiple key exchanges
934 static void process_payloads_multi_ke(private_ike_init_t
*this,
939 ke
= (ke_payload_t
*)message
->get_payload(message
, PLV2_KEY_EXCHANGE
);
942 process_ke_payload(this, ke
);
946 DBG1(DBG_IKE
, "KE payload missing in message");
950 METHOD(task_t
, process_r_multi_ke
, status_t
,
951 private_ike_init_t
*this, message_t
*message
)
953 if (message
->get_exchange_type(message
) == exchange_type_multi_ke(this))
955 process_payloads_multi_ke(this, message
);
960 METHOD(task_t
, process_r
, status_t
,
961 private_ike_init_t
*this, message_t
*message
)
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
);
966 if (!generate_nonce(this))
973 notify_payload_t
*notify
= message
->get_notify(message
, ME_CONNECTID
);
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
,
984 process_payloads(this, message
);
990 * Derive the keymat for the IKE_SA
992 static bool derive_keys_internal(private_ike_init_t
*this, chunk_t nonce_i
,
996 keymat_v2_t
*old_keymat
;
997 pseudo_random_function_t prf_alg
= PRF_UNDEFINED
;
998 chunk_t skd
= chunk_empty
;
1000 array_t
*kes
= this->kes
;
1005 if (additional_key_exchange_required(this))
1006 { /* when rekeying, we only derive keys once all exchanges are done */
1009 old_sa
= this->old_sa
;
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
;
1017 id
= this->ike_sa
->get_id(this->ike_sa
);
1020 array_insert_create(&kes
, ARRAY_HEAD
, this->ke
);
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
);
1029 charon
->bus
->ike_keys(charon
->bus
, this->ike_sa
, kes
, chunk_empty
,
1030 nonce_i
, nonce_r
, skd
.len
? old_sa
: NULL
, NULL
,
1033 if (kes
!= this->kes
)
1040 METHOD(ike_init_t
, derive_keys
, status_t
,
1041 private_ike_init_t
*this)
1045 if (!this->ke_index
|| this->key_exchanges
[this->ke_index
-1].derived
)
1050 if (this->initiator
)
1052 success
= derive_keys_internal(this, this->my_nonce
, this->other_nonce
);
1056 success
= derive_keys_internal(this, this->other_nonce
, this->my_nonce
);
1059 this->key_exchanges
[this->ke_index
-1].derived
= TRUE
;
1063 DBG1(DBG_IKE
, "key derivation failed");
1066 return additional_key_exchange_required(this) ? NEED_MORE
: SUCCESS
;
1070 * Called when a key exchange is done
1072 static status_t
key_exchange_done(private_ike_init_t
*this)
1076 /* during rekeying, we store all the key exchanges performed */
1077 array_insert_create(&this->kes
, ARRAY_TAIL
, this->ke
);
1081 this->key_exchanges
[this->ke_index
++].done
= TRUE
;
1083 return additional_key_exchange_required(this) ? NEED_MORE
: SUCCESS
;
1086 METHOD(task_t
, build_r_multi_ke
, status_t
,
1087 private_ike_init_t
*this, message_t
*message
)
1091 message
->add_notify(message
, FALSE
, INVALID_SYNTAX
, chunk_empty
);
1094 if (this->ke_failed
)
1096 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
1099 if (!build_payloads_multi_ke(this, message
))
1104 if (key_exchange_done(this) != NEED_MORE
&& this->old_sa
)
1106 /* during rekeying, we derive keys once all exchanges are done */
1107 if (derive_keys(this) != SUCCESS
)
1109 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
1114 /* we derive keys after each IKE_INTERMEDIATE once we receive the next
1115 * message, otherwise, IntAuth would be based on the wrong keys */
1119 METHOD(task_t
, build_r
, status_t
,
1120 private_ike_init_t
*this, message_t
*message
)
1122 identification_t
*gateway
;
1124 /* check if we have everything we need */
1125 if (this->proposal
== NULL
||
1126 this->other_nonce
.len
== 0 || this->my_nonce
.len
== 0)
1128 DBG1(DBG_IKE
, "received proposals unacceptable");
1129 message
->add_notify(message
, TRUE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
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
,
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
);
1150 !this->proposal
->has_transform(this->proposal
, KEY_EXCHANGE_METHOD
,
1155 if (this->proposal
->get_algorithm(this->proposal
, KEY_EXCHANGE_METHOD
,
1157 this->ke_method
!= group
)
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
));
1169 DBG1(DBG_IKE
, "no acceptable proposal found");
1170 message
->add_notify(message
, TRUE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
1175 if (this->ke_failed
)
1177 DBG1(DBG_IKE
, "applying DH public value failed");
1178 message
->add_notify(message
, TRUE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
1182 if (!build_payloads(this, message
))
1184 message
->add_notify(message
, TRUE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
1188 if (key_exchange_done(this) == NEED_MORE
)
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
;
1194 else if (this->old_sa
)
1196 /* during rekeying, we derive keys here directly */
1197 if (derive_keys(this) != SUCCESS
)
1199 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
1204 /* key derivation is done before the next request is processed */
1209 * Raise alerts for received notify errors
1211 static void raise_alerts(private_ike_init_t
*this, notify_type_t type
)
1214 linked_list_t
*list
;
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
));
1229 METHOD(task_t
, pre_process_i
, status_t
,
1230 private_ike_init_t
*this, message_t
*message
)
1232 enumerator_t
*enumerator
;
1235 /* check for erroneous notifies */
1236 enumerator
= message
->create_payload_enumerator(message
);
1237 while (enumerator
->enumerate(enumerator
, &payload
))
1239 if (payload
->get_type(payload
) == PLV2_NOTIFY
)
1241 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
1242 notify_type_t type
= notify
->get_notify_type(notify
);
1250 cookie
= notify
->get_notification_data(notify
);
1251 if (chunk_equals(cookie
, this->cookie
))
1253 DBG1(DBG_IKE
, "ignore response with duplicate COOKIE "
1255 enumerator
->destroy(enumerator
);
1262 identification_t
*gateway
;
1263 chunk_t data
, nonce
= chunk_empty
;
1264 status_t status
= SUCCESS
;
1270 data
= notify
->get_notification_data(notify
);
1271 gateway
= redirect_data_parse(data
, &nonce
);
1272 if (!gateway
|| !chunk_equals(nonce
, this->my_nonce
))
1274 DBG1(DBG_IKE
, "received invalid REDIRECT notify");
1277 DESTROY_IF(gateway
);
1279 enumerator
->destroy(enumerator
);
1287 enumerator
->destroy(enumerator
);
1291 METHOD(task_t
, process_i_multi_ke
, status_t
,
1292 private_ike_init_t
*this, message_t
*message
)
1294 process_payloads_multi_ke(this, message
);
1296 if (this->ke_failed
)
1301 if (key_exchange_done(this) != NEED_MORE
&& this->old_sa
)
1303 /* during rekeying, we derive keys once all exchanges are done */
1304 return derive_keys(this);
1306 /* we derive keys after each IKE_INTERMEDIATE once we send the next
1307 * message, otherwise, IntAuth would be based on the wrong keys */
1311 METHOD(task_t
, process_i
, status_t
,
1312 private_ike_init_t
*this, message_t
*message
)
1314 enumerator_t
*enumerator
;
1317 /* check for erroneous notifies */
1318 enumerator
= message
->create_payload_enumerator(message
);
1319 while (enumerator
->enumerate(enumerator
, &payload
))
1321 if (payload
->get_type(payload
) == PLV2_NOTIFY
)
1323 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
1324 notify_type_t type
= notify
->get_notify_type(notify
);
1328 case INVALID_KE_PAYLOAD
:
1331 key_exchange_method_t bad_group
;
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
);
1341 { /* reset the IKE_SA if we are not rekeying */
1342 this->ike_sa
->reset(this->ike_sa
, FALSE
);
1345 enumerator
->destroy(enumerator
);
1349 case NAT_DETECTION_SOURCE_IP
:
1350 case NAT_DETECTION_DESTINATION_IP
:
1351 /* skip, handled in ike_natd_t */
1353 case MULTIPLE_AUTH_SUPPORTED
:
1354 /* handled in ike_auth_t */
1360 DBG1(DBG_IKE
, "received COOKIE notify during rekeying"
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
);
1374 identification_t
*gateway
;
1375 chunk_t data
, nonce
= chunk_empty
;
1376 status_t status
= FAILED
;
1380 DBG1(DBG_IKE
, "received REDIRECT notify during rekeying"
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
))
1390 DESTROY_IF(gateway
);
1392 enumerator
->destroy(enumerator
);
1399 DBG1(DBG_IKE
, "received %N notify error",
1400 notify_type_names
, type
);
1401 enumerator
->destroy(enumerator
);
1402 raise_alerts(this, type
);
1405 DBG2(DBG_IKE
, "received %N notify",
1406 notify_type_names
, type
);
1412 enumerator
->destroy(enumerator
);
1414 process_payloads(this, message
);
1416 /* check if we have everything */
1417 if (this->proposal
== NULL
||
1418 this->other_nonce
.len
== 0 || this->my_nonce
.len
== 0)
1420 DBG1(DBG_IKE
, "peer's proposal selection invalid");
1424 if (!this->proposal
->has_transform(this->proposal
, KEY_EXCHANGE_METHOD
,
1427 DBG1(DBG_IKE
, "peer's DH group selection invalid");
1431 if (this->ke_failed
)
1433 DBG1(DBG_IKE
, "applying DH public value failed");
1437 if (key_exchange_done(this) == NEED_MORE
)
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
;
1443 else if (this->old_sa
)
1445 /* during rekeying, we derive keys here directly */
1446 return derive_keys(this);
1448 /* key derivation is done before we send the next message */
1452 METHOD(task_t
, get_type
, task_type_t
,
1453 private_ike_init_t
*this)
1455 return TASK_IKE_INIT
;
1458 METHOD(task_t
, migrate
, void,
1459 private_ike_init_t
*this, ike_sa_t
*ike_sa
)
1461 DESTROY_IF(this->proposal
);
1462 chunk_free(&this->other_nonce
);
1463 clear_key_exchanges(this);
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
;
1473 METHOD(task_t
, destroy
, void,
1474 private_ike_init_t
*this)
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);
1486 METHOD(ike_init_t
, get_lower_nonce
, chunk_t
,
1487 private_ike_init_t
*this)
1489 if (memcmp(this->my_nonce
.ptr
, this->other_nonce
.ptr
,
1490 min(this->my_nonce
.len
, this->other_nonce
.len
)) < 0)
1492 return this->my_nonce
;
1496 return this->other_nonce
;
1501 * Described in header.
1503 ike_init_t
*ike_init_create(ike_sa_t
*ike_sa
, bool initiator
, ike_sa_t
*old_sa
)
1505 private_ike_init_t
*this;
1510 .get_type
= _get_type
,
1511 .migrate
= _migrate
,
1512 .destroy
= _destroy
,
1514 .derive_keys
= _derive_keys
,
1515 .get_lower_nonce
= _get_lower_nonce
,
1518 .initiator
= initiator
,
1519 .ke_method
= KE_NONE
,
1520 .keymat
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_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
),
1527 this->nonceg
= this->keymat
->keymat
.create_nonce_gen(&this->keymat
->keymat
);
1531 this->public.task
.build
= _build_i
;
1532 this->public.task
.process
= _process_i
;
1533 this->public.task
.pre_process
= _pre_process_i
;
1537 this->public.task
.build
= _build_r
;
1538 this->public.task
.process
= _process_r
;
1540 return &this->public;