2 * Copyright (C) 2008-2015 Tobias Brunner
3 * Copyright (C) 2005-2008 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 #include <bio/bio_reader.h>
24 #include <bio/bio_writer.h>
25 #include <sa/ikev2/keymat_v2.h>
26 #include <crypto/diffie_hellman.h>
27 #include <crypto/hashers/hash_algorithm_set.h>
28 #include <encoding/payloads/sa_payload.h>
29 #include <encoding/payloads/ke_payload.h>
30 #include <encoding/payloads/nonce_payload.h>
32 /** maximum retries to do with cookies/other dh groups */
35 typedef struct private_ike_init_t private_ike_init_t
;
38 * Private members of a ike_init_t task.
40 struct private_ike_init_t
{
43 * Public methods and task_t interface.
53 * Are we the initiator?
58 * IKE config to establish
63 * diffie hellman group to use
65 diffie_hellman_group_t dh_group
;
68 * diffie hellman key exchange
73 * Applying DH public value failed?
78 * Keymat derivation (from IKE_SA)
88 * nonce chosen by peer
98 * Negotiated proposal used for IKE_SA
100 proposal_t
*proposal
;
103 * Old IKE_SA which gets rekeyed
108 * cookie received from responder
113 * retries done so far after failure (cookie or bad dh group)
118 * Whether to use Signature Authentication as per RFC 7427
120 bool signature_authentication
;
123 * Whether to follow IKEv2 redirects as per RFC 5685
125 bool follow_redirects
;
129 * Allocate our own nonce value
131 static bool generate_nonce(private_ike_init_t
*this)
135 DBG1(DBG_IKE
, "no nonce generator found to create nonce");
138 if (!this->nonceg
->allocate_nonce(this->nonceg
, NONCE_SIZE
,
141 DBG1(DBG_IKE
, "nonce allocation failed");
148 * Notify the peer about the hash algorithms we support or expect,
151 static void send_supported_hash_algorithms(private_ike_init_t
*this,
154 hash_algorithm_set_t
*algos
;
155 enumerator_t
*enumerator
, *rounds
;
156 bio_writer_t
*writer
;
157 hash_algorithm_t hash
;
164 algos
= hash_algorithm_set_create();
165 peer
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
168 rounds
= peer
->create_auth_cfg_enumerator(peer
, FALSE
);
169 while (rounds
->enumerate(rounds
, &auth
))
171 enumerator
= auth
->create_enumerator(auth
);
172 while (enumerator
->enumerate(enumerator
, &rule
, &config
))
174 if (rule
== AUTH_RULE_SIGNATURE_SCHEME
)
176 hash
= hasher_from_signature_scheme(config
);
177 if (hasher_algorithm_for_ikev2(hash
))
179 algos
->add(algos
, hash
);
183 enumerator
->destroy(enumerator
);
185 rounds
->destroy(rounds
);
188 if (!algos
->count(algos
))
190 enumerator
= lib
->crypto
->create_hasher_enumerator(lib
->crypto
);
191 while (enumerator
->enumerate(enumerator
, &hash
, &plugin_name
))
193 if (hasher_algorithm_for_ikev2(hash
))
195 algos
->add(algos
, hash
);
198 enumerator
->destroy(enumerator
);
201 if (algos
->count(algos
))
203 writer
= bio_writer_create(0);
204 enumerator
= algos
->create_enumerator(algos
);
205 while (enumerator
->enumerate(enumerator
, &hash
))
207 writer
->write_uint16(writer
, hash
);
209 enumerator
->destroy(enumerator
);
210 message
->add_notify(message
, FALSE
, SIGNATURE_HASH_ALGORITHMS
,
211 writer
->get_buf(writer
));
212 writer
->destroy(writer
);
214 algos
->destroy(algos
);
218 * Store algorithms supported by other peer
220 static void handle_supported_hash_algorithms(private_ike_init_t
*this,
221 notify_payload_t
*notify
)
223 bio_reader_t
*reader
;
227 reader
= bio_reader_create(notify
->get_notification_data(notify
));
228 while (reader
->remaining(reader
) >= 2 && reader
->read_uint16(reader
, &algo
))
230 if (hasher_algorithm_for_ikev2(algo
))
232 this->keymat
->add_hash_algorithm(this->keymat
, algo
);
236 reader
->destroy(reader
);
240 this->ike_sa
->enable_extension(this->ike_sa
, EXT_SIGNATURE_AUTH
);
245 * build the payloads for the message
247 static bool build_payloads(private_ike_init_t
*this, message_t
*message
)
249 sa_payload_t
*sa_payload
;
250 ke_payload_t
*ke_payload
;
251 nonce_payload_t
*nonce_payload
;
252 linked_list_t
*proposal_list
;
254 proposal_t
*proposal
;
255 enumerator_t
*enumerator
;
257 id
= this->ike_sa
->get_id(this->ike_sa
);
259 this->config
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
263 proposal_list
= this->config
->get_proposals(this->config
);
266 /* include SPI of new IKE_SA when we are rekeying */
267 enumerator
= proposal_list
->create_enumerator(proposal_list
);
268 while (enumerator
->enumerate(enumerator
, (void**)&proposal
))
270 proposal
->set_spi(proposal
, id
->get_initiator_spi(id
));
272 enumerator
->destroy(enumerator
);
275 sa_payload
= sa_payload_create_from_proposals_v2(proposal_list
);
276 proposal_list
->destroy_offset(proposal_list
, offsetof(proposal_t
, destroy
));
282 /* include SPI of new IKE_SA when we are rekeying */
283 this->proposal
->set_spi(this->proposal
, id
->get_responder_spi(id
));
285 sa_payload
= sa_payload_create_from_proposal_v2(this->proposal
);
287 message
->add_payload(message
, (payload_t
*)sa_payload
);
289 nonce_payload
= nonce_payload_create(PLV2_NONCE
);
290 nonce_payload
->set_nonce(nonce_payload
, this->my_nonce
);
291 ke_payload
= ke_payload_create_from_diffie_hellman(PLV2_KEY_EXCHANGE
,
295 DBG1(DBG_IKE
, "creating KE payload failed");
300 { /* payload order differs if we are rekeying */
301 message
->add_payload(message
, (payload_t
*)nonce_payload
);
302 message
->add_payload(message
, (payload_t
*)ke_payload
);
306 message
->add_payload(message
, (payload_t
*)ke_payload
);
307 message
->add_payload(message
, (payload_t
*)nonce_payload
);
310 /* negotiate fragmentation if we are not rekeying */
312 this->config
->fragmentation(this->config
) != FRAGMENTATION_NO
)
314 if (this->initiator
||
315 this->ike_sa
->supports_extension(this->ike_sa
,
316 EXT_IKE_FRAGMENTATION
))
318 message
->add_notify(message
, FALSE
, FRAGMENTATION_SUPPORTED
,
322 /* submit supported hash algorithms for signature authentication */
323 if (!this->old_sa
&& this->signature_authentication
)
325 if (this->initiator
||
326 this->ike_sa
->supports_extension(this->ike_sa
,
329 send_supported_hash_algorithms(this, message
);
332 /* notify other peer if we support redirection */
333 if (!this->old_sa
&& this->initiator
&& this->follow_redirects
)
335 identification_t
*gateway
;
339 from
= this->ike_sa
->get_redirected_from(this->ike_sa
);
342 gateway
= identification_create_from_sockaddr(
343 from
->get_sockaddr(from
));
344 data
= redirect_data_create(gateway
, chunk_empty
);
345 message
->add_notify(message
, FALSE
, REDIRECTED_FROM
, data
);
347 gateway
->destroy(gateway
);
351 message
->add_notify(message
, FALSE
, REDIRECT_SUPPORTED
,
359 * Read payloads from message
361 static void process_payloads(private_ike_init_t
*this, message_t
*message
)
363 enumerator_t
*enumerator
;
365 ke_payload_t
*ke_payload
= NULL
;
367 enumerator
= message
->create_payload_enumerator(message
);
368 while (enumerator
->enumerate(enumerator
, &payload
))
370 switch (payload
->get_type(payload
))
372 case PLV2_SECURITY_ASSOCIATION
:
374 sa_payload_t
*sa_payload
= (sa_payload_t
*)payload
;
375 linked_list_t
*proposal_list
;
378 proposal_list
= sa_payload
->get_proposals(sa_payload
);
379 private = this->ike_sa
->supports_extension(this->ike_sa
,
381 this->proposal
= this->config
->select_proposal(this->config
,
382 proposal_list
, private);
385 charon
->bus
->alert(charon
->bus
, ALERT_PROPOSAL_MISMATCH_IKE
,
388 proposal_list
->destroy_offset(proposal_list
,
389 offsetof(proposal_t
, destroy
));
392 case PLV2_KEY_EXCHANGE
:
394 ke_payload
= (ke_payload_t
*)payload
;
396 this->dh_group
= ke_payload
->get_dh_group_number(ke_payload
);
401 nonce_payload_t
*nonce_payload
= (nonce_payload_t
*)payload
;
403 this->other_nonce
= nonce_payload
->get_nonce(nonce_payload
);
408 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
410 switch (notify
->get_notify_type(notify
))
412 case FRAGMENTATION_SUPPORTED
:
413 this->ike_sa
->enable_extension(this->ike_sa
,
414 EXT_IKE_FRAGMENTATION
);
416 case SIGNATURE_HASH_ALGORITHMS
:
417 if (this->signature_authentication
)
419 handle_supported_hash_algorithms(this, notify
);
422 case REDIRECTED_FROM
:
424 identification_t
*gateway
;
427 data
= notify
->get_notification_data(notify
);
428 gateway
= redirect_data_parse(data
, NULL
);
431 DBG1(DBG_IKE
, "received invalid REDIRECTED_FROM "
435 DBG1(DBG_IKE
, "client got redirected from %Y", gateway
);
436 gateway
->destroy(gateway
);
439 case REDIRECT_SUPPORTED
:
442 this->ike_sa
->enable_extension(this->ike_sa
,
443 EXT_IKE_REDIRECTION
);
447 /* other notifies are handled elsewhere */
456 enumerator
->destroy(enumerator
);
458 if (ke_payload
&& this->proposal
&&
459 this->proposal
->has_dh_group(this->proposal
, this->dh_group
))
461 if (!this->initiator
)
463 this->dh
= this->keymat
->keymat
.create_dh(
464 &this->keymat
->keymat
, this->dh_group
);
468 this->dh_failed
= !this->dh
->set_other_public_value(this->dh
,
469 ke_payload
->get_key_exchange_data(ke_payload
));
474 METHOD(task_t
, build_i
, status_t
,
475 private_ike_init_t
*this, message_t
*message
)
477 this->config
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
478 DBG0(DBG_IKE
, "initiating IKE_SA %s[%d] to %H",
479 this->ike_sa
->get_name(this->ike_sa
),
480 this->ike_sa
->get_unique_id(this->ike_sa
),
481 this->ike_sa
->get_other_host(this->ike_sa
));
482 this->ike_sa
->set_state(this->ike_sa
, IKE_CONNECTING
);
484 if (this->retry
>= MAX_RETRIES
)
486 DBG1(DBG_IKE
, "giving up after %d retries", MAX_RETRIES
);
490 /* if the DH group is set via use_dh_group(), we already have a DH object */
493 this->dh_group
= this->config
->get_dh_group(this->config
);
494 this->dh
= this->keymat
->keymat
.create_dh(&this->keymat
->keymat
,
498 DBG1(DBG_IKE
, "configured DH group %N not supported",
499 diffie_hellman_group_names
, this->dh_group
);
504 /* generate nonce only when we are trying the first time */
505 if (this->my_nonce
.ptr
== NULL
)
507 if (!generate_nonce(this))
513 if (this->cookie
.ptr
)
515 message
->add_notify(message
, FALSE
, COOKIE
, this->cookie
);
518 if (!build_payloads(this, message
))
525 chunk_t connect_id
= this->ike_sa
->get_connect_id(this->ike_sa
);
528 message
->add_notify(message
, FALSE
, ME_CONNECTID
, connect_id
);
536 METHOD(task_t
, process_r
, status_t
,
537 private_ike_init_t
*this, message_t
*message
)
539 this->config
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
540 DBG0(DBG_IKE
, "%H is initiating an IKE_SA", message
->get_source(message
));
541 this->ike_sa
->set_state(this->ike_sa
, IKE_CONNECTING
);
543 if (!generate_nonce(this))
550 notify_payload_t
*notify
= message
->get_notify(message
, ME_CONNECTID
);
553 chunk_t connect_id
= notify
->get_notification_data(notify
);
554 DBG2(DBG_IKE
, "received ME_CONNECTID %#B", &connect_id
);
555 charon
->connect_manager
->stop_checks(charon
->connect_manager
,
561 process_payloads(this, message
);
567 * Derive the keymat for the IKE_SA
569 static bool derive_keys(private_ike_init_t
*this,
570 chunk_t nonce_i
, chunk_t nonce_r
)
572 keymat_v2_t
*old_keymat
;
573 pseudo_random_function_t prf_alg
= PRF_UNDEFINED
;
574 chunk_t skd
= chunk_empty
;
577 id
= this->ike_sa
->get_id(this->ike_sa
);
580 /* rekeying: Include old SKd, use old PRF, apply SPI */
581 old_keymat
= (keymat_v2_t
*)this->old_sa
->get_keymat(this->old_sa
);
582 prf_alg
= old_keymat
->get_skd(old_keymat
, &skd
);
585 id
->set_responder_spi(id
, this->proposal
->get_spi(this->proposal
));
589 id
->set_initiator_spi(id
, this->proposal
->get_spi(this->proposal
));
592 if (!this->keymat
->derive_ike_keys(this->keymat
, this->proposal
, this->dh
,
593 nonce_i
, nonce_r
, id
, prf_alg
, skd
))
597 charon
->bus
->ike_keys(charon
->bus
, this->ike_sa
, this->dh
, chunk_empty
,
598 nonce_i
, nonce_r
, this->old_sa
, NULL
);
602 METHOD(task_t
, build_r
, status_t
,
603 private_ike_init_t
*this, message_t
*message
)
605 identification_t
*gateway
;
607 /* check if we have everything we need */
608 if (this->proposal
== NULL
||
609 this->other_nonce
.len
== 0 || this->my_nonce
.len
== 0)
611 DBG1(DBG_IKE
, "received proposals inacceptable");
612 message
->add_notify(message
, TRUE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
615 this->ike_sa
->set_proposal(this->ike_sa
, this->proposal
);
617 /* check if we'd have to redirect the client */
619 this->ike_sa
->supports_extension(this->ike_sa
, EXT_IKE_REDIRECTION
) &&
620 charon
->redirect
->redirect_on_init(charon
->redirect
, this->ike_sa
,
625 DBG1(DBG_IKE
, "redirecting peer to %Y", gateway
);
626 data
= redirect_data_create(gateway
, this->other_nonce
);
627 message
->add_notify(message
, TRUE
, REDIRECT
, data
);
628 gateway
->destroy(gateway
);
633 if (this->dh
== NULL
||
634 !this->proposal
->has_dh_group(this->proposal
, this->dh_group
))
638 if (this->proposal
->get_algorithm(this->proposal
, DIFFIE_HELLMAN_GROUP
,
641 DBG1(DBG_IKE
, "DH group %N inacceptable, requesting %N",
642 diffie_hellman_group_names
, this->dh_group
,
643 diffie_hellman_group_names
, group
);
644 this->dh_group
= group
;
645 group
= htons(group
);
646 message
->add_notify(message
, FALSE
, INVALID_KE_PAYLOAD
,
647 chunk_from_thing(group
));
651 DBG1(DBG_IKE
, "no acceptable proposal found");
658 DBG1(DBG_IKE
, "applying DH public value failed");
659 message
->add_notify(message
, TRUE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
663 if (!derive_keys(this, this->other_nonce
, this->my_nonce
))
665 DBG1(DBG_IKE
, "key derivation failed");
666 message
->add_notify(message
, TRUE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
669 if (!build_payloads(this, message
))
671 message
->add_notify(message
, TRUE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
678 * Raise alerts for received notify errors
680 static void raise_alerts(private_ike_init_t
*this, notify_type_t type
)
686 case NO_PROPOSAL_CHOSEN
:
687 list
= this->config
->get_proposals(this->config
);
688 charon
->bus
->alert(charon
->bus
, ALERT_PROPOSAL_MISMATCH_IKE
, list
);
689 list
->destroy_offset(list
, offsetof(proposal_t
, destroy
));
696 METHOD(task_t
, pre_process_i
, status_t
,
697 private_ike_init_t
*this, message_t
*message
)
699 enumerator_t
*enumerator
;
702 /* check for erroneous notifies */
703 enumerator
= message
->create_payload_enumerator(message
);
704 while (enumerator
->enumerate(enumerator
, &payload
))
706 if (payload
->get_type(payload
) == PLV2_NOTIFY
)
708 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
709 notify_type_t type
= notify
->get_notify_type(notify
);
715 identification_t
*gateway
;
716 chunk_t data
, nonce
= chunk_empty
;
717 status_t status
= SUCCESS
;
723 data
= notify
->get_notification_data(notify
);
724 gateway
= redirect_data_parse(data
, &nonce
);
725 if (!gateway
|| !chunk_equals(nonce
, this->my_nonce
))
727 DBG1(DBG_IKE
, "received invalid REDIRECT notify");
732 enumerator
->destroy(enumerator
);
740 enumerator
->destroy(enumerator
);
744 METHOD(task_t
, process_i
, status_t
,
745 private_ike_init_t
*this, message_t
*message
)
747 enumerator_t
*enumerator
;
750 /* check for erroneous notifies */
751 enumerator
= message
->create_payload_enumerator(message
);
752 while (enumerator
->enumerate(enumerator
, &payload
))
754 if (payload
->get_type(payload
) == PLV2_NOTIFY
)
756 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
757 notify_type_t type
= notify
->get_notify_type(notify
);
761 case INVALID_KE_PAYLOAD
:
764 diffie_hellman_group_t bad_group
;
766 bad_group
= this->dh_group
;
767 data
= notify
->get_notification_data(notify
);
768 this->dh_group
= ntohs(*((u_int16_t
*)data
.ptr
));
769 DBG1(DBG_IKE
, "peer didn't accept DH group %N, "
770 "it requested %N", diffie_hellman_group_names
,
771 bad_group
, diffie_hellman_group_names
, this->dh_group
);
773 if (this->old_sa
== NULL
)
774 { /* reset the IKE_SA if we are not rekeying */
775 this->ike_sa
->reset(this->ike_sa
);
778 enumerator
->destroy(enumerator
);
782 case NAT_DETECTION_SOURCE_IP
:
783 case NAT_DETECTION_DESTINATION_IP
:
784 /* skip, handled in ike_natd_t */
786 case MULTIPLE_AUTH_SUPPORTED
:
787 /* handled in ike_auth_t */
791 chunk_free(&this->cookie
);
792 this->cookie
= chunk_clone(notify
->get_notification_data(notify
));
793 this->ike_sa
->reset(this->ike_sa
);
794 enumerator
->destroy(enumerator
);
795 DBG2(DBG_IKE
, "received %N notify", notify_type_names
, type
);
801 identification_t
*gateway
;
802 chunk_t data
, nonce
= chunk_empty
;
803 status_t status
= FAILED
;
807 DBG1(DBG_IKE
, "received REDIRECT notify during rekeying"
811 data
= notify
->get_notification_data(notify
);
812 gateway
= redirect_data_parse(data
, &nonce
);
813 if (this->ike_sa
->handle_redirect(this->ike_sa
, gateway
))
819 enumerator
->destroy(enumerator
);
826 DBG1(DBG_IKE
, "received %N notify error",
827 notify_type_names
, type
);
828 enumerator
->destroy(enumerator
);
829 raise_alerts(this, type
);
832 DBG2(DBG_IKE
, "received %N notify",
833 notify_type_names
, type
);
839 enumerator
->destroy(enumerator
);
841 process_payloads(this, message
);
843 /* check if we have everything */
844 if (this->proposal
== NULL
||
845 this->other_nonce
.len
== 0 || this->my_nonce
.len
== 0)
847 DBG1(DBG_IKE
, "peers proposal selection invalid");
850 this->ike_sa
->set_proposal(this->ike_sa
, this->proposal
);
852 if (this->dh
== NULL
||
853 !this->proposal
->has_dh_group(this->proposal
, this->dh_group
))
855 DBG1(DBG_IKE
, "peer DH group selection invalid");
861 DBG1(DBG_IKE
, "applying DH public value failed");
865 if (!derive_keys(this, this->my_nonce
, this->other_nonce
))
867 DBG1(DBG_IKE
, "key derivation failed");
873 METHOD(task_t
, get_type
, task_type_t
,
874 private_ike_init_t
*this)
876 return TASK_IKE_INIT
;
879 METHOD(task_t
, migrate
, void,
880 private_ike_init_t
*this, ike_sa_t
*ike_sa
)
882 DESTROY_IF(this->proposal
);
883 chunk_free(&this->other_nonce
);
885 this->ike_sa
= ike_sa
;
886 this->keymat
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
);
887 this->proposal
= NULL
;
888 this->dh_failed
= FALSE
;
889 if (this->dh
&& this->dh
->get_dh_group(this->dh
) != this->dh_group
)
890 { /* reset DH value only if group changed (INVALID_KE_PAYLOAD) */
891 this->dh
->destroy(this->dh
);
892 this->dh
= this->keymat
->keymat
.create_dh(&this->keymat
->keymat
,
897 METHOD(task_t
, destroy
, void,
898 private_ike_init_t
*this)
900 DESTROY_IF(this->dh
);
901 DESTROY_IF(this->proposal
);
902 DESTROY_IF(this->nonceg
);
903 chunk_free(&this->my_nonce
);
904 chunk_free(&this->other_nonce
);
905 chunk_free(&this->cookie
);
909 METHOD(ike_init_t
, get_lower_nonce
, chunk_t
,
910 private_ike_init_t
*this)
912 if (memcmp(this->my_nonce
.ptr
, this->other_nonce
.ptr
,
913 min(this->my_nonce
.len
, this->other_nonce
.len
)) < 0)
915 return this->my_nonce
;
919 return this->other_nonce
;
924 * Described in header.
926 ike_init_t
*ike_init_create(ike_sa_t
*ike_sa
, bool initiator
, ike_sa_t
*old_sa
)
928 private_ike_init_t
*this;
933 .get_type
= _get_type
,
937 .get_lower_nonce
= _get_lower_nonce
,
940 .initiator
= initiator
,
941 .dh_group
= MODP_NONE
,
942 .keymat
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
),
944 .signature_authentication
= lib
->settings
->get_bool(lib
->settings
,
945 "%s.signature_authentication", TRUE
, lib
->ns
),
946 .follow_redirects
= lib
->settings
->get_bool(lib
->settings
,
947 "%s.follow_redirects", TRUE
, lib
->ns
),
949 this->nonceg
= this->keymat
->keymat
.create_nonce_gen(&this->keymat
->keymat
);
953 this->public.task
.build
= _build_i
;
954 this->public.task
.process
= _process_i
;
955 this->public.task
.pre_process
= _pre_process_i
;
959 this->public.task
.build
= _build_r
;
960 this->public.task
.process
= _process_r
;
962 return &this->public;