Select IKEv1 configurations by main/aggressive mode option
[strongswan.git] / src / libcharon / sa / ikev1 / phase1.c
1 /*
2 * Copyright (C) 2012 Martin Willi
3 * Copyright (C) 2012 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "phase1.h"
17
18 #include <daemon.h>
19 #include <sa/ikev1/keymat_v1.h>
20 #include <encoding/payloads/ke_payload.h>
21 #include <encoding/payloads/nonce_payload.h>
22
23 typedef struct private_phase1_t private_phase1_t;
24
25 /**
26 * Private data of an phase1_t object.
27 */
28 struct private_phase1_t {
29
30 /**
31 * Public phase1_t interface.
32 */
33 phase1_t public;
34
35 /**
36 * IKE_SA we negotiate
37 */
38 ike_sa_t *ike_sa;
39
40 /**
41 * Acting as initiator
42 */
43 bool initiator;
44
45 /**
46 * Extracted SA payload bytes
47 */
48 chunk_t sa_payload;
49
50 /**
51 * DH exchange
52 */
53 diffie_hellman_t *dh;
54
55 /**
56 * Keymat derivation (from SA)
57 */
58 keymat_v1_t *keymat;
59
60 /**
61 * Received public DH value from peer
62 */
63 chunk_t dh_value;
64
65 /**
66 * Initiators nonce
67 */
68 chunk_t nonce_i;
69
70 /**
71 * Responder nonce
72 */
73 chunk_t nonce_r;
74 };
75
76 /**
77 * Get the first authentcation config from peer config
78 */
79 static auth_cfg_t *get_auth_cfg(peer_cfg_t *peer_cfg, bool local)
80 {
81 enumerator_t *enumerator;
82 auth_cfg_t *cfg = NULL;
83
84 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
85 enumerator->enumerate(enumerator, &cfg);
86 enumerator->destroy(enumerator);
87 return cfg;
88 }
89
90 /**
91 * Lookup a shared secret for this IKE_SA
92 */
93 static shared_key_t *lookup_shared_key(private_phase1_t *this,
94 peer_cfg_t *peer_cfg)
95 {
96 host_t *me, *other;
97 identification_t *my_id, *other_id;
98 shared_key_t *shared_key = NULL;
99 auth_cfg_t *my_auth, *other_auth;
100 enumerator_t *enumerator;
101
102 /* try to get a PSK for IP addresses */
103 me = this->ike_sa->get_my_host(this->ike_sa);
104 other = this->ike_sa->get_other_host(this->ike_sa);
105 my_id = identification_create_from_sockaddr(me->get_sockaddr(me));
106 other_id = identification_create_from_sockaddr(other->get_sockaddr(other));
107 if (my_id && other_id)
108 {
109 shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
110 my_id, other_id);
111 }
112 DESTROY_IF(my_id);
113 DESTROY_IF(other_id);
114 if (shared_key)
115 {
116 return shared_key;
117 }
118
119 if (peer_cfg)
120 { /* as initiator, use identities from configuraiton */
121 my_auth = get_auth_cfg(peer_cfg, TRUE);
122 other_auth = get_auth_cfg(peer_cfg, FALSE);
123 if (my_auth && other_auth)
124 {
125 my_id = my_auth->get(my_auth, AUTH_RULE_IDENTITY);
126 other_id = other_auth->get(other_auth, AUTH_RULE_IDENTITY);
127 if (my_id && other_id)
128 {
129 shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
130 my_id, other_id);
131 if (!shared_key)
132 {
133 DBG1(DBG_IKE, "no shared key found for '%Y'[%H] - '%Y'[%H]",
134 my_id, me, other_id, other);
135 }
136 }
137 }
138 return shared_key;
139 }
140 /* as responder, we try to find a config by IP */
141 enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
142 me, other, NULL, NULL, IKEV1);
143 while (enumerator->enumerate(enumerator, &peer_cfg))
144 {
145 my_auth = get_auth_cfg(peer_cfg, TRUE);
146 other_auth = get_auth_cfg(peer_cfg, FALSE);
147 if (my_auth && other_auth)
148 {
149 my_id = my_auth->get(my_auth, AUTH_RULE_IDENTITY);
150 other_id = other_auth->get(other_auth, AUTH_RULE_IDENTITY);
151 if (my_id && other_id)
152 {
153 shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
154 my_id, other_id);
155 if (shared_key)
156 {
157 break;
158 }
159 else
160 {
161 DBG1(DBG_IKE, "no shared key found for '%Y'[%H] - '%Y'[%H]",
162 my_id, me, other_id, other);
163 }
164 }
165 }
166 }
167 enumerator->destroy(enumerator);
168 if (!peer_cfg)
169 {
170 DBG1(DBG_IKE, "no shared key found for %H - %H", me, other);
171 }
172 return shared_key;
173 }
174
175 METHOD(phase1_t, create_hasher, bool,
176 private_phase1_t *this, proposal_t *proposal)
177 {
178 return this->keymat->create_hasher(this->keymat, proposal);
179 }
180
181 METHOD(phase1_t, create_dh, bool,
182 private_phase1_t *this, diffie_hellman_group_t group)
183 {
184 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat, group);
185 return this->dh != NULL;
186 }
187
188 METHOD(phase1_t, derive_keys, bool,
189 private_phase1_t *this, peer_cfg_t *peer_cfg, auth_method_t method,
190 proposal_t *proposal)
191 {
192 shared_key_t *shared_key = NULL;
193
194 switch (method)
195 {
196 case AUTH_PSK:
197 case AUTH_XAUTH_INIT_PSK:
198 case AUTH_XAUTH_RESP_PSK:
199 shared_key = lookup_shared_key(this, peer_cfg);
200 if (!shared_key)
201 {
202 return FALSE;
203 }
204 break;
205 default:
206 break;
207 }
208
209 if (!this->keymat->derive_ike_keys(this->keymat, proposal,
210 this->dh, this->dh_value, this->nonce_i, this->nonce_r,
211 this->ike_sa->get_id(this->ike_sa), method, shared_key))
212 {
213 DESTROY_IF(shared_key);
214 DBG1(DBG_IKE, "key derivation for %N failed", auth_method_names, method);
215 return FALSE;
216 }
217 DESTROY_IF(shared_key);
218 charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh,
219 this->nonce_i, this->nonce_r, NULL);
220 return TRUE;
221 }
222
223 /**
224 * Check if a peer skipped authentication by using Hybrid authentication
225 */
226 static bool skipped_auth(private_phase1_t *this,
227 auth_method_t method, bool local)
228 {
229 bool initiator;
230
231 initiator = local == this->initiator;
232 if (initiator && method == AUTH_HYBRID_INIT_RSA)
233 {
234 return TRUE;
235 }
236 if (!initiator && method == AUTH_HYBRID_RESP_RSA)
237 {
238 return TRUE;
239 }
240 return FALSE;
241 }
242
243 /**
244 * Check if remote authentication constraints fulfilled
245 */
246 static bool check_constraints(private_phase1_t *this, auth_method_t method)
247 {
248 identification_t *id;
249 auth_cfg_t *auth, *cfg;
250 peer_cfg_t *peer_cfg;
251
252 auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
253 /* auth identity to comply */
254 id = this->ike_sa->get_other_id(this->ike_sa);
255 auth->add(auth, AUTH_RULE_IDENTITY, id->clone(id));
256 if (skipped_auth(this, method, FALSE))
257 {
258 return TRUE;
259 }
260 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
261 cfg = get_auth_cfg(peer_cfg, FALSE);
262 return cfg && auth->complies(auth, cfg, TRUE);
263 }
264
265 /**
266 * Save authentication information after authentication succeeded
267 */
268 static void save_auth_cfg(private_phase1_t *this,
269 auth_method_t method, bool local)
270 {
271 auth_cfg_t *auth;
272
273 if (skipped_auth(this, method, local))
274 {
275 return;
276 }
277 auth = auth_cfg_create();
278 /* for local config, we _copy_ entires from the config, as it contains
279 * certificates we must send later. */
280 auth->merge(auth, this->ike_sa->get_auth_cfg(this->ike_sa, local), local);
281 this->ike_sa->add_auth_cfg(this->ike_sa, local, auth);
282 }
283
284 /**
285 * Create an authenticator instance
286 */
287 static authenticator_t* create_authenticator(private_phase1_t *this,
288 auth_method_t method, chunk_t id)
289 {
290 authenticator_t *authenticator;
291
292 authenticator = authenticator_create_v1(this->ike_sa, this->initiator,
293 method, this->dh, this->dh_value, this->sa_payload, id);
294 if (!authenticator)
295 {
296 DBG1(DBG_IKE, "negotiated authentication method %N not supported",
297 auth_method_names, method);
298 }
299 return authenticator;
300 }
301
302 METHOD(phase1_t, verify_auth, bool,
303 private_phase1_t *this, auth_method_t method, message_t *message,
304 chunk_t id_data)
305 {
306 authenticator_t *authenticator;
307 status_t status;
308
309 authenticator = create_authenticator(this, method, id_data);
310 if (authenticator)
311 {
312 status = authenticator->process(authenticator, message);
313 authenticator->destroy(authenticator);
314 if (status == SUCCESS && check_constraints(this, method))
315 {
316 save_auth_cfg(this, method, FALSE);
317 return TRUE;
318 }
319 }
320 return FALSE;
321 }
322
323 METHOD(phase1_t, build_auth, bool,
324 private_phase1_t *this, auth_method_t method, message_t *message,
325 chunk_t id_data)
326 {
327 authenticator_t *authenticator;
328 status_t status;
329
330 authenticator = create_authenticator(this, method, id_data);
331 if (authenticator)
332 {
333 status = authenticator->build(authenticator, message);
334 authenticator->destroy(authenticator);
335 if (status == SUCCESS)
336 {
337 save_auth_cfg(this, method, TRUE);
338 return TRUE;
339 }
340 }
341 return FALSE;
342 }
343
344 /**
345 * Get the two auth classes from local or remote config
346 */
347 static void get_auth_class(peer_cfg_t *peer_cfg, bool local,
348 auth_class_t *c1, auth_class_t *c2)
349 {
350 enumerator_t *enumerator;
351 auth_cfg_t *auth;
352
353 *c1 = *c2 = AUTH_CLASS_ANY;
354
355 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
356 while (enumerator->enumerate(enumerator, &auth))
357 {
358 if (*c1 == AUTH_CLASS_ANY)
359 {
360 *c1 = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
361 }
362 else
363 {
364 *c2 = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
365 break;
366 }
367 }
368 enumerator->destroy(enumerator);
369 }
370
371 METHOD(phase1_t, get_auth_method, auth_method_t,
372 private_phase1_t *this, peer_cfg_t *peer_cfg)
373 {
374 auth_class_t i1, i2, r1, r2;
375
376 get_auth_class(peer_cfg, this->initiator, &i1, &i2);
377 get_auth_class(peer_cfg, !this->initiator, &r1, &r2);
378
379 if (i1 == AUTH_CLASS_PUBKEY && r1 == AUTH_CLASS_PUBKEY)
380 {
381 if (i2 == AUTH_CLASS_ANY && r2 == AUTH_CLASS_ANY)
382 {
383 /* TODO-IKEv1: ECDSA? */
384 return AUTH_RSA;
385 }
386 if (i2 == AUTH_CLASS_XAUTH)
387 {
388 return AUTH_XAUTH_INIT_RSA;
389 }
390 if (r2 == AUTH_CLASS_XAUTH)
391 {
392 return AUTH_XAUTH_RESP_RSA;
393 }
394 }
395 if (i1 == AUTH_CLASS_PSK && r1 == AUTH_CLASS_PSK)
396 {
397 if (i2 == AUTH_CLASS_ANY && r2 == AUTH_CLASS_ANY)
398 {
399 return AUTH_PSK;
400 }
401 if (i2 == AUTH_CLASS_XAUTH)
402 {
403 return AUTH_XAUTH_INIT_PSK;
404 }
405 if (r2 == AUTH_CLASS_XAUTH)
406 {
407 return AUTH_XAUTH_RESP_PSK;
408 }
409 }
410 if (i1 == AUTH_CLASS_XAUTH && r1 == AUTH_CLASS_PUBKEY &&
411 i2 == AUTH_CLASS_ANY && r2 == AUTH_CLASS_ANY)
412 {
413 return AUTH_HYBRID_INIT_RSA;
414 }
415 return AUTH_NONE;
416 }
417
418 METHOD(phase1_t, select_config, peer_cfg_t*,
419 private_phase1_t *this, auth_method_t method, bool aggressive,
420 identification_t *id)
421 {
422 enumerator_t *enumerator;
423 peer_cfg_t *current, *found = NULL;
424 host_t *me, *other;
425
426 me = this->ike_sa->get_my_host(this->ike_sa);
427 other = this->ike_sa->get_other_host(this->ike_sa);
428 DBG1(DBG_CFG, "looking for %N peer configs matching %H...%H[%Y]",
429 auth_method_names, method, me, other, id);
430 enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
431 me, other, NULL, id, IKEV1);
432 while (enumerator->enumerate(enumerator, &current))
433 {
434 if (get_auth_method(this, current) == method &&
435 current->use_aggressive(current) == aggressive)
436 {
437 found = current->get_ref(current);
438 break;
439 }
440 }
441 enumerator->destroy(enumerator);
442
443 if (found)
444 {
445 DBG2(DBG_CFG, "selected peer config \"%s\"", found->get_name(found));
446 }
447 return found;
448 }
449
450 METHOD(phase1_t, get_id, identification_t*,
451 private_phase1_t *this, peer_cfg_t *peer_cfg, bool local)
452 {
453 auth_cfg_t *auth;
454
455 auth = get_auth_cfg(peer_cfg, local);
456 if (auth)
457 {
458 return auth->get(auth, AUTH_RULE_IDENTITY);
459 }
460 return NULL;
461 }
462
463 METHOD(phase1_t, save_sa_payload, bool,
464 private_phase1_t *this, message_t *message)
465 {
466 enumerator_t *enumerator;
467 payload_t *payload, *sa = NULL;
468 chunk_t data;
469 size_t offset = IKE_HEADER_LENGTH;
470
471 enumerator = message->create_payload_enumerator(message);
472 while (enumerator->enumerate(enumerator, &payload))
473 {
474 if (payload->get_type(payload) == SECURITY_ASSOCIATION_V1)
475 {
476 sa = payload;
477 break;
478 }
479 else
480 {
481 offset += payload->get_length(payload);
482 }
483 }
484 enumerator->destroy(enumerator);
485
486 data = message->get_packet_data(message);
487 if (sa && data.len >= offset + sa->get_length(sa))
488 {
489 /* Get SA payload without 4 byte fixed header */
490 data = chunk_skip(data, offset);
491 data.len = sa->get_length(sa);
492 data = chunk_skip(data, 4);
493 this->sa_payload = chunk_clone(data);
494 return TRUE;
495 }
496 DBG1(DBG_IKE, "unable to extract SA payload encoding");
497 return FALSE;
498 }
499
500 METHOD(phase1_t, add_nonce_ke, bool,
501 private_phase1_t *this, message_t *message)
502 {
503 nonce_payload_t *nonce_payload;
504 ke_payload_t *ke_payload;
505 chunk_t nonce;
506 rng_t *rng;
507
508 ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE_V1, this->dh);
509 message->add_payload(message, &ke_payload->payload_interface);
510
511 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
512 if (!rng)
513 {
514 DBG1(DBG_IKE, "no RNG found to create nonce");
515 return FALSE;
516 }
517 rng->allocate_bytes(rng, NONCE_SIZE, &nonce);
518 rng->destroy(rng);
519
520 nonce_payload = nonce_payload_create(NONCE_V1);
521 nonce_payload->set_nonce(nonce_payload, nonce);
522 message->add_payload(message, &nonce_payload->payload_interface);
523
524 if (this->initiator)
525 {
526 this->nonce_i = nonce;
527 }
528 else
529 {
530 this->nonce_r = nonce;
531 }
532 return TRUE;
533 }
534
535 METHOD(phase1_t, get_nonce_ke, bool,
536 private_phase1_t *this, message_t *message)
537 {
538 nonce_payload_t *nonce_payload;
539 ke_payload_t *ke_payload;
540
541 ke_payload = (ke_payload_t*)message->get_payload(message, KEY_EXCHANGE_V1);
542 if (!ke_payload)
543 {
544 DBG1(DBG_IKE, "KE payload missing in message");
545 return FALSE;
546 }
547 this->dh_value = chunk_clone(ke_payload->get_key_exchange_data(ke_payload));
548 this->dh->set_other_public_value(this->dh, this->dh_value);
549
550 nonce_payload = (nonce_payload_t*)message->get_payload(message, NONCE_V1);
551 if (!nonce_payload)
552 {
553 DBG1(DBG_IKE, "NONCE payload missing in message");
554 return FALSE;
555 }
556
557 if (this->initiator)
558 {
559 this->nonce_r = nonce_payload->get_nonce(nonce_payload);
560 }
561 else
562 {
563 this->nonce_i = nonce_payload->get_nonce(nonce_payload);
564 }
565 return TRUE;
566 }
567
568 METHOD(phase1_t, destroy, void,
569 private_phase1_t *this)
570 {
571 chunk_free(&this->sa_payload);
572 DESTROY_IF(this->dh);
573 free(this->dh_value.ptr);
574 free(this->nonce_i.ptr);
575 free(this->nonce_r.ptr);
576 free(this);
577 }
578
579 /**
580 * See header
581 */
582 phase1_t *phase1_create(ike_sa_t *ike_sa, bool initiator)
583 {
584 private_phase1_t *this;
585
586 INIT(this,
587 .public = {
588 .create_hasher = _create_hasher,
589 .create_dh = _create_dh,
590 .derive_keys = _derive_keys,
591 .get_auth_method = _get_auth_method,
592 .get_id = _get_id,
593 .select_config = _select_config,
594 .verify_auth = _verify_auth,
595 .build_auth = _build_auth,
596 .save_sa_payload = _save_sa_payload,
597 .add_nonce_ke = _add_nonce_ke,
598 .get_nonce_ke = _get_nonce_ke,
599 .destroy = _destroy,
600 },
601 .ike_sa = ike_sa,
602 .initiator = initiator,
603 .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
604 );
605
606 return &this->public;
607 }