use the Diffie-Hellman functionality of libstrongswan
[strongswan.git] / src / pluto / ike_alg.c
1 /* IKE modular algorithm handling interface
2 * Copyright (C) JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
3 * Copyright (C) 2009 Andreas Steffen - 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 <stdio.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <errno.h>
20 #include <sys/queue.h>
21
22 #include <freeswan.h>
23 #include <ipsec_policy.h>
24
25 #include <library.h>
26 #include <debug.h>
27 #include <crypto/hashers/hasher.h>
28 #include <crypto/crypters/crypter.h>
29 #include <crypto/prfs/prf.h>
30
31 #include "constants.h"
32 #include "defs.h"
33 #include "crypto.h"
34
35 #include "state.h"
36 #include "packet.h"
37 #include "log.h"
38 #include "whack.h"
39 #include "spdb.h"
40 #include "alg_info.h"
41 #include "ike_alg.h"
42 #include "db_ops.h"
43 #include "connections.h"
44 #include "kernel.h"
45
46 #define return_on(var, val) do { var=val;goto return_out; } while(0);
47
48 /**
49 * IKE algorithm list handling - registration and lookup
50 */
51
52 /* Modular IKE algorithm storage structure */
53
54 static struct ike_alg *ike_alg_base[IKE_ALG_MAX+1] = {NULL, NULL};
55
56 /**
57 * Return ike_algo object by {type, id}
58 */
59 static struct ike_alg *ike_alg_find(u_int algo_type, u_int algo_id,
60 u_int keysize __attribute__((unused)))
61 {
62 struct ike_alg *e = ike_alg_base[algo_type];
63
64 while (e != NULL && algo_id > e->algo_id)
65 {
66 e = e->algo_next;
67 }
68 return (e != NULL && e->algo_id == algo_id) ? e : NULL;
69 }
70
71 /**
72 * "raw" ike_alg list adding function
73 */
74 int ike_alg_add(struct ike_alg* a)
75 {
76 if (a->algo_type > IKE_ALG_MAX)
77 {
78 plog("ike_alg: Not added, invalid algorithm type");
79 return -EINVAL;
80 }
81
82 if (ike_alg_find(a->algo_type, a->algo_id, 0) != NULL)
83 {
84 plog("ike_alg: Not added, algorithm already exists");
85 return -EEXIST;
86 }
87
88 {
89 struct ike_alg **ep = &ike_alg_base[a->algo_type];
90 struct ike_alg *e = *ep;
91
92 while (e != NULL && a->algo_id > e->algo_id)
93 {
94 ep = &e->algo_next;
95 e = *ep;
96 }
97 *ep = a;
98 a->algo_next = e;
99 return 0;
100 }
101 }
102
103 /**
104 * Get IKE hash algorithm
105 */
106 struct hash_desc *ike_alg_get_hasher(u_int alg)
107 {
108 return (struct hash_desc *) ike_alg_find(IKE_ALG_HASH, alg, 0);
109 }
110
111 /**
112 * Get IKE encryption algorithm
113 */
114 struct encrypt_desc *ike_alg_get_crypter(u_int alg)
115 {
116 return (struct encrypt_desc *) ike_alg_find(IKE_ALG_ENCRYPT, alg, 0);
117 }
118
119 /**
120 * Get IKE dh group
121 */
122 struct dh_desc *ike_alg_get_dh_group(u_int alg)
123 {
124 return (struct dh_desc *) ike_alg_find(IKE_ALG_DH_GROUP, alg, 0);
125 }
126
127 /**
128 * Get pfsgroup for this connection
129 */
130 const struct dh_desc *ike_alg_pfsgroup(struct connection *c, lset_t policy)
131 {
132 const struct dh_desc *ret = NULL;
133
134 if ((policy & POLICY_PFS) &&
135 c->alg_info_esp && c->alg_info_esp->esp_pfsgroup)
136 {
137 ret = ike_alg_get_dh_group(c->alg_info_esp->esp_pfsgroup);
138 }
139 return ret;
140 }
141
142 /**
143 * Create an OAKLEY proposal based on alg_info and policy
144 */
145 struct db_context *ike_alg_db_new(struct alg_info_ike *ai , lset_t policy)
146 {
147 struct db_context *db_ctx = NULL;
148 struct ike_info *ike_info;
149 struct encrypt_desc *enc_desc;
150 u_int ealg, halg, modp, eklen = 0;
151 int i;
152
153 bool is_xauth_server = (policy & POLICY_XAUTH_SERVER) != LEMPTY;
154
155 if (!ai)
156 {
157 whack_log(RC_LOG_SERIOUS, "no IKE algorithms "
158 "for this connection "
159 "(check ike algorithm string)");
160 goto fail;
161 }
162 policy &= POLICY_ID_AUTH_MASK;
163 db_ctx = db_prop_new(PROTO_ISAKMP, 8, 8 * 5);
164
165 /* for each group */
166 ALG_INFO_IKE_FOREACH(ai, ike_info, i)
167 {
168 ealg = ike_info->ike_ealg;
169 halg = ike_info->ike_halg;
170 modp = ike_info->ike_modp;
171 eklen= ike_info->ike_eklen;
172
173 if (!ike_alg_get_crypter(ealg))
174 {
175 DBG_log("ike_alg: ike crypter %s not present",
176 enum_show(&oakley_enc_names, ealg));
177 continue;
178 }
179 if (!ike_alg_get_hasher(halg))
180 {
181 DBG_log("ike_alg: ike hasher %s not present",
182 enum_show(&oakley_hash_names, halg));
183 continue;
184 }
185 if (!ike_alg_get_dh_group(modp))
186 {
187 DBG_log("ike_alg: ike dh group %s not present",
188 enum_show(&oakley_group_names, modp));
189 continue;
190 }
191 enc_desc = ike_alg_get_crypter(ealg);
192
193 if (policy & POLICY_RSASIG)
194 {
195 db_trans_add(db_ctx, KEY_IKE);
196 db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
197 db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
198 if (eklen)
199 db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
200 db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG);
201 db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
202 }
203
204 if (policy & POLICY_PSK)
205 {
206 db_trans_add(db_ctx, KEY_IKE);
207 db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
208 db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
209 if (eklen)
210 db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
211 db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY);
212 db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
213 }
214
215 if (policy & POLICY_XAUTH_RSASIG)
216 {
217 db_trans_add(db_ctx, KEY_IKE);
218 db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
219 db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
220 if (eklen)
221 db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
222 db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD
223 , is_xauth_server ? XAUTHRespRSA : XAUTHInitRSA);
224 db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
225 }
226
227 if (policy & POLICY_XAUTH_PSK)
228 {
229 db_trans_add(db_ctx, KEY_IKE);
230 db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
231 db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
232 if (eklen)
233 db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
234 db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD
235 , is_xauth_server ? XAUTHRespPreShared : XAUTHInitPreShared);
236 db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
237 }
238 }
239 fail:
240 return db_ctx;
241 }
242
243 /**
244 * Show registered IKE algorithms
245 */
246 void ike_alg_list(void)
247 {
248 char buf[BUF_LEN];
249 char *pos;
250 int n, len;
251 struct ike_alg *a;
252
253 whack_log(RC_COMMENT, " ");
254 whack_log(RC_COMMENT, "List of registered IKEv1 Algorithms:");
255 whack_log(RC_COMMENT, " ");
256
257 pos = buf;
258 *pos = '\0';
259 len = BUF_LEN;
260 for (a = ike_alg_base[IKE_ALG_ENCRYPT]; a != NULL; a = a->algo_next)
261 {
262 n = snprintf(pos, len, " %s", enum_name(&oakley_enc_names, a->algo_id));
263 pos += n;
264 len -= n;
265 if (len <= 0)
266 {
267 break;
268 }
269 }
270 whack_log(RC_COMMENT, " encryption:%s", buf);
271
272 pos = buf;
273 *pos = '\0';
274 len = BUF_LEN;
275 for (a = ike_alg_base[IKE_ALG_HASH]; a != NULL; a = a->algo_next)
276 {
277 n = snprintf(pos, len, " %s", enum_name(&oakley_hash_names, a->algo_id));
278 pos += n;
279 len -= n;
280 if (len <= 0)
281 {
282 break;
283 }
284 }
285 whack_log(RC_COMMENT, " hasher: %s", buf);
286
287 pos = buf;
288 *pos = '\0';
289 len = BUF_LEN;
290 for (a = ike_alg_base[IKE_ALG_DH_GROUP]; a != NULL; a = a->algo_next)
291 {
292 n = snprintf(pos, len, " %s", enum_name(&oakley_group_names, a->algo_id));
293 pos += n;
294 len -= n;
295 if (len <= 0)
296 {
297 break;
298 }
299 }
300 whack_log(RC_COMMENT, " dh-group: %s", buf);
301 }
302
303 /**
304 * Show IKE algorithms for this connection (result from ike= string)
305 * and newest SA
306 */
307 void ike_alg_show_connection(struct connection *c, const char *instance)
308 {
309 struct state *st = state_with_serialno(c->newest_isakmp_sa);
310
311 if (st)
312 {
313 if (st->st_oakley.encrypt == OAKLEY_3DES_CBC)
314 {
315 whack_log(RC_COMMENT,
316 "\"%s\"%s: IKE proposal: %s/%s/%s",
317 c->name, instance,
318 enum_show(&oakley_enc_names, st->st_oakley.encrypt),
319 enum_show(&oakley_hash_names, st->st_oakley.hash),
320 enum_show(&oakley_group_names, st->st_oakley.group->algo_id)
321 );
322 }
323 else
324 {
325 whack_log(RC_COMMENT,
326 "\"%s\"%s: IKE proposal: %s_%u/%s/%s",
327 c->name, instance,
328 enum_show(&oakley_enc_names, st->st_oakley.encrypt),
329 st->st_oakley.enckeylen,
330 enum_show(&oakley_hash_names, st->st_oakley.hash),
331 enum_show(&oakley_group_names, st->st_oakley.group->algo_id)
332 );
333 }
334 }
335 }
336
337 /**
338 * Apply a suite of testvectors to an encryption algorithm
339 */
340 static bool ike_encrypt_test(const struct encrypt_desc *desc)
341 {
342 bool encrypt_results = TRUE;
343
344 if (desc->enc_testvectors == NULL)
345 {
346 plog(" %s encryption self-test not available",
347 enum_name(&oakley_enc_names, desc->algo_id));
348 }
349 else
350 {
351 int i;
352 encryption_algorithm_t enc_alg;
353
354 enc_alg = oakley_to_encryption_algorithm(desc->algo_id);
355
356 for (i = 0; desc->enc_testvectors[i].key != NULL; i++)
357 {
358 bool result;
359 crypter_t *crypter;
360 chunk_t key = { (u_char*)desc->enc_testvectors[i].key,
361 desc->enc_testvectors[i].key_size };
362 chunk_t plain = { (u_char*)desc->enc_testvectors[i].plain,
363 desc->enc_testvectors[i].data_size};
364 chunk_t cipher = { (u_char*)desc->enc_testvectors[i].cipher,
365 desc->enc_testvectors[i].data_size};
366 chunk_t encrypted = chunk_empty;
367 chunk_t decrypted = chunk_empty;
368 chunk_t iv;
369
370 crypter = lib->crypto->create_crypter(lib->crypto, enc_alg, key.len);
371 if (crypter == NULL)
372 {
373 plog(" %s encryption function not available",
374 enum_name(&oakley_enc_names, desc->algo_id));
375 return FALSE;
376 }
377 iv = chunk_create((u_char*)desc->enc_testvectors[i].iv,
378 crypter->get_block_size(crypter));
379 crypter->set_key(crypter, key);
380 crypter->decrypt(crypter, cipher, iv, &decrypted);
381 result = chunk_equals(decrypted, plain);
382 crypter->encrypt(crypter, plain, iv, &encrypted);
383 result &= chunk_equals(encrypted, cipher);
384 DBG(DBG_CRYPT,
385 DBG_log(" enc testvector %d: %s", i, result ? "ok":"failed")
386 )
387 encrypt_results &= result;
388 crypter->destroy(crypter);
389 free(encrypted.ptr);
390 free(decrypted.ptr);
391 }
392 plog(" %s encryption self-test %s",
393 enum_name(&oakley_enc_names, desc->algo_id),
394 encrypt_results ? "passed":"failed");
395 }
396 return encrypt_results;
397 }
398
399 /**
400 * Apply a suite of testvectors to a hash algorithm
401 */
402 static bool ike_hash_test(const struct hash_desc *desc)
403 {
404 bool hash_results = TRUE;
405 bool hmac_results = TRUE;
406
407 if (desc->hash_testvectors == NULL)
408 {
409 plog(" %s hash self-test not available",
410 enum_name(&oakley_hash_names, desc->algo_id));
411 }
412 else
413 {
414 int i;
415 hash_algorithm_t hash_alg;
416 hasher_t *hasher;
417
418 hash_alg = oakley_to_hash_algorithm(desc->algo_id);
419 hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
420 if (hasher == NULL)
421 {
422 plog(" %s hash function not available",
423 enum_name(&oakley_hash_names, desc->algo_id));
424 return FALSE;
425 }
426
427 for (i = 0; desc->hash_testvectors[i].msg_digest != NULL; i++)
428 {
429 u_char digest[MAX_DIGEST_LEN];
430 chunk_t msg = { (u_char*)desc->hash_testvectors[i].msg,
431 desc->hash_testvectors[i].msg_size };
432 bool result;
433
434 hasher->get_hash(hasher, msg, digest);
435 result = memeq(digest, desc->hash_testvectors[i].msg_digest
436 , desc->hash_digest_size);
437 DBG(DBG_CRYPT,
438 DBG_log(" hash testvector %d: %s", i, result ? "ok":"failed")
439 )
440 hash_results &= result;
441 }
442 hasher->destroy(hasher);
443 plog(" %s hash self-test %s", enum_name(&oakley_hash_names, desc->algo_id),
444 hash_results ? "passed":"failed");
445 }
446
447 if (desc->hmac_testvectors == NULL)
448 {
449 plog(" %s hmac self-test not available", enum_name(&oakley_hash_names, desc->algo_id));
450 }
451 else
452 {
453 int i;
454 pseudo_random_function_t prf_alg;
455
456 prf_alg = oakley_to_prf(desc->algo_id);
457
458 for (i = 0; desc->hmac_testvectors[i].hmac != NULL; i++)
459 {
460 u_char digest[MAX_DIGEST_LEN];
461 chunk_t key = { (u_char*)desc->hmac_testvectors[i].key,
462 desc->hmac_testvectors[i].key_size };
463 chunk_t msg = { (u_char*)desc->hmac_testvectors[i].msg,
464 desc->hmac_testvectors[i].msg_size };
465 prf_t *prf;
466 bool result;
467
468 prf = lib->crypto->create_prf(lib->crypto, prf_alg);
469 if (prf == NULL)
470 {
471 plog(" %s hmac function not available",
472 enum_name(&oakley_hash_names, desc->algo_id));
473 return FALSE;
474 }
475 prf->set_key(prf, key);
476 prf->get_bytes(prf, msg, digest);
477 prf->destroy(prf);
478 result = memeq(digest, desc->hmac_testvectors[i].hmac,
479 desc->hash_digest_size);
480 DBG(DBG_CRYPT,
481 DBG_log(" hmac testvector %d: %s", i, result ? "ok":"failed")
482 )
483 hmac_results &= result;
484 }
485 plog(" %s hmac self-test %s", enum_name(&oakley_hash_names, desc->algo_id)
486 , hmac_results ? "passed":"failed");
487 }
488 return hash_results && hmac_results;
489 }
490
491 /**
492 * Apply test vectors to registered encryption and hash algorithms
493 */
494 bool ike_alg_test(void)
495 {
496 bool all_results = TRUE;
497 struct ike_alg *a;
498
499 plog("Testing registered IKE crypto algorithms:");
500
501 for (a = ike_alg_base[IKE_ALG_ENCRYPT]; a != NULL; a = a->algo_next)
502 {
503 struct encrypt_desc *desc = (struct encrypt_desc*)a;
504
505 all_results &= ike_encrypt_test(desc);
506 }
507
508 for (a = ike_alg_base[IKE_ALG_HASH]; a != NULL; a = a->algo_next)
509 {
510 struct hash_desc *desc = (struct hash_desc*)a;
511
512 all_results &= ike_hash_test(desc);
513 }
514
515 if (all_results)
516 plog("All crypto self-tests passed");
517 else
518 plog("Some crypto self-tests failed");
519 return all_results;
520 }
521
522 /**
523 * ML: make F_STRICT logic consider enc,hash/auth,modp algorithms
524 */
525 bool ike_alg_ok_final(u_int ealg, u_int key_len, u_int aalg, u_int group,
526 struct alg_info_ike *alg_info_ike)
527 {
528 /*
529 * simple test to discard low key_len, will accept it only
530 * if specified in "esp" string
531 */
532 bool ealg_insecure = (key_len < 128);
533
534 if (ealg_insecure
535 || (alg_info_ike && alg_info_ike->alg_info_flags & ALG_INFO_F_STRICT))
536 {
537 int i;
538 struct ike_info *ike_info;
539
540 if (alg_info_ike)
541 {
542 ALG_INFO_IKE_FOREACH(alg_info_ike, ike_info, i)
543 {
544 if (ike_info->ike_ealg == ealg
545 && (ike_info->ike_eklen == 0 || key_len == 0 || ike_info->ike_eklen == key_len)
546 && ike_info->ike_halg == aalg
547 && ike_info->ike_modp == group)
548 {
549 if (ealg_insecure)
550 loglog(RC_LOG_SERIOUS, "You should NOT use insecure IKE algorithms (%s)!"
551 , enum_name(&oakley_enc_names, ealg));
552 return TRUE;
553 }
554 }
555 }
556 plog("Oakley Transform [%s (%d), %s, %s] refused due to %s"
557 , enum_name(&oakley_enc_names, ealg), key_len
558 , enum_name(&oakley_hash_names, aalg)
559 , enum_name(&oakley_group_names, group)
560 , ealg_insecure ?
561 "insecure key_len and enc. alg. not listed in \"ike\" string" : "strict flag"
562 );
563 return FALSE;
564 }
565 return TRUE;
566 }
567