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