Fixed scheduling of IKEv2 init tasks in a second keyingtry
[strongswan.git] / src / libcharon / sa / ikev2 / keymat_v2.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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 "keymat_v2.h"
17
18 #include <daemon.h>
19 #include <crypto/prf_plus.h>
20
21 typedef struct private_keymat_v2_t private_keymat_v2_t;
22
23 /**
24 * Private data of an keymat_t object.
25 */
26 struct private_keymat_v2_t {
27
28 /**
29 * Public keymat_v2_t interface.
30 */
31 keymat_v2_t public;
32
33 /**
34 * IKE_SA Role, initiator or responder
35 */
36 bool initiator;
37
38 /**
39 * inbound AEAD
40 */
41 aead_t *aead_in;
42
43 /**
44 * outbound AEAD
45 */
46 aead_t *aead_out;
47
48 /**
49 * General purpose PRF
50 */
51 prf_t *prf;
52
53 /**
54 * Negotiated PRF algorithm
55 */
56 pseudo_random_function_t prf_alg;
57
58 /**
59 * Key to derive key material from for CHILD_SAs, rekeying
60 */
61 chunk_t skd;
62
63 /**
64 * Key to build outging authentication data (SKp)
65 */
66 chunk_t skp_build;
67
68 /**
69 * Key to verify incoming authentication data (SKp)
70 */
71 chunk_t skp_verify;
72 };
73
74 METHOD(keymat_t, create_dh, diffie_hellman_t*,
75 private_keymat_v2_t *this, diffie_hellman_group_t group)
76 {
77 return lib->crypto->create_dh(lib->crypto, group);
78 }
79
80 /**
81 * Derive IKE keys for a combined AEAD algorithm
82 */
83 static bool derive_ike_aead(private_keymat_v2_t *this, u_int16_t alg,
84 u_int16_t key_size, prf_plus_t *prf_plus)
85 {
86 aead_t *aead_i, *aead_r;
87 chunk_t key;
88
89 /* SK_ei/SK_er used for encryption */
90 aead_i = lib->crypto->create_aead(lib->crypto, alg, key_size / 8);
91 aead_r = lib->crypto->create_aead(lib->crypto, alg, key_size / 8);
92 if (aead_i == NULL || aead_r == NULL)
93 {
94 DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
95 transform_type_names, ENCRYPTION_ALGORITHM,
96 encryption_algorithm_names, alg, key_size);
97 return FALSE;
98 }
99 key_size = aead_i->get_key_size(aead_i);
100
101 prf_plus->allocate_bytes(prf_plus, key_size, &key);
102 DBG4(DBG_IKE, "Sk_ei secret %B", &key);
103 aead_i->set_key(aead_i, key);
104 chunk_clear(&key);
105
106 prf_plus->allocate_bytes(prf_plus, key_size, &key);
107 DBG4(DBG_IKE, "Sk_er secret %B", &key);
108 aead_r->set_key(aead_r, key);
109 chunk_clear(&key);
110
111 if (this->initiator)
112 {
113 this->aead_in = aead_r;
114 this->aead_out = aead_i;
115 }
116 else
117 {
118 this->aead_in = aead_i;
119 this->aead_out = aead_r;
120 }
121 return TRUE;
122 }
123
124 /**
125 * Derive IKE keys for traditional encryption and MAC algorithms
126 */
127 static bool derive_ike_traditional(private_keymat_v2_t *this, u_int16_t enc_alg,
128 u_int16_t enc_size, u_int16_t int_alg, prf_plus_t *prf_plus)
129 {
130 crypter_t *crypter_i, *crypter_r;
131 signer_t *signer_i, *signer_r;
132 size_t key_size;
133 chunk_t key;
134
135 /* SK_ai/SK_ar used for integrity protection */
136 signer_i = lib->crypto->create_signer(lib->crypto, int_alg);
137 signer_r = lib->crypto->create_signer(lib->crypto, int_alg);
138 if (signer_i == NULL || signer_r == NULL)
139 {
140 DBG1(DBG_IKE, "%N %N not supported!",
141 transform_type_names, INTEGRITY_ALGORITHM,
142 integrity_algorithm_names, int_alg);
143 return FALSE;
144 }
145 key_size = signer_i->get_key_size(signer_i);
146
147 prf_plus->allocate_bytes(prf_plus, key_size, &key);
148 DBG4(DBG_IKE, "Sk_ai secret %B", &key);
149 signer_i->set_key(signer_i, key);
150 chunk_clear(&key);
151
152 prf_plus->allocate_bytes(prf_plus, key_size, &key);
153 DBG4(DBG_IKE, "Sk_ar secret %B", &key);
154 signer_r->set_key(signer_r, key);
155 chunk_clear(&key);
156
157 /* SK_ei/SK_er used for encryption */
158 crypter_i = lib->crypto->create_crypter(lib->crypto, enc_alg, enc_size / 8);
159 crypter_r = lib->crypto->create_crypter(lib->crypto, enc_alg, enc_size / 8);
160 if (crypter_i == NULL || crypter_r == NULL)
161 {
162 DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
163 transform_type_names, ENCRYPTION_ALGORITHM,
164 encryption_algorithm_names, enc_alg, enc_size);
165 signer_i->destroy(signer_i);
166 signer_r->destroy(signer_r);
167 return FALSE;
168 }
169 key_size = crypter_i->get_key_size(crypter_i);
170
171 prf_plus->allocate_bytes(prf_plus, key_size, &key);
172 DBG4(DBG_IKE, "Sk_ei secret %B", &key);
173 crypter_i->set_key(crypter_i, key);
174 chunk_clear(&key);
175
176 prf_plus->allocate_bytes(prf_plus, key_size, &key);
177 DBG4(DBG_IKE, "Sk_er secret %B", &key);
178 crypter_r->set_key(crypter_r, key);
179 chunk_clear(&key);
180
181 if (this->initiator)
182 {
183 this->aead_in = aead_create(crypter_r, signer_r);
184 this->aead_out = aead_create(crypter_i, signer_i);
185 }
186 else
187 {
188 this->aead_in = aead_create(crypter_i, signer_i);
189 this->aead_out = aead_create(crypter_r, signer_r);
190 }
191 return TRUE;
192 }
193
194 METHOD(keymat_v2_t, derive_ike_keys, bool,
195 private_keymat_v2_t *this, proposal_t *proposal, diffie_hellman_t *dh,
196 chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id,
197 pseudo_random_function_t rekey_function, chunk_t rekey_skd)
198 {
199 chunk_t skeyseed, key, secret, full_nonce, fixed_nonce, prf_plus_seed;
200 chunk_t spi_i, spi_r;
201 prf_plus_t *prf_plus;
202 u_int16_t alg, key_size, int_alg;
203 prf_t *rekey_prf = NULL;
204
205 spi_i = chunk_alloca(sizeof(u_int64_t));
206 spi_r = chunk_alloca(sizeof(u_int64_t));
207
208 if (dh->get_shared_secret(dh, &secret) != SUCCESS)
209 {
210 return FALSE;
211 }
212
213 /* Create SAs general purpose PRF first, we may use it here */
214 if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
215 {
216 DBG1(DBG_IKE, "no %N selected",
217 transform_type_names, PSEUDO_RANDOM_FUNCTION);
218 return FALSE;
219 }
220 this->prf_alg = alg;
221 this->prf = lib->crypto->create_prf(lib->crypto, alg);
222 if (this->prf == NULL)
223 {
224 DBG1(DBG_IKE, "%N %N not supported!",
225 transform_type_names, PSEUDO_RANDOM_FUNCTION,
226 pseudo_random_function_names, alg);
227 return FALSE;
228 }
229 DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &secret);
230 /* full nonce is used as seed for PRF+ ... */
231 full_nonce = chunk_cat("cc", nonce_i, nonce_r);
232 /* but the PRF may need a fixed key which only uses the first bytes of
233 * the nonces. */
234 switch (alg)
235 {
236 case PRF_AES128_XCBC:
237 /* while rfc4434 defines variable keys for AES-XCBC, rfc3664 does
238 * not and therefore fixed key semantics apply to XCBC for key
239 * derivation. */
240 case PRF_CAMELLIA128_XCBC:
241 /* draft-kanno-ipsecme-camellia-xcbc refers to rfc 4434, we
242 * assume fixed key length. */
243 key_size = this->prf->get_key_size(this->prf)/2;
244 nonce_i.len = min(nonce_i.len, key_size);
245 nonce_r.len = min(nonce_r.len, key_size);
246 break;
247 default:
248 /* all other algorithms use variable key length, full nonce */
249 break;
250 }
251 fixed_nonce = chunk_cat("cc", nonce_i, nonce_r);
252 *((u_int64_t*)spi_i.ptr) = id->get_initiator_spi(id);
253 *((u_int64_t*)spi_r.ptr) = id->get_responder_spi(id);
254 prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r);
255
256 /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
257 *
258 * if we are rekeying, SKEYSEED is built on another way
259 */
260 if (rekey_function == PRF_UNDEFINED) /* not rekeying */
261 {
262 /* SKEYSEED = prf(Ni | Nr, g^ir) */
263 this->prf->set_key(this->prf, fixed_nonce);
264 this->prf->allocate_bytes(this->prf, secret, &skeyseed);
265 this->prf->set_key(this->prf, skeyseed);
266 prf_plus = prf_plus_create(this->prf, TRUE, prf_plus_seed);
267 }
268 else
269 {
270 /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr)
271 * use OLD SAs PRF functions for both prf_plus and prf */
272 rekey_prf = lib->crypto->create_prf(lib->crypto, rekey_function);
273 if (!rekey_prf)
274 {
275 DBG1(DBG_IKE, "PRF of old SA %N not supported!",
276 pseudo_random_function_names, rekey_function);
277 chunk_free(&full_nonce);
278 chunk_free(&fixed_nonce);
279 chunk_clear(&prf_plus_seed);
280 return FALSE;
281 }
282 secret = chunk_cat("mc", secret, full_nonce);
283 rekey_prf->set_key(rekey_prf, rekey_skd);
284 rekey_prf->allocate_bytes(rekey_prf, secret, &skeyseed);
285 rekey_prf->set_key(rekey_prf, skeyseed);
286 prf_plus = prf_plus_create(rekey_prf, TRUE, prf_plus_seed);
287 }
288 DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
289
290 chunk_clear(&skeyseed);
291 chunk_clear(&secret);
292 chunk_free(&full_nonce);
293 chunk_free(&fixed_nonce);
294 chunk_clear(&prf_plus_seed);
295
296 /* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */
297
298 /* SK_d is used for generating CHILD_SA key mat => store for later use */
299 key_size = this->prf->get_key_size(this->prf);
300 prf_plus->allocate_bytes(prf_plus, key_size, &this->skd);
301 DBG4(DBG_IKE, "Sk_d secret %B", &this->skd);
302
303 if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &key_size))
304 {
305 DBG1(DBG_IKE, "no %N selected",
306 transform_type_names, ENCRYPTION_ALGORITHM);
307 prf_plus->destroy(prf_plus);
308 DESTROY_IF(rekey_prf);
309 return FALSE;
310 }
311
312 if (encryption_algorithm_is_aead(alg))
313 {
314 if (!derive_ike_aead(this, alg, key_size, prf_plus))
315 {
316 prf_plus->destroy(prf_plus);
317 DESTROY_IF(rekey_prf);
318 return FALSE;
319 }
320 }
321 else
322 {
323 if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
324 &int_alg, NULL))
325 {
326 DBG1(DBG_IKE, "no %N selected",
327 transform_type_names, INTEGRITY_ALGORITHM);
328 prf_plus->destroy(prf_plus);
329 DESTROY_IF(rekey_prf);
330 return FALSE;
331 }
332 if (!derive_ike_traditional(this, alg, key_size, int_alg, prf_plus))
333 {
334 prf_plus->destroy(prf_plus);
335 DESTROY_IF(rekey_prf);
336 return FALSE;
337 }
338 }
339
340 /* SK_pi/SK_pr used for authentication => stored for later */
341 key_size = this->prf->get_key_size(this->prf);
342 prf_plus->allocate_bytes(prf_plus, key_size, &key);
343 DBG4(DBG_IKE, "Sk_pi secret %B", &key);
344 if (this->initiator)
345 {
346 this->skp_build = key;
347 }
348 else
349 {
350 this->skp_verify = key;
351 }
352 prf_plus->allocate_bytes(prf_plus, key_size, &key);
353 DBG4(DBG_IKE, "Sk_pr secret %B", &key);
354 if (this->initiator)
355 {
356 this->skp_verify = key;
357 }
358 else
359 {
360 this->skp_build = key;
361 }
362
363 /* all done, prf_plus not needed anymore */
364 prf_plus->destroy(prf_plus);
365 DESTROY_IF(rekey_prf);
366
367 return TRUE;
368 }
369
370 METHOD(keymat_v2_t, derive_child_keys, bool,
371 private_keymat_v2_t *this, proposal_t *proposal, diffie_hellman_t *dh,
372 chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i,
373 chunk_t *encr_r, chunk_t *integ_r)
374 {
375 u_int16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
376 chunk_t seed, secret = chunk_empty;
377 prf_plus_t *prf_plus;
378
379 if (dh)
380 {
381 if (dh->get_shared_secret(dh, &secret) != SUCCESS)
382 {
383 return FALSE;
384 }
385 DBG4(DBG_CHD, "DH secret %B", &secret);
386 }
387 seed = chunk_cata("mcc", secret, nonce_i, nonce_r);
388 DBG4(DBG_CHD, "seed %B", &seed);
389
390 if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
391 &enc_alg, &enc_size))
392 {
393 DBG2(DBG_CHD, " using %N for encryption",
394 encryption_algorithm_names, enc_alg);
395
396 if (!enc_size)
397 {
398 enc_size = keymat_get_keylen_encr(enc_alg);
399 }
400 if (enc_alg != ENCR_NULL && !enc_size)
401 {
402 DBG1(DBG_CHD, "no keylength defined for %N",
403 encryption_algorithm_names, enc_alg);
404 return FALSE;
405 }
406 /* to bytes */
407 enc_size /= 8;
408
409 /* CCM/GCM/CTR/GMAC needs additional bytes */
410 switch (enc_alg)
411 {
412 case ENCR_AES_CCM_ICV8:
413 case ENCR_AES_CCM_ICV12:
414 case ENCR_AES_CCM_ICV16:
415 case ENCR_CAMELLIA_CCM_ICV8:
416 case ENCR_CAMELLIA_CCM_ICV12:
417 case ENCR_CAMELLIA_CCM_ICV16:
418 enc_size += 3;
419 break;
420 case ENCR_AES_GCM_ICV8:
421 case ENCR_AES_GCM_ICV12:
422 case ENCR_AES_GCM_ICV16:
423 case ENCR_AES_CTR:
424 case ENCR_NULL_AUTH_AES_GMAC:
425 enc_size += 4;
426 break;
427 default:
428 break;
429 }
430 }
431
432 if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
433 &int_alg, &int_size))
434 {
435 DBG2(DBG_CHD, " using %N for integrity",
436 integrity_algorithm_names, int_alg);
437
438 if (!int_size)
439 {
440 int_size = keymat_get_keylen_integ(int_alg);
441 }
442 if (!int_size)
443 {
444 DBG1(DBG_CHD, "no keylength defined for %N",
445 integrity_algorithm_names, int_alg);
446 return FALSE;
447 }
448 /* to bytes */
449 int_size /= 8;
450 }
451
452 this->prf->set_key(this->prf, this->skd);
453 prf_plus = prf_plus_create(this->prf, TRUE, seed);
454
455 prf_plus->allocate_bytes(prf_plus, enc_size, encr_i);
456 prf_plus->allocate_bytes(prf_plus, int_size, integ_i);
457 prf_plus->allocate_bytes(prf_plus, enc_size, encr_r);
458 prf_plus->allocate_bytes(prf_plus, int_size, integ_r);
459
460 prf_plus->destroy(prf_plus);
461
462 if (enc_size)
463 {
464 DBG4(DBG_CHD, "encryption initiator key %B", encr_i);
465 DBG4(DBG_CHD, "encryption responder key %B", encr_r);
466 }
467 if (int_size)
468 {
469 DBG4(DBG_CHD, "integrity initiator key %B", integ_i);
470 DBG4(DBG_CHD, "integrity responder key %B", integ_r);
471 }
472 return TRUE;
473 }
474
475 METHOD(keymat_v2_t, get_skd, pseudo_random_function_t,
476 private_keymat_v2_t *this, chunk_t *skd)
477 {
478 *skd = this->skd;
479 return this->prf_alg;
480 }
481
482 METHOD(keymat_t, get_aead, aead_t*,
483 private_keymat_v2_t *this, bool in)
484 {
485 return in ? this->aead_in : this->aead_out;
486 }
487
488 METHOD(keymat_v2_t, get_auth_octets, chunk_t,
489 private_keymat_v2_t *this, bool verify, chunk_t ike_sa_init,
490 chunk_t nonce, identification_t *id, char reserved[3])
491 {
492 chunk_t chunk, idx, octets;
493 chunk_t skp;
494
495 skp = verify ? this->skp_verify : this->skp_build;
496
497 chunk = chunk_alloca(4);
498 chunk.ptr[0] = id->get_type(id);
499 memcpy(chunk.ptr + 1, reserved, 3);
500 idx = chunk_cata("cc", chunk, id->get_encoding(id));
501
502 DBG3(DBG_IKE, "IDx' %B", &idx);
503 DBG3(DBG_IKE, "SK_p %B", &skp);
504 this->prf->set_key(this->prf, skp);
505 this->prf->allocate_bytes(this->prf, idx, &chunk);
506
507 octets = chunk_cat("ccm", ike_sa_init, nonce, chunk);
508 DBG3(DBG_IKE, "octets = message + nonce + prf(Sk_px, IDx') %B", &octets);
509 return octets;
510 }
511
512 /**
513 * Key pad for the AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
514 */
515 #define IKEV2_KEY_PAD "Key Pad for IKEv2"
516 #define IKEV2_KEY_PAD_LENGTH 17
517
518 METHOD(keymat_v2_t, get_psk_sig, chunk_t,
519 private_keymat_v2_t *this, bool verify, chunk_t ike_sa_init,
520 chunk_t nonce, chunk_t secret, identification_t *id, char reserved[3])
521 {
522 chunk_t key_pad, key, sig, octets;
523
524 if (!secret.len)
525 { /* EAP uses SK_p if no MSK has been established */
526 secret = verify ? this->skp_verify : this->skp_build;
527 }
528 octets = get_auth_octets(this, verify, ike_sa_init, nonce, id, reserved);
529 /* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */
530 key_pad = chunk_create(IKEV2_KEY_PAD, IKEV2_KEY_PAD_LENGTH);
531 this->prf->set_key(this->prf, secret);
532 this->prf->allocate_bytes(this->prf, key_pad, &key);
533 this->prf->set_key(this->prf, key);
534 this->prf->allocate_bytes(this->prf, octets, &sig);
535 DBG4(DBG_IKE, "secret %B", &secret);
536 DBG4(DBG_IKE, "prf(secret, keypad) %B", &key);
537 DBG3(DBG_IKE, "AUTH = prf(prf(secret, keypad), octets) %B", &sig);
538 chunk_free(&octets);
539 chunk_free(&key);
540
541 return sig;
542 }
543
544 METHOD(keymat_t, destroy, void,
545 private_keymat_v2_t *this)
546 {
547 DESTROY_IF(this->aead_in);
548 DESTROY_IF(this->aead_out);
549 DESTROY_IF(this->prf);
550 chunk_clear(&this->skd);
551 chunk_clear(&this->skp_verify);
552 chunk_clear(&this->skp_build);
553 free(this);
554 }
555
556 /**
557 * See header
558 */
559 keymat_v2_t *keymat_v2_create(bool initiator)
560 {
561 private_keymat_v2_t *this;
562
563 INIT(this,
564 .public = {
565 .keymat = {
566 .create_dh = _create_dh,
567 .get_aead = _get_aead,
568 .destroy = _destroy,
569 },
570 .derive_ike_keys = _derive_ike_keys,
571 .derive_child_keys = _derive_child_keys,
572 .get_skd = _get_skd,
573 .get_auth_octets = _get_auth_octets,
574 .get_psk_sig = _get_psk_sig,
575 },
576 .initiator = initiator,
577 .prf_alg = PRF_UNDEFINED,
578 );
579
580 return &this->public;
581 }