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