Moved generic RADIUS protocol support to a dedicated libradius
[strongswan.git] / src / pluto / alg_info.c
1 /*
2 * Algorithm info parsing and creation functions
3 * Copyright (C) JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
4 * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include <stddef.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <netinet/in.h>
22 #include <sys/socket.h>
23 #include <sys/stat.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
26
27 #include <ctype.h>
28 #include <freeswan.h>
29 #include <pfkeyv2.h>
30
31 #include <utils.h>
32 #include <utils/lexparser.h>
33 #include <crypto/diffie_hellman.h>
34 #include <crypto/transform.h>
35 #include <crypto/proposal/proposal_keywords.h>
36
37
38 #include "alg_info.h"
39 #include "constants.h"
40 #include "defs.h"
41 #include "log.h"
42 #include "whack.h"
43 #include "crypto.h"
44 #include "kernel_alg.h"
45 #include "ike_alg.h"
46
47 /*
48 * sadb/ESP aa attrib converters
49 */
50 int alg_info_esp_aa2sadb(int auth)
51 {
52 int sadb_aalg = 0;
53
54 switch(auth)
55 {
56 case AUTH_ALGORITHM_HMAC_MD5:
57 case AUTH_ALGORITHM_HMAC_SHA1:
58 sadb_aalg = auth + 1;
59 break;
60 default:
61 sadb_aalg = auth;
62 }
63 return sadb_aalg;
64 }
65
66 int alg_info_esp_sadb2aa(int sadb_aalg)
67 {
68 int auth = 0;
69
70 switch(sadb_aalg)
71 {
72 case SADB_AALG_MD5HMAC:
73 case SADB_AALG_SHA1HMAC:
74 auth = sadb_aalg - 1;
75 break;
76 default:
77 auth = sadb_aalg;
78 }
79 return auth;
80 }
81
82 void alg_info_free(struct alg_info *alg_info)
83 {
84 free(alg_info);
85 }
86
87 /*
88 * Raw add routine: only checks for no duplicates
89 */
90 static void __alg_info_esp_add(struct alg_info_esp *alg_info, int ealg_id,
91 unsigned ek_bits, int aalg_id, unsigned ak_bits)
92 {
93 struct esp_info *esp_info = alg_info->esp;
94 unsigned cnt = alg_info->alg_info_cnt, i;
95
96 /* check for overflows */
97 passert(cnt < countof(alg_info->esp));
98
99 /* dont add duplicates */
100 for (i = 0; i < cnt; i++)
101 {
102 if (esp_info[i].esp_ealg_id == ealg_id
103 && (!ek_bits || esp_info[i].esp_ealg_keylen == ek_bits)
104 && esp_info[i].esp_aalg_id == aalg_id
105 && (!ak_bits || esp_info[i].esp_aalg_keylen == ak_bits))
106 {
107 return;
108 }
109 }
110
111 esp_info[cnt].esp_ealg_id = ealg_id;
112 esp_info[cnt].esp_ealg_keylen = ek_bits;
113 esp_info[cnt].esp_aalg_id = aalg_id;
114 esp_info[cnt].esp_aalg_keylen = ak_bits;
115
116 /* sadb values */
117 esp_info[cnt].encryptalg = ealg_id;
118 esp_info[cnt].authalg = alg_info_esp_aa2sadb(aalg_id);
119 alg_info->alg_info_cnt++;
120
121 DBG(DBG_CRYPT,
122 DBG_log("esp alg added: %s_%d/%s, cnt=%d",
123 enum_show(&esp_transform_names, ealg_id), ek_bits,
124 enum_show(&auth_alg_names, aalg_id),
125 alg_info->alg_info_cnt)
126 )
127 }
128
129 /**
130 * Returns true if the given alg is an authenticated encryption algorithm
131 */
132 static bool is_authenticated_encryption(int ealg_id)
133 {
134 switch (ealg_id)
135 {
136 case ESP_AES_CCM_8:
137 case ESP_AES_CCM_12:
138 case ESP_AES_CCM_16:
139 case ESP_AES_GCM_8:
140 case ESP_AES_GCM_12:
141 case ESP_AES_GCM_16:
142 case ESP_AES_GMAC:
143 return TRUE;
144 }
145 return FALSE;
146 }
147
148 /*
149 * Add ESP alg info _with_ logic (policy):
150 */
151 static void alg_info_esp_add(struct alg_info *alg_info, int ealg_id,
152 int ek_bits, int aalg_id, int ak_bits)
153 {
154 /* Policy: default to 3DES */
155 if (ealg_id == 0)
156 {
157 ealg_id = ESP_3DES;
158 }
159 if (ealg_id > 0)
160 {
161 if (is_authenticated_encryption(ealg_id))
162 {
163 __alg_info_esp_add((struct alg_info_esp *)alg_info,
164 ealg_id, ek_bits,
165 AUTH_ALGORITHM_NONE, 0);
166 }
167 else if (aalg_id > 0)
168 {
169 __alg_info_esp_add((struct alg_info_esp *)alg_info,
170 ealg_id, ek_bits,
171 aalg_id, ak_bits);
172 }
173 else
174 {
175 /* Policy: default to SHA-1 and MD5 */
176 __alg_info_esp_add((struct alg_info_esp *)alg_info,
177 ealg_id, ek_bits,
178 AUTH_ALGORITHM_HMAC_SHA1, ak_bits);
179 __alg_info_esp_add((struct alg_info_esp *)alg_info,
180 ealg_id, ek_bits,
181 AUTH_ALGORITHM_HMAC_MD5, ak_bits);
182 }
183 }
184 }
185
186 static void __alg_info_ike_add (struct alg_info_ike *alg_info, int ealg_id,
187 unsigned ek_bits, int aalg_id, unsigned ak_bits,
188 int modp_id)
189 {
190 struct ike_info *ike_info = alg_info->ike;
191 unsigned cnt = alg_info->alg_info_cnt;
192 unsigned i;
193
194 /* check for overflows */
195 passert(cnt < countof(alg_info->ike));
196
197 /* dont add duplicates */
198 for (i = 0; i < cnt; i++)
199 {
200 if (ike_info[i].ike_ealg == ealg_id
201 && (!ek_bits || ike_info[i].ike_eklen == ek_bits)
202 && ike_info[i].ike_halg == aalg_id
203 && (!ak_bits || ike_info[i].ike_hklen == ak_bits)
204 && ike_info[i].ike_modp==modp_id)
205 return;
206 }
207
208 ike_info[cnt].ike_ealg = ealg_id;
209 ike_info[cnt].ike_eklen = ek_bits;
210 ike_info[cnt].ike_halg = aalg_id;
211 ike_info[cnt].ike_hklen = ak_bits;
212 ike_info[cnt].ike_modp = modp_id;
213 alg_info->alg_info_cnt++;
214
215 DBG(DBG_CRYPT,
216 DBG_log("ikg alg added: %s_%d/%s/%s, cnt=%d",
217 enum_show(&oakley_enc_names, ealg_id), ek_bits,
218 enum_show(&oakley_hash_names, aalg_id),
219 enum_show(&oakley_group_names, modp_id),
220 alg_info->alg_info_cnt)
221 )
222 }
223
224 /*
225 * Proposals will be built by looping over default_ike_groups array and
226 * merging alg_info (ike_info) contents
227 */
228
229 static int default_ike_groups[] = {
230 MODP_1536_BIT,
231 MODP_1024_BIT
232 };
233
234 /*
235 * Add IKE alg info _with_ logic (policy):
236 */
237 static void alg_info_ike_add (struct alg_info *alg_info, int ealg_id,
238 int ek_bits, int aalg_id, int ak_bits, int modp_id)
239 {
240 int i = 0;
241 int n_groups = countof(default_ike_groups);
242
243 /* if specified modp_id avoid loop over default_ike_groups */
244 if (modp_id)
245 {
246 n_groups=0;
247 goto in_loop;
248 }
249
250 for (; n_groups--; i++)
251 {
252 modp_id = default_ike_groups[i];
253 in_loop:
254 /* Policy: default to 3DES */
255 if (ealg_id == 0)
256 {
257 ealg_id = OAKLEY_3DES_CBC;
258 }
259 if (ealg_id > 0)
260 {
261 if (aalg_id > 0)
262 {
263 __alg_info_ike_add((struct alg_info_ike *)alg_info,
264 ealg_id, ek_bits,
265 aalg_id, ak_bits,
266 modp_id);
267 }
268 else
269 {
270 /* Policy: default to MD5 and SHA */
271 __alg_info_ike_add((struct alg_info_ike *)alg_info,
272 ealg_id, ek_bits,
273 OAKLEY_MD5, ak_bits,
274 modp_id);
275 __alg_info_ike_add((struct alg_info_ike *)alg_info,
276 ealg_id, ek_bits,
277 OAKLEY_SHA, ak_bits,
278 modp_id);
279 }
280 }
281 }
282 }
283
284 static status_t alg_info_add(chunk_t alg, unsigned protoid,
285 int *ealg, size_t *ealg_keysize,
286 int *aalg, size_t *aalg_keysize, int *dh_group)
287 {
288 const proposal_token_t *token = proposal_get_token(alg.ptr, alg.len);
289
290 if (token == NULL)
291 {
292 return FAILED;
293 }
294 switch (token->type)
295 {
296 case ENCRYPTION_ALGORITHM:
297 if (*ealg != 0)
298 {
299 return FAILED;
300 }
301 *ealg = (protoid == PROTO_ISAKMP) ?
302 oakley_from_encryption_algorithm(token->algorithm) :
303 esp_from_encryption_algorithm(token->algorithm);
304 if (*ealg == 0)
305 {
306 return FAILED;
307 }
308 *ealg_keysize = token->keysize;
309 break;
310 case INTEGRITY_ALGORITHM:
311 if (*aalg != 0)
312 {
313 return FAILED;
314 }
315 *aalg = (protoid == PROTO_ISAKMP) ?
316 oakley_from_integrity_algorithm(token->algorithm) :
317 esp_from_integrity_algorithm(token->algorithm);
318 if (*aalg == 0)
319 {
320 return FAILED;
321 }
322 *aalg_keysize = token->keysize;
323 break;
324 case DIFFIE_HELLMAN_GROUP:
325 if (protoid == PROTO_ISAKMP)
326 {
327 if (*dh_group != 0)
328 {
329 return FAILED;
330 }
331 *dh_group = token->algorithm;
332 }
333 break;
334 default:
335 return FAILED;
336 }
337 return SUCCESS;
338 }
339
340
341 static status_t alg_info_parse_str(struct alg_info *alg_info, char *alg_str)
342 {
343 char *strict, *single;
344 status_t status = SUCCESS;
345
346 strict = alg_str + strlen(alg_str) - 1;
347 if (*strict == '!')
348 {
349 alg_info->alg_info_flags |= ALG_INFO_F_STRICT;
350 *strict = '\0';
351 }
352 while ((single = strsep(&alg_str, ",")))
353 {
354 chunk_t string = { (u_char *)single, strlen(single) };
355 int ealg = 0;
356 int aalg = 0;
357 int dh_group = 0;
358 size_t ealg_keysize = 0;
359 size_t aalg_keysize = 0;
360
361 eat_whitespace(&string);
362
363 if (string.len > 0)
364 {
365 chunk_t alg;
366
367 /* get all token, separated by '-' */
368 while (extract_token(&alg, '-', &string))
369 {
370 status |= alg_info_add(alg, alg_info->alg_info_protoid,
371 &ealg, &ealg_keysize,
372 &aalg, &aalg_keysize, &dh_group);
373 }
374 if (string.len)
375 {
376 status |= alg_info_add(string, alg_info->alg_info_protoid,
377 &ealg, &ealg_keysize,
378 &aalg, &aalg_keysize, &dh_group);
379 }
380 }
381 if (status == SUCCESS)
382
383 {
384 switch (alg_info->alg_info_protoid)
385 {
386 case PROTO_IPSEC_ESP:
387 alg_info_esp_add(alg_info, ealg, ealg_keysize,
388 aalg, aalg_keysize);
389 break;
390 case PROTO_ISAKMP:
391 alg_info_ike_add(alg_info, ealg, ealg_keysize,
392 aalg, aalg_keysize,
393 dh_group);
394 break;
395 default:
396 break;
397 }
398 }
399 }
400 return status;
401 }
402
403 struct alg_info_esp *alg_info_esp_create_from_str(char *alg_str)
404 {
405 struct alg_info_esp *alg_info_esp;
406 char esp_buf[BUF_LEN];
407 char *pfs_name;
408 status_t status = SUCCESS;
409 /*
410 * alg_info storage should be sized dynamically
411 * but this may require 2passes to know
412 * transform count in advance.
413 */
414 alg_info_esp = malloc_thing (struct alg_info_esp);
415 zero(alg_info_esp);
416
417 pfs_name=strchr(alg_str, ';');
418 if (pfs_name)
419 {
420 memcpy(esp_buf, alg_str, pfs_name-alg_str);
421 esp_buf[pfs_name-alg_str] = 0;
422 alg_str = esp_buf;
423 pfs_name++;
424
425 /* if pfs strings AND first char is not '0' */
426 if (*pfs_name && pfs_name[0] != '0')
427 {
428 const proposal_token_t *token;
429
430 token = proposal_get_token(pfs_name, strlen(pfs_name));
431 if (token == NULL || token->type != DIFFIE_HELLMAN_GROUP)
432 {
433 /* Bomb if pfsgroup not found */
434 DBG(DBG_CRYPT,
435 DBG_log("alg_info_esp_create_from_str(): pfsgroup \"%s\" not found"
436 , pfs_name)
437 )
438 status = FAILED;
439 goto out;
440 }
441 alg_info_esp->esp_pfsgroup = token->algorithm;
442 }
443 }
444 else
445 {
446 alg_info_esp->esp_pfsgroup = 0;
447 }
448 alg_info_esp->alg_info_protoid = PROTO_IPSEC_ESP;
449 status = alg_info_parse_str((struct alg_info *)alg_info_esp, alg_str);
450
451 out:
452 if (status == SUCCESS)
453 {
454 alg_info_esp->ref_cnt = 1;
455 return alg_info_esp;
456 }
457 else
458 {
459 free(alg_info_esp);
460 return NULL;
461 }
462 }
463
464 struct alg_info_ike *alg_info_ike_create_from_str(char *alg_str)
465 {
466 struct alg_info_ike *alg_info_ike;
467 /*
468 * alg_info storage should be sized dynamically
469 * but this may require 2passes to know
470 * transform count in advance.
471 */
472 alg_info_ike = malloc_thing (struct alg_info_ike);
473 zero(alg_info_ike);
474 alg_info_ike->alg_info_protoid = PROTO_ISAKMP;
475
476 if (alg_info_parse_str((struct alg_info *)alg_info_ike, alg_str) == SUCCESS)
477 {
478 alg_info_ike->ref_cnt = 1;
479 return alg_info_ike;
480 }
481 else
482 {
483 free(alg_info_ike);
484 return NULL;
485 }
486 }
487
488 /*
489 * alg_info struct can be shared by
490 * several connections instances,
491 * handle free() with ref_cnts
492 */
493 void
494 alg_info_addref(struct alg_info *alg_info)
495 {
496 if (alg_info != NULL)
497 {
498 alg_info->ref_cnt++;
499 }
500 }
501
502 void
503 alg_info_delref(struct alg_info **alg_info_p)
504 {
505 struct alg_info *alg_info = *alg_info_p;
506
507 if (alg_info != NULL)
508 {
509 passert(alg_info->ref_cnt != 0);
510 alg_info->ref_cnt--;
511 if (alg_info->ref_cnt == 0)
512 {
513 alg_info_free(alg_info);
514 }
515 *alg_info_p = NULL;
516 }
517 }
518
519 /* snprint already parsed transform list (alg_info) */
520 int
521 alg_info_snprint(char *buf, int buflen, struct alg_info *alg_info)
522 {
523 char *ptr = buf;
524 int np = 0;
525 struct esp_info *esp_info;
526 struct ike_info *ike_info;
527 int cnt;
528
529 switch (alg_info->alg_info_protoid) {
530 case PROTO_IPSEC_ESP:
531 {
532 struct alg_info_esp *alg_info_esp = (struct alg_info_esp *)alg_info;
533
534 ALG_INFO_ESP_FOREACH(alg_info_esp, esp_info, cnt)
535 {
536 np = snprintf(ptr, buflen, "%s",
537 enum_show(&esp_transform_names, esp_info->esp_ealg_id));
538 ptr += np;
539 buflen -= np;
540 if (esp_info->esp_ealg_keylen)
541 {
542 np = snprintf(ptr, buflen, "_%zu", esp_info->esp_ealg_keylen);
543 ptr += np;
544 buflen -= np;
545 }
546 np = snprintf(ptr, buflen, "/%s, ",
547 enum_show(&auth_alg_names, esp_info->esp_aalg_id));
548 ptr += np;
549 buflen -= np;
550 if (buflen < 0)
551 goto out;
552 }
553 if (alg_info_esp->esp_pfsgroup)
554 {
555 np = snprintf(ptr, buflen, "; pfsgroup=%s; ",
556 enum_show(&oakley_group_names, alg_info_esp->esp_pfsgroup));
557 ptr += np;
558 buflen -= np;
559 if (buflen < 0)
560 goto out;
561 }
562 break;
563 }
564
565 case PROTO_ISAKMP:
566 ALG_INFO_IKE_FOREACH((struct alg_info_ike *)alg_info, ike_info, cnt)
567 {
568 np = snprintf(ptr, buflen, "%s",
569 enum_show(&oakley_enc_names, ike_info->ike_ealg));
570 ptr += np;
571 buflen -= np;
572 if (ike_info->ike_eklen)
573 {
574 np = snprintf(ptr, buflen, "_%zu", ike_info->ike_eklen);
575 ptr += np;
576 buflen -= np;
577 }
578 np = snprintf(ptr, buflen, "/%s/%s, ",
579 enum_show(&oakley_hash_names, ike_info->ike_halg),
580 enum_show(&oakley_group_names, ike_info->ike_modp));
581 ptr += np;
582 buflen -= np;
583 if (buflen < 0)
584 goto out;
585 }
586 break;
587 default:
588 np = snprintf(buf, buflen, "INVALID protoid=%d\n"
589 , alg_info->alg_info_protoid);
590 ptr += np;
591 buflen -= np;
592 goto out;
593 }
594
595 np = snprintf(ptr, buflen, "%s"
596 , alg_info->alg_info_flags & ALG_INFO_F_STRICT?
597 "strict":"");
598 ptr += np;
599 buflen -= np;
600 out:
601 if (buflen < 0)
602 {
603 loglog(RC_LOG_SERIOUS
604 , "buffer space exhausted in alg_info_snprint_ike(), buflen=%d"
605 , buflen);
606 }
607
608 return ptr - buf;
609 }
610
611 int alg_info_snprint_esp(char *buf, int buflen, struct alg_info_esp *alg_info)
612 {
613 char *ptr = buf;
614
615 int cnt = alg_info->alg_info_cnt;
616 struct esp_info *esp_info = alg_info->esp;
617
618 while (cnt--)
619 {
620 if (kernel_alg_esp_enc_ok(esp_info->esp_ealg_id, 0, NULL)
621 && kernel_alg_esp_auth_ok(esp_info->esp_aalg_id, NULL))
622 {
623 u_int eklen = (esp_info->esp_ealg_keylen)
624 ? esp_info->esp_ealg_keylen
625 : kernel_alg_esp_enc_keylen(esp_info->esp_ealg_id)
626 * BITS_PER_BYTE;
627
628 u_int aklen = esp_info->esp_aalg_keylen
629 ? esp_info->esp_aalg_keylen
630 : kernel_alg_esp_auth_keylen(esp_info->esp_aalg_id)
631 * BITS_PER_BYTE;
632
633 int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d, ",
634 esp_info->esp_ealg_id, eklen,
635 esp_info->esp_aalg_id, aklen);
636 ptr += ret;
637 buflen -= ret;
638 if (buflen < 0)
639 break;
640 }
641 esp_info++;
642 }
643 return ptr - buf;
644 }
645
646 int alg_info_snprint_ike(char *buf, int buflen, struct alg_info_ike *alg_info)
647 {
648 char *ptr = buf;
649
650 int cnt = alg_info->alg_info_cnt;
651 struct ike_info *ike_info = alg_info->ike;
652
653 while (cnt--)
654 {
655 struct encrypt_desc *enc_desc = ike_alg_get_crypter(ike_info->ike_ealg);
656 struct hash_desc *hash_desc = ike_alg_get_hasher(ike_info->ike_halg);
657 struct dh_desc *dh_desc = ike_alg_get_dh_group(ike_info->ike_modp);
658
659 if (enc_desc && hash_desc && dh_desc)
660 {
661
662 u_int eklen = (ike_info->ike_eklen)
663 ? ike_info->ike_eklen
664 : enc_desc->keydeflen;
665
666 u_int aklen = (ike_info->ike_hklen)
667 ? ike_info->ike_hklen
668 : hash_desc->hash_digest_size * BITS_PER_BYTE;
669
670 int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d-%d, ",
671 ike_info->ike_ealg, eklen,
672 ike_info->ike_halg, aklen,
673 ike_info->ike_modp);
674 ptr += ret;
675 buflen -= ret;
676 if (buflen < 0)
677 break;
678 }
679 ike_info++;
680 }
681 return ptr - buf;
682 }
683