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