Implemented a common Phase 1 helper class to use by main and aggressive modes
[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, identification_t *id)
420 {
421 enumerator_t *enumerator;
422 peer_cfg_t *current, *found = NULL;
423 host_t *me, *other;
424
425 me = this->ike_sa->get_my_host(this->ike_sa);
426 other = this->ike_sa->get_other_host(this->ike_sa);
427 DBG1(DBG_CFG, "looking for %N peer configs matching %H...%H[%Y]",
428 auth_method_names, method, me, other, id);
429 enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
430 me, other, NULL, id, IKEV1);
431 while (enumerator->enumerate(enumerator, &current))
432 {
433 if (get_auth_method(this, current) == method)
434 {
435 found = current->get_ref(current);
436 break;
437 }
438 }
439 enumerator->destroy(enumerator);
440
441 if (found)
442 {
443 DBG2(DBG_CFG, "selected peer config \"%s\"", found->get_name(found));
444 }
445 return found;
446 }
447
448 METHOD(phase1_t, get_id, identification_t*,
449 private_phase1_t *this, peer_cfg_t *peer_cfg, bool local)
450 {
451 auth_cfg_t *auth;
452
453 auth = get_auth_cfg(peer_cfg, local);
454 if (auth)
455 {
456 return auth->get(auth, AUTH_RULE_IDENTITY);
457 }
458 return NULL;
459 }
460
461 METHOD(phase1_t, save_sa_payload, bool,
462 private_phase1_t *this, message_t *message)
463 {
464 enumerator_t *enumerator;
465 payload_t *payload, *sa = NULL;
466 chunk_t data;
467 size_t offset = IKE_HEADER_LENGTH;
468
469 enumerator = message->create_payload_enumerator(message);
470 while (enumerator->enumerate(enumerator, &payload))
471 {
472 if (payload->get_type(payload) == SECURITY_ASSOCIATION_V1)
473 {
474 sa = payload;
475 break;
476 }
477 else
478 {
479 offset += payload->get_length(payload);
480 }
481 }
482 enumerator->destroy(enumerator);
483
484 data = message->get_packet_data(message);
485 if (sa && data.len >= offset + sa->get_length(sa))
486 {
487 /* Get SA payload without 4 byte fixed header */
488 data = chunk_skip(data, offset);
489 data.len = sa->get_length(sa);
490 data = chunk_skip(data, 4);
491 this->sa_payload = chunk_clone(data);
492 return TRUE;
493 }
494 DBG1(DBG_IKE, "unable to extract SA payload encoding");
495 return FALSE;
496 }
497
498 METHOD(phase1_t, add_nonce_ke, bool,
499 private_phase1_t *this, message_t *message)
500 {
501 nonce_payload_t *nonce_payload;
502 ke_payload_t *ke_payload;
503 chunk_t nonce;
504 rng_t *rng;
505
506 ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE_V1, this->dh);
507 message->add_payload(message, &ke_payload->payload_interface);
508
509 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
510 if (!rng)
511 {
512 DBG1(DBG_IKE, "no RNG found to create nonce");
513 return FALSE;
514 }
515 rng->allocate_bytes(rng, NONCE_SIZE, &nonce);
516 rng->destroy(rng);
517
518 nonce_payload = nonce_payload_create(NONCE_V1);
519 nonce_payload->set_nonce(nonce_payload, nonce);
520 message->add_payload(message, &nonce_payload->payload_interface);
521
522 if (this->initiator)
523 {
524 this->nonce_i = nonce;
525 }
526 else
527 {
528 this->nonce_r = nonce;
529 }
530 return TRUE;
531 }
532
533 METHOD(phase1_t, get_nonce_ke, bool,
534 private_phase1_t *this, message_t *message)
535 {
536 nonce_payload_t *nonce_payload;
537 ke_payload_t *ke_payload;
538
539 ke_payload = (ke_payload_t*)message->get_payload(message, KEY_EXCHANGE_V1);
540 if (!ke_payload)
541 {
542 DBG1(DBG_IKE, "KE payload missing in message");
543 return FALSE;
544 }
545 this->dh_value = chunk_clone(ke_payload->get_key_exchange_data(ke_payload));
546 this->dh->set_other_public_value(this->dh, this->dh_value);
547
548 nonce_payload = (nonce_payload_t*)message->get_payload(message, NONCE_V1);
549 if (!nonce_payload)
550 {
551 DBG1(DBG_IKE, "NONCE payload missing in message");
552 return FALSE;
553 }
554
555 if (this->initiator)
556 {
557 this->nonce_r = nonce_payload->get_nonce(nonce_payload);
558 }
559 else
560 {
561 this->nonce_i = nonce_payload->get_nonce(nonce_payload);
562 }
563 return TRUE;
564 }
565
566 METHOD(phase1_t, destroy, void,
567 private_phase1_t *this)
568 {
569 chunk_free(&this->sa_payload);
570 DESTROY_IF(this->dh);
571 free(this->dh_value.ptr);
572 free(this->nonce_i.ptr);
573 free(this->nonce_r.ptr);
574 free(this);
575 }
576
577 /**
578 * See header
579 */
580 phase1_t *phase1_create(ike_sa_t *ike_sa, bool initiator)
581 {
582 private_phase1_t *this;
583
584 INIT(this,
585 .public = {
586 .create_hasher = _create_hasher,
587 .create_dh = _create_dh,
588 .derive_keys = _derive_keys,
589 .get_auth_method = _get_auth_method,
590 .get_id = _get_id,
591 .select_config = _select_config,
592 .verify_auth = _verify_auth,
593 .build_auth = _build_auth,
594 .save_sa_payload = _save_sa_payload,
595 .add_nonce_ke = _add_nonce_ke,
596 .get_nonce_ke = _get_nonce_ke,
597 .destroy = _destroy,
598 },
599 .ike_sa = ike_sa,
600 .initiator = initiator,
601 .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
602 );
603
604 return &this->public;
605 }