]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/algorithm.c
3440fc31e474694a7b24023440399bc086a525c7
[apple/ipsec.git] / ipsec-tools / racoon / algorithm.c
1 /* $Id: algorithm.c,v 1.11.4.1 2005/06/28 22:38:02 manubsd Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include "config.h"
33
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <stdlib.h>
37
38 #include "var.h"
39 #include "misc.h"
40 #include "vmbuf.h"
41 #include "plog.h"
42 #include "debug.h"
43
44 #include "crypto_openssl.h"
45 #include "dhgroup.h"
46 #include "algorithm.h"
47 #include "oakley.h"
48 #include "isakmp_var.h"
49 #include "isakmp.h"
50 #include "ipsec_doi.h"
51 #include "gcmalloc.h"
52
53 static struct hash_algorithm oakley_hashdef[] = {
54 { "md5", algtype_md5, OAKLEY_ATTR_HASH_ALG_MD5,
55 eay_md5_init, eay_md5_update,
56 eay_md5_final, eay_md5_hashlen,
57 eay_md5_one, },
58 { "sha1", algtype_sha1, OAKLEY_ATTR_HASH_ALG_SHA,
59 eay_sha1_init, eay_sha1_update,
60 eay_sha1_final, eay_sha1_hashlen,
61 eay_sha1_one, },
62 #ifdef WITH_SHA2
63 { "sha2_256", algtype_sha2_256, OAKLEY_ATTR_HASH_ALG_SHA2_256,
64 eay_sha2_256_init, eay_sha2_256_update,
65 eay_sha2_256_final, eay_sha2_256_hashlen,
66 eay_sha2_256_one, },
67 { "sha2_384", algtype_sha2_384, OAKLEY_ATTR_HASH_ALG_SHA2_384,
68 eay_sha2_384_init, eay_sha2_384_update,
69 eay_sha2_384_final, eay_sha2_384_hashlen,
70 eay_sha2_384_one, },
71 { "sha2_512", algtype_sha2_512, OAKLEY_ATTR_HASH_ALG_SHA2_512,
72 eay_sha2_512_init, eay_sha2_512_update,
73 eay_sha2_512_final, eay_sha2_512_hashlen,
74 eay_sha2_512_one, },
75 #endif
76 };
77
78 static struct hmac_algorithm oakley_hmacdef[] = {
79 { "hmac_md5", algtype_md5, OAKLEY_ATTR_HASH_ALG_MD5,
80 eay_hmacmd5_init, eay_hmacmd5_update,
81 eay_hmacmd5_final, NULL,
82 eay_hmacmd5_one, },
83 { "hmac_sha1", algtype_sha1, OAKLEY_ATTR_HASH_ALG_SHA,
84 eay_hmacsha1_init, eay_hmacsha1_update,
85 eay_hmacsha1_final, NULL,
86 eay_hmacsha1_one, },
87 #ifdef WITH_SHA2
88 { "hmac_sha2_256", algtype_sha2_256, OAKLEY_ATTR_HASH_ALG_SHA2_256,
89 eay_hmacsha2_256_init, eay_hmacsha2_256_update,
90 eay_hmacsha2_256_final, NULL,
91 eay_hmacsha2_256_one, },
92 { "hmac_sha2_384", algtype_sha2_384, OAKLEY_ATTR_HASH_ALG_SHA2_384,
93 eay_hmacsha2_384_init, eay_hmacsha2_384_update,
94 eay_hmacsha2_384_final, NULL,
95 eay_hmacsha2_384_one, },
96 { "hmac_sha2_512", algtype_sha2_512, OAKLEY_ATTR_HASH_ALG_SHA2_512,
97 eay_hmacsha2_512_init, eay_hmacsha2_512_update,
98 eay_hmacsha2_512_final, NULL,
99 eay_hmacsha2_512_one, },
100 #endif
101 };
102
103 static struct enc_algorithm oakley_encdef[] = {
104 { "des", algtype_des, OAKLEY_ATTR_ENC_ALG_DES, 8,
105 eay_des_encrypt, eay_des_decrypt,
106 eay_des_weakkey, eay_des_keylen, },
107 #ifdef HAVE_OPENSSL
108 #ifdef HAVE_OPENSSL_IDEA_H
109 { "idea", algtype_idea, OAKLEY_ATTR_ENC_ALG_IDEA, 8,
110 eay_idea_encrypt, eay_idea_decrypt,
111 eay_idea_weakkey, eay_idea_keylen, },
112 #endif
113 { "blowfish", algtype_blowfish, OAKLEY_ATTR_ENC_ALG_BLOWFISH, 8,
114 eay_bf_encrypt, eay_bf_decrypt,
115 eay_bf_weakkey, eay_bf_keylen, },
116 #ifdef HAVE_OPENSSL_RC5_H
117 { "rc5", algtype_rc5, OAKLEY_ATTR_ENC_ALG_RC5, 8,
118 eay_rc5_encrypt, eay_rc5_decrypt,
119 eay_rc5_weakkey, eay_rc5_keylen, },
120 #endif
121 #endif
122 { "3des", algtype_3des, OAKLEY_ATTR_ENC_ALG_3DES, 8,
123 eay_3des_encrypt, eay_3des_decrypt,
124 eay_3des_weakkey, eay_3des_keylen, },
125 #ifdef HAVE_OPENSSL
126 { "cast", algtype_cast128, OAKLEY_ATTR_ENC_ALG_CAST, 8,
127 eay_cast_encrypt, eay_cast_decrypt,
128 eay_cast_weakkey, eay_cast_keylen, },
129 #endif
130 { "aes", algtype_aes, OAKLEY_ATTR_ENC_ALG_AES, 16,
131 eay_aes_encrypt, eay_aes_decrypt,
132 eay_aes_weakkey, eay_aes_keylen, },
133 };
134
135 static struct enc_algorithm ipsec_encdef[] = {
136 { "des-iv64", algtype_des_iv64, IPSECDOI_ESP_DES_IV64, 8,
137 NULL, NULL,
138 NULL, eay_des_keylen, },
139 { "des", algtype_des, IPSECDOI_ESP_DES, 8,
140 NULL, NULL,
141 NULL, eay_des_keylen, },
142 { "3des", algtype_3des, IPSECDOI_ESP_3DES, 8,
143 NULL, NULL,
144 NULL, eay_3des_keylen, },
145 #ifdef HAVE_OPENSSL
146 #ifdef HAVE_OPENSSL_RC5_H
147 { "rc5", algtype_rc5, IPSECDOI_ESP_RC5, 8,
148 NULL, NULL,
149 NULL, eay_rc5_keylen, },
150 #endif
151 { "cast", algtype_cast128, IPSECDOI_ESP_CAST, 8,
152 NULL, NULL,
153 NULL, eay_cast_keylen, },
154 { "blowfish", algtype_blowfish, IPSECDOI_ESP_BLOWFISH, 8,
155 NULL, NULL,
156 NULL, eay_bf_keylen, },
157 #endif
158 { "des-iv32", algtype_des_iv32, IPSECDOI_ESP_DES_IV32, 8,
159 NULL, NULL,
160 NULL, eay_des_keylen, },
161 { "null", algtype_null_enc, IPSECDOI_ESP_NULL, 8,
162 NULL, NULL,
163 NULL, eay_null_keylen, },
164 { "aes", algtype_aes, IPSECDOI_ESP_AES, 16,
165 NULL, NULL,
166 NULL, eay_aes_keylen, },
167 #ifdef HAVE_OPENSSL
168 { "twofish", algtype_twofish, IPSECDOI_ESP_TWOFISH, 16,
169 NULL, NULL,
170 NULL, eay_twofish_keylen, },
171 #ifdef HAVE_OPENSSL_IDEA_H
172 { "3idea", algtype_3idea, IPSECDOI_ESP_3IDEA, 8,
173 NULL, NULL,
174 NULL, NULL, },
175 { "idea", algtype_idea, IPSECDOI_ESP_IDEA, 8,
176 NULL, NULL,
177 NULL, NULL, },
178 #endif
179 { "rc4", algtype_rc4, IPSECDOI_ESP_RC4, 8,
180 NULL, NULL,
181 NULL, NULL, },
182 #endif
183 };
184
185 static struct hmac_algorithm ipsec_hmacdef[] = {
186 { "md5", algtype_hmac_md5, IPSECDOI_ATTR_AUTH_HMAC_MD5,
187 NULL, NULL,
188 NULL, eay_md5_hashlen,
189 NULL, },
190 { "sha1", algtype_hmac_sha1, IPSECDOI_ATTR_AUTH_HMAC_SHA1,
191 NULL, NULL,
192 NULL, eay_sha1_hashlen,
193 NULL, },
194 #ifdef HAVE_OPENSSL
195 { "kpdk", algtype_kpdk, IPSECDOI_ATTR_AUTH_KPDK,
196 NULL, NULL,
197 NULL, eay_kpdk_hashlen,
198 NULL, },
199 #endif
200 { "null", algtype_non_auth, IPSECDOI_ATTR_AUTH_NONE,
201 NULL, NULL,
202 NULL, eay_null_hashlen,
203 NULL, },
204 #ifdef WITH_SHA2
205 { "hmac_sha2_256", algtype_hmac_sha2_256,IPSECDOI_ATTR_AUTH_HMAC_SHA2_256,
206 NULL, NULL,
207 NULL, eay_sha2_256_hashlen,
208 NULL, },
209 { "hmac_sha2_384", algtype_hmac_sha2_384,IPSECDOI_ATTR_AUTH_HMAC_SHA2_384,
210 NULL, NULL,
211 NULL, eay_sha2_384_hashlen,
212 NULL, },
213 { "hmac_sha2_512", algtype_hmac_sha2_512,IPSECDOI_ATTR_AUTH_HMAC_SHA2_512,
214 NULL, NULL,
215 NULL, eay_sha2_512_hashlen,
216 NULL, },
217 #endif
218 };
219
220 static struct misc_algorithm ipsec_compdef[] = {
221 { "oui", algtype_oui, IPSECDOI_IPCOMP_OUI, },
222 { "deflate", algtype_deflate, IPSECDOI_IPCOMP_DEFLATE, },
223 { "lzs", algtype_lzs, IPSECDOI_IPCOMP_LZS, },
224 };
225
226 /*
227 * In case of asymetric modes (hybrid xauth), what's racoon mode of
228 * operations ; it seems that the proposal should always use the
229 * initiator half (unless a server initiates a connection, which is
230 * not handled, and probably not useful).
231 */
232 static struct misc_algorithm oakley_authdef[] = {
233 { "pre_shared_key", algtype_psk, OAKLEY_ATTR_AUTH_METHOD_PSKEY, },
234 { "dsssig", algtype_dsssig, OAKLEY_ATTR_AUTH_METHOD_DSSSIG, },
235 { "rsasig", algtype_rsasig, OAKLEY_ATTR_AUTH_METHOD_RSASIG, },
236 { "rsaenc", algtype_rsaenc, OAKLEY_ATTR_AUTH_METHOD_RSAENC, },
237 { "rsarev", algtype_rsarev, OAKLEY_ATTR_AUTH_METHOD_RSAREV, },
238
239 { "gssapi_krb", algtype_gssapikrb,
240 OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB, },
241
242 #ifdef ENABLE_HYBRID
243 { "hybrid_rsa_server", algtype_hybrid_rsa_s,
244 OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R, },
245
246 { "hybrid_dss_server", algtype_hybrid_dss_s,
247 OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R, },
248
249 { "xauth_psk_server", algtype_xauth_psk_s,
250 OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R, },
251
252 { "xauth_rsa_server", algtype_xauth_rsa_s,
253 OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R, },
254
255 { "hybrid_rsa_client", algtype_hybrid_rsa_c,
256 OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I, },
257
258 { "hybrid_dss_client", algtype_hybrid_dss_c,
259 OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I, },
260
261 { "xauth_psk_client", algtype_xauth_psk_c,
262 OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I, },
263
264 { "xauth_rsa_client", algtype_xauth_rsa_c,
265 OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I, },
266 #endif
267 };
268
269 static struct dh_algorithm oakley_dhdef[] = {
270 { "modp768", algtype_modp768, OAKLEY_ATTR_GRP_DESC_MODP768,
271 &dh_modp768, },
272 { "modp1024", algtype_modp1024, OAKLEY_ATTR_GRP_DESC_MODP1024,
273 &dh_modp1024, },
274 { "modp1536", algtype_modp1536, OAKLEY_ATTR_GRP_DESC_MODP1536,
275 &dh_modp1536, },
276 { "modp2048", algtype_modp2048, OAKLEY_ATTR_GRP_DESC_MODP2048,
277 &dh_modp2048, },
278 { "modp3072", algtype_modp3072, OAKLEY_ATTR_GRP_DESC_MODP3072,
279 &dh_modp3072, },
280 { "modp4096", algtype_modp4096, OAKLEY_ATTR_GRP_DESC_MODP4096,
281 &dh_modp4096, },
282 { "modp6144", algtype_modp6144, OAKLEY_ATTR_GRP_DESC_MODP6144,
283 &dh_modp6144, },
284 { "modp8192", algtype_modp8192, OAKLEY_ATTR_GRP_DESC_MODP8192,
285 &dh_modp8192, },
286 };
287
288 static struct hash_algorithm *alg_oakley_hashdef __P((int));
289 static struct hmac_algorithm *alg_oakley_hmacdef __P((int));
290 static struct enc_algorithm *alg_oakley_encdef __P((int));
291 static struct enc_algorithm *alg_ipsec_encdef __P((int));
292 static struct hmac_algorithm *alg_ipsec_hmacdef __P((int));
293 static struct dh_algorithm *alg_oakley_dhdef __P((int));
294
295 /* oakley hash algorithm */
296 static struct hash_algorithm *
297 alg_oakley_hashdef(doi)
298 int doi;
299 {
300 int i;
301
302 for (i = 0; i < ARRAYLEN(oakley_hashdef); i++)
303 if (doi == oakley_hashdef[i].doi) {
304 plog(LLV_DEBUG, LOCATION, NULL, "hash(%s)\n",
305 oakley_hashdef[i].name);
306 return &oakley_hashdef[i];
307 }
308 return NULL;
309 }
310
311 int
312 alg_oakley_hashdef_ok(doi)
313 int doi;
314 {
315 struct hash_algorithm *f;
316
317 f = alg_oakley_hashdef(doi);
318 if (f == NULL)
319 return 0;
320
321 return 1;
322 }
323
324 int
325 alg_oakley_hashdef_doi(type)
326 int type;
327 {
328 int i, res = -1;
329
330 for (i = 0; i < ARRAYLEN(oakley_hashdef); i++)
331 if (type == oakley_hashdef[i].type) {
332 res = oakley_hashdef[i].doi;
333 break;
334 }
335 return res;
336 }
337
338 int
339 alg_oakley_hashdef_hashlen(doi)
340 int doi;
341 {
342 struct hash_algorithm *f;
343
344 f = alg_oakley_hashdef(doi);
345 if (f == NULL || f->hashlen == NULL)
346 return 0;
347
348 return (f->hashlen)();
349 }
350
351 const char *
352 alg_oakley_hashdef_name (doi)
353 int doi;
354 {
355 struct hash_algorithm *f;
356
357 f = alg_oakley_hashdef(doi);
358 if (f == NULL)
359 return "*UNKNOWN*";
360
361 return f->name;
362 }
363
364 vchar_t *
365 alg_oakley_hashdef_one(doi, buf)
366 int doi;
367 vchar_t *buf;
368 {
369 struct hash_algorithm *f;
370
371 f = alg_oakley_hashdef(doi);
372 if (f == NULL || f->hashlen == NULL)
373 return NULL;
374
375 return (f->one)(buf);
376 }
377
378 /* oakley hmac algorithm */
379 static struct hmac_algorithm *
380 alg_oakley_hmacdef(doi)
381 int doi;
382 {
383 int i;
384
385 for (i = 0; i < ARRAYLEN(oakley_hmacdef); i++)
386 if (doi == oakley_hmacdef[i].doi) {
387 plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
388 oakley_hmacdef[i].name);
389 return &oakley_hmacdef[i];
390 }
391 return NULL;
392 }
393
394 int
395 alg_oakley_hmacdef_doi(type)
396 int type;
397 {
398 int i, res = -1;
399
400 for (i = 0; i < ARRAYLEN(oakley_hmacdef); i++)
401 if (type == oakley_hmacdef[i].type) {
402 res = oakley_hmacdef[i].doi;
403 break;
404 }
405 return res;
406 }
407
408 vchar_t *
409 alg_oakley_hmacdef_one(doi, key, buf)
410 int doi;
411 vchar_t *key, *buf;
412 {
413 struct hmac_algorithm *f;
414 vchar_t *res;
415 #ifdef ENABLE_STATS
416 struct timeval start, end;
417 #endif
418
419 f = alg_oakley_hmacdef(doi);
420 if (f == NULL || f->one == NULL)
421 return NULL;
422
423 #ifdef ENABLE_STATS
424 gettimeofday(&start, NULL);
425 #endif
426
427 res = (f->one)(key, buf);
428
429 #ifdef ENABLE_STATS
430 gettimeofday(&end, NULL);
431 syslog(LOG_NOTICE, "%s(%s size=%zu): %8.6f", __func__,
432 f->name, buf->l, timedelta(&start, &end));
433 #endif
434
435 return res;
436 }
437
438 /* oakley encryption algorithm */
439 static struct enc_algorithm *
440 alg_oakley_encdef(doi)
441 int doi;
442 {
443 int i;
444
445 for (i = 0; i < ARRAYLEN(oakley_encdef); i++)
446 if (doi == oakley_encdef[i].doi) {
447 plog(LLV_DEBUG, LOCATION, NULL, "encryption(%s)\n",
448 oakley_encdef[i].name);
449 return &oakley_encdef[i];
450 }
451 return NULL;
452 }
453
454 int
455 alg_oakley_encdef_ok(doi)
456 int doi;
457 {
458 struct enc_algorithm *f;
459
460 f = alg_oakley_encdef(doi);
461 if (f == NULL)
462 return 0;
463
464 return 1;
465 }
466
467 int
468 alg_oakley_encdef_doi(type)
469 int type;
470 {
471 int i, res = -1;
472
473 for (i = 0; i < ARRAYLEN(oakley_encdef); i++)
474 if (type == oakley_encdef[i].type) {
475 res = oakley_encdef[i].doi;
476 break;
477 }
478 return res;
479 }
480
481 int
482 alg_oakley_encdef_keylen(doi, len)
483 int doi, len;
484 {
485 struct enc_algorithm *f;
486
487 f = alg_oakley_encdef(doi);
488 if (f == NULL || f->keylen == NULL)
489 return -1;
490
491 return (f->keylen)(len);
492 }
493
494 int
495 alg_oakley_encdef_blocklen(doi)
496 int doi;
497 {
498 struct enc_algorithm *f;
499
500 f = alg_oakley_encdef(doi);
501 if (f == NULL)
502 return -1;
503
504 return f->blocklen;
505 }
506
507 const char *
508 alg_oakley_encdef_name (doi)
509 int doi;
510 {
511 struct enc_algorithm *f;
512
513 f = alg_oakley_encdef(doi);
514 if (f == NULL)
515 return "*UNKNOWN*";
516
517 return f->name;
518 }
519
520 vchar_t *
521 alg_oakley_encdef_decrypt(doi, buf, key, iv)
522 int doi;
523 vchar_t *buf, *key, *iv;
524 {
525 vchar_t *res;
526 struct enc_algorithm *f;
527 #ifdef ENABLE_STATS
528 struct timeval start, end;
529 #endif
530
531 f = alg_oakley_encdef(doi);
532 if (f == NULL || f->decrypt == NULL)
533 return NULL;
534
535 #ifdef ENABLE_STATS
536 gettimeofday(&start, NULL);
537 #endif
538
539 res = (f->decrypt)(buf, key, iv);
540
541 #ifdef ENABLE_STATS
542 gettimeofday(&end, NULL);
543 syslog(LOG_NOTICE, "%s(%s klen=%zu size=%zu): %8.6f", __func__,
544 f->name, key->l << 3, buf->l, timedelta(&start, &end));
545 #endif
546 return res;
547 }
548
549 vchar_t *
550 alg_oakley_encdef_encrypt(doi, buf, key, iv)
551 int doi;
552 vchar_t *buf, *key, *iv;
553 {
554 vchar_t *res;
555 struct enc_algorithm *f;
556 #ifdef ENABLE_STATS
557 struct timeval start, end;
558 #endif
559
560 f = alg_oakley_encdef(doi);
561 if (f == NULL || f->encrypt == NULL)
562 return NULL;
563
564 #ifdef ENABLE_STATS
565 gettimeofday(&start, NULL);
566 #endif
567
568 res = (f->encrypt)(buf, key, iv);
569
570 #ifdef ENABLE_STATS
571 gettimeofday(&end, NULL);
572 syslog(LOG_NOTICE, "%s(%s klen=%zu size=%zu): %8.6f", __func__,
573 f->name, key->l << 3, buf->l, timedelta(&start, &end));
574 #endif
575 return res;
576 }
577
578 /* ipsec encryption algorithm */
579 static struct enc_algorithm *
580 alg_ipsec_encdef(doi)
581 int doi;
582 {
583 int i;
584
585 for (i = 0; i < ARRAYLEN(ipsec_encdef); i++)
586 if (doi == ipsec_encdef[i].doi) {
587 plog(LLV_DEBUG, LOCATION, NULL, "encryption(%s)\n",
588 ipsec_encdef[i].name);
589 return &ipsec_encdef[i];
590 }
591 return NULL;
592 }
593
594 int
595 alg_ipsec_encdef_doi(type)
596 int type;
597 {
598 int i, res = -1;
599
600 for (i = 0; i < ARRAYLEN(ipsec_encdef); i++)
601 if (type == ipsec_encdef[i].type) {
602 res = ipsec_encdef[i].doi;
603 break;
604 }
605 return res;
606 }
607
608 int
609 alg_ipsec_encdef_keylen(doi, len)
610 int doi, len;
611 {
612 struct enc_algorithm *f;
613
614 f = alg_ipsec_encdef(doi);
615 if (f == NULL || f->keylen == NULL)
616 return -1;
617
618 return (f->keylen)(len);
619 }
620
621 /* ipsec hmac algorithm */
622 static struct hmac_algorithm *
623 alg_ipsec_hmacdef(doi)
624 int doi;
625 {
626 int i;
627
628 for (i = 0; i < ARRAYLEN(ipsec_hmacdef); i++)
629 if (doi == ipsec_hmacdef[i].doi) {
630 plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
631 ipsec_hmacdef[i].name);
632 return &ipsec_hmacdef[i];
633 }
634 return NULL;
635 }
636
637 int
638 alg_ipsec_hmacdef_doi(type)
639 int type;
640 {
641 int i, res = -1;
642
643 for (i = 0; i < ARRAYLEN(ipsec_hmacdef); i++)
644 if (type == ipsec_hmacdef[i].type) {
645 res = ipsec_hmacdef[i].doi;
646 break;
647 }
648 return res;
649 }
650
651 int
652 alg_ipsec_hmacdef_hashlen(doi)
653 int doi;
654 {
655 struct hmac_algorithm *f;
656
657 f = alg_ipsec_hmacdef(doi);
658 if (f == NULL || f->hashlen == NULL)
659 return -1;
660
661 return (f->hashlen)();
662 }
663
664 /* ip compression */
665 int
666 alg_ipsec_compdef_doi(type)
667 int type;
668 {
669 int i, res = -1;
670
671 for (i = 0; i < ARRAYLEN(ipsec_compdef); i++)
672 if (type == ipsec_compdef[i].type) {
673 res = ipsec_compdef[i].doi;
674 break;
675 }
676 return res;
677 }
678
679 /* dh algorithm */
680 static struct dh_algorithm *
681 alg_oakley_dhdef(doi)
682 int doi;
683 {
684 int i;
685
686 for (i = 0; i < ARRAYLEN(oakley_dhdef); i++)
687 if (doi == oakley_dhdef[i].doi) {
688 plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
689 oakley_dhdef[i].name);
690 return &oakley_dhdef[i];
691 }
692 return NULL;
693 }
694
695 int
696 alg_oakley_dhdef_ok(doi)
697 int doi;
698 {
699 struct dh_algorithm *f;
700
701 f = alg_oakley_dhdef(doi);
702 if (f == NULL)
703 return 0;
704
705 return 1;
706 }
707
708 int
709 alg_oakley_dhdef_doi(type)
710 int type;
711 {
712 int i, res = -1;
713
714 for (i = 0; i < ARRAYLEN(oakley_dhdef); i++)
715 if (type == oakley_dhdef[i].type) {
716 res = oakley_dhdef[i].doi;
717 break;
718 }
719 return res;
720 }
721
722 struct dhgroup *
723 alg_oakley_dhdef_group(doi)
724 int doi;
725 {
726 struct dh_algorithm *f;
727
728 f = alg_oakley_dhdef(doi);
729 if (f == NULL || f->dhgroup == NULL)
730 return NULL;
731
732 return f->dhgroup;
733 }
734
735 const char *
736 alg_oakley_dhdef_name (doi)
737 int doi;
738 {
739 struct dh_algorithm *f;
740
741 f = alg_oakley_dhdef(doi);
742 if (f == NULL)
743 return "*UNKNOWN*";
744 return f->name;
745 }
746
747 /* authentication method */
748 int
749 alg_oakley_authdef_doi(type)
750 int type;
751 {
752 int i, res = -1;
753
754 for (i = 0; i < ARRAYLEN(oakley_authdef); i++)
755 if (type == oakley_authdef[i].type) {
756 res = oakley_authdef[i].doi;
757 break;
758 }
759 return res;
760 }
761
762 const char *
763 alg_oakley_authdef_name (doi)
764 int doi;
765 {
766 int i;
767
768 for (i = 0; i < ARRAYLEN(oakley_authdef); i++)
769 if (doi == oakley_authdef[i].doi) {
770 return oakley_authdef[i].name;
771 }
772 return "*UNKNOWN*";
773 }
774
775 /*
776 * give the default key length
777 * OUT: -1: NG
778 * 0: fixed key cipher, key length not allowed
779 * positive: default key length
780 */
781 int
782 default_keylen(class, type)
783 int class, type;
784 {
785
786 switch (class) {
787 case algclass_isakmp_enc:
788 case algclass_ipsec_enc:
789 break;
790 default:
791 return 0;
792 }
793
794 switch (type) {
795 case algtype_blowfish:
796 case algtype_rc5:
797 case algtype_cast128:
798 case algtype_aes:
799 case algtype_twofish:
800 return 128;
801 default:
802 return 0;
803 }
804 }
805
806 /*
807 * check key length
808 * OUT: -1: NG
809 * 0: OK
810 */
811 int
812 check_keylen(class, type, len)
813 int class, type, len;
814 {
815 int badrange;
816
817 switch (class) {
818 case algclass_isakmp_enc:
819 case algclass_ipsec_enc:
820 break;
821 default:
822 /* unknown class, punt */
823 plog(LLV_ERROR, LOCATION, NULL,
824 "unknown algclass %d\n", class);
825 return -1;
826 }
827
828 /* key length must be multiple of 8 bytes - RFC2451 2.2 */
829 switch (type) {
830 case algtype_blowfish:
831 case algtype_rc5:
832 case algtype_cast128:
833 case algtype_aes:
834 case algtype_twofish:
835 if (len % 8 != 0) {
836 plog(LLV_ERROR, LOCATION, NULL,
837 "key length %d is not multiple of 8\n", len);
838 return -1;
839 }
840 break;
841 }
842
843 /* key length range */
844 badrange = 0;
845 switch (type) {
846 case algtype_blowfish:
847 if (len < 40 || 448 < len)
848 badrange++;
849 break;
850 case algtype_rc5:
851 if (len < 40 || 2040 < len)
852 badrange++;
853 break;
854 case algtype_cast128:
855 if (len < 40 || 128 < len)
856 badrange++;
857 break;
858 case algtype_aes:
859 if (!(len == 128 || len == 192 || len == 256))
860 badrange++;
861 break;
862 case algtype_twofish:
863 if (len < 40 || 256 < len)
864 badrange++;
865 break;
866 default:
867 if (len) {
868 plog(LLV_ERROR, LOCATION, NULL,
869 "key length is not allowed");
870 return -1;
871 }
872 break;
873 }
874 if (badrange) {
875 plog(LLV_ERROR, LOCATION, NULL,
876 "key length out of range\n");
877 return -1;
878 }
879
880 return 0;
881 }
882
883 /*
884 * convert algorithm type to DOI value.
885 * OUT -1 : NG
886 * other: converted.
887 */
888 int
889 algtype2doi(class, type)
890 int class, type;
891 {
892 int res = -1;
893
894 switch (class) {
895 case algclass_ipsec_enc:
896 res = alg_ipsec_encdef_doi(type);
897 break;
898 case algclass_ipsec_auth:
899 res = alg_ipsec_hmacdef_doi(type);
900 break;
901 case algclass_ipsec_comp:
902 res = alg_ipsec_compdef_doi(type);
903 break;
904 case algclass_isakmp_enc:
905 res = alg_oakley_encdef_doi(type);
906 break;
907 case algclass_isakmp_hash:
908 res = alg_oakley_hashdef_doi(type);
909 break;
910 case algclass_isakmp_dh:
911 res = alg_oakley_dhdef_doi(type);
912 break;
913 case algclass_isakmp_ameth:
914 res = alg_oakley_authdef_doi(type);
915 break;
916 }
917 return res;
918 }
919
920 /*
921 * convert algorithm class to DOI value.
922 * OUT -1 : NG
923 * other: converted.
924 */
925 int
926 algclass2doi(class)
927 int class;
928 {
929 switch (class) {
930 case algclass_ipsec_enc:
931 return IPSECDOI_PROTO_IPSEC_ESP;
932 case algclass_ipsec_auth:
933 return IPSECDOI_ATTR_AUTH;
934 case algclass_ipsec_comp:
935 return IPSECDOI_PROTO_IPCOMP;
936 case algclass_isakmp_enc:
937 return OAKLEY_ATTR_ENC_ALG;
938 case algclass_isakmp_hash:
939 return OAKLEY_ATTR_HASH_ALG;
940 case algclass_isakmp_dh:
941 return OAKLEY_ATTR_GRP_DESC;
942 case algclass_isakmp_ameth:
943 return OAKLEY_ATTR_AUTH_METHOD;
944 default:
945 return -1;
946 }
947 /*NOTREACHED*/
948 return -1;
949 }