do not store DH redundant in keymat
[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 /**
87 * Implementation of keymat_t.create_dh
88 */
89 static diffie_hellman_t* create_dh(private_keymat_t *this,
90 diffie_hellman_group_t group)
91 {
92 return lib->crypto->create_dh(lib->crypto, group);;
93 }
94
95 /**
96 * Implementation of keymat_t.derive_keys
97 */
98 static bool derive_keys(private_keymat_t *this, proposal_t *proposal,
99 diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r,
100 ike_sa_id_t *id, private_keymat_t *rekey)
101 {
102 chunk_t skeyseed, key, secret, full_nonce, fixed_nonce, prf_plus_seed;
103 chunk_t spi_i, spi_r;
104 crypter_t *crypter_i, *crypter_r;
105 signer_t *signer_i, *signer_r;
106 prf_plus_t *prf_plus;
107 u_int16_t alg, key_size;
108
109 spi_i = chunk_alloca(sizeof(u_int64_t));
110 spi_r = chunk_alloca(sizeof(u_int64_t));
111
112 if (dh->get_shared_secret(dh, &secret) != SUCCESS)
113 {
114 return FALSE;
115 }
116
117 /* Create SAs general purpose PRF first, we may use it here */
118 if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
119 {
120 DBG1(DBG_IKE, "no %N selected",
121 transform_type_names, PSEUDO_RANDOM_FUNCTION);
122 return FALSE;
123 }
124 this->prf = lib->crypto->create_prf(lib->crypto, alg);
125 if (this->prf == NULL)
126 {
127 DBG1(DBG_IKE, "%N %N not supported!",
128 transform_type_names, PSEUDO_RANDOM_FUNCTION,
129 pseudo_random_function_names, alg);
130 return FALSE;
131 }
132 DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &secret);
133 /* full nonce is used as seed for PRF+ ... */
134 full_nonce = chunk_cat("cc", nonce_i, nonce_r);
135 /* but the PRF may need a fixed key which only uses the first bytes of
136 * the nonces. */
137 switch (alg)
138 {
139 case PRF_AES128_XCBC:
140 /* while rfc4434 defines variable keys for AES-XCBC, rfc3664 does
141 * not and therefore fixed key semantics apply to XCBC for key
142 * derivation. */
143 nonce_i.len = min(nonce_i.len, this->prf->get_key_size(this->prf)/2);
144 nonce_r.len = min(nonce_r.len, this->prf->get_key_size(this->prf)/2);
145 break;
146 default:
147 /* all other algorithms use variable key length, full nonce */
148 break;
149 }
150 fixed_nonce = chunk_cat("cc", nonce_i, nonce_r);
151 *((u_int64_t*)spi_i.ptr) = id->get_initiator_spi(id);
152 *((u_int64_t*)spi_r.ptr) = id->get_responder_spi(id);
153 prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r);
154
155 /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
156 *
157 * if we are rekeying, SKEYSEED is built on another way
158 */
159 if (rekey == NULL) /* not rekeying */
160 {
161 /* SKEYSEED = prf(Ni | Nr, g^ir) */
162 this->prf->set_key(this->prf, fixed_nonce);
163 this->prf->allocate_bytes(this->prf, secret, &skeyseed);
164 DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
165 this->prf->set_key(this->prf, skeyseed);
166 chunk_clear(&skeyseed);
167 chunk_clear(&secret);
168 prf_plus = prf_plus_create(this->prf, prf_plus_seed);
169 }
170 else
171 {
172 /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr)
173 * use OLD SAs PRF functions for both prf_plus and prf */
174 secret = chunk_cat("mc", secret, full_nonce);
175 rekey->child_prf->allocate_bytes(rekey->child_prf, secret, &skeyseed);
176 DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
177 rekey->prf->set_key(rekey->prf, skeyseed);
178 chunk_clear(&skeyseed);
179 chunk_clear(&secret);
180 prf_plus = prf_plus_create(rekey->prf, prf_plus_seed);
181 }
182 chunk_free(&full_nonce);
183 chunk_free(&fixed_nonce);
184 chunk_clear(&prf_plus_seed);
185
186 /* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */
187
188 /* SK_d is used for generating CHILD_SA key mat => child_prf */
189 proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL);
190 this->child_prf = lib->crypto->create_prf(lib->crypto, alg);
191 key_size = this->child_prf->get_key_size(this->child_prf);
192 prf_plus->allocate_bytes(prf_plus, key_size, &key);
193 DBG4(DBG_IKE, "Sk_d secret %B", &key);
194 this->child_prf->set_key(this->child_prf, key);
195 chunk_clear(&key);
196
197 /* SK_ai/SK_ar used for integrity protection => signer_in/signer_out */
198 if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL))
199 {
200 DBG1(DBG_IKE, "no %N selected",
201 transform_type_names, INTEGRITY_ALGORITHM);
202 return FALSE;
203 }
204 signer_i = lib->crypto->create_signer(lib->crypto, alg);
205 signer_r = lib->crypto->create_signer(lib->crypto, alg);
206 if (signer_i == NULL || signer_r == NULL)
207 {
208 DBG1(DBG_IKE, "%N %N not supported!",
209 transform_type_names, INTEGRITY_ALGORITHM,
210 integrity_algorithm_names ,alg);
211 prf_plus->destroy(prf_plus);
212 return FALSE;
213 }
214 key_size = signer_i->get_key_size(signer_i);
215
216 prf_plus->allocate_bytes(prf_plus, key_size, &key);
217 DBG4(DBG_IKE, "Sk_ai secret %B", &key);
218 signer_i->set_key(signer_i, key);
219 chunk_clear(&key);
220
221 prf_plus->allocate_bytes(prf_plus, key_size, &key);
222 DBG4(DBG_IKE, "Sk_ar secret %B", &key);
223 signer_r->set_key(signer_r, key);
224 chunk_clear(&key);
225
226 if (this->initiator)
227 {
228 this->signer_in = signer_r;
229 this->signer_out = signer_i;
230 }
231 else
232 {
233 this->signer_in = signer_i;
234 this->signer_out = signer_r;
235 }
236
237 /* SK_ei/SK_er used for encryption => crypter_in/crypter_out */
238 if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &key_size))
239 {
240 DBG1(DBG_IKE, "no %N selected",
241 transform_type_names, ENCRYPTION_ALGORITHM);
242 prf_plus->destroy(prf_plus);
243 return FALSE;
244 }
245 crypter_i = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
246 crypter_r = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
247 if (crypter_i == NULL || crypter_r == NULL)
248 {
249 DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
250 transform_type_names, ENCRYPTION_ALGORITHM,
251 encryption_algorithm_names, alg, key_size);
252 prf_plus->destroy(prf_plus);
253 return FALSE;
254 }
255 key_size = crypter_i->get_key_size(crypter_i);
256
257 prf_plus->allocate_bytes(prf_plus, key_size, &key);
258 DBG4(DBG_IKE, "Sk_ei secret %B", &key);
259 crypter_i->set_key(crypter_i, key);
260 chunk_clear(&key);
261
262 prf_plus->allocate_bytes(prf_plus, key_size, &key);
263 DBG4(DBG_IKE, "Sk_er secret %B", &key);
264 crypter_r->set_key(crypter_r, key);
265 chunk_clear(&key);
266
267 if (this->initiator)
268 {
269 this->crypter_in = crypter_r;
270 this->crypter_out = crypter_i;
271 }
272 else
273 {
274 this->crypter_in = crypter_i;
275 this->crypter_out = crypter_r;
276 }
277
278 /* SK_pi/SK_pr used for authentication => stored for later */
279 key_size = this->prf->get_key_size(this->prf);
280 prf_plus->allocate_bytes(prf_plus, key_size, &key);
281 DBG4(DBG_IKE, "Sk_pi secret %B", &key);
282 if (this->initiator)
283 {
284 this->skp_build = key;
285 }
286 else
287 {
288 this->skp_verify = key;
289 }
290 prf_plus->allocate_bytes(prf_plus, key_size, &key);
291 DBG4(DBG_IKE, "Sk_pr secret %B", &key);
292 if (this->initiator)
293 {
294 this->skp_verify = key;
295 }
296 else
297 {
298 this->skp_build = key;
299 }
300
301 /* all done, prf_plus not needed anymore */
302 prf_plus->destroy(prf_plus);
303
304 /* save selected proposal */
305 this->proposal = proposal->clone(proposal);
306
307 return TRUE;
308 }
309
310 /**
311 * Implementation of keymat_t.get_proposal
312 */
313 static proposal_t* get_proposal(private_keymat_t *this)
314 {
315 return this->proposal;
316 }
317
318 /**
319 * Implementation of keymat_t.get_signer
320 */
321 static signer_t* get_signer(private_keymat_t *this, bool in)
322 {
323 return in ? this->signer_in : this->signer_out;
324 }
325
326 /**
327 * Implementation of keymat_t.get_crypter
328 */
329 static crypter_t* get_crypter(private_keymat_t *this, bool in)
330 {
331 return in ? this->crypter_in : this->crypter_out;
332 }
333
334 /**
335 * Implementation of keymat_t.get_child_prf
336 */
337 static prf_t* get_child_prf(private_keymat_t *this)
338 {
339 return this->child_prf;
340 }
341
342 /**
343 * Implementation of keymat_t.get_auth_octets
344 */
345 static chunk_t get_auth_octets(private_keymat_t *this, bool verify,
346 chunk_t ike_sa_init, chunk_t nonce,
347 identification_t *id)
348 {
349 chunk_t chunk, idx, octets;
350 chunk_t skp;
351
352 skp = verify ? this->skp_verify : this->skp_build;
353
354 chunk = chunk_alloca(4);
355 memset(chunk.ptr, 0, chunk.len);
356 chunk.ptr[0] = id->get_type(id);
357 idx = chunk_cata("cc", chunk, id->get_encoding(id));
358
359 DBG3(DBG_IKE, "IDx' %B", &idx);
360 DBG3(DBG_IKE, "SK_p %B", &skp);
361 this->prf->set_key(this->prf, skp);
362 this->prf->allocate_bytes(this->prf, idx, &chunk);
363
364 octets = chunk_cat("ccm", ike_sa_init, nonce, chunk);
365 DBG3(DBG_IKE, "octets = message + nonce + prf(Sk_px, IDx') %B", &octets);
366 return octets;
367 }
368
369 /**
370 * Key pad for the AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
371 */
372 #define IKEV2_KEY_PAD "Key Pad for IKEv2"
373 #define IKEV2_KEY_PAD_LENGTH 17
374
375 /**
376 * Implementation of keymat_t.get_psk_sig
377 */
378 static chunk_t get_psk_sig(private_keymat_t *this, bool verify,
379 chunk_t ike_sa_init, chunk_t nonce, chunk_t secret,
380 identification_t *id)
381 {
382 chunk_t key_pad, key, sig, octets;
383
384 if (!secret.len)
385 { /* EAP uses SK_p if no MSK has been established */
386 secret = verify ? this->skp_verify : this->skp_build;
387 }
388 octets = get_auth_octets(this, verify, ike_sa_init, nonce, id);
389 /* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */
390 key_pad = chunk_create(IKEV2_KEY_PAD, IKEV2_KEY_PAD_LENGTH);
391 this->prf->set_key(this->prf, secret);
392 this->prf->allocate_bytes(this->prf, key_pad, &key);
393 this->prf->set_key(this->prf, key);
394 this->prf->allocate_bytes(this->prf, octets, &sig);
395 DBG4(DBG_IKE, "secret %B", &secret);
396 DBG4(DBG_IKE, "prf(secret, keypad) %B", &key);
397 DBG3(DBG_IKE, "AUTH = prf(prf(secret, keypad), octets) %B", &sig);
398 chunk_free(&octets);
399 chunk_free(&key);
400
401 return sig;
402 }
403
404 /**
405 * Implementation of keymat_t.destroy.
406 */
407 static void destroy(private_keymat_t *this)
408 {
409 DESTROY_IF(this->signer_in);
410 DESTROY_IF(this->signer_out);
411 DESTROY_IF(this->crypter_in);
412 DESTROY_IF(this->crypter_out);
413 DESTROY_IF(this->prf);
414 DESTROY_IF(this->child_prf);
415 DESTROY_IF(this->proposal);
416 chunk_clear(&this->skp_verify);
417 chunk_clear(&this->skp_build);
418 free(this);
419 }
420
421 /**
422 * See header
423 */
424 keymat_t *keymat_create(bool initiator)
425 {
426 private_keymat_t *this = malloc_thing(private_keymat_t);
427
428 this->public.create_dh = (diffie_hellman_t*(*)(keymat_t*, diffie_hellman_group_t group))create_dh;
429 this->public.derive_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_keys;
430 this->public.get_proposal = (proposal_t*(*)(keymat_t*))get_proposal;
431 this->public.get_signer = (signer_t*(*)(keymat_t*, bool in))get_signer;
432 this->public.get_crypter = (crypter_t*(*)(keymat_t*, bool in))get_crypter;
433 this->public.get_child_prf = (prf_t*(*)(keymat_t*))get_child_prf;
434 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;
435 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;
436 this->public.destroy = (void(*)(keymat_t*))destroy;
437
438 this->initiator = initiator;
439
440 this->signer_in = NULL;
441 this->signer_out = NULL;
442 this->crypter_in = NULL;
443 this->crypter_out = NULL;
444 this->prf = NULL;
445 this->child_prf = NULL;
446 this->proposal = NULL;
447 this->skp_verify = chunk_empty;
448 this->skp_build = chunk_empty;
449
450 return &this->public;
451 }
452