2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2005-2007 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
25 #include <crypto/diffie_hellman.h>
26 #include <encoding/payloads/sa_payload.h>
27 #include <encoding/payloads/ke_payload.h>
28 #include <encoding/payloads/nonce_payload.h>
30 /** maximum retries to do with cookies/other dh groups */
33 typedef struct private_ike_init_t private_ike_init_t
;
36 * Private members of a ike_init_t task.
38 struct private_ike_init_t
{
41 * Public methods and task_t interface.
51 * Are we the initiator?
56 * IKE config to establish
61 * diffie hellman group to use
63 diffie_hellman_group_t dh_group
;
66 * Diffie hellman object used to generate public DH value.
76 * nonce chosen by peer
81 * Negotiated proposal used for IKE_SA
86 * Old IKE_SA which gets rekeyed
91 * cookie received from responder
96 * retries done so far after failure (cookie or bad dh group)
102 * build the payloads for the message
104 static void build_payloads(private_ike_init_t
*this, message_t
*message
)
106 sa_payload_t
*sa_payload
;
107 ke_payload_t
*ke_payload
;
108 nonce_payload_t
*nonce_payload
;
109 linked_list_t
*proposal_list
;
111 proposal_t
*proposal
;
112 iterator_t
*iterator
;
114 id
= this->ike_sa
->get_id(this->ike_sa
);
116 this->config
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
120 proposal_list
= this->config
->get_proposals(this->config
);
123 /* include SPI of new IKE_SA when we are rekeying */
124 iterator
= proposal_list
->create_iterator(proposal_list
, TRUE
);
125 while (iterator
->iterate(iterator
, (void**)&proposal
))
127 proposal
->set_spi(proposal
, id
->get_initiator_spi(id
));
129 iterator
->destroy(iterator
);
132 sa_payload
= sa_payload_create_from_proposal_list(proposal_list
);
133 proposal_list
->destroy_offset(proposal_list
, offsetof(proposal_t
, destroy
));
139 /* include SPI of new IKE_SA when we are rekeying */
140 this->proposal
->set_spi(this->proposal
, id
->get_responder_spi(id
));
142 sa_payload
= sa_payload_create_from_proposal(this->proposal
);
144 message
->add_payload(message
, (payload_t
*)sa_payload
);
146 nonce_payload
= nonce_payload_create();
147 nonce_payload
->set_nonce(nonce_payload
, this->my_nonce
);
148 ke_payload
= ke_payload_create_from_diffie_hellman(this->dh
);
151 { /* payload order differs if we are rekeying */
152 message
->add_payload(message
, (payload_t
*)nonce_payload
);
153 message
->add_payload(message
, (payload_t
*)ke_payload
);
157 message
->add_payload(message
, (payload_t
*)ke_payload
);
158 message
->add_payload(message
, (payload_t
*)nonce_payload
);
163 * Read payloads from message
165 static void process_payloads(private_ike_init_t
*this, message_t
*message
)
167 iterator_t
*iterator
;
170 iterator
= message
->get_payload_iterator(message
);
171 while (iterator
->iterate(iterator
, (void**)&payload
))
173 switch (payload
->get_type(payload
))
175 case SECURITY_ASSOCIATION
:
177 sa_payload_t
*sa_payload
= (sa_payload_t
*)payload
;
178 linked_list_t
*proposal_list
;
180 proposal_list
= sa_payload
->get_proposals(sa_payload
);
181 this->proposal
= this->config
->select_proposal(this->config
,
183 proposal_list
->destroy_offset(proposal_list
,
184 offsetof(proposal_t
, destroy
));
189 ke_payload_t
*ke_payload
= (ke_payload_t
*)payload
;
191 this->dh_group
= ke_payload
->get_dh_group_number(ke_payload
);
192 if (!this->initiator
)
194 this->dh
= lib
->crypto
->create_dh(lib
->crypto
, this->dh_group
);
198 this->dh
->set_other_public_value(this->dh
,
199 ke_payload
->get_key_exchange_data(ke_payload
));
205 nonce_payload_t
*nonce_payload
= (nonce_payload_t
*)payload
;
206 this->other_nonce
= nonce_payload
->get_nonce(nonce_payload
);
213 iterator
->destroy(iterator
);
217 * Implementation of task_t.process for initiator
219 static status_t
build_i(private_ike_init_t
*this, message_t
*message
)
223 this->config
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
224 SIG(IKE_UP_START
, "initiating IKE_SA '%s' to %H",
225 this->ike_sa
->get_name(this->ike_sa
),
226 this->config
->get_other_host(this->config
));
227 this->ike_sa
->set_state(this->ike_sa
, IKE_CONNECTING
);
229 if (this->retry
++ >= MAX_RETRIES
)
231 SIG(IKE_UP_FAILED
, "giving up after %d retries", MAX_RETRIES
);
235 /* if the DH group is set via use_dh_group(), we already have a DH object */
238 this->dh_group
= this->config
->get_dh_group(this->config
);
239 this->dh
= lib
->crypto
->create_dh(lib
->crypto
, this->dh_group
);
240 if (this->dh
== NULL
)
242 SIG(IKE_UP_FAILED
, "configured DH group %N not supported",
243 diffie_hellman_group_names
, this->dh_group
);
248 /* generate nonce only when we are trying the first time */
249 if (this->my_nonce
.ptr
== NULL
)
251 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
254 SIG(IKE_UP_FAILED
, "error generating nonce");
257 rng
->allocate_bytes(rng
, NONCE_SIZE
, &this->my_nonce
);
261 if (this->cookie
.ptr
)
263 message
->add_notify(message
, FALSE
, COOKIE
, this->cookie
);
266 build_payloads(this, message
);
270 chunk_t connect_id
= this->ike_sa
->get_connect_id(this->ike_sa
);
273 message
->add_notify(message
, FALSE
, ME_CONNECTID
, connect_id
);
282 * Implementation of task_t.process for responder
284 static status_t
process_r(private_ike_init_t
*this, message_t
*message
)
288 this->config
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
289 SIG(IKE_UP_START
, "%H is initiating an IKE_SA",
290 message
->get_source(message
));
291 this->ike_sa
->set_state(this->ike_sa
, IKE_CONNECTING
);
293 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
296 DBG1(DBG_IKE
, "error generating nonce");
299 rng
->allocate_bytes(rng
, NONCE_SIZE
, &this->my_nonce
);
304 chunk_t connect_id
= chunk_empty
;
305 iterator_t
*iterator
;
308 /* check for a ME_CONNECTID notify */
309 iterator
= message
->get_payload_iterator(message
);
310 while (iterator
->iterate(iterator
, (void**)&payload
))
312 if (payload
->get_type(payload
) == NOTIFY
)
314 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
315 notify_type_t type
= notify
->get_notify_type(notify
);
321 chunk_free(&connect_id
);
322 connect_id
= chunk_clone(notify
->get_notification_data(notify
));
323 DBG2(DBG_IKE
, "received ME_CONNECTID %#B", &connect_id
);
330 DBG1(DBG_IKE
, "received %N notify error",
331 notify_type_names
, type
);
334 DBG2(DBG_IKE
, "received %N notify",
335 notify_type_names
, type
);
341 iterator
->destroy(iterator
);
345 charon
->connect_manager
->stop_checks(charon
->connect_manager
,
347 chunk_free(&connect_id
);
352 process_payloads(this, message
);
358 * Implementation of task_t.build for responder
360 static status_t
build_r(private_ike_init_t
*this, message_t
*message
)
365 /* check if we have everything we need */
366 if (this->proposal
== NULL
||
367 this->other_nonce
.len
== 0 || this->my_nonce
.len
== 0)
369 SIG(IKE_UP_FAILED
, "received proposals inacceptable");
370 message
->add_notify(message
, TRUE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
374 if (this->dh
== NULL
||
375 !this->proposal
->has_dh_group(this->proposal
, this->dh_group
) ||
376 this->dh
->get_shared_secret(this->dh
, &secret
) != SUCCESS
)
380 if (this->proposal
->get_algorithm(this->proposal
, DIFFIE_HELLMAN_GROUP
,
383 SIG(CHILD_UP_FAILED
, "DH group %N inacceptable, requesting %N",
384 diffie_hellman_group_names
, this->dh_group
,
385 diffie_hellman_group_names
, group
);
386 this->dh_group
= group
;
387 group
= htons(group
);
388 message
->add_notify(message
, FALSE
, INVALID_KE_PAYLOAD
,
389 chunk_from_thing(group
));
393 SIG(IKE_UP_FAILED
, "no acceptable proposal found");
401 prf_t
*prf
, *child_prf
;
403 /* Apply SPI if we are rekeying */
404 id
= this->ike_sa
->get_id(this->ike_sa
);
405 id
->set_initiator_spi(id
, this->proposal
->get_spi(this->proposal
));
407 /* setup crypto keys for the rekeyed SA */
408 prf
= this->old_sa
->get_prf(this->old_sa
);
409 child_prf
= this->old_sa
->get_child_prf(this->old_sa
);
410 status
= this->ike_sa
->derive_keys(this->ike_sa
, this->proposal
, secret
,
411 this->other_nonce
, this->my_nonce
,
412 FALSE
, child_prf
, prf
);
416 /* setup crypto keys */
417 status
= this->ike_sa
->derive_keys(this->ike_sa
, this->proposal
, secret
,
418 this->other_nonce
, this->my_nonce
,
421 if (status
!= SUCCESS
)
423 SIG(IKE_UP_FAILED
, "key derivation failed");
424 message
->add_notify(message
, TRUE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
428 build_payloads(this, message
);
434 * Implementation of task_t.process for initiator
436 static status_t
process_i(private_ike_init_t
*this, message_t
*message
)
440 iterator_t
*iterator
;
443 /* check for erronous notifies */
444 iterator
= message
->get_payload_iterator(message
);
445 while (iterator
->iterate(iterator
, (void**)&payload
))
447 if (payload
->get_type(payload
) == NOTIFY
)
449 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
450 notify_type_t type
= notify
->get_notify_type(notify
);
454 case INVALID_KE_PAYLOAD
:
457 diffie_hellman_group_t bad_group
;
459 bad_group
= this->dh_group
;
460 data
= notify
->get_notification_data(notify
);
461 this->dh_group
= ntohs(*((u_int16_t
*)data
.ptr
));
462 DBG1(DBG_IKE
, "peer didn't accept DH group %N, "
463 "it requested %N", diffie_hellman_group_names
,
464 bad_group
, diffie_hellman_group_names
, this->dh_group
);
466 if (this->old_sa
== NULL
)
467 { /* reset the IKE_SA if we are not rekeying */
468 this->ike_sa
->reset(this->ike_sa
);
471 iterator
->destroy(iterator
);
474 case NAT_DETECTION_SOURCE_IP
:
475 case NAT_DETECTION_DESTINATION_IP
:
476 /* skip, handled in ike_natd_t */
480 chunk_free(&this->cookie
);
481 this->cookie
= chunk_clone(notify
->get_notification_data(notify
));
482 this->ike_sa
->reset(this->ike_sa
);
483 iterator
->destroy(iterator
);
484 DBG2(DBG_IKE
, "received %N notify", notify_type_names
, type
);
491 SIG(IKE_UP_FAILED
, "received %N notify error",
492 notify_type_names
, type
);
493 iterator
->destroy(iterator
);
496 DBG2(DBG_IKE
, "received %N notify",
497 notify_type_names
, type
);
503 iterator
->destroy(iterator
);
505 process_payloads(this, message
);
507 /* check if we have everything */
508 if (this->proposal
== NULL
||
509 this->other_nonce
.len
== 0 || this->my_nonce
.len
== 0)
511 SIG(IKE_UP_FAILED
, "peers proposal selection invalid");
515 if (this->dh
== NULL
||
516 !this->proposal
->has_dh_group(this->proposal
, this->dh_group
) ||
517 this->dh
->get_shared_secret(this->dh
, &secret
) != SUCCESS
)
519 SIG(IKE_UP_FAILED
, "peers DH group selection invalid");
523 /* Apply SPI if we are rekeying */
527 prf_t
*prf
, *child_prf
;
529 id
= this->ike_sa
->get_id(this->ike_sa
);
530 id
->set_responder_spi(id
, this->proposal
->get_spi(this->proposal
));
532 /* setup crypto keys for the rekeyed SA */
533 prf
= this->old_sa
->get_prf(this->old_sa
);
534 child_prf
= this->old_sa
->get_child_prf(this->old_sa
);
535 status
= this->ike_sa
->derive_keys(this->ike_sa
, this->proposal
, secret
,
536 this->my_nonce
, this->other_nonce
,
537 TRUE
, child_prf
, prf
);
541 /* setup crypto keys for a new SA */
542 status
= this->ike_sa
->derive_keys(this->ike_sa
, this->proposal
, secret
,
543 this->my_nonce
, this->other_nonce
,
546 if (status
!= SUCCESS
)
548 SIG(IKE_UP_FAILED
, "key derivation failed");
555 * Implementation of task_t.get_type
557 static task_type_t
get_type(private_ike_init_t
*this)
563 * Implementation of task_t.get_type
565 static chunk_t
get_lower_nonce(private_ike_init_t
*this)
567 if (memcmp(this->my_nonce
.ptr
, this->other_nonce
.ptr
,
568 min(this->my_nonce
.len
, this->other_nonce
.len
)) < 0)
570 return this->my_nonce
;
574 return this->other_nonce
;
579 * Implementation of task_t.migrate
581 static void migrate(private_ike_init_t
*this, ike_sa_t
*ike_sa
)
583 DESTROY_IF(this->proposal
);
584 DESTROY_IF(this->dh
);
585 chunk_free(&this->other_nonce
);
587 this->ike_sa
= ike_sa
;
588 this->proposal
= NULL
;
589 this->dh
= lib
->crypto
->create_dh(lib
->crypto
, this->dh_group
);
593 * Implementation of task_t.destroy
595 static void destroy(private_ike_init_t
*this)
597 DESTROY_IF(this->proposal
);
598 DESTROY_IF(this->dh
);
599 chunk_free(&this->my_nonce
);
600 chunk_free(&this->other_nonce
);
601 chunk_free(&this->cookie
);
606 * Described in header.
608 ike_init_t
*ike_init_create(ike_sa_t
*ike_sa
, bool initiator
, ike_sa_t
*old_sa
)
610 private_ike_init_t
*this = malloc_thing(private_ike_init_t
);
612 this->public.get_lower_nonce
= (chunk_t(*)(ike_init_t
*))get_lower_nonce
;
613 this->public.task
.get_type
= (task_type_t(*)(task_t
*))get_type
;
614 this->public.task
.migrate
= (void(*)(task_t
*,ike_sa_t
*))migrate
;
615 this->public.task
.destroy
= (void(*)(task_t
*))destroy
;
618 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_i
;
619 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_i
;
623 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_r
;
624 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_r
;
627 this->ike_sa
= ike_sa
;
628 this->initiator
= initiator
;
629 this->dh_group
= MODP_NONE
;
631 this->my_nonce
= chunk_empty
;
632 this->other_nonce
= chunk_empty
;
633 this->cookie
= chunk_empty
;
634 this->proposal
= NULL
;
636 this->old_sa
= old_sa
;
639 return &this->public;