OSDN Git Service

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