2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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>.
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
19 #include <crypto/prf_plus.h>
21 typedef struct private_keymat_t private_keymat_t
;
24 * Private data of an keymat_t object.
26 struct private_keymat_t
{
29 * Public keymat_t interface.
34 * IKE_SA Role, initiator or responder
39 * inbound signer (verify)
44 * outbound signer (sign)
49 * inbound crypter (decrypt)
51 crypter_t
*crypter_in
;
54 * outbound crypter (encrypt)
56 crypter_t
*crypter_out
;
64 * Negotiated PRF algorithm
66 pseudo_random_function_t prf_alg
;
69 * Key to derive key material from for CHILD_SAs, rekeying
74 * Key to build outging authentication data (SKp)
79 * Key to verify incoming authentication data (SKp)
84 typedef struct keylen_entry_t keylen_entry_t
;
87 * Implicit key length for an algorithm
89 struct keylen_entry_t
{
90 /** IKEv2 algorithm identifier */
92 /** key length in bits */
96 #define END_OF_LIST -1
99 * Keylen for encryption algos
101 keylen_entry_t keylen_enc
[] = {
108 * Keylen for integrity algos
110 keylen_entry_t keylen_int
[] = {
111 {AUTH_HMAC_MD5_96
, 128},
112 {AUTH_HMAC_SHA1_96
, 160},
113 {AUTH_HMAC_SHA2_256_128
, 256},
114 {AUTH_HMAC_SHA2_384_192
, 384},
115 {AUTH_HMAC_SHA2_512_256
, 512},
116 {AUTH_AES_XCBC_96
, 128},
121 * Lookup key length of an algorithm
123 static int lookup_keylen(keylen_entry_t
*list
, int algo
)
125 while (list
->algo
!= END_OF_LIST
)
127 if (algo
== list
->algo
)
137 * Implementation of keymat_t.create_dh
139 static diffie_hellman_t
* create_dh(private_keymat_t
*this,
140 diffie_hellman_group_t group
)
142 return lib
->crypto
->create_dh(lib
->crypto
, group
);;
146 * Implementation of keymat_t.derive_keys
148 static bool derive_ike_keys(private_keymat_t
*this, proposal_t
*proposal
,
149 diffie_hellman_t
*dh
, chunk_t nonce_i
,
150 chunk_t nonce_r
, ike_sa_id_t
*id
,
151 pseudo_random_function_t rekey_function
,
154 chunk_t skeyseed
, key
, secret
, full_nonce
, fixed_nonce
, prf_plus_seed
;
155 chunk_t spi_i
, spi_r
;
156 crypter_t
*crypter_i
, *crypter_r
;
157 signer_t
*signer_i
, *signer_r
;
158 prf_plus_t
*prf_plus
;
159 u_int16_t alg
, key_size
;
160 prf_t
*rekey_prf
= NULL
;
162 spi_i
= chunk_alloca(sizeof(u_int64_t
));
163 spi_r
= chunk_alloca(sizeof(u_int64_t
));
165 if (dh
->get_shared_secret(dh
, &secret
) != SUCCESS
)
170 /* Create SAs general purpose PRF first, we may use it here */
171 if (!proposal
->get_algorithm(proposal
, PSEUDO_RANDOM_FUNCTION
, &alg
, NULL
))
173 DBG1(DBG_IKE
, "no %N selected",
174 transform_type_names
, PSEUDO_RANDOM_FUNCTION
);
178 this->prf
= lib
->crypto
->create_prf(lib
->crypto
, alg
);
179 if (this->prf
== NULL
)
181 DBG1(DBG_IKE
, "%N %N not supported!",
182 transform_type_names
, PSEUDO_RANDOM_FUNCTION
,
183 pseudo_random_function_names
, alg
);
186 DBG4(DBG_IKE
, "shared Diffie Hellman secret %B", &secret
);
187 /* full nonce is used as seed for PRF+ ... */
188 full_nonce
= chunk_cat("cc", nonce_i
, nonce_r
);
189 /* but the PRF may need a fixed key which only uses the first bytes of
193 case PRF_AES128_XCBC
:
194 /* while rfc4434 defines variable keys for AES-XCBC, rfc3664 does
195 * not and therefore fixed key semantics apply to XCBC for key
197 key_size
= this->prf
->get_key_size(this->prf
)/2;
198 nonce_i
.len
= min(nonce_i
.len
, key_size
);
199 nonce_r
.len
= min(nonce_r
.len
, key_size
);
202 /* all other algorithms use variable key length, full nonce */
205 fixed_nonce
= chunk_cat("cc", nonce_i
, nonce_r
);
206 *((u_int64_t
*)spi_i
.ptr
) = id
->get_initiator_spi(id
);
207 *((u_int64_t
*)spi_r
.ptr
) = id
->get_responder_spi(id
);
208 prf_plus_seed
= chunk_cat("ccc", full_nonce
, spi_i
, spi_r
);
210 /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
212 * if we are rekeying, SKEYSEED is built on another way
214 if (rekey_function
== PRF_UNDEFINED
) /* not rekeying */
216 /* SKEYSEED = prf(Ni | Nr, g^ir) */
217 this->prf
->set_key(this->prf
, fixed_nonce
);
218 this->prf
->allocate_bytes(this->prf
, secret
, &skeyseed
);
219 this->prf
->set_key(this->prf
, skeyseed
);
220 prf_plus
= prf_plus_create(this->prf
, prf_plus_seed
);
224 /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr)
225 * use OLD SAs PRF functions for both prf_plus and prf */
226 rekey_prf
= lib
->crypto
->create_prf(lib
->crypto
, rekey_function
);
229 DBG1(DBG_IKE
, "PRF of old SA %N not supported!",
230 pseudo_random_function_names
, rekey_function
);
231 chunk_free(&full_nonce
);
232 chunk_free(&fixed_nonce
);
233 chunk_clear(&prf_plus_seed
);
236 secret
= chunk_cat("mc", secret
, full_nonce
);
237 rekey_prf
->set_key(rekey_prf
, rekey_skd
);
238 rekey_prf
->allocate_bytes(rekey_prf
, secret
, &skeyseed
);
239 rekey_prf
->set_key(rekey_prf
, skeyseed
);
240 prf_plus
= prf_plus_create(rekey_prf
, prf_plus_seed
);
242 DBG4(DBG_IKE
, "SKEYSEED %B", &skeyseed
);
244 chunk_clear(&skeyseed
);
245 chunk_clear(&secret
);
246 chunk_free(&full_nonce
);
247 chunk_free(&fixed_nonce
);
248 chunk_clear(&prf_plus_seed
);
250 /* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */
252 /* SK_d is used for generating CHILD_SA key mat => store for later use */
253 key_size
= this->prf
->get_key_size(this->prf
);
254 prf_plus
->allocate_bytes(prf_plus
, key_size
, &this->skd
);
255 DBG4(DBG_IKE
, "Sk_d secret %B", &this->skd
);
257 /* SK_ai/SK_ar used for integrity protection => signer_in/signer_out */
258 if (!proposal
->get_algorithm(proposal
, INTEGRITY_ALGORITHM
, &alg
, NULL
))
260 DBG1(DBG_IKE
, "no %N selected",
261 transform_type_names
, INTEGRITY_ALGORITHM
);
262 prf_plus
->destroy(prf_plus
);
263 DESTROY_IF(rekey_prf
);
266 signer_i
= lib
->crypto
->create_signer(lib
->crypto
, alg
);
267 signer_r
= lib
->crypto
->create_signer(lib
->crypto
, alg
);
268 if (signer_i
== NULL
|| signer_r
== NULL
)
270 DBG1(DBG_IKE
, "%N %N not supported!",
271 transform_type_names
, INTEGRITY_ALGORITHM
,
272 integrity_algorithm_names
,alg
);
273 prf_plus
->destroy(prf_plus
);
274 DESTROY_IF(rekey_prf
);
277 key_size
= signer_i
->get_key_size(signer_i
);
279 prf_plus
->allocate_bytes(prf_plus
, key_size
, &key
);
280 DBG4(DBG_IKE
, "Sk_ai secret %B", &key
);
281 signer_i
->set_key(signer_i
, key
);
284 prf_plus
->allocate_bytes(prf_plus
, key_size
, &key
);
285 DBG4(DBG_IKE
, "Sk_ar secret %B", &key
);
286 signer_r
->set_key(signer_r
, key
);
291 this->signer_in
= signer_r
;
292 this->signer_out
= signer_i
;
296 this->signer_in
= signer_i
;
297 this->signer_out
= signer_r
;
300 /* SK_ei/SK_er used for encryption => crypter_in/crypter_out */
301 if (!proposal
->get_algorithm(proposal
, ENCRYPTION_ALGORITHM
, &alg
, &key_size
))
303 DBG1(DBG_IKE
, "no %N selected",
304 transform_type_names
, ENCRYPTION_ALGORITHM
);
305 prf_plus
->destroy(prf_plus
);
306 DESTROY_IF(rekey_prf
);
309 crypter_i
= lib
->crypto
->create_crypter(lib
->crypto
, alg
, key_size
/ 8);
310 crypter_r
= lib
->crypto
->create_crypter(lib
->crypto
, alg
, key_size
/ 8);
311 if (crypter_i
== NULL
|| crypter_r
== NULL
)
313 DBG1(DBG_IKE
, "%N %N (key size %d) not supported!",
314 transform_type_names
, ENCRYPTION_ALGORITHM
,
315 encryption_algorithm_names
, alg
, key_size
);
316 prf_plus
->destroy(prf_plus
);
317 DESTROY_IF(rekey_prf
);
320 key_size
= crypter_i
->get_key_size(crypter_i
);
322 prf_plus
->allocate_bytes(prf_plus
, key_size
, &key
);
323 DBG4(DBG_IKE
, "Sk_ei secret %B", &key
);
324 crypter_i
->set_key(crypter_i
, key
);
327 prf_plus
->allocate_bytes(prf_plus
, key_size
, &key
);
328 DBG4(DBG_IKE
, "Sk_er secret %B", &key
);
329 crypter_r
->set_key(crypter_r
, key
);
334 this->crypter_in
= crypter_r
;
335 this->crypter_out
= crypter_i
;
339 this->crypter_in
= crypter_i
;
340 this->crypter_out
= crypter_r
;
343 /* SK_pi/SK_pr used for authentication => stored for later */
344 key_size
= this->prf
->get_key_size(this->prf
);
345 prf_plus
->allocate_bytes(prf_plus
, key_size
, &key
);
346 DBG4(DBG_IKE
, "Sk_pi secret %B", &key
);
349 this->skp_build
= key
;
353 this->skp_verify
= key
;
355 prf_plus
->allocate_bytes(prf_plus
, key_size
, &key
);
356 DBG4(DBG_IKE
, "Sk_pr secret %B", &key
);
359 this->skp_verify
= key
;
363 this->skp_build
= key
;
366 /* all done, prf_plus not needed anymore */
367 prf_plus
->destroy(prf_plus
);
368 DESTROY_IF(rekey_prf
);
374 * Implementation of keymat_t.derive_child_keys
376 static bool derive_child_keys(private_keymat_t
*this,
377 proposal_t
*proposal
, diffie_hellman_t
*dh
,
378 chunk_t nonce_i
, chunk_t nonce_r
,
379 chunk_t
*encr_i
, chunk_t
*integ_i
,
380 chunk_t
*encr_r
, chunk_t
*integ_r
)
382 u_int16_t enc_alg
, int_alg
, enc_size
= 0, int_size
= 0;
383 chunk_t seed
, secret
= chunk_empty
;
384 prf_plus_t
*prf_plus
;
388 if (dh
->get_shared_secret(dh
, &secret
) != SUCCESS
)
392 DBG4(DBG_CHD
, "DH secret %B", &secret
);
394 seed
= chunk_cata("mcc", secret
, nonce_i
, nonce_r
);
395 DBG4(DBG_CHD
, "seed %B", &seed
);
397 if (proposal
->get_algorithm(proposal
, ENCRYPTION_ALGORITHM
,
398 &enc_alg
, &enc_size
))
400 DBG2(DBG_CHD
, " using %N for encryption",
401 encryption_algorithm_names
, enc_alg
);
405 enc_size
= lookup_keylen(keylen_enc
, enc_alg
);
407 if (enc_alg
!= ENCR_NULL
&& !enc_size
)
409 DBG1(DBG_CHD
, "no keylength defined for %N",
410 encryption_algorithm_names
, enc_alg
);
416 /* CCM/GCM/CTR needs additional bytes */
419 case ENCR_AES_CCM_ICV8
:
420 case ENCR_AES_CCM_ICV12
:
421 case ENCR_AES_CCM_ICV16
:
424 case ENCR_AES_GCM_ICV8
:
425 case ENCR_AES_GCM_ICV12
:
426 case ENCR_AES_GCM_ICV16
:
435 if (proposal
->get_algorithm(proposal
, INTEGRITY_ALGORITHM
,
436 &int_alg
, &int_size
))
438 DBG2(DBG_CHD
, " using %N for integrity",
439 integrity_algorithm_names
, int_alg
);
443 int_size
= lookup_keylen(keylen_int
, int_alg
);
447 DBG1(DBG_CHD
, "no keylength defined for %N",
448 integrity_algorithm_names
, int_alg
);
455 this->prf
->set_key(this->prf
, this->skd
);
456 prf_plus
= prf_plus_create(this->prf
, seed
);
458 prf_plus
->allocate_bytes(prf_plus
, enc_size
, encr_i
);
459 prf_plus
->allocate_bytes(prf_plus
, int_size
, integ_i
);
460 prf_plus
->allocate_bytes(prf_plus
, enc_size
, encr_r
);
461 prf_plus
->allocate_bytes(prf_plus
, int_size
, integ_r
);
463 prf_plus
->destroy(prf_plus
);
467 DBG4(DBG_CHD
, "encryption initiator key %B", encr_i
);
468 DBG4(DBG_CHD
, "encryption responder key %B", encr_r
);
472 DBG4(DBG_CHD
, "integrity initiator key %B", integ_i
);
473 DBG4(DBG_CHD
, "integrity responder key %B", integ_r
);
479 * Implementation of keymat_t.get_skd
481 static pseudo_random_function_t
get_skd(private_keymat_t
*this, chunk_t
*skd
)
484 return this->prf_alg
;
488 * Implementation of keymat_t.get_signer
490 static signer_t
* get_signer(private_keymat_t
*this, bool in
)
492 return in ?
this->signer_in
: this->signer_out
;
496 * Implementation of keymat_t.get_crypter
498 static crypter_t
* get_crypter(private_keymat_t
*this, bool in
)
500 return in ?
this->crypter_in
: this->crypter_out
;
504 * Implementation of keymat_t.get_auth_octets
506 static chunk_t
get_auth_octets(private_keymat_t
*this, bool verify
,
507 chunk_t ike_sa_init
, chunk_t nonce
,
508 identification_t
*id
)
510 chunk_t chunk
, idx
, octets
;
513 skp
= verify ?
this->skp_verify
: this->skp_build
;
515 chunk
= chunk_alloca(4);
516 memset(chunk
.ptr
, 0, chunk
.len
);
517 chunk
.ptr
[0] = id
->get_type(id
);
518 idx
= chunk_cata("cc", chunk
, id
->get_encoding(id
));
520 DBG3(DBG_IKE
, "IDx' %B", &idx
);
521 DBG3(DBG_IKE
, "SK_p %B", &skp
);
522 this->prf
->set_key(this->prf
, skp
);
523 this->prf
->allocate_bytes(this->prf
, idx
, &chunk
);
525 octets
= chunk_cat("ccm", ike_sa_init
, nonce
, chunk
);
526 DBG3(DBG_IKE
, "octets = message + nonce + prf(Sk_px, IDx') %B", &octets
);
531 * Key pad for the AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
533 #define IKEV2_KEY_PAD "Key Pad for IKEv2"
534 #define IKEV2_KEY_PAD_LENGTH 17
537 * Implementation of keymat_t.get_psk_sig
539 static chunk_t
get_psk_sig(private_keymat_t
*this, bool verify
,
540 chunk_t ike_sa_init
, chunk_t nonce
, chunk_t secret
,
541 identification_t
*id
)
543 chunk_t key_pad
, key
, sig
, octets
;
546 { /* EAP uses SK_p if no MSK has been established */
547 secret
= verify ?
this->skp_verify
: this->skp_build
;
549 octets
= get_auth_octets(this, verify
, ike_sa_init
, nonce
, id
);
550 /* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */
551 key_pad
= chunk_create(IKEV2_KEY_PAD
, IKEV2_KEY_PAD_LENGTH
);
552 this->prf
->set_key(this->prf
, secret
);
553 this->prf
->allocate_bytes(this->prf
, key_pad
, &key
);
554 this->prf
->set_key(this->prf
, key
);
555 this->prf
->allocate_bytes(this->prf
, octets
, &sig
);
556 DBG4(DBG_IKE
, "secret %B", &secret
);
557 DBG4(DBG_IKE
, "prf(secret, keypad) %B", &key
);
558 DBG3(DBG_IKE
, "AUTH = prf(prf(secret, keypad), octets) %B", &sig
);
566 * Implementation of keymat_t.destroy.
568 static void destroy(private_keymat_t
*this)
570 DESTROY_IF(this->signer_in
);
571 DESTROY_IF(this->signer_out
);
572 DESTROY_IF(this->crypter_in
);
573 DESTROY_IF(this->crypter_out
);
574 DESTROY_IF(this->prf
);
575 chunk_clear(&this->skd
);
576 chunk_clear(&this->skp_verify
);
577 chunk_clear(&this->skp_build
);
584 keymat_t
*keymat_create(bool initiator
)
586 private_keymat_t
*this = malloc_thing(private_keymat_t
);
588 this->public.create_dh
= (diffie_hellman_t
*(*)(keymat_t
*, diffie_hellman_group_t group
))create_dh
;
589 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
, pseudo_random_function_t
,chunk_t
))derive_ike_keys
;
590 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
;
591 this->public.get_skd
= (pseudo_random_function_t(*)(keymat_t
*, chunk_t
*skd
))get_skd
;
592 this->public.get_signer
= (signer_t
*(*)(keymat_t
*, bool in
))get_signer
;
593 this->public.get_crypter
= (crypter_t
*(*)(keymat_t
*, bool in
))get_crypter
;
594 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
;
595 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
;
596 this->public.destroy
= (void(*)(keymat_t
*))destroy
;
598 this->initiator
= initiator
;
600 this->signer_in
= NULL
;
601 this->signer_out
= NULL
;
602 this->crypter_in
= NULL
;
603 this->crypter_out
= NULL
;
605 this->prf_alg
= PRF_UNDEFINED
;
606 this->skd
= chunk_empty
;
607 this->skp_verify
= chunk_empty
;
608 this->skp_build
= chunk_empty
;
610 return &this->public;