2 * Copyright (C) 2012 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
5 * Copyright (C) 2012 Martin Willi
6 * Copyright (C) 2012 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
22 #include <sa/ikev1/keymat_v1.h>
23 #include <encoding/payloads/ke_payload.h>
24 #include <encoding/payloads/nonce_payload.h>
25 #include <collections/linked_list.h>
27 typedef struct private_phase1_t private_phase1_t
;
30 * Private data of an phase1_t object.
32 struct private_phase1_t
{
35 * Public phase1_t interface.
45 * Currently selected peer config
50 * Other possible peer config candidates
52 linked_list_t
*candidates
;
60 * Extracted SA payload bytes
70 * Keymat derivation (from SA)
75 * Received public DH value from peer
91 * Get the first authentcation config from peer config
93 static auth_cfg_t
*get_auth_cfg(peer_cfg_t
*peer_cfg
, bool local
)
95 enumerator_t
*enumerator
;
96 auth_cfg_t
*cfg
= NULL
;
98 enumerator
= peer_cfg
->create_auth_cfg_enumerator(peer_cfg
, local
);
99 enumerator
->enumerate(enumerator
, &cfg
);
100 enumerator
->destroy(enumerator
);
105 * Lookup a shared secret for this IKE_SA
107 static shared_key_t
*lookup_shared_key(private_phase1_t
*this,
108 peer_cfg_t
*peer_cfg
)
111 identification_t
*my_id
, *other_id
;
112 shared_key_t
*shared_key
= NULL
;
113 auth_cfg_t
*my_auth
, *other_auth
;
114 enumerator_t
*enumerator
;
116 /* try to get a PSK for IP addresses */
117 me
= this->ike_sa
->get_my_host(this->ike_sa
);
118 other
= this->ike_sa
->get_other_host(this->ike_sa
);
119 my_id
= identification_create_from_sockaddr(me
->get_sockaddr(me
));
120 other_id
= identification_create_from_sockaddr(other
->get_sockaddr(other
));
121 if (my_id
&& other_id
)
123 shared_key
= lib
->credmgr
->get_shared(lib
->credmgr
, SHARED_IKE
,
127 DESTROY_IF(other_id
);
134 { /* as initiator or aggressive responder, use identities */
135 my_auth
= get_auth_cfg(peer_cfg
, TRUE
);
136 other_auth
= get_auth_cfg(peer_cfg
, FALSE
);
137 if (my_auth
&& other_auth
)
139 my_id
= my_auth
->get(my_auth
, AUTH_RULE_IDENTITY
);
140 if (peer_cfg
->use_aggressive(peer_cfg
))
142 other_id
= this->ike_sa
->get_other_id(this->ike_sa
);
146 other_id
= other_auth
->get(other_auth
, AUTH_RULE_IDENTITY
);
148 if (my_id
&& other_id
)
150 shared_key
= lib
->credmgr
->get_shared(lib
->credmgr
, SHARED_IKE
,
154 DBG1(DBG_IKE
, "no shared key found for '%Y'[%H] - '%Y'[%H]",
155 my_id
, me
, other_id
, other
);
161 /* as responder, we try to find a config by IP */
162 enumerator
= charon
->backends
->create_peer_cfg_enumerator(charon
->backends
,
163 me
, other
, NULL
, NULL
, IKEV1
);
164 while (enumerator
->enumerate(enumerator
, &peer_cfg
))
166 my_auth
= get_auth_cfg(peer_cfg
, TRUE
);
167 other_auth
= get_auth_cfg(peer_cfg
, FALSE
);
168 if (my_auth
&& other_auth
)
170 my_id
= my_auth
->get(my_auth
, AUTH_RULE_IDENTITY
);
171 other_id
= other_auth
->get(other_auth
, AUTH_RULE_IDENTITY
);
174 shared_key
= lib
->credmgr
->get_shared(lib
->credmgr
, SHARED_IKE
,
182 DBG1(DBG_IKE
, "no shared key found for '%Y'[%H] - '%Y'[%H]",
183 my_id
, me
, other_id
, other
);
188 enumerator
->destroy(enumerator
);
191 DBG1(DBG_IKE
, "no shared key found for %H - %H", me
, other
);
196 METHOD(phase1_t
, create_hasher
, bool,
197 private_phase1_t
*this)
199 return this->keymat
->create_hasher(this->keymat
,
200 this->ike_sa
->get_proposal(this->ike_sa
));
203 METHOD(phase1_t
, create_dh
, bool,
204 private_phase1_t
*this, diffie_hellman_group_t group
)
206 this->dh
= this->keymat
->keymat
.create_dh(&this->keymat
->keymat
, group
);
207 return this->dh
!= NULL
;
210 METHOD(phase1_t
, derive_keys
, bool,
211 private_phase1_t
*this, peer_cfg_t
*peer_cfg
, auth_method_t method
)
213 shared_key_t
*shared_key
= NULL
;
218 case AUTH_XAUTH_INIT_PSK
:
219 case AUTH_XAUTH_RESP_PSK
:
220 shared_key
= lookup_shared_key(this, peer_cfg
);
230 if (!this->keymat
->derive_ike_keys(this->keymat
,
231 this->ike_sa
->get_proposal(this->ike_sa
),
232 this->dh
, this->dh_value
, this->nonce_i
, this->nonce_r
,
233 this->ike_sa
->get_id(this->ike_sa
), method
, shared_key
))
235 DESTROY_IF(shared_key
);
236 DBG1(DBG_IKE
, "key derivation for %N failed", auth_method_names
, method
);
239 charon
->bus
->ike_keys(charon
->bus
, this->ike_sa
, this->dh
, this->dh_value
,
240 this->nonce_i
, this->nonce_r
, NULL
, shared_key
);
241 DESTROY_IF(shared_key
);
246 * Check if a peer skipped authentication by using Hybrid authentication
248 static bool skipped_auth(private_phase1_t
*this,
249 auth_method_t method
, bool local
)
253 initiator
= local
== this->initiator
;
254 if (initiator
&& method
== AUTH_HYBRID_INIT_RSA
)
258 if (!initiator
&& method
== AUTH_HYBRID_RESP_RSA
)
266 * Check if remote authentication constraints fulfilled
268 static bool check_constraints(private_phase1_t
*this, auth_method_t method
)
270 identification_t
*id
;
271 auth_cfg_t
*auth
, *cfg
;
272 peer_cfg_t
*peer_cfg
;
274 auth
= this->ike_sa
->get_auth_cfg(this->ike_sa
, FALSE
);
275 /* auth identity to comply */
276 id
= this->ike_sa
->get_other_id(this->ike_sa
);
277 auth
->add(auth
, AUTH_RULE_IDENTITY
, id
->clone(id
));
278 if (skipped_auth(this, method
, FALSE
))
282 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
283 cfg
= get_auth_cfg(peer_cfg
, FALSE
);
284 return cfg
&& auth
->complies(auth
, cfg
, TRUE
);
288 * Save authentication information after authentication succeeded
290 static void save_auth_cfg(private_phase1_t
*this,
291 auth_method_t method
, bool local
)
295 if (skipped_auth(this, method
, local
))
299 auth
= auth_cfg_create();
300 /* for local config, we _copy_ entires from the config, as it contains
301 * certificates we must send later. */
302 auth
->merge(auth
, this->ike_sa
->get_auth_cfg(this->ike_sa
, local
), local
);
303 this->ike_sa
->add_auth_cfg(this->ike_sa
, local
, auth
);
307 * Create an authenticator instance
309 static authenticator_t
* create_authenticator(private_phase1_t
*this,
310 auth_method_t method
, chunk_t id
)
312 authenticator_t
*authenticator
;
314 authenticator
= authenticator_create_v1(this->ike_sa
, this->initiator
,
315 method
, this->dh
, this->dh_value
, this->sa_payload
, id
);
318 DBG1(DBG_IKE
, "negotiated authentication method %N not supported",
319 auth_method_names
, method
);
321 return authenticator
;
324 METHOD(phase1_t
, verify_auth
, bool,
325 private_phase1_t
*this, auth_method_t method
, message_t
*message
,
328 authenticator_t
*authenticator
;
331 authenticator
= create_authenticator(this, method
, id_data
);
334 status
= authenticator
->process(authenticator
, message
);
335 authenticator
->destroy(authenticator
);
336 if (status
== SUCCESS
&& check_constraints(this, method
))
338 save_auth_cfg(this, method
, FALSE
);
345 METHOD(phase1_t
, build_auth
, bool,
346 private_phase1_t
*this, auth_method_t method
, message_t
*message
,
349 authenticator_t
*authenticator
;
352 authenticator
= create_authenticator(this, method
, id_data
);
355 status
= authenticator
->build(authenticator
, message
);
356 authenticator
->destroy(authenticator
);
357 if (status
== SUCCESS
)
359 save_auth_cfg(this, method
, TRUE
);
367 * Get the two auth classes from local or remote config
369 static void get_auth_class(peer_cfg_t
*peer_cfg
, bool local
,
370 auth_class_t
*c1
, auth_class_t
*c2
)
372 enumerator_t
*enumerator
;
375 *c1
= *c2
= AUTH_CLASS_ANY
;
377 enumerator
= peer_cfg
->create_auth_cfg_enumerator(peer_cfg
, local
);
378 while (enumerator
->enumerate(enumerator
, &auth
))
380 if (*c1
== AUTH_CLASS_ANY
)
382 *c1
= (uintptr_t)auth
->get(auth
, AUTH_RULE_AUTH_CLASS
);
386 *c2
= (uintptr_t)auth
->get(auth
, AUTH_RULE_AUTH_CLASS
);
390 enumerator
->destroy(enumerator
);
394 * Select an auth method to use by checking what key we have
396 static auth_method_t
get_pubkey_method(private_phase1_t
*this, auth_cfg_t
*auth
)
398 auth_method_t method
= AUTH_NONE
;
399 identification_t
*id
;
400 private_key_t
*private;
404 id
= (identification_t
*)auth
->get(auth
, AUTH_RULE_IDENTITY
);
407 private = lib
->credmgr
->get_private(lib
->credmgr
, KEY_ANY
, id
, NULL
);
410 switch (private->get_type(private))
416 switch (private->get_keysize(private))
419 method
= AUTH_ECDSA_256
;
422 method
= AUTH_ECDSA_384
;
425 method
= AUTH_ECDSA_521
;
428 DBG1(DBG_IKE
, "%d bit ECDSA private key size not "
429 "supported", private->get_keysize(private));
434 DBG1(DBG_IKE
, "private key of type %N not supported",
435 key_type_names
, private->get_type(private));
438 private->destroy(private);
442 DBG1(DBG_IKE
, "no private key found for '%Y'", id
);
450 * Calculate authentication method from a peer config
452 static auth_method_t
calc_auth_method(private_phase1_t
*this,
453 peer_cfg_t
*peer_cfg
)
455 auth_class_t i1
, i2
, r1
, r2
;
457 get_auth_class(peer_cfg
, this->initiator
, &i1
, &i2
);
458 get_auth_class(peer_cfg
, !this->initiator
, &r1
, &r2
);
460 if (i1
== AUTH_CLASS_PUBKEY
&& r1
== AUTH_CLASS_PUBKEY
)
462 if (i2
== AUTH_CLASS_ANY
&& r2
== AUTH_CLASS_ANY
)
464 /* for any pubkey method, return RSA */
467 if (i2
== AUTH_CLASS_XAUTH
)
469 return AUTH_XAUTH_INIT_RSA
;
471 if (r2
== AUTH_CLASS_XAUTH
)
473 return AUTH_XAUTH_RESP_RSA
;
476 if (i1
== AUTH_CLASS_PSK
&& r1
== AUTH_CLASS_PSK
)
478 if (i2
== AUTH_CLASS_ANY
&& r2
== AUTH_CLASS_ANY
)
482 if (i2
== AUTH_CLASS_XAUTH
)
484 return AUTH_XAUTH_INIT_PSK
;
486 if (r2
== AUTH_CLASS_XAUTH
)
488 return AUTH_XAUTH_RESP_PSK
;
491 if (i1
== AUTH_CLASS_XAUTH
&& r1
== AUTH_CLASS_PUBKEY
&&
492 i2
== AUTH_CLASS_ANY
&& r2
== AUTH_CLASS_ANY
)
494 return AUTH_HYBRID_INIT_RSA
;
499 METHOD(phase1_t
, get_auth_method
, auth_method_t
,
500 private_phase1_t
*this, peer_cfg_t
*peer_cfg
)
502 auth_method_t method
;
504 method
= calc_auth_method(this, peer_cfg
);
505 if (method
== AUTH_RSA
)
507 return get_pubkey_method(this, get_auth_cfg(peer_cfg
, TRUE
));
513 * Check if a peer config can be used with a given auth method
515 static bool check_auth_method(private_phase1_t
*this, peer_cfg_t
*peer_cfg
,
518 auth_method_t method
;
520 method
= calc_auth_method(this, peer_cfg
);
526 return method
== AUTH_RSA
;
528 return method
== given
;
532 METHOD(phase1_t
, select_config
, peer_cfg_t
*,
533 private_phase1_t
*this, auth_method_t method
, bool aggressive
,
534 identification_t
*id
)
536 enumerator_t
*enumerator
;
542 { /* try to find an alternative config */
543 if (this->candidates
->remove_first(this->candidates
,
544 (void**)¤t
) != SUCCESS
)
546 DBG1(DBG_CFG
, "no alternative config found");
549 DBG1(DBG_CFG
, "switching to peer config '%s'",
550 current
->get_name(current
));
554 me
= this->ike_sa
->get_my_host(this->ike_sa
);
555 other
= this->ike_sa
->get_other_host(this->ike_sa
);
556 DBG1(DBG_CFG
, "looking for %N peer configs matching %H...%H[%Y]",
557 auth_method_names
, method
, me
, other
, id
);
558 enumerator
= charon
->backends
->create_peer_cfg_enumerator(charon
->backends
,
559 me
, other
, NULL
, id
, IKEV1
);
560 while (enumerator
->enumerate(enumerator
, ¤t
))
562 if (check_auth_method(this, current
, method
) &&
563 current
->use_aggressive(current
) == aggressive
)
565 current
->get_ref(current
);
568 this->peer_cfg
= current
;
572 this->candidates
->insert_last(this->candidates
, current
);
580 enumerator
->destroy(enumerator
);
584 DBG1(DBG_CFG
, "selected peer config \"%s\"",
585 this->peer_cfg
->get_name(this->peer_cfg
));
586 return this->peer_cfg
->get_ref(this->peer_cfg
);
590 DBG1(DBG_IKE
, "found %d matching config%s, but none allows %N "
591 "authentication using %s Mode", unusable
, unusable
> 1 ?
"s" : "",
592 auth_method_names
, method
, aggressive ?
"Aggressive" : "Main");
595 DBG1(DBG_IKE
, "no peer config found");
599 METHOD(phase1_t
, get_id
, identification_t
*,
600 private_phase1_t
*this, peer_cfg_t
*peer_cfg
, bool local
)
602 identification_t
*id
= NULL
;
605 auth
= get_auth_cfg(peer_cfg
, local
);
608 id
= auth
->get(auth
, AUTH_RULE_IDENTITY
);
609 if (local
&& (!id
|| id
->get_type(id
) == ID_ANY
))
610 { /* no ID configured, use local IP address */
613 me
= this->ike_sa
->get_my_host(this->ike_sa
);
614 if (!me
->is_anyaddr(me
))
616 id
= identification_create_from_sockaddr(me
->get_sockaddr(me
));
617 auth
->add(auth
, AUTH_RULE_IDENTITY
, id
);
624 METHOD(phase1_t
, has_virtual_ip
, bool,
625 private_phase1_t
*this, peer_cfg_t
*peer_cfg
)
627 enumerator_t
*enumerator
;
631 enumerator
= peer_cfg
->create_virtual_ip_enumerator(peer_cfg
);
632 found
= enumerator
->enumerate(enumerator
, &host
);
633 enumerator
->destroy(enumerator
);
638 METHOD(phase1_t
, has_pool
, bool,
639 private_phase1_t
*this, peer_cfg_t
*peer_cfg
)
641 enumerator_t
*enumerator
;
645 enumerator
= peer_cfg
->create_pool_enumerator(peer_cfg
);
646 found
= enumerator
->enumerate(enumerator
, &pool
);
647 enumerator
->destroy(enumerator
);
652 METHOD(phase1_t
, save_sa_payload
, bool,
653 private_phase1_t
*this, message_t
*message
)
655 enumerator_t
*enumerator
;
656 payload_t
*payload
, *sa
= NULL
;
658 size_t offset
= IKE_HEADER_LENGTH
;
660 enumerator
= message
->create_payload_enumerator(message
);
661 while (enumerator
->enumerate(enumerator
, &payload
))
663 if (payload
->get_type(payload
) == PLV1_SECURITY_ASSOCIATION
)
670 offset
+= payload
->get_length(payload
);
673 enumerator
->destroy(enumerator
);
675 data
= message
->get_packet_data(message
);
676 if (sa
&& data
.len
>= offset
+ sa
->get_length(sa
))
678 /* Get SA payload without 4 byte fixed header */
679 data
= chunk_skip(data
, offset
);
680 data
.len
= sa
->get_length(sa
);
681 data
= chunk_skip(data
, 4);
682 this->sa_payload
= chunk_clone(data
);
685 DBG1(DBG_IKE
, "unable to extract SA payload encoding");
689 METHOD(phase1_t
, add_nonce_ke
, bool,
690 private_phase1_t
*this, message_t
*message
)
692 nonce_payload_t
*nonce_payload
;
693 ke_payload_t
*ke_payload
;
697 ke_payload
= ke_payload_create_from_diffie_hellman(PLV1_KEY_EXCHANGE
, this->dh
);
698 message
->add_payload(message
, &ke_payload
->payload_interface
);
700 nonceg
= this->keymat
->keymat
.create_nonce_gen(&this->keymat
->keymat
);
703 DBG1(DBG_IKE
, "no nonce generator found to create nonce");
706 if (!nonceg
->allocate_nonce(nonceg
, NONCE_SIZE
, &nonce
))
708 DBG1(DBG_IKE
, "nonce allocation failed");
709 nonceg
->destroy(nonceg
);
712 nonceg
->destroy(nonceg
);
714 nonce_payload
= nonce_payload_create(PLV1_NONCE
);
715 nonce_payload
->set_nonce(nonce_payload
, nonce
);
716 message
->add_payload(message
, &nonce_payload
->payload_interface
);
720 this->nonce_i
= nonce
;
724 this->nonce_r
= nonce
;
729 METHOD(phase1_t
, get_nonce_ke
, bool,
730 private_phase1_t
*this, message_t
*message
)
732 nonce_payload_t
*nonce_payload
;
733 ke_payload_t
*ke_payload
;
735 ke_payload
= (ke_payload_t
*)message
->get_payload(message
, PLV1_KEY_EXCHANGE
);
738 DBG1(DBG_IKE
, "KE payload missing in message");
741 this->dh_value
= chunk_clone(ke_payload
->get_key_exchange_data(ke_payload
));
742 this->dh
->set_other_public_value(this->dh
, this->dh_value
);
744 nonce_payload
= (nonce_payload_t
*)message
->get_payload(message
, PLV1_NONCE
);
747 DBG1(DBG_IKE
, "NONCE payload missing in message");
753 this->nonce_r
= nonce_payload
->get_nonce(nonce_payload
);
757 this->nonce_i
= nonce_payload
->get_nonce(nonce_payload
);
762 METHOD(phase1_t
, destroy
, void,
763 private_phase1_t
*this)
765 DESTROY_IF(this->peer_cfg
);
766 this->candidates
->destroy_offset(this->candidates
,
767 offsetof(peer_cfg_t
, destroy
));
768 chunk_free(&this->sa_payload
);
769 DESTROY_IF(this->dh
);
770 free(this->dh_value
.ptr
);
771 free(this->nonce_i
.ptr
);
772 free(this->nonce_r
.ptr
);
779 phase1_t
*phase1_create(ike_sa_t
*ike_sa
, bool initiator
)
781 private_phase1_t
*this;
785 .create_hasher
= _create_hasher
,
786 .create_dh
= _create_dh
,
787 .derive_keys
= _derive_keys
,
788 .get_auth_method
= _get_auth_method
,
790 .select_config
= _select_config
,
791 .has_virtual_ip
= _has_virtual_ip
,
792 .has_pool
= _has_pool
,
793 .verify_auth
= _verify_auth
,
794 .build_auth
= _build_auth
,
795 .save_sa_payload
= _save_sa_payload
,
796 .add_nonce_ke
= _add_nonce_ke
,
797 .get_nonce_ke
= _get_nonce_ke
,
800 .candidates
= linked_list_create(),
802 .initiator
= initiator
,
803 .keymat
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
),
806 return &this->public;