SKEYID derivation based on libstrongswan
[strongswan.git] / src / pluto / alg_info.c
1 /*
2 * Algorithm info parsing and creation functions
3 * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
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 <stddef.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <string.h>
20 #include <netinet/in.h>
21 #include <sys/socket.h>
22 #include <sys/stat.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
25
26 #include <ctype.h>
27 #include <freeswan.h>
28 #include <ipsec_policy.h>
29 #include <pfkeyv2.h>
30
31 #include "alg_info.h"
32 #include "constants.h"
33 #include "defs.h"
34 #include "log.h"
35 #include "whack.h"
36 #include "crypto.h"
37 #include "kernel_alg.h"
38 #include "ike_alg.h"
39
40 /*
41 * sadb/ESP aa attrib converters
42 */
43 int
44 alg_info_esp_aa2sadb(int auth)
45 {
46 int sadb_aalg = 0;
47
48 switch(auth) {
49 case AUTH_ALGORITHM_HMAC_MD5:
50 case AUTH_ALGORITHM_HMAC_SHA1:
51 sadb_aalg = auth + 1;
52 break;
53 case AUTH_ALGORITHM_HMAC_SHA2_256:
54 case AUTH_ALGORITHM_HMAC_SHA2_384:
55 case AUTH_ALGORITHM_HMAC_SHA2_512:
56 case AUTH_ALGORITHM_HMAC_RIPEMD:
57 sadb_aalg = auth;
58 break;
59 default:
60 /* loose ... */
61 sadb_aalg = auth;
62 }
63 return sadb_aalg;
64 }
65
66 int /* __attribute__ ((unused)) */
67 alg_info_esp_sadb2aa(int sadb_aalg)
68 {
69 int auth = 0;
70
71 switch(sadb_aalg) {
72 case SADB_AALG_MD5HMAC:
73 case SADB_AALG_SHA1HMAC:
74 auth = sadb_aalg - 1;
75 break;
76 /* since they are the same ... :) */
77 case AUTH_ALGORITHM_HMAC_SHA2_256:
78 case AUTH_ALGORITHM_HMAC_SHA2_384:
79 case AUTH_ALGORITHM_HMAC_SHA2_512:
80 case AUTH_ALGORITHM_HMAC_RIPEMD:
81 auth = sadb_aalg;
82 break;
83 default:
84 /* loose ... */
85 auth = sadb_aalg;
86 }
87 return auth;
88 }
89
90 /*
91 * Search enum_name array with in prefixed uppercase
92 */
93 static int
94 enum_search_prefix (enum_names *ed, const char *prefix, const char *str, int strlen)
95 {
96 char buf[64];
97 char *ptr;
98 int ret;
99 int len = sizeof(buf) - 1; /* reserve space for final \0 */
100
101 for (ptr = buf; *prefix; *ptr++ = *prefix++, len--);
102 while (strlen-- && len-- && *str) *ptr++ = toupper(*str++);
103 *ptr = 0;
104
105 DBG(DBG_CRYPT,
106 DBG_log("enum_search_prefix () calling enum_search(%p, \"%s\")"
107 , ed, buf)
108 )
109 ret = enum_search(ed, buf);
110 return ret;
111 }
112
113 /*
114 * Search enum_name array with in prefixed and postfixed uppercase
115 */
116 static int
117 enum_search_ppfix (enum_names *ed, const char *prefix, const char *postfix, const char *str, int strlen)
118 {
119 char buf[64];
120 char *ptr;
121 int ret;
122 int len = sizeof(buf) - 1; /* reserve space for final \0 */
123
124 for (ptr = buf; *prefix; *ptr++ = *prefix++, len--);
125 while (strlen-- && len-- && *str) *ptr++ = toupper(*str++);
126 while (len-- && *postfix) *ptr++ = *postfix++;
127 *ptr = 0;
128
129 DBG(DBG_CRYPT,
130 DBG_log("enum_search_ppfixi () calling enum_search(%p, \"%s\")"
131 , ed, buf)
132 )
133 ret = enum_search(ed, buf);
134 return ret;
135 }
136
137 /*
138 * Search esp_transformid_names for a match, eg:
139 * "3des" <=> "ESP_3DES"
140 */
141 #define ESP_MAGIC_ID 0x00ffff01
142
143 static int
144 ealg_getbyname_esp(const char *const str, int len)
145 {
146 if (!str || !*str)
147 {
148 return -1;
149 }
150
151 /* leave special case for eg: "id248" string */
152 if (streq("id", str))
153 {
154 return ESP_MAGIC_ID;
155 }
156 return enum_search_prefix(&esp_transformid_names, "ESP_", str, len);
157 }
158
159 /*
160 * Search auth_alg_names for a match, eg:
161 * "md5" <=> "AUTH_ALGORITHM_HMAC_MD5"
162 */
163 static int
164 aalg_getbyname_esp(const char *const str, int len)
165 {
166 int ret;
167 unsigned num;
168
169 if (!str || !*str)
170 return -1;
171
172 /* interpret 'SHA' as 'SHA1' */
173 if (strncasecmp("SHA", str, len) == 0)
174 return AUTH_ALGORITHM_HMAC_SHA1;
175
176 /* interpret 'AESXCBC' as 'AES_XCBC_MAC' */
177 if (strncasecmp("AESXCBC", str, len) == 0)
178 return AUTH_ALGORITHM_AES_XCBC_MAC;
179
180 ret = enum_search_prefix(&auth_alg_names,"AUTH_ALGORITHM_HMAC_", str ,len);
181 if (ret >= 0)
182 return ret;
183
184 ret = enum_search_prefix(&auth_alg_names,"AUTH_ALGORITHM_", str, len);
185 if (ret >= 0)
186 return ret;
187
188 sscanf(str, "id%d%n", &ret, &num);
189 return (ret >= 0 && num != strlen(str))? -1 : ret;
190 }
191
192 static int
193 modp_getbyname_esp(const char *const str, int len)
194 {
195 int ret;
196
197 if (!str || !*str)
198 return -1;
199
200 ret = enum_search_prefix(&oakley_group_names,"OAKLEY_GROUP_", str, len);
201 if (ret >= 0)
202 return ret;
203
204 ret = enum_search_ppfix(&oakley_group_names, "OAKLEY_GROUP_", " (extension)", str, len);
205 return ret;
206 }
207
208 void
209 alg_info_free(struct alg_info *alg_info)
210 {
211 free(alg_info);
212 }
213
214 /*
215 * Raw add routine: only checks for no duplicates
216 */
217 static void
218 __alg_info_esp_add (struct alg_info_esp *alg_info, int ealg_id, unsigned ek_bits, int aalg_id, unsigned ak_bits)
219 {
220 struct esp_info *esp_info = alg_info->esp;
221 unsigned cnt = alg_info->alg_info_cnt, i;
222
223 /* check for overflows */
224 passert(cnt < countof(alg_info->esp));
225
226 /* dont add duplicates */
227 for (i = 0; i < cnt; i++)
228 {
229 if (esp_info[i].esp_ealg_id == ealg_id
230 && (!ek_bits || esp_info[i].esp_ealg_keylen == ek_bits)
231 && esp_info[i].esp_aalg_id == aalg_id
232 && (!ak_bits || esp_info[i].esp_aalg_keylen == ak_bits))
233 return;
234 }
235
236 esp_info[cnt].esp_ealg_id = ealg_id;
237 esp_info[cnt].esp_ealg_keylen = ek_bits;
238 esp_info[cnt].esp_aalg_id = aalg_id;
239 esp_info[cnt].esp_aalg_keylen = ak_bits;
240
241 /* sadb values */
242 esp_info[cnt].encryptalg = ealg_id;
243 esp_info[cnt].authalg = alg_info_esp_aa2sadb(aalg_id);
244 alg_info->alg_info_cnt++;
245
246 DBG(DBG_CRYPT,
247 DBG_log("__alg_info_esp_add() ealg=%d aalg=%d cnt=%d"
248 , ealg_id, aalg_id, alg_info->alg_info_cnt)
249 )
250 }
251
252 /*
253 * Add ESP alg info _with_ logic (policy):
254 */
255 static void
256 alg_info_esp_add (struct alg_info *alg_info, int ealg_id, int ek_bits, int aalg_id, int ak_bits)
257 {
258 /* Policy: default to 3DES */
259 if (ealg_id == 0)
260 ealg_id = ESP_3DES;
261
262 if (ealg_id > 0)
263 {
264 #ifndef NO_PLUTO
265 if (aalg_id > 0)
266 #else
267 /* Allow no auth for manual conns (from spi.c) */
268 if (aalg_id >= 0)
269 #endif
270 __alg_info_esp_add((struct alg_info_esp *)alg_info,
271 ealg_id, ek_bits,
272 aalg_id, ak_bits);
273 else
274 {
275 /* Policy: default to MD5 and SHA1 */
276 __alg_info_esp_add((struct alg_info_esp *)alg_info,
277 ealg_id, ek_bits,
278 AUTH_ALGORITHM_HMAC_MD5, ak_bits);
279 __alg_info_esp_add((struct alg_info_esp *)alg_info,
280 ealg_id, ek_bits,
281 AUTH_ALGORITHM_HMAC_SHA1, ak_bits);
282 }
283 }
284 }
285
286 #ifndef NO_PLUTO
287 /**************************************
288 *
289 * IKE alg
290 *
291 *************************************/
292 /*
293 * Search oakley_enc_names for a match, eg:
294 * "3des_cbc" <=> "OAKLEY_3DES_CBC"
295 */
296 static int
297 ealg_getbyname_ike(const char *const str, int len)
298 {
299 int ret;
300
301 if (!str || !*str)
302 return -1;
303
304 ret = enum_search_prefix(&oakley_enc_names,"OAKLEY_", str, len);
305 if (ret >= 0)
306 return ret;
307
308 ret = enum_search_ppfix(&oakley_enc_names, "OAKLEY_", "_CBC", str, len);
309 return ret;
310 }
311
312 /*
313 * Search oakley_hash_names for a match, eg:
314 * "md5" <=> "OAKLEY_MD5"
315 */
316 static int
317 aalg_getbyname_ike(const char *const str, int len)
318 {
319 int ret;
320 unsigned num;
321
322 if (!str || !*str)
323 return -1;
324
325 /* interpret 'SHA1' as 'SHA' */
326 if (strncasecmp("SHA1", str, len) == 0)
327 return enum_search(&oakley_hash_names, "OAKLEY_SHA");
328
329 ret = enum_search_prefix(&oakley_hash_names,"OAKLEY_", str, len);
330 if (ret >= 0)
331 return ret;
332
333 sscanf(str, "id%d%n", &ret, &num);
334 return (ret >=0 && num != strlen(str))? -1 : ret;
335 }
336
337 /*
338 * Search oakley_group_names for a match, eg:
339 * "modp1024" <=> "OAKLEY_GROUP_MODP1024"
340 */
341 static int
342 modp_getbyname_ike(const char *const str, int len)
343 {
344 int ret;
345
346 if (!str || !*str)
347 return -1;
348
349 ret = enum_search_prefix(&oakley_group_names,"OAKLEY_GROUP_", str, len);
350 if (ret >= 0)
351 return ret;
352
353 ret = enum_search_ppfix(&oakley_group_names, "OAKLEY_GROUP_", " (extension)", str, len);
354 return ret;
355 }
356
357 static void
358 __alg_info_ike_add (struct alg_info_ike *alg_info, int ealg_id, unsigned ek_bits, int aalg_id, unsigned ak_bits, int modp_id)
359 {
360 struct ike_info *ike_info = alg_info->ike;
361 unsigned cnt = alg_info->alg_info_cnt;
362 unsigned i;
363
364 /* check for overflows */
365 passert(cnt < countof(alg_info->ike));
366
367 /* dont add duplicates */
368 for (i = 0;i < cnt; i++)
369 {
370 if (ike_info[i].ike_ealg == ealg_id
371 && (!ek_bits || ike_info[i].ike_eklen == ek_bits)
372 && ike_info[i].ike_halg == aalg_id
373 && (!ak_bits || ike_info[i].ike_hklen == ak_bits)
374 && ike_info[i].ike_modp==modp_id)
375 return;
376 }
377
378 ike_info[cnt].ike_ealg = ealg_id;
379 ike_info[cnt].ike_eklen = ek_bits;
380 ike_info[cnt].ike_halg = aalg_id;
381 ike_info[cnt].ike_hklen = ak_bits;
382 ike_info[cnt].ike_modp = modp_id;
383 alg_info->alg_info_cnt++;
384
385 DBG(DBG_CRYPT,
386 DBG_log("__alg_info_ike_add() ealg=%d aalg=%d modp_id=%d, cnt=%d"
387 , ealg_id, aalg_id, modp_id
388 , alg_info->alg_info_cnt)
389 )
390 }
391
392 /*
393 * Proposals will be built by looping over default_ike_groups array and
394 * merging alg_info (ike_info) contents
395 */
396
397 static int default_ike_groups[] = {
398 OAKLEY_GROUP_MODP1536,
399 OAKLEY_GROUP_MODP1024
400 };
401
402 /*
403 * Add IKE alg info _with_ logic (policy):
404 */
405 static void
406 alg_info_ike_add (struct alg_info *alg_info, int ealg_id, int ek_bits, int aalg_id, int ak_bits, int modp_id)
407 {
408 int i = 0;
409 int n_groups = countof(default_ike_groups);
410
411 /* if specified modp_id avoid loop over default_ike_groups */
412 if (modp_id)
413 {
414 n_groups=0;
415 goto in_loop;
416 }
417
418 for (; n_groups--; i++)
419 {
420 modp_id = default_ike_groups[i];
421 in_loop:
422 /* Policy: default to 3DES */
423 if (ealg_id == 0)
424 ealg_id = OAKLEY_3DES_CBC;
425
426 if (ealg_id > 0)
427 {
428 if (aalg_id > 0)
429 __alg_info_ike_add((struct alg_info_ike *)alg_info,
430 ealg_id, ek_bits,
431 aalg_id, ak_bits,
432 modp_id);
433 else
434 {
435 /* Policy: default to MD5 and SHA */
436 __alg_info_ike_add((struct alg_info_ike *)alg_info,
437 ealg_id, ek_bits,
438 OAKLEY_MD5, ak_bits,
439 modp_id);
440 __alg_info_ike_add((struct alg_info_ike *)alg_info,
441 ealg_id, ek_bits,
442 OAKLEY_SHA, ak_bits,
443 modp_id);
444 }
445 }
446 }
447 }
448 #endif /* NO_PLUTO */
449
450 /*
451 * Creates a new alg_info by parsing passed string
452 */
453 enum parser_state_esp {
454 ST_INI,
455 ST_EA, /* encrypt algo */
456 ST_EA_END,
457 ST_EK, /* enc. key length */
458 ST_EK_END,
459 ST_AA, /* auth algo */
460 ST_AA_END,
461 ST_AK, /* auth. key length */
462 ST_AK_END,
463 ST_MODP, /* modp spec */
464 ST_FLAG_STRICT,
465 ST_END,
466 ST_EOF,
467 ST_ERR
468 };
469
470 static const char *parser_state_esp_names[] = {
471 "ST_INI",
472 "ST_EA",
473 "ST_EA_END",
474 "ST_EK",
475 "ST_EK_END",
476 "ST_AA",
477 "ST_AA_END",
478 "ST_AK",
479 "ST_AK_END",
480 "ST_MOPD",
481 "ST_FLAG_STRICT",
482 "ST_END",
483 "ST_EOF",
484 "ST_ERR"
485 };
486
487 static const char*
488 parser_state_name_esp(enum parser_state_esp state)
489 {
490 return parser_state_esp_names[state];
491 }
492
493 /* XXX:jjo to implement different parser for ESP and IKE */
494 struct parser_context {
495 unsigned state, old_state;
496 unsigned protoid;
497 char ealg_buf[16];
498 char aalg_buf[16];
499 char modp_buf[16];
500 int (*ealg_getbyname)(const char *const str, int len);
501 int (*aalg_getbyname)(const char *const str, int len);
502 int (*modp_getbyname)(const char *const str, int len);
503 char *ealg_str;
504 char *aalg_str;
505 char *modp_str;
506 int eklen;
507 int aklen;
508 int ch;
509 const char *err;
510 };
511
512 static inline void
513 parser_set_state(struct parser_context *p_ctx, enum parser_state_esp state)
514 {
515 if (state != p_ctx->state)
516 {
517 p_ctx->old_state = p_ctx->state;
518 p_ctx->state = state;
519 }
520 }
521
522 static int
523 parser_machine(struct parser_context *p_ctx)
524 {
525 int ch = p_ctx->ch;
526
527 /* special 'absolute' cases */
528 p_ctx->err = "No error.";
529
530 /* chars that end algo strings */
531 switch (ch){
532 case 0: /* end-of-string */
533 case '!': /* flag as strict algo list */
534 case ',': /* algo string separator */
535 switch (p_ctx->state) {
536 case ST_EA:
537 case ST_EK:
538 case ST_AA:
539 case ST_AK:
540 case ST_MODP:
541 case ST_FLAG_STRICT:
542 {
543 enum parser_state_esp next_state = 0;
544
545 switch (ch) {
546 case 0:
547 next_state = ST_EOF;
548 break;
549 case ',':
550 next_state = ST_END;
551 break;
552 case '!':
553 next_state = ST_FLAG_STRICT;
554 break;
555 }
556 /* ch? parser_set_state(p_ctx, ST_END) : parser_set_state(p_ctx, ST_EOF) ; */
557 parser_set_state(p_ctx, next_state);
558 goto out;
559 }
560 default:
561 p_ctx->err = "String ended with invalid char";
562 goto err;
563 }
564 }
565 re_eval:
566 switch (p_ctx->state) {
567 case ST_INI:
568 if (isspace(ch))
569 break;
570 if (isalnum(ch))
571 {
572 *(p_ctx->ealg_str++) = ch;
573 parser_set_state(p_ctx, ST_EA);
574 break;
575 }
576 p_ctx->err = "No alphanum. char initially found";
577 goto err;
578 case ST_EA:
579 if (isalpha(ch) || ch == '_')
580 {
581 *(p_ctx->ealg_str++) = ch;
582 break;
583 }
584 if (isdigit(ch))
585 {
586 /* bravely switch to enc keylen */
587 *(p_ctx->ealg_str) = 0;
588 parser_set_state(p_ctx, ST_EK);
589 goto re_eval;
590 }
591 if (ch == '-')
592 {
593 *(p_ctx->ealg_str) = 0;
594 parser_set_state(p_ctx, ST_EA_END);
595 break;
596 }
597 p_ctx->err = "No valid char found after enc alg string";
598 goto err;
599 case ST_EA_END:
600 if (isdigit(ch))
601 {
602 /* bravely switch to enc keylen */
603 parser_set_state(p_ctx, ST_EK);
604 goto re_eval;
605 }
606 if (isalpha(ch))
607 {
608 parser_set_state(p_ctx, ST_AA);
609 goto re_eval;
610 }
611 p_ctx->err = "No alphanum char found after enc alg separator";
612 goto err;
613 case ST_EK:
614 if (ch == '-')
615 {
616 parser_set_state(p_ctx, ST_EK_END);
617 break;
618 }
619 if (isdigit(ch))
620 {
621 p_ctx->eklen = p_ctx->eklen*10 + ch - '0';
622 break;
623 }
624 p_ctx->err = "Non digit or valid separator found while reading enc keylen";
625 goto err;
626 case ST_EK_END:
627 if (isalpha(ch))
628 {
629 parser_set_state(p_ctx, ST_AA);
630 goto re_eval;
631 }
632 p_ctx->err = "Non alpha char found after enc keylen end separator";
633 goto err;
634 case ST_AA:
635 if (ch == '-')
636 {
637 *(p_ctx->aalg_str++) = 0;
638 parser_set_state(p_ctx, ST_AA_END);
639 break;
640 }
641 if (isalnum(ch) || ch == '_')
642 {
643 *(p_ctx->aalg_str++) = ch;
644 break;
645 }
646 p_ctx->err = "Non alphanum or valid separator found in auth string";
647 goto err;
648 case ST_AA_END:
649 if (isdigit(ch))
650 {
651 parser_set_state(p_ctx, ST_AK);
652 goto re_eval;
653 }
654 /* Only allow modpXXXX string if we have a modp_getbyname method */
655 if ((p_ctx->modp_getbyname) && isalpha(ch))
656 {
657 parser_set_state(p_ctx, ST_MODP);
658 goto re_eval;
659 }
660 p_ctx->err = "Non initial digit found for auth keylen";
661 goto err;
662 case ST_AK:
663 if (ch=='-')
664 {
665 parser_set_state(p_ctx, ST_AK_END);
666 break;
667 }
668 if (isdigit(ch))
669 {
670 p_ctx->aklen = p_ctx->aklen*10 + ch - '0';
671 break;
672 }
673 p_ctx->err = "Non digit found for auth keylen";
674 goto err;
675 case ST_AK_END:
676 /* Only allow modpXXXX string if we have a modp_getbyname method */
677 if ((p_ctx->modp_getbyname) && isalpha(ch))
678 {
679 parser_set_state(p_ctx, ST_MODP);
680 goto re_eval;
681 }
682 p_ctx->err = "Non alpha char found after auth keylen";
683 goto err;
684 case ST_MODP:
685 if (isalnum(ch))
686 {
687 *(p_ctx->modp_str++) = ch;
688 break;
689 }
690 p_ctx->err = "Non alphanum char found after in modp string";
691 goto err;
692 case ST_FLAG_STRICT:
693 if (ch == 0)
694 parser_set_state(p_ctx, ST_END);
695 p_ctx->err = "Flags character(s) must be at end of whole string";
696 goto err;
697
698 /* XXX */
699 case ST_END:
700 case ST_EOF:
701 case ST_ERR:
702 break;
703 /* XXX */
704 }
705 out:
706 return p_ctx->state;
707 err:
708 parser_set_state(p_ctx, ST_ERR);
709 return ST_ERR;
710 }
711
712 /*
713 * Must be called for each "new" char, with new
714 * character in ctx.ch
715 */
716 static void
717 parser_init(struct parser_context *p_ctx, unsigned protoid)
718 {
719 memset(p_ctx, 0, sizeof (*p_ctx));
720 p_ctx->protoid = protoid; /* XXX: jjo */
721 p_ctx->protoid = PROTO_IPSEC_ESP;
722 p_ctx->ealg_str = p_ctx->ealg_buf;
723 p_ctx->aalg_str = p_ctx->aalg_buf;
724 p_ctx->modp_str = p_ctx->modp_buf;
725 p_ctx->state = ST_INI;
726
727 switch (protoid) {
728 #ifndef NO_PLUTO
729 case PROTO_ISAKMP:
730 p_ctx->ealg_getbyname = ealg_getbyname_ike;
731 p_ctx->aalg_getbyname = aalg_getbyname_ike;
732 p_ctx->modp_getbyname = modp_getbyname_ike;
733 break;
734 #endif
735 case PROTO_IPSEC_ESP:
736 p_ctx->ealg_getbyname = ealg_getbyname_esp;
737 p_ctx->aalg_getbyname = aalg_getbyname_esp;
738 break;
739 }
740 }
741
742 static int
743 parser_alg_info_add(struct parser_context *p_ctx, struct alg_info *alg_info)
744 {
745 int ealg_id = 0;
746 int aalg_id = 0;
747 int modp_id = 0;
748 #ifndef NO_PLUTO
749 const struct oakley_group_desc *gd;
750 #endif
751
752 if (*p_ctx->ealg_buf)
753 {
754 ealg_id = p_ctx->ealg_getbyname(p_ctx->ealg_buf, strlen(p_ctx->ealg_buf));
755 if (ealg_id == ESP_MAGIC_ID)
756 {
757 ealg_id = p_ctx->eklen;
758 p_ctx->eklen = 0;
759 }
760 if (ealg_id < 0)
761 {
762 p_ctx->err = "enc_alg not found";
763 return -1;
764 }
765 DBG(DBG_CRYPT,
766 DBG_log("parser_alg_info_add() ealg_getbyname(\"%s\")=%d"
767 , p_ctx->ealg_buf
768 , ealg_id)
769 )
770 }
771 if (*p_ctx->aalg_buf)
772 {
773 aalg_id = p_ctx->aalg_getbyname(p_ctx->aalg_buf, strlen(p_ctx->aalg_buf));
774 if (aalg_id < 0)
775 {
776 p_ctx->err = "hash_alg not found";
777 return -1;
778 }
779 DBG(DBG_CRYPT,
780 DBG_log("parser_alg_info_add() aalg_getbyname(\"%s\")=%d"
781 , p_ctx->aalg_buf
782 , aalg_id)
783 )
784 }
785 if (p_ctx->modp_getbyname && *p_ctx->modp_buf)
786 {
787 modp_id = p_ctx->modp_getbyname(p_ctx->modp_buf, strlen(p_ctx->modp_buf));
788 if (modp_id < 0)
789 {
790 p_ctx->err = "modp group not found";
791 return -1;
792 }
793 DBG(DBG_CRYPT,
794 DBG_log("parser_alg_info_add() modp_getbyname(\"%s\")=%d"
795 , p_ctx->modp_buf
796 , modp_id)
797 )
798 }
799 switch (alg_info->alg_info_protoid) {
800 case PROTO_IPSEC_ESP:
801 alg_info_esp_add(alg_info,
802 ealg_id, p_ctx->eklen,
803 aalg_id, p_ctx->aklen);
804 break;
805 #ifndef NO_PLUTO
806 case PROTO_ISAKMP:
807 if (modp_id && !(gd = lookup_group(modp_id)))
808 {
809 p_ctx->err = "found modp group id, but not supported";
810 return -1;
811 }
812 alg_info_ike_add(alg_info,
813 ealg_id, p_ctx->eklen,
814 aalg_id, p_ctx->aklen,
815 modp_id);
816 break;
817 #endif
818 default:
819 return -1;
820 }
821 return 0;
822 }
823
824 static int
825 alg_info_parse_str (struct alg_info *alg_info, const char *alg_str, const char **err_p)
826 {
827 struct parser_context ctx;
828 int ret;
829 const char *ptr;
830 static char err_buf[256];
831
832 *err_buf = 0;
833 parser_init(&ctx, alg_info->alg_info_protoid);
834 if (err_p)
835 *err_p = NULL;
836
837 /* use default if nul esp string */
838 if (!*alg_str)
839 {
840 switch (alg_info->alg_info_protoid) {
841 #ifndef NO_PLUTO
842 case PROTO_ISAKMP:
843 alg_info_ike_add(alg_info, 0, 0, 0, 0, 0);
844 return 0;
845 #endif
846 case PROTO_IPSEC_ESP:
847 alg_info_esp_add(alg_info, 0, 0, 0, 0);
848 return 0;
849 default:
850 /* IMPOSSIBLE */
851 passert(alg_info->alg_info_protoid);
852 }
853 }
854
855 for (ret = 0, ptr = alg_str; ret < ST_EOF;)
856 {
857 ctx.ch = *ptr++;
858 ret = parser_machine(&ctx);
859
860 switch (ret) {
861 case ST_FLAG_STRICT:
862 alg_info->alg_info_flags |= ALG_INFO_F_STRICT;
863 break;
864 case ST_END:
865 case ST_EOF:
866 DBG(DBG_CRYPT,
867 DBG_log("alg_info_parse_str() ealg_buf=%s aalg_buf=%s"
868 "eklen=%d aklen=%d",
869 ctx.ealg_buf, ctx.aalg_buf,
870 ctx.eklen, ctx.aklen)
871 )
872 if (parser_alg_info_add(&ctx, alg_info) < 0)
873 {
874 snprintf(err_buf, sizeof(err_buf),
875 "%s, enc_alg=\"%s\", auth_alg=\"%s\", modp=\"%s\"",
876 ctx.err,
877 ctx.ealg_buf,
878 ctx.aalg_buf,
879 ctx.modp_buf);
880 goto err;
881 }
882 /* zero out for next run (ST_END) */
883 parser_init(&ctx, alg_info->alg_info_protoid);
884 break;
885 case ST_ERR:
886 snprintf(err_buf, sizeof(err_buf),
887 "%s, just after \"%.*s\" (old_state=%s)",
888 ctx.err,
889 (int)(ptr-alg_str-1), alg_str ,
890 parser_state_name_esp(ctx.old_state));
891 goto err;
892 default:
893 if (!ctx.ch)
894 break;
895 }
896 }
897 return 0;
898 err:
899 if (err_p)
900 *err_p=err_buf;
901 return -1;
902 }
903
904 struct alg_info_esp *
905 alg_info_esp_create_from_str (const char *alg_str, const char **err_p)
906 {
907 struct alg_info_esp *alg_info_esp;
908 char esp_buf[256];
909 static char err_buf[256];
910 char *pfs_name;
911 int ret = 0;
912 /*
913 * alg_info storage should be sized dynamically
914 * but this may require 2passes to know
915 * transform count in advance.
916 */
917 alg_info_esp = malloc_thing (struct alg_info_esp);
918 zero(alg_info_esp);
919
920 pfs_name=index (alg_str, ';');
921 if (pfs_name)
922 {
923 memcpy(esp_buf, alg_str, pfs_name-alg_str);
924 esp_buf[pfs_name-alg_str] = 0;
925 alg_str = esp_buf;
926 pfs_name++;
927
928 /* if pfs strings AND first char is not '0' */
929 if (*pfs_name && pfs_name[0] != '0')
930 {
931 ret = modp_getbyname_esp(pfs_name, strlen(pfs_name));
932 if (ret < 0)
933 {
934 /* Bomb if pfsgroup not found */
935 DBG(DBG_CRYPT,
936 DBG_log("alg_info_esp_create_from_str(): pfsgroup \"%s\" not found"
937 , pfs_name)
938 )
939 if (*err_p)
940 {
941 snprintf(err_buf, sizeof(err_buf),
942 "pfsgroup \"%s\" not found",
943 pfs_name);
944
945 *err_p = err_buf;
946 }
947 goto out;
948 }
949 alg_info_esp->esp_pfsgroup = ret;
950 }
951 }
952 else
953 alg_info_esp->esp_pfsgroup = 0;
954
955 alg_info_esp->alg_info_protoid = PROTO_IPSEC_ESP;
956 ret = alg_info_parse_str((struct alg_info *)alg_info_esp, alg_str, err_p) ;
957 out:
958 if (ret < 0)
959 {
960 free(alg_info_esp);
961 alg_info_esp = NULL;
962 }
963 return alg_info_esp;
964 }
965
966 #ifndef NO_PLUTO
967 struct alg_info_ike *
968 alg_info_ike_create_from_str (const char *alg_str, const char **err_p)
969 {
970 struct alg_info_ike *alg_info_ike;
971 /*
972 * alg_info storage should be sized dynamically
973 * but this may require 2passes to know
974 * transform count in advance.
975 */
976 alg_info_ike = malloc_thing (struct alg_info_ike);
977 zero(alg_info_ike);
978 alg_info_ike->alg_info_protoid = PROTO_ISAKMP;
979
980 if (alg_info_parse_str((struct alg_info *)alg_info_ike, alg_str, err_p) < 0)
981 {
982 free(alg_info_ike);
983 return NULL;
984 }
985 return alg_info_ike;
986 }
987 #endif
988
989 /*
990 * alg_info struct can be shared by
991 * several connections instances,
992 * handle free() with ref_cnts
993 */
994 void
995 alg_info_addref(struct alg_info *alg_info)
996 {
997 if (alg_info != NULL)
998 {
999 alg_info->ref_cnt++;
1000 DBG(DBG_CRYPT,
1001 DBG_log("alg_info_addref() alg_info->ref_cnt=%d"
1002 , alg_info->ref_cnt)
1003 )
1004 }
1005 }
1006
1007 void
1008 alg_info_delref(struct alg_info **alg_info_p)
1009 {
1010 struct alg_info *alg_info = *alg_info_p;
1011
1012 if (alg_info != NULL)
1013 {
1014 passert(alg_info->ref_cnt != 0);
1015 alg_info->ref_cnt--;
1016 DBG(DBG_CRYPT,
1017 DBG_log("alg_info_delref() alg_info->ref_cnt=%d"
1018 , alg_info->ref_cnt)
1019 )
1020 if (alg_info->ref_cnt == 0)
1021 {
1022 DBG(DBG_CRYPT,
1023 DBG_log("alg_info_delref() freeing alg_info")
1024 )
1025 alg_info_free(alg_info);
1026 }
1027 *alg_info_p = NULL;
1028 }
1029 }
1030
1031 /* snprint already parsed transform list (alg_info) */
1032 int
1033 alg_info_snprint(char *buf, int buflen, struct alg_info *alg_info)
1034 {
1035 char *ptr = buf;
1036 int np = 0;
1037 struct esp_info *esp_info;
1038 #ifndef NO_PLUTO
1039 struct ike_info *ike_info;
1040 #endif
1041 int cnt;
1042
1043 switch (alg_info->alg_info_protoid) {
1044 case PROTO_IPSEC_ESP:
1045 {
1046 struct alg_info_esp *alg_info_esp = (struct alg_info_esp *)alg_info;
1047
1048 ALG_INFO_ESP_FOREACH(alg_info_esp, esp_info, cnt)
1049 {
1050 np = snprintf(ptr, buflen, "%d_%03d-%d, "
1051 , esp_info->esp_ealg_id
1052 , (int)esp_info->esp_ealg_keylen
1053 , esp_info->esp_aalg_id);
1054 ptr += np;
1055 buflen -= np;
1056 if (buflen < 0)
1057 goto out;
1058 }
1059 if (alg_info_esp->esp_pfsgroup)
1060 {
1061 np = snprintf(ptr, buflen, "; pfsgroup=%d; "
1062 , alg_info_esp->esp_pfsgroup);
1063 ptr += np;
1064 buflen -= np;
1065 if (buflen < 0)
1066 goto out;
1067 }
1068 break;
1069 }
1070 #ifndef NO_PLUTO
1071 case PROTO_ISAKMP:
1072 ALG_INFO_IKE_FOREACH((struct alg_info_ike *)alg_info, ike_info, cnt)
1073 {
1074 np = snprintf(ptr, buflen, "%d_%03d-%d-%d, "
1075 , ike_info->ike_ealg
1076 , (int)ike_info->ike_eklen
1077 , ike_info->ike_halg
1078 , ike_info->ike_modp);
1079 ptr += np;
1080 buflen -= np;
1081 if (buflen < 0)
1082 goto out;
1083 }
1084 break;
1085 #endif
1086 default:
1087 np = snprintf(buf, buflen, "INVALID protoid=%d\n"
1088 , alg_info->alg_info_protoid);
1089 ptr += np;
1090 buflen -= np;
1091 goto out;
1092 }
1093
1094 np = snprintf(ptr, buflen, "%s"
1095 , alg_info->alg_info_flags & ALG_INFO_F_STRICT?
1096 "strict":"");
1097 ptr += np;
1098 buflen -= np;
1099 out:
1100 if (buflen < 0)
1101 {
1102 loglog(RC_LOG_SERIOUS
1103 , "buffer space exhausted in alg_info_snprint_ike(), buflen=%d"
1104 , buflen);
1105 }
1106
1107 return ptr - buf;
1108 }
1109
1110 #ifndef NO_PLUTO
1111 int
1112 alg_info_snprint_esp(char *buf, int buflen, struct alg_info_esp *alg_info)
1113 {
1114 char *ptr = buf;
1115
1116 int cnt = alg_info->alg_info_cnt;
1117 struct esp_info *esp_info = alg_info->esp;
1118
1119 while (cnt--)
1120 {
1121 if (kernel_alg_esp_enc_ok(esp_info->esp_ealg_id, 0, NULL)
1122 && kernel_alg_esp_auth_ok(esp_info->esp_aalg_id, NULL))
1123 {
1124 u_int eklen = (esp_info->esp_ealg_keylen)
1125 ? esp_info->esp_ealg_keylen
1126 : kernel_alg_esp_enc_keylen(esp_info->esp_ealg_id)
1127 * BITS_PER_BYTE;
1128
1129 u_int aklen = esp_info->esp_aalg_keylen
1130 ? esp_info->esp_aalg_keylen
1131 : kernel_alg_esp_auth_keylen(esp_info->esp_aalg_id)
1132 * BITS_PER_BYTE;
1133
1134 int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d, ",
1135 esp_info->esp_ealg_id, eklen,
1136 esp_info->esp_aalg_id, aklen);
1137 ptr += ret;
1138 buflen -= ret;
1139 if (buflen < 0)
1140 break;
1141 }
1142 esp_info++;
1143 }
1144 return ptr - buf;
1145 }
1146
1147 int
1148 alg_info_snprint_ike(char *buf, int buflen, struct alg_info_ike *alg_info)
1149 {
1150 char *ptr = buf;
1151
1152 int cnt = alg_info->alg_info_cnt;
1153 struct ike_info *ike_info = alg_info->ike;
1154
1155 while (cnt--)
1156 {
1157 struct encrypt_desc *enc_desc = ike_alg_get_encrypter(ike_info->ike_ealg);
1158 struct hash_desc *hash_desc = ike_alg_get_hasher(ike_info->ike_halg);
1159
1160 if (enc_desc != NULL && hash_desc != NULL
1161 && lookup_group(ike_info->ike_modp))
1162 {
1163
1164 u_int eklen = (ike_info->ike_eklen)
1165 ? ike_info->ike_eklen
1166 : enc_desc->keydeflen;
1167
1168 u_int aklen = (ike_info->ike_hklen)
1169 ? ike_info->ike_hklen
1170 : hash_desc->hash_digest_size * BITS_PER_BYTE;
1171
1172 int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d-%d, ",
1173 ike_info->ike_ealg, eklen,
1174 ike_info->ike_halg, aklen,
1175 ike_info->ike_modp);
1176 ptr += ret;
1177 buflen -= ret;
1178 if (buflen < 0)
1179 break;
1180 }
1181 ike_info++;
1182 }
1183 return ptr - buf;
1184 }
1185 #endif /* NO_PLUTO */