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