2 * Copyright (C) 2011 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
5 * Copyright (C) 2011 Martin Willi
6 * Copyright (C) 2011 revosec 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
19 #include "main_mode.h"
24 #include <sa/keymat_v1.h>
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>
29 #include <encoding/payloads/id_payload.h>
30 #include <encoding/payloads/hash_payload.h>
32 typedef struct private_main_mode_t private_main_mode_t
;
35 * Private members of a main_mode_t task.
37 struct private_main_mode_t
{
40 * Public methods and task_t interface.
50 * Are we the initiator?
55 * IKE config to establish
65 * Local authentication configuration
70 * Remote authentication configuration
72 auth_cfg_t
*other_auth
;
75 * selected IKE proposal
85 * Keymat derivation (from SA)
90 * Received public DH value from peer
105 * Encoded SA initiator payload used for authentication
110 * Negotiated SA lifetime
115 * Negotiated authentication method
117 auth_method_t auth_method
;
119 /** states of main mode */
129 * Get the first authentcation config from peer config
131 static auth_cfg_t
*get_auth_cfg(private_main_mode_t
*this, bool local
)
133 enumerator_t
*enumerator
;
134 auth_cfg_t
*cfg
= NULL
;
136 enumerator
= this->peer_cfg
->create_auth_cfg_enumerator(this->peer_cfg
,
138 enumerator
->enumerate(enumerator
, &cfg
);
139 enumerator
->destroy(enumerator
);
144 * Save the encoded SA payload of a message
146 static bool save_sa_payload(private_main_mode_t
*this, message_t
*message
)
148 enumerator_t
*enumerator
;
149 payload_t
*payload
, *sa
= NULL
;
151 size_t offset
= IKE_HEADER_LENGTH
;
153 enumerator
= message
->create_payload_enumerator(message
);
154 while (enumerator
->enumerate(enumerator
, &payload
))
156 if (payload
->get_type(payload
) == SECURITY_ASSOCIATION_V1
)
163 offset
+= payload
->get_length(payload
);
166 enumerator
->destroy(enumerator
);
168 data
= message
->get_packet_data(message
);
169 if (sa
&& data
.len
>= offset
+ sa
->get_length(sa
))
171 /* Get SA payload without 4 byte fixed header */
172 data
= chunk_skip(data
, offset
);
173 data
.len
= sa
->get_length(sa
);
174 data
= chunk_skip(data
, 4);
175 this->sa_payload
= chunk_clone(data
);
182 * Build main mode hash payloads
184 static void build_hash(private_main_mode_t
*this, bool initiator
,
185 message_t
*message
, identification_t
*id
)
187 hash_payload_t
*hash_payload
;
190 this->dh
->get_my_public_value(this->dh
, &dh
);
191 hash
= this->keymat
->get_hash(this->keymat
, initiator
, dh
, this->dh_value
,
192 this->ike_sa
->get_id(this->ike_sa
), this->sa_payload
, id
);
195 hash_payload
= hash_payload_create();
196 hash_payload
->set_hash(hash_payload
, hash
);
199 message
->add_payload(message
, &hash_payload
->payload_interface
);
203 * Verify main mode hash payload
205 static bool verify_hash(private_main_mode_t
*this, bool initiator
,
206 message_t
*message
, identification_t
*id
)
208 hash_payload_t
*hash_payload
;
212 hash_payload
= (hash_payload_t
*)message
->get_payload(message
,
216 DBG1(DBG_IKE
, "HASH payload missing in message");
219 hash
= hash_payload
->get_hash(hash_payload
);
220 this->dh
->get_my_public_value(this->dh
, &dh
);
221 hash
= this->keymat
->get_hash(this->keymat
, initiator
, this->dh_value
, dh
,
222 this->ike_sa
->get_id(this->ike_sa
), this->sa_payload
, id
);
224 equal
= chunk_equals(hash
, hash_payload
->get_hash(hash_payload
));
228 DBG1(DBG_IKE
, "calculated HASH does not match HASH payload");
234 * Generate and add NONCE, KE payload
236 static bool add_nonce_ke(private_main_mode_t
*this, chunk_t
*nonce
,
239 nonce_payload_t
*nonce_payload
;
240 ke_payload_t
*ke_payload
;
243 ke_payload
= ke_payload_create_from_diffie_hellman(KEY_EXCHANGE_V1
,
245 message
->add_payload(message
, &ke_payload
->payload_interface
);
247 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
250 DBG1(DBG_IKE
, "no RNG found to create nonce");
253 rng
->allocate_bytes(rng
, NONCE_SIZE
, nonce
);
256 nonce_payload
= nonce_payload_create(NONCE_V1
);
257 nonce_payload
->set_nonce(nonce_payload
, *nonce
);
258 message
->add_payload(message
, &nonce_payload
->payload_interface
);
264 * Extract nonce from NONCE payload, process KE payload
266 static bool get_nonce_ke(private_main_mode_t
*this, chunk_t
*nonce
,
269 nonce_payload_t
*nonce_payload
;
270 ke_payload_t
*ke_payload
;
272 ke_payload
= (ke_payload_t
*)message
->get_payload(message
, KEY_EXCHANGE_V1
);
275 DBG1(DBG_IKE
, "KE payload missing in message");
278 this->dh_value
= chunk_clone(ke_payload
->get_key_exchange_data(ke_payload
));
279 this->dh
->set_other_public_value(this->dh
, this->dh_value
);
281 nonce_payload
= (nonce_payload_t
*)message
->get_payload(message
, NONCE_V1
);
284 DBG1(DBG_IKE
, "NONCE payload missing in message");
287 *nonce
= nonce_payload
->get_nonce(nonce_payload
);
293 * Get auth method to use
295 static auth_method_t
get_auth_method(private_main_mode_t
*this)
297 switch ((uintptr_t)this->my_auth
->get(this->my_auth
, AUTH_RULE_AUTH_CLASS
))
301 case AUTH_CLASS_XAUTH_PSK
:
302 return AUTH_XAUTH_INIT_PSK
;
303 case AUTH_CLASS_XAUTH_PUBKEY
:
304 return AUTH_XAUTH_INIT_RSA
;
305 case AUTH_CLASS_PUBKEY
:
306 /* TODO-IKEv1: look for a key, return RSA or ECDSA */
308 /* TODO-IKEv1: XAUTH methods */
313 METHOD(task_t
, build_i
, status_t
,
314 private_main_mode_t
*this, message_t
*message
)
320 sa_payload_t
*sa_payload
;
321 linked_list_t
*proposals
;
324 this->ike_cfg
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
325 DBG0(DBG_IKE
, "initiating IKE_SA %s[%d] to %H",
326 this->ike_sa
->get_name(this->ike_sa
),
327 this->ike_sa
->get_unique_id(this->ike_sa
),
328 this->ike_sa
->get_other_host(this->ike_sa
));
329 this->ike_sa
->set_state(this->ike_sa
, IKE_CONNECTING
);
331 this->peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
332 this->peer_cfg
->get_ref(this->peer_cfg
);
334 this->my_auth
= get_auth_cfg(this, TRUE
);
335 this->other_auth
= get_auth_cfg(this, FALSE
);
336 if (!this->my_auth
|| !this->other_auth
)
338 DBG1(DBG_CFG
, "no auth config found");
342 proposals
= this->ike_cfg
->get_proposals(this->ike_cfg
);
343 this->auth_method
= get_auth_method(this);
344 this->lifetime
= this->peer_cfg
->get_reauth_time(this->peer_cfg
,
347 { /* fall back to rekey time of no rekey time configured */
348 this->lifetime
= this->peer_cfg
->get_rekey_time(this->peer_cfg
,
351 sa_payload
= sa_payload_create_from_proposals_v1(proposals
,
352 this->lifetime
, 0, this->auth_method
, MODE_NONE
, FALSE
);
353 proposals
->destroy_offset(proposals
, offsetof(proposal_t
, destroy
));
355 message
->add_payload(message
, &sa_payload
->payload_interface
);
357 /* pregenerate message to store SA payload */
358 if (this->ike_sa
->generate_message(this->ike_sa
, message
,
361 DBG1(DBG_IKE
, "pregenerating SA payload failed");
364 packet
->destroy(packet
);
365 if (!save_sa_payload(this, message
))
367 DBG1(DBG_IKE
, "SA payload invalid");
378 if (!this->proposal
->get_algorithm(this->proposal
,
379 DIFFIE_HELLMAN_GROUP
, &group
, NULL
))
381 DBG1(DBG_IKE
, "DH group selection failed");
384 this->dh
= this->keymat
->keymat
.create_dh(&this->keymat
->keymat
,
388 DBG1(DBG_IKE
, "negotiated DH group not supported");
391 if (!add_nonce_ke(this, &this->nonce_i
, message
))
400 id_payload_t
*id_payload
;
401 identification_t
*id
;
403 id
= this->my_auth
->get(this->my_auth
, AUTH_RULE_IDENTITY
);
406 DBG1(DBG_CFG
, "own identity not known");
410 this->ike_sa
->set_my_id(this->ike_sa
, id
->clone(id
));
412 id_payload
= id_payload_create_from_identification(ID_V1
, id
);
413 message
->add_payload(message
, &id_payload
->payload_interface
);
415 build_hash(this, TRUE
, message
, id
);
417 this->state
= MM_AUTH
;
425 METHOD(task_t
, process_r
, status_t
,
426 private_main_mode_t
*this, message_t
*message
)
433 sa_payload_t
*sa_payload
;
435 this->ike_cfg
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
436 DBG0(DBG_IKE
, "%H is initiating a Main Mode",
437 message
->get_source(message
));
438 this->ike_sa
->set_state(this->ike_sa
, IKE_CONNECTING
);
440 this->ike_sa
->update_hosts(this->ike_sa
,
441 message
->get_destination(message
),
442 message
->get_source(message
), TRUE
);
444 sa_payload
= (sa_payload_t
*)message
->get_payload(message
,
445 SECURITY_ASSOCIATION_V1
);
446 if (!sa_payload
|| !save_sa_payload(this, message
))
448 DBG1(DBG_IKE
, "SA payload missing or invalid");
452 list
= sa_payload
->get_proposals(sa_payload
);
453 this->proposal
= this->ike_cfg
->select_proposal(this->ike_cfg
,
455 list
->destroy_offset(list
, offsetof(proposal_t
, destroy
));
458 DBG1(DBG_IKE
, "no proposal found");
462 this->auth_method
= sa_payload
->get_auth_method(sa_payload
);
463 this->lifetime
= sa_payload
->get_lifetime(sa_payload
);
472 if (!this->proposal
->get_algorithm(this->proposal
,
473 DIFFIE_HELLMAN_GROUP
, &group
, NULL
))
475 DBG1(DBG_IKE
, "DH group selection failed");
478 this->dh
= lib
->crypto
->create_dh(lib
->crypto
, group
);
481 DBG1(DBG_IKE
, "negotiated DH group not supported");
484 if (!get_nonce_ke(this, &this->nonce_i
, message
))
493 enumerator_t
*enumerator
;
494 id_payload_t
*id_payload
;
495 identification_t
*id
, *any
;
497 id_payload
= (id_payload_t
*)message
->get_payload(message
, ID_V1
);
500 DBG1(DBG_IKE
, "IDii payload missing");
504 id
= id_payload
->get_identification(id_payload
);
505 any
= identification_create_from_encoding(ID_ANY
, chunk_empty
);
506 enumerator
= charon
->backends
->create_peer_cfg_enumerator(
508 this->ike_sa
->get_my_host(this->ike_sa
),
509 this->ike_sa
->get_other_host(this->ike_sa
),
511 if (!enumerator
->enumerate(enumerator
, &this->peer_cfg
))
513 DBG1(DBG_IKE
, "no peer config found");
516 enumerator
->destroy(enumerator
);
519 this->peer_cfg
->get_ref(this->peer_cfg
);
520 enumerator
->destroy(enumerator
);
523 this->ike_sa
->set_other_id(this->ike_sa
, id
);
525 this->ike_sa
->set_peer_cfg(this->ike_sa
, this->peer_cfg
);
527 this->my_auth
= get_auth_cfg(this, TRUE
);
528 this->other_auth
= get_auth_cfg(this, FALSE
);
529 if (!this->my_auth
|| !this->other_auth
)
531 DBG1(DBG_IKE
, "auth config missing");
535 if (!verify_hash(this, TRUE
, message
, id
))
540 this->state
= MM_AUTH
;
549 * Lookup a shared secret for this IKE_SA
551 static shared_key_t
*lookup_shared_key(private_main_mode_t
*this)
554 identification_t
*my_id
, *other_id
;
555 shared_key_t
*shared_key
;
557 me
= this->ike_sa
->get_my_host(this->ike_sa
);
558 other
= this->ike_sa
->get_other_host(this->ike_sa
);
559 my_id
= identification_create_from_sockaddr(me
->get_sockaddr(me
));
560 other_id
= identification_create_from_sockaddr(other
->get_sockaddr(other
));
561 if (!my_id
|| !other_id
)
564 DESTROY_IF(other_id
);
567 shared_key
= lib
->credmgr
->get_shared(lib
->credmgr
, SHARED_IKE
, my_id
,
571 DBG1(DBG_IKE
, "no shared key found for %H - %H", me
, other
);
573 my_id
->destroy(my_id
);
574 other_id
->destroy(other_id
);
579 * Derive key material for this IKE_SA
581 static bool derive_keys(private_main_mode_t
*this, chunk_t nonce_i
,
584 ike_sa_id_t
*id
= this->ike_sa
->get_id(this->ike_sa
);
585 shared_key_t
*shared_key
= NULL
;
587 switch (this->auth_method
)
590 case AUTH_XAUTH_INIT_PSK
:
591 shared_key
= lookup_shared_key(this);
596 if (!this->keymat
->derive_ike_keys(this->keymat
, this->proposal
, this->dh
,
597 this->dh_value
, nonce_i
, nonce_r
, id
, this->auth_method
, shared_key
))
599 DESTROY_IF(shared_key
);
602 DESTROY_IF(shared_key
);
603 charon
->bus
->ike_keys(charon
->bus
, this->ike_sa
, this->dh
, nonce_i
, nonce_r
,
608 METHOD(task_t
, build_r
, status_t
,
609 private_main_mode_t
*this, message_t
*message
)
615 sa_payload_t
*sa_payload
;
617 sa_payload
= sa_payload_create_from_proposal_v1(this->proposal
,
618 this->lifetime
, 0, this->auth_method
, MODE_NONE
, FALSE
);
619 message
->add_payload(message
, &sa_payload
->payload_interface
);
625 if (!add_nonce_ke(this, &this->nonce_r
, message
))
629 if (!derive_keys(this, this->nonce_i
, this->nonce_r
))
631 DBG1(DBG_IKE
, "key derivation failed");
638 id_payload_t
*id_payload
;
639 identification_t
*id
;
641 id
= this->my_auth
->get(this->my_auth
, AUTH_RULE_IDENTITY
);
644 DBG1(DBG_CFG
, "own identity not known");
648 this->ike_sa
->set_my_id(this->ike_sa
, id
->clone(id
));
650 id_payload
= id_payload_create_from_identification(ID_V1
, id
);
651 message
->add_payload(message
, &id_payload
->payload_interface
);
653 build_hash(this, FALSE
, message
, id
);
655 DBG0(DBG_IKE
, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
656 this->ike_sa
->get_name(this->ike_sa
),
657 this->ike_sa
->get_unique_id(this->ike_sa
),
658 this->ike_sa
->get_my_host(this->ike_sa
),
659 this->ike_sa
->get_my_id(this->ike_sa
),
660 this->ike_sa
->get_other_host(this->ike_sa
),
661 this->ike_sa
->get_other_id(this->ike_sa
));
662 this->ike_sa
->set_state(this->ike_sa
, IKE_ESTABLISHED
);
663 charon
->bus
->ike_updown(charon
->bus
, this->ike_sa
, TRUE
);
665 /* TODO-IKEv1: Check the proposal for XAuthInit* auth modes */
666 /* TODO-IKEv1: check for XAUTH rounds, queue them */
667 if(0) /* TODO-IKEv1: Change to 1 if XAUTH is desired. */
676 METHOD(task_t
, process_i
, status_t
,
677 private_main_mode_t
*this, message_t
*message
)
684 sa_payload_t
*sa_payload
;
685 auth_method_t auth_method
;
688 sa_payload
= (sa_payload_t
*)message
->get_payload(message
,
689 SECURITY_ASSOCIATION_V1
);
692 DBG1(DBG_IKE
, "SA payload missing");
695 list
= sa_payload
->get_proposals(sa_payload
);
696 this->proposal
= this->ike_cfg
->select_proposal(this->ike_cfg
,
698 list
->destroy_offset(list
, offsetof(proposal_t
, destroy
));
701 DBG1(DBG_IKE
, "no proposal found");
705 lifetime
= sa_payload
->get_lifetime(sa_payload
);
706 if (lifetime
!= this->lifetime
)
708 DBG1(DBG_IKE
, "received lifetime %us does not match configured "
709 "%us, using lower value", lifetime
, this->lifetime
);
711 this->lifetime
= min(this->lifetime
, lifetime
);
712 auth_method
= sa_payload
->get_auth_method(sa_payload
);
713 if (auth_method
!= this->auth_method
)
715 DBG1(DBG_IKE
, "received %N authentication, but configured %N, "
716 "continue with configured", auth_method_names
, auth_method
,
717 auth_method_names
, this->auth_method
);
723 if (!get_nonce_ke(this, &this->nonce_r
, message
))
727 if (!derive_keys(this, this->nonce_i
, this->nonce_r
))
729 DBG1(DBG_IKE
, "key derivation failed");
736 id_payload_t
*id_payload
;
737 identification_t
*id
;
739 id_payload
= (id_payload_t
*)message
->get_payload(message
, ID_V1
);
742 DBG1(DBG_IKE
, "IDir payload missing");
745 id
= id_payload
->get_identification(id_payload
);
746 if (!id
->matches(id
, this->other_auth
->get(this->other_auth
,
747 AUTH_RULE_IDENTITY
)))
749 DBG1(DBG_IKE
, "IDir does not match");
753 this->ike_sa
->set_other_id(this->ike_sa
, id
);
755 if (!verify_hash(this, FALSE
, message
, id
))
760 /* TODO-IKEv1: check for XAUTH rounds, queue them */
761 DBG0(DBG_IKE
, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
762 this->ike_sa
->get_name(this->ike_sa
),
763 this->ike_sa
->get_unique_id(this->ike_sa
),
764 this->ike_sa
->get_my_host(this->ike_sa
),
765 this->ike_sa
->get_my_id(this->ike_sa
),
766 this->ike_sa
->get_other_host(this->ike_sa
),
767 this->ike_sa
->get_other_id(this->ike_sa
));
768 this->ike_sa
->set_state(this->ike_sa
, IKE_ESTABLISHED
);
769 charon
->bus
->ike_updown(charon
->bus
, this->ike_sa
, TRUE
);
777 METHOD(task_t
, get_type
, task_type_t
,
778 private_main_mode_t
*this)
780 return TASK_MAIN_MODE
;
783 METHOD(task_t
, migrate
, void,
784 private_main_mode_t
*this, ike_sa_t
*ike_sa
)
786 this->ike_sa
= ike_sa
;
789 METHOD(task_t
, destroy
, void,
790 private_main_mode_t
*this)
792 DESTROY_IF(this->peer_cfg
);
793 DESTROY_IF(this->proposal
);
794 DESTROY_IF(this->dh
);
795 free(this->dh_value
.ptr
);
796 free(this->nonce_i
.ptr
);
797 free(this->nonce_r
.ptr
);
798 free(this->sa_payload
.ptr
);
803 * Described in header.
805 main_mode_t
*main_mode_create(ike_sa_t
*ike_sa
, bool initiator
)
807 private_main_mode_t
*this;
812 .get_type
= _get_type
,
818 .keymat
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
),
819 .initiator
= initiator
,
825 this->public.task
.build
= _build_i
;
826 this->public.task
.process
= _process_i
;
830 this->public.task
.build
= _build_r
;
831 this->public.task
.process
= _process_r
;
834 return &this->public;