OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / freeswan / pluto / ike_alg.c
1 /*
2  * IKE modular algorithm handling interface
3  * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
4  * 
5  * ike_alg.c,v 1.1.4.3 2002/05/30 03:26:08 jjo 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 <stdio.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #include <errno.h>
21
22 #include <freeswan.h>
23
24 #include "constants.h"
25 #include "defs.h"
26 #include "sha1.h"
27 #include "md5.h"
28 #include "crypto.h"
29
30 #include "state.h"
31 #include "packet.h"
32 #include "kernel.h"
33 #include "log.h"
34 #include "whack.h"
35 #include "spdb.h"
36 #include "alg_info.h"
37 #include "ike_alg.h"
38 #include "db_ops.h"
39 #include "id.h"
40 #include "x509.h"
41 #include "connections.h"
42
43 #define return_on(var, val) do { var=val;goto return_out; } while(0);
44
45 /*
46  *      Create an OAKLEY proposal based on alg_info and policy
47  */
48 struct db_context *
49 ike_alg_db_new(struct alg_info_ike *ai , lset_t policy)
50 {
51         struct db_context *db_ctx = NULL;
52         struct ike_info *ike_info;
53         unsigned ealg, halg, modp, eklen=0;
54         struct encrypt_desc *enc_desc;
55         int i;
56
57         if (!ai) {
58                 whack_log(RC_LOG_SERIOUS, "no IKE algorithms "
59                                 "for this connection "
60                                 "(check ike algorithm string)");
61                 goto fail;
62         }
63         policy &= POLICY_ID_AUTH_MASK;
64         db_ctx = db_prop_new(PROTO_ISAKMP, 8, 8 * 5);
65
66         /* for each group */
67         ALG_INFO_IKE_FOREACH(ai, ike_info, i) {
68                 ealg = ike_info->ike_ealg;
69                 halg = ike_info->ike_halg;
70                 modp = ike_info->ike_modp;
71                 eklen= ike_info->ike_eklen;
72
73                 if (!ike_alg_enc_present(ealg)) {
74                         DBG_log("%s() ike enc ealg=%d not present",
75                                         __FUNCTION__, ealg);
76                         continue;
77                 }
78
79                 if (!ike_alg_hash_present(halg)) {
80                         DBG_log("%s() ike hash halg=%d not present",
81                                         __FUNCTION__, halg);
82                         continue;
83                 }
84
85                 enc_desc = ike_alg_get_encrypter(ealg);
86                 passert(enc_desc != NULL);
87
88                 if (eklen 
89                 /*
90                         && eklen != enc_desc->keydeflen)
91                 */
92                         && (eklen < enc_desc->keyminlen
93                                 || eklen >  enc_desc->keymaxlen))
94                 {
95                         DBG_log("%s() "
96                                         "ealg=%d (specified) keylen:%d, "
97                                         "not valid "
98                                         /*
99                                          "keylen != %d"
100                                          */
101                                         "min=%d, max=%d"
102                                         , __FUNCTION__
103                                         , ealg
104                                         , eklen
105                                         /*
106                                         , enc_desc->keydeflen
107                                         */
108                                         , enc_desc->keyminlen
109                                         , enc_desc->keymaxlen
110                                         );
111                         continue;
112                 }
113
114                 if (policy & POLICY_RSASIG) {
115                         db_trans_add(db_ctx, KEY_IKE);
116                         db_attr_add_values(db_ctx, 
117                                         OAKLEY_ENCRYPTION_ALGORITHM, ealg);
118                         db_attr_add_values(db_ctx, 
119                                         OAKLEY_HASH_ALGORITHM, halg);
120                         if (eklen)
121                                 db_attr_add_values(db_ctx, 
122                                                 OAKLEY_KEY_LENGTH, eklen);
123                         db_attr_add_values(db_ctx, 
124                                         OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG);
125                         db_attr_add_values(db_ctx, 
126                                         OAKLEY_GROUP_DESCRIPTION, modp);
127                 }
128                 if (policy & POLICY_PSK) {
129                         db_trans_add(db_ctx, KEY_IKE);
130                         db_attr_add_values(db_ctx, 
131                                         OAKLEY_ENCRYPTION_ALGORITHM, ealg);
132                         db_attr_add_values(db_ctx, 
133                                         OAKLEY_HASH_ALGORITHM, halg);
134                         if (ike_info->ike_eklen) 
135                                 db_attr_add_values(db_ctx, 
136                                                 OAKLEY_KEY_LENGTH, ike_info->ike_eklen);
137                         db_attr_add_values(db_ctx, 
138                                         OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY);
139                         db_attr_add_values(db_ctx, 
140                                         OAKLEY_GROUP_DESCRIPTION, modp);
141                 }
142         }
143 fail:
144         return db_ctx;
145 }
146 /*
147  *      Show registered IKE algorithms
148  */
149 void
150 ike_alg_show_status(void)
151 {
152         unsigned alg, i;
153         struct ike_alg *algo;
154         IKE_EALG_FOR_EACH(algo) {
155                 passert(algo != NULL);
156                 alg=algo->algo_id;
157                 whack_log(RC_COMMENT, "algorithm IKE encrypt: id=%d, name=%s, blocksize=%d, keydeflen=%d"
158                         , alg
159                         , enum_name(&oakley_enc_names, alg)
160                         , ((struct encrypt_desc *)algo)->enc_blocksize
161                         , ((struct encrypt_desc *)algo)->keydeflen
162                         );
163                 
164         }
165         IKE_HALG_FOR_EACH(algo) {
166                 whack_log(RC_COMMENT, "algorithm IKE hash: id=%d, name=%s, hashsize=%d"
167                         , algo->algo_id
168                         , enum_name(&oakley_hash_names, algo->algo_id)
169                         , ((struct hash_desc *)algo)->hash_digest_size
170                         );
171         }
172 #define IKE_DH_ALG_FOR_EACH(idx) for(idx = 0; idx != elemsof(oakley_group); idx++)
173         IKE_DH_ALG_FOR_EACH(i) {
174                 const struct oakley_group_desc *gdesc=oakley_group+i;
175                 whack_log(RC_COMMENT, "algorithm IKE dh group: id=%d, name=%s, bits=%d"
176                         , gdesc->group
177                         , enum_name(&oakley_group_names, gdesc->group)
178                         , gdesc->bytes*BITS_PER_BYTE
179                         );
180         }
181 }
182 /*
183  *      Show IKE algorithms for 
184  *      - this connection (result from ike= string)
185  *      - newest SA
186  */
187 void
188 ike_alg_show_connection(struct connection *c, const char *instance)
189 {
190         char buf[256];
191         struct state *st;
192         if (c->alg_info_ike) {
193                 alg_info_snprint(buf, sizeof(buf), 
194                                 (struct alg_info *)c->alg_info_ike);
195                 whack_log(RC_COMMENT
196                     , "\"%s\"%s:   IKE algorithms wanted: %s"
197                     , c->name
198                     , instance
199                     , buf);
200         }
201         if (c->alg_info_ike) {
202                 alg_info_snprint_ike(buf, sizeof(buf), c->alg_info_ike);
203                 whack_log(RC_COMMENT
204                     , "\"%s\"%s:   IKE algorithms found:  %s"
205                     , c->name
206                     , instance
207                     , buf);
208         }
209         st = state_with_serialno(c->newest_isakmp_sa);
210         if (st)
211                 whack_log(RC_COMMENT
212                 , "\"%s\"%s:   IKE algorithm newest: %s_%d-%s-%s"
213                 , c->name
214                 , instance
215                 , enum_show(&oakley_enc_names, st->st_oakley.encrypt)
216                 +7 /* strlen("OAKLEY_") */
217                 /* , st->st_oakley.encrypter->keydeflen */
218                 , st->st_oakley.enckeylen
219                 , enum_show(&oakley_hash_names, st->st_oakley.hash)
220                 +7 /* strlen("OAKLEY_") */
221                 , enum_show(&oakley_group_names, st->st_oakley.group->group)
222                 +13 /* strlen("OAKLEY_GROUP_") */
223          );
224 }
225 /*==========================================================
226  *
227  *      IKE algo list handling
228  *
229  *      - registration
230  *      - lookup
231  *=========================================================*/
232 struct ike_alg *ike_alg_base[IKE_ALG_MAX+1] = {NULL, NULL};
233 /*      check if IKE encrypt algo is present */
234 bool ike_alg_enc_present(int ealg)
235 {
236         struct encrypt_desc *enc_desc = ike_alg_get_encrypter(ealg);
237         return enc_desc ? enc_desc->enc_blocksize : 0;
238 }
239 /*      check if IKE hash algo is present */
240 bool ike_alg_hash_present(int halg)
241 {
242         struct hash_desc *hash_desc = ike_alg_get_hasher(halg);
243         return hash_desc ? hash_desc->hash_digest_size : 0;
244 }
245 bool ike_alg_enc_ok(int ealg, unsigned key_len, struct alg_info_ike *alg_info_ike, const char **errp)
246 {
247         int ret=TRUE;
248         struct encrypt_desc *enc_desc;
249         char errbuf[256]="encrypt algo not found";
250         /* 
251          * test #1: encrypt algo must be present 
252          */
253         enc_desc = ike_alg_get_encrypter(ealg);
254         if (!enc_desc) return_on(ret, FALSE);
255         /* 
256          * test #2: if key_len specified, it must be in range 
257          */
258         if ((key_len) && ((key_len < enc_desc->keyminlen) ||
259                          (key_len > enc_desc->keymaxlen))) {
260                 snprintf(errbuf, sizeof(errbuf),
261                                 "key_len not in range: encalg=%d, "
262                                 "key_len=%d, keyminlen=%d, keymaxlen=%d",
263                                 ealg, key_len,
264                                 enc_desc->keyminlen,
265                                 enc_desc->keymaxlen
266                        );
267                 log ("%s(): %s", __FUNCTION__, errbuf);
268                 return_on(ret, FALSE);
269         } 
270         /* 
271          * test #3: if alg_info specified AND strict flag, only
272          * only allow algo iff listed in st->alg_info_esp
273          */
274         else if (alg_info_ike && (alg_info_ike->alg_info_flags & ALG_INFO_F_STRICT) ) {
275                 int i;
276                 struct ike_info *ike_info;
277                 ALG_INFO_IKE_FOREACH(alg_info_ike, ike_info, i) {
278                         if ((ike_info->ike_ealg == ealg) &&
279                                 ((ike_info->ike_eklen==0) || (key_len==0) ||
280                                  (ike_info->ike_eklen==key_len))) {
281                                 return_on(ret, TRUE);
282                         }
283                 }
284                 snprintf(errbuf, sizeof(errbuf),
285                                 "strict flag and encrypt algorithm "
286                                 "not in transform string list: "
287                                 "ealg=%d, "
288                                 "key_len=%d, keyminbits=%d, keymaxbits=%d",
289                                 ealg, key_len,
290                                 enc_desc->keyminlen,
291                                 enc_desc->keymaxlen
292                    );
293                 log("%s(): %s", __FUNCTION__, errbuf);
294                 return_on(ret, FALSE);
295         }
296 return_out:
297         DBG(DBG_KLIPS, 
298                 if (ret) 
299                         DBG_log("%s(ealg=%d,key_len=%d): "
300                                 "blocksize=%d, keyminlen=%d, "
301                                 "keydeflen=%d, keymaxlen=%d, "
302                                 "ret=%d",
303                                 __FUNCTION__,
304                                 ealg, key_len,
305                                 enc_desc->enc_blocksize,
306                                 enc_desc->keyminlen,
307                                 enc_desc->keydeflen,
308                                 enc_desc->keymaxlen,
309                                 ret);
310                 else 
311                         DBG_log("%s(ealg=%d,key_len=%d): NO",
312                                 __FUNCTION__, ealg, key_len);
313         );
314         if (!ret && *errp)
315                 *errp=errbuf;
316         return ret;
317 }
318 /*
319  *      return ike_algo object by {type, id}
320  */
321 /* XXX:jjo use keysize */
322 struct ike_alg *
323 ike_alg_find(unsigned algo_type, unsigned algo_id, unsigned keysize __attribute__((unused)))
324 {
325         struct ike_alg *e=ike_alg_base[algo_type];
326         for(;e!=NULL;e=e->algo_next) {
327                 if (e->algo_id==algo_id)
328                         break;
329         }
330
331         return e;
332 }
333
334 /*
335  *      Main "raw" ike_alg list adding function
336  */
337 int
338 ike_alg_add(struct ike_alg* a)
339 {
340         int ret=0;
341         const char *ugh="No error";
342         if (a->algo_type > IKE_ALG_MAX)
343         {
344                 ugh="Invalid algo_type";
345                 return_on(ret,-EINVAL);
346         }
347         if (ike_alg_find(a->algo_type, a->algo_id, 0))
348         {
349                 ugh="Algorithm already exists";
350                 return_on(ret,-EEXIST);
351         }
352         if (ret==0) {
353                 a->algo_next=ike_alg_base[a->algo_type];
354                 ike_alg_base[a->algo_type]=a;
355         }
356 return_out:
357         if (ret) 
358                 log("%s(): ERROR: %s", __FUNCTION__, ugh);
359         return ret;
360 }
361
362 /*
363  *      Validate and register IKE hash algorithm object
364  */
365 int
366 ike_alg_register_hash(struct hash_desc *hash_desc)
367 {
368         const char *alg_name;
369         int ret=0;
370         if (hash_desc->algo_id > OAKLEY_HASH_MAX) {
371                 log ("%s(): hash alg=%d < max=%d",
372                                 __FUNCTION__, hash_desc->algo_id, OAKLEY_HASH_MAX);
373                 return_on(ret,-EINVAL);
374         }
375         if (hash_desc->hash_ctx_size > sizeof (union hash_ctx)) {
376                 log ("%s(): hash alg=%d has "
377                                 "ctx_size=%d > hash_ctx=%d",
378                                 __FUNCTION__,
379                                 hash_desc->algo_id, 
380                                 hash_desc->hash_ctx_size,
381                                 sizeof (union hash_ctx));
382                 return_on(ret,-EOVERFLOW);
383         }
384         if (!(hash_desc->hash_init&&hash_desc->hash_update&&hash_desc->hash_final)) {
385                 log ("%s(): hash alg=%d needs  "
386                                 "hash_init(), hash_update() and hash_final()",
387                                 __FUNCTION__, hash_desc->algo_id);
388                 return_on(ret,-EINVAL);
389         }
390         alg_name=enum_name(&oakley_hash_names, hash_desc->algo_id);
391         if (!alg_name) {
392                 log ("%s(): WARNING: hash alg=%d not found in "
393                                 "constants.c:oakley_hash_names  ",
394                                 __FUNCTION__, hash_desc->algo_id);
395                 alg_name="<NULL>";
396         }
397
398 return_out:
399         if (ret==0)
400                 ret=ike_alg_add((struct ike_alg *)hash_desc);
401         log("%s: Activating %s: %s (ret=%d)", 
402                         __FUNCTION__,
403                         alg_name, ret==0? "Ok" : "FAILED", ret);
404         return ret;
405 }
406
407 /*
408  *      Validate and register IKE encryption algorithm object
409  */
410 int
411 ike_alg_register_enc(struct encrypt_desc *enc_desc)
412 {
413         const char *alg_name;
414         int ret=0;
415         if (enc_desc->algo_id > OAKLEY_ENCRYPT_MAX) {
416                 log ("%s(): enc alg=%d < max=%d\n",
417                                 __FUNCTION__,
418                                 enc_desc->algo_id, OAKLEY_ENCRYPT_MAX);
419                 return_on(ret, -EINVAL);
420         }
421         alg_name=enum_name(&oakley_enc_names, enc_desc->algo_id);
422         if (!alg_name) {
423                 log ("%s(): WARNING: enc alg=%d not found in "
424                                 "constants.c:oakley_enc_names  ",
425                                 __FUNCTION__, enc_desc->algo_id);
426                 alg_name="<NULL>";
427         }
428 return_out:
429         if (ret==0)
430                 ret=ike_alg_add((struct ike_alg *)enc_desc);
431         log("%s: Activating %s: %s (ret=%d)", 
432                         __FUNCTION__,
433                         alg_name, ret==0? "Ok" : "FAILED", ret);
434         return 0;
435 }