fee304e6f5ad716e799f3a5d878ab6648809aec9
[strongswan.git] / src / libcharon / sa / ikev1 / phase1.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2012 Martin Willi
6 * Copyright (C) 2012 revosec AG
7 *
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>.
12 *
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
16 * for more details.
17 */
18
19 #include "phase1.h"
20
21 #include <daemon.h>
22 #include <sa/ikev1/keymat_v1.h>
23 #include <encoding/payloads/ke_payload.h>
24 #include <encoding/payloads/nonce_payload.h>
25 #include <utils/linked_list.h>
26
27 typedef struct private_phase1_t private_phase1_t;
28
29 /**
30 * Private data of an phase1_t object.
31 */
32 struct private_phase1_t {
33
34 /**
35 * Public phase1_t interface.
36 */
37 phase1_t public;
38
39 /**
40 * IKE_SA we negotiate
41 */
42 ike_sa_t *ike_sa;
43
44 /**
45 * Currently selected peer config
46 */
47 peer_cfg_t *peer_cfg;
48
49 /**
50 * Other possible peer config candidates
51 */
52 linked_list_t *candidates;
53
54 /**
55 * Acting as initiator
56 */
57 bool initiator;
58
59 /**
60 * Extracted SA payload bytes
61 */
62 chunk_t sa_payload;
63
64 /**
65 * DH exchange
66 */
67 diffie_hellman_t *dh;
68
69 /**
70 * Keymat derivation (from SA)
71 */
72 keymat_v1_t *keymat;
73
74 /**
75 * Received public DH value from peer
76 */
77 chunk_t dh_value;
78
79 /**
80 * Initiators nonce
81 */
82 chunk_t nonce_i;
83
84 /**
85 * Responder nonce
86 */
87 chunk_t nonce_r;
88 };
89
90 /**
91 * Get the first authentcation config from peer config
92 */
93 static auth_cfg_t *get_auth_cfg(peer_cfg_t *peer_cfg, bool local)
94 {
95 enumerator_t *enumerator;
96 auth_cfg_t *cfg = NULL;
97
98 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
99 enumerator->enumerate(enumerator, &cfg);
100 enumerator->destroy(enumerator);
101 return cfg;
102 }
103
104 /**
105 * Lookup a shared secret for this IKE_SA
106 */
107 static shared_key_t *lookup_shared_key(private_phase1_t *this,
108 peer_cfg_t *peer_cfg)
109 {
110 host_t *me, *other;
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;
115
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)
122 {
123 shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
124 my_id, other_id);
125 }
126 DESTROY_IF(my_id);
127 DESTROY_IF(other_id);
128 if (shared_key)
129 {
130 return shared_key;
131 }
132
133 if (peer_cfg)
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)
138 {
139 my_id = my_auth->get(my_auth, AUTH_RULE_IDENTITY);
140 if (peer_cfg->use_aggressive(peer_cfg))
141 {
142 other_id = this->ike_sa->get_other_id(this->ike_sa);
143 }
144 else
145 {
146 other_id = other_auth->get(other_auth, AUTH_RULE_IDENTITY);
147 }
148 if (my_id && other_id)
149 {
150 shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
151 my_id, other_id);
152 if (!shared_key)
153 {
154 DBG1(DBG_IKE, "no shared key found for '%Y'[%H] - '%Y'[%H]",
155 my_id, me, other_id, other);
156 }
157 }
158 }
159 return shared_key;
160 }
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))
165 {
166 my_auth = get_auth_cfg(peer_cfg, TRUE);
167 other_auth = get_auth_cfg(peer_cfg, FALSE);
168 if (my_auth && other_auth)
169 {
170 my_id = my_auth->get(my_auth, AUTH_RULE_IDENTITY);
171 other_id = other_auth->get(other_auth, AUTH_RULE_IDENTITY);
172 if (my_id)
173 {
174 shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
175 my_id, other_id);
176 if (shared_key)
177 {
178 break;
179 }
180 else
181 {
182 DBG1(DBG_IKE, "no shared key found for '%Y'[%H] - '%Y'[%H]",
183 my_id, me, other_id, other);
184 }
185 }
186 }
187 }
188 enumerator->destroy(enumerator);
189 if (!peer_cfg)
190 {
191 DBG1(DBG_IKE, "no shared key found for %H - %H", me, other);
192 }
193 return shared_key;
194 }
195
196 METHOD(phase1_t, create_hasher, bool,
197 private_phase1_t *this)
198 {
199 return this->keymat->create_hasher(this->keymat,
200 this->ike_sa->get_proposal(this->ike_sa));
201 }
202
203 METHOD(phase1_t, create_dh, bool,
204 private_phase1_t *this, diffie_hellman_group_t group)
205 {
206 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat, group);
207 return this->dh != NULL;
208 }
209
210 METHOD(phase1_t, derive_keys, bool,
211 private_phase1_t *this, peer_cfg_t *peer_cfg, auth_method_t method)
212 {
213 shared_key_t *shared_key = NULL;
214
215 switch (method)
216 {
217 case AUTH_PSK:
218 case AUTH_XAUTH_INIT_PSK:
219 case AUTH_XAUTH_RESP_PSK:
220 shared_key = lookup_shared_key(this, peer_cfg);
221 if (!shared_key)
222 {
223 return FALSE;
224 }
225 break;
226 default:
227 break;
228 }
229
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))
234 {
235 DESTROY_IF(shared_key);
236 DBG1(DBG_IKE, "key derivation for %N failed", auth_method_names, method);
237 return FALSE;
238 }
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);
242 return TRUE;
243 }
244
245 /**
246 * Check if a peer skipped authentication by using Hybrid authentication
247 */
248 static bool skipped_auth(private_phase1_t *this,
249 auth_method_t method, bool local)
250 {
251 bool initiator;
252
253 initiator = local == this->initiator;
254 if (initiator && method == AUTH_HYBRID_INIT_RSA)
255 {
256 return TRUE;
257 }
258 if (!initiator && method == AUTH_HYBRID_RESP_RSA)
259 {
260 return TRUE;
261 }
262 return FALSE;
263 }
264
265 /**
266 * Check if remote authentication constraints fulfilled
267 */
268 static bool check_constraints(private_phase1_t *this, auth_method_t method)
269 {
270 identification_t *id;
271 auth_cfg_t *auth, *cfg;
272 peer_cfg_t *peer_cfg;
273
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))
279 {
280 return TRUE;
281 }
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);
285 }
286
287 /**
288 * Save authentication information after authentication succeeded
289 */
290 static void save_auth_cfg(private_phase1_t *this,
291 auth_method_t method, bool local)
292 {
293 auth_cfg_t *auth;
294
295 if (skipped_auth(this, method, local))
296 {
297 return;
298 }
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);
304 }
305
306 /**
307 * Create an authenticator instance
308 */
309 static authenticator_t* create_authenticator(private_phase1_t *this,
310 auth_method_t method, chunk_t id)
311 {
312 authenticator_t *authenticator;
313
314 authenticator = authenticator_create_v1(this->ike_sa, this->initiator,
315 method, this->dh, this->dh_value, this->sa_payload, id);
316 if (!authenticator)
317 {
318 DBG1(DBG_IKE, "negotiated authentication method %N not supported",
319 auth_method_names, method);
320 }
321 return authenticator;
322 }
323
324 METHOD(phase1_t, verify_auth, bool,
325 private_phase1_t *this, auth_method_t method, message_t *message,
326 chunk_t id_data)
327 {
328 authenticator_t *authenticator;
329 status_t status;
330
331 authenticator = create_authenticator(this, method, id_data);
332 if (authenticator)
333 {
334 status = authenticator->process(authenticator, message);
335 authenticator->destroy(authenticator);
336 if (status == SUCCESS && check_constraints(this, method))
337 {
338 save_auth_cfg(this, method, FALSE);
339 return TRUE;
340 }
341 }
342 return FALSE;
343 }
344
345 METHOD(phase1_t, build_auth, bool,
346 private_phase1_t *this, auth_method_t method, message_t *message,
347 chunk_t id_data)
348 {
349 authenticator_t *authenticator;
350 status_t status;
351
352 authenticator = create_authenticator(this, method, id_data);
353 if (authenticator)
354 {
355 status = authenticator->build(authenticator, message);
356 authenticator->destroy(authenticator);
357 if (status == SUCCESS)
358 {
359 save_auth_cfg(this, method, TRUE);
360 return TRUE;
361 }
362 }
363 return FALSE;
364 }
365
366 /**
367 * Get the two auth classes from local or remote config
368 */
369 static void get_auth_class(peer_cfg_t *peer_cfg, bool local,
370 auth_class_t *c1, auth_class_t *c2)
371 {
372 enumerator_t *enumerator;
373 auth_cfg_t *auth;
374
375 *c1 = *c2 = AUTH_CLASS_ANY;
376
377 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
378 while (enumerator->enumerate(enumerator, &auth))
379 {
380 if (*c1 == AUTH_CLASS_ANY)
381 {
382 *c1 = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
383 }
384 else
385 {
386 *c2 = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
387 break;
388 }
389 }
390 enumerator->destroy(enumerator);
391 }
392
393 /**
394 * Select an auth method to use by checking what key we have
395 */
396 static auth_method_t get_pubkey_method(private_phase1_t *this, auth_cfg_t *auth)
397 {
398 auth_method_t method = AUTH_NONE;
399 identification_t *id;
400 private_key_t *private;
401
402 if (auth)
403 {
404 id = (identification_t*)auth->get(auth, AUTH_RULE_IDENTITY);
405 if (id)
406 {
407 private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, id, NULL);
408 if (private)
409 {
410 switch (private->get_type(private))
411 {
412 case KEY_RSA:
413 method = AUTH_RSA;
414 break;
415 case KEY_ECDSA:
416 switch (private->get_keysize(private))
417 {
418 case 256:
419 method = AUTH_ECDSA_256;
420 break;
421 case 384:
422 method = AUTH_ECDSA_384;
423 break;
424 case 521:
425 method = AUTH_ECDSA_521;
426 break;
427 default:
428 DBG1(DBG_IKE, "%d bit ECDSA private key size not "
429 "supported", private->get_keysize(private));
430 break;
431 }
432 break;
433 default:
434 DBG1(DBG_IKE, "private key of type %N not supported",
435 key_type_names, private->get_type(private));
436 break;
437 }
438 private->destroy(private);
439 }
440 else
441 {
442 DBG1(DBG_IKE, "no private key found for '%Y'", id);
443 }
444 }
445 }
446 return method;
447 }
448
449 /**
450 * Calculate authentication method from a peer config
451 */
452 static auth_method_t calc_auth_method(private_phase1_t *this,
453 peer_cfg_t *peer_cfg)
454 {
455 auth_class_t i1, i2, r1, r2;
456
457 get_auth_class(peer_cfg, this->initiator, &i1, &i2);
458 get_auth_class(peer_cfg, !this->initiator, &r1, &r2);
459
460 if (i1 == AUTH_CLASS_PUBKEY && r1 == AUTH_CLASS_PUBKEY)
461 {
462 if (i2 == AUTH_CLASS_ANY && r2 == AUTH_CLASS_ANY)
463 {
464 /* for any pubkey method, return RSA */
465 return AUTH_RSA;
466 }
467 if (i2 == AUTH_CLASS_XAUTH)
468 {
469 return AUTH_XAUTH_INIT_RSA;
470 }
471 if (r2 == AUTH_CLASS_XAUTH)
472 {
473 return AUTH_XAUTH_RESP_RSA;
474 }
475 }
476 if (i1 == AUTH_CLASS_PSK && r1 == AUTH_CLASS_PSK)
477 {
478 if (i2 == AUTH_CLASS_ANY && r2 == AUTH_CLASS_ANY)
479 {
480 return AUTH_PSK;
481 }
482 if (i2 == AUTH_CLASS_XAUTH)
483 {
484 return AUTH_XAUTH_INIT_PSK;
485 }
486 if (r2 == AUTH_CLASS_XAUTH)
487 {
488 return AUTH_XAUTH_RESP_PSK;
489 }
490 }
491 if (i1 == AUTH_CLASS_XAUTH && r1 == AUTH_CLASS_PUBKEY &&
492 i2 == AUTH_CLASS_ANY && r2 == AUTH_CLASS_ANY)
493 {
494 return AUTH_HYBRID_INIT_RSA;
495 }
496 return AUTH_NONE;
497 }
498
499 METHOD(phase1_t, get_auth_method, auth_method_t,
500 private_phase1_t *this, peer_cfg_t *peer_cfg)
501 {
502 auth_method_t method;
503
504 method = calc_auth_method(this, peer_cfg);
505 if (method == AUTH_RSA)
506 {
507 return get_pubkey_method(this, get_auth_cfg(peer_cfg, TRUE));
508 }
509 return method;
510 }
511
512 /**
513 * Check if a peer config can be used with a given auth method
514 */
515 static bool check_auth_method(private_phase1_t *this, peer_cfg_t *peer_cfg,
516 auth_method_t given)
517 {
518 auth_method_t method;
519
520 method = calc_auth_method(this, peer_cfg);
521 switch (given)
522 {
523 case AUTH_ECDSA_256:
524 case AUTH_ECDSA_384:
525 case AUTH_ECDSA_521:
526 return method == AUTH_RSA;
527 default:
528 return method == given;
529 }
530 }
531
532 METHOD(phase1_t, select_config, peer_cfg_t*,
533 private_phase1_t *this, auth_method_t method, bool aggressive,
534 identification_t *id)
535 {
536 enumerator_t *enumerator;
537 peer_cfg_t *current;
538 host_t *me, *other;
539
540 if (this->peer_cfg)
541 { /* try to find an alternative config */
542 if (this->candidates->remove_first(this->candidates,
543 (void**)&current) != SUCCESS)
544 {
545 DBG1(DBG_CFG, "no alternative config found");
546 return NULL;
547 }
548 DBG1(DBG_CFG, "switching to peer config '%s'",
549 current->get_name(current));
550 return current;
551 }
552
553 me = this->ike_sa->get_my_host(this->ike_sa);
554 other = this->ike_sa->get_other_host(this->ike_sa);
555 DBG1(DBG_CFG, "looking for %N peer configs matching %H...%H[%Y]",
556 auth_method_names, method, me, other, id);
557 enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
558 me, other, NULL, id, IKEV1);
559 while (enumerator->enumerate(enumerator, &current))
560 {
561 if (check_auth_method(this, current, method) &&
562 current->use_aggressive(current) == aggressive)
563 {
564 current->get_ref(current);
565 if (!this->peer_cfg)
566 {
567 this->peer_cfg = current;
568 }
569 else
570 {
571 this->candidates->insert_last(this->candidates, current);
572 }
573 }
574 }
575 enumerator->destroy(enumerator);
576
577 if (this->peer_cfg)
578 {
579 DBG1(DBG_CFG, "selected peer config \"%s\"",
580 this->peer_cfg->get_name(this->peer_cfg));
581 return this->peer_cfg->get_ref(this->peer_cfg);
582 }
583 DBG1(DBG_IKE, "no peer config found");
584 return NULL;
585 }
586
587 METHOD(phase1_t, get_id, identification_t*,
588 private_phase1_t *this, peer_cfg_t *peer_cfg, bool local)
589 {
590 auth_cfg_t *auth;
591
592 auth = get_auth_cfg(peer_cfg, local);
593 if (auth)
594 {
595 return auth->get(auth, AUTH_RULE_IDENTITY);
596 }
597 return NULL;
598 }
599
600 METHOD(phase1_t, save_sa_payload, bool,
601 private_phase1_t *this, message_t *message)
602 {
603 enumerator_t *enumerator;
604 payload_t *payload, *sa = NULL;
605 chunk_t data;
606 size_t offset = IKE_HEADER_LENGTH;
607
608 enumerator = message->create_payload_enumerator(message);
609 while (enumerator->enumerate(enumerator, &payload))
610 {
611 if (payload->get_type(payload) == SECURITY_ASSOCIATION_V1)
612 {
613 sa = payload;
614 break;
615 }
616 else
617 {
618 offset += payload->get_length(payload);
619 }
620 }
621 enumerator->destroy(enumerator);
622
623 data = message->get_packet_data(message);
624 if (sa && data.len >= offset + sa->get_length(sa))
625 {
626 /* Get SA payload without 4 byte fixed header */
627 data = chunk_skip(data, offset);
628 data.len = sa->get_length(sa);
629 data = chunk_skip(data, 4);
630 this->sa_payload = chunk_clone(data);
631 return TRUE;
632 }
633 DBG1(DBG_IKE, "unable to extract SA payload encoding");
634 return FALSE;
635 }
636
637 METHOD(phase1_t, add_nonce_ke, bool,
638 private_phase1_t *this, message_t *message)
639 {
640 nonce_payload_t *nonce_payload;
641 ke_payload_t *ke_payload;
642 nonce_gen_t *nonceg;
643 chunk_t nonce;
644
645 ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE_V1, this->dh);
646 message->add_payload(message, &ke_payload->payload_interface);
647
648 nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
649 if (!nonceg)
650 {
651 DBG1(DBG_IKE, "no nonce generator found to create nonce");
652 return FALSE;
653 }
654 if (!nonceg->allocate_nonce(nonceg, NONCE_SIZE, &nonce))
655 {
656 DBG1(DBG_IKE, "nonce allocation failed");
657 nonceg->destroy(nonceg);
658 return FALSE;
659 }
660 nonceg->destroy(nonceg);
661
662 nonce_payload = nonce_payload_create(NONCE_V1);
663 nonce_payload->set_nonce(nonce_payload, nonce);
664 message->add_payload(message, &nonce_payload->payload_interface);
665
666 if (this->initiator)
667 {
668 this->nonce_i = nonce;
669 }
670 else
671 {
672 this->nonce_r = nonce;
673 }
674 return TRUE;
675 }
676
677 METHOD(phase1_t, get_nonce_ke, bool,
678 private_phase1_t *this, message_t *message)
679 {
680 nonce_payload_t *nonce_payload;
681 ke_payload_t *ke_payload;
682
683 ke_payload = (ke_payload_t*)message->get_payload(message, KEY_EXCHANGE_V1);
684 if (!ke_payload)
685 {
686 DBG1(DBG_IKE, "KE payload missing in message");
687 return FALSE;
688 }
689 this->dh_value = chunk_clone(ke_payload->get_key_exchange_data(ke_payload));
690 this->dh->set_other_public_value(this->dh, this->dh_value);
691
692 nonce_payload = (nonce_payload_t*)message->get_payload(message, NONCE_V1);
693 if (!nonce_payload)
694 {
695 DBG1(DBG_IKE, "NONCE payload missing in message");
696 return FALSE;
697 }
698
699 if (this->initiator)
700 {
701 this->nonce_r = nonce_payload->get_nonce(nonce_payload);
702 }
703 else
704 {
705 this->nonce_i = nonce_payload->get_nonce(nonce_payload);
706 }
707 return TRUE;
708 }
709
710 METHOD(phase1_t, destroy, void,
711 private_phase1_t *this)
712 {
713 DESTROY_IF(this->peer_cfg);
714 this->candidates->destroy_offset(this->candidates,
715 offsetof(peer_cfg_t, destroy));
716 chunk_free(&this->sa_payload);
717 DESTROY_IF(this->dh);
718 free(this->dh_value.ptr);
719 free(this->nonce_i.ptr);
720 free(this->nonce_r.ptr);
721 free(this);
722 }
723
724 /**
725 * See header
726 */
727 phase1_t *phase1_create(ike_sa_t *ike_sa, bool initiator)
728 {
729 private_phase1_t *this;
730
731 INIT(this,
732 .public = {
733 .create_hasher = _create_hasher,
734 .create_dh = _create_dh,
735 .derive_keys = _derive_keys,
736 .get_auth_method = _get_auth_method,
737 .get_id = _get_id,
738 .select_config = _select_config,
739 .verify_auth = _verify_auth,
740 .build_auth = _build_auth,
741 .save_sa_payload = _save_sa_payload,
742 .add_nonce_ke = _add_nonce_ke,
743 .get_nonce_ke = _get_nonce_ke,
744 .destroy = _destroy,
745 },
746 .candidates = linked_list_create(),
747 .ike_sa = ike_sa,
748 .initiator = initiator,
749 .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
750 );
751
752 return &this->public;
753 }