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