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