xref: /netbsd-src/crypto/dist/ipsec-tools/src/racoon/algorithm.c (revision 1c9b56c830954ccf3b57004ac65562e3d6afacf6)
1 /* $Id: algorithm.c,v 1.1.1.1 2005/02/12 11:11:39 manu 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_IDEA_H
108 { "idea",	algtype_idea,		OAKLEY_ATTR_ENC_ALG_IDEA,	8,
109 		eay_idea_encrypt,	eay_idea_decrypt,
110 		eay_idea_weakkey,	eay_idea_keylen, },
111 #endif
112 { "blowfish",	algtype_blowfish,	OAKLEY_ATTR_ENC_ALG_BLOWFISH,	8,
113 		eay_bf_encrypt,		eay_bf_decrypt,
114 		eay_bf_weakkey,		eay_bf_keylen, },
115 #ifdef HAVE_OPENSSL_RC5_H
116 { "rc5",	algtype_rc5,		OAKLEY_ATTR_ENC_ALG_RC5,	8,
117 		eay_rc5_encrypt,	eay_rc5_decrypt,
118 		eay_rc5_weakkey,	eay_rc5_keylen, },
119 #endif
120 { "3des",	algtype_3des,		OAKLEY_ATTR_ENC_ALG_3DES,	8,
121 		eay_3des_encrypt,	eay_3des_decrypt,
122 		eay_3des_weakkey,	eay_3des_keylen, },
123 { "cast",	algtype_cast128,	OAKLEY_ATTR_ENC_ALG_CAST,	8,
124 		eay_cast_encrypt,	eay_cast_decrypt,
125 		eay_cast_weakkey,	eay_cast_keylen, },
126 { "aes",	algtype_aes,	OAKLEY_ATTR_ENC_ALG_AES,	16,
127 		eay_aes_encrypt,	eay_aes_decrypt,
128 		eay_aes_weakkey,	eay_aes_keylen, },
129 };
130 
131 static struct enc_algorithm ipsec_encdef[] = {
132 { "des-iv64",	algtype_des_iv64,	IPSECDOI_ESP_DES_IV64,		8,
133 		NULL,			NULL,
134 		NULL,			eay_des_keylen, },
135 { "des",	algtype_des,		IPSECDOI_ESP_DES,		8,
136 		NULL,			NULL,
137 		NULL,			eay_des_keylen, },
138 { "3des",	algtype_3des,		IPSECDOI_ESP_3DES,		8,
139 		NULL,			NULL,
140 		NULL,			eay_3des_keylen, },
141 #ifdef HAVE_OPENSSL_RC5_H
142 { "rc5",	algtype_rc5,		IPSECDOI_ESP_RC5,		8,
143 		NULL,			NULL,
144 		NULL,			eay_rc5_keylen, },
145 #endif
146 { "cast",	algtype_cast128,	IPSECDOI_ESP_CAST,		8,
147 		NULL,			NULL,
148 		NULL,			eay_cast_keylen, },
149 { "blowfish",	algtype_blowfish,	IPSECDOI_ESP_BLOWFISH,		8,
150 		NULL,			NULL,
151 		NULL,			eay_bf_keylen, },
152 { "des-iv32",	algtype_des_iv32,	IPSECDOI_ESP_DES_IV32,		8,
153 		NULL,			NULL,
154 		NULL,			eay_des_keylen, },
155 { "null",	algtype_null_enc,	IPSECDOI_ESP_NULL,		8,
156 		NULL,			NULL,
157 		NULL,			eay_null_keylen, },
158 { "aes",	algtype_aes,		IPSECDOI_ESP_AES,		16,
159 		NULL,			NULL,
160 		NULL,			eay_aes_keylen, },
161 { "twofish",	algtype_twofish,	IPSECDOI_ESP_TWOFISH,		16,
162 		NULL,			NULL,
163 		NULL,			eay_twofish_keylen, },
164 #ifdef HAVE_OPENSSL_IDEA_H
165 { "3idea",	algtype_3idea,		IPSECDOI_ESP_3IDEA,		8,
166 		NULL,			NULL,
167 		NULL,			NULL, },
168 { "idea",	algtype_idea,		IPSECDOI_ESP_IDEA,		8,
169 		NULL,			NULL,
170 		NULL,			NULL, },
171 #endif
172 { "rc4",	algtype_rc4,		IPSECDOI_ESP_RC4,		8,
173 		NULL,			NULL,
174 		NULL,			NULL, },
175 };
176 
177 static struct hmac_algorithm ipsec_hmacdef[] = {
178 { "md5",	algtype_hmac_md5,	IPSECDOI_ATTR_AUTH_HMAC_MD5,
179 		NULL,			NULL,
180 		NULL,			eay_md5_hashlen,
181 		NULL, },
182 { "sha1",	algtype_hmac_sha1,	IPSECDOI_ATTR_AUTH_HMAC_SHA1,
183 		NULL,			NULL,
184 		NULL,			eay_sha1_hashlen,
185 		NULL, },
186 { "kpdk",	algtype_kpdk,		IPSECDOI_ATTR_AUTH_KPDK,
187 		NULL,			NULL,
188 		NULL,			eay_kpdk_hashlen,
189 		NULL, },
190 { "null",	algtype_non_auth,	IPSECDOI_ATTR_AUTH_NONE,
191 		NULL,			NULL,
192 		NULL,			eay_null_hashlen,
193 		NULL, },
194 #ifdef WITH_SHA2
195 { "hmac_sha2_256",	algtype_hmac_sha2_256,	IPSECDOI_ATTR_SHA2_256,
196 		NULL,			NULL,
197 		NULL,			eay_sha2_256_hashlen,
198 		NULL, },
199 { "hmac_sha2_384",	algtype_hmac_sha2_384,	IPSECDOI_ATTR_SHA2_384,
200 		NULL,			NULL,
201 		NULL,			eay_sha2_384_hashlen,
202 		NULL, },
203 { "hmac_sha2_512",	algtype_hmac_sha2_512,	IPSECDOI_ATTR_SHA2_512,
204 		NULL,			NULL,
205 		NULL,			eay_sha2_512_hashlen,
206 		NULL, },
207 #endif
208 };
209 
210 static struct misc_algorithm ipsec_compdef[] = {
211 { "oui",	algtype_oui,		IPSECDOI_IPCOMP_OUI, },
212 { "deflate",	algtype_deflate,	IPSECDOI_IPCOMP_DEFLATE, },
213 { "lzs",	algtype_lzs,		IPSECDOI_IPCOMP_LZS, },
214 };
215 
216 static struct misc_algorithm oakley_authdef[] = {
217 { "pre_shared_key",	algtype_psk,		OAKLEY_ATTR_AUTH_METHOD_PSKEY, },
218 { "dsssig",	algtype_dsssig,		OAKLEY_ATTR_AUTH_METHOD_DSSSIG, },
219 { "rsasig",	algtype_rsasig,		OAKLEY_ATTR_AUTH_METHOD_RSASIG, },
220 { "rsaenc",	algtype_rsaenc,		OAKLEY_ATTR_AUTH_METHOD_RSAENC, },
221 { "rsarev",	algtype_rsarev,		OAKLEY_ATTR_AUTH_METHOD_RSAREV, },
222 { "gssapi_krb",	algtype_gssapikrb,	OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB, },
223 #ifdef ENABLE_HYBRID
224 { "hybrid_rsa_server",        algtype_hybrid_rsa_s,
225 	OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I, },
226 { "hybrid_dss_server",        algtype_hybrid_dss_s,
227 	OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I, },
228 { "hybrid_rsa_client",        algtype_hybrid_rsa_c,
229 	OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R, },
230 { "hybrid_dss_client",        algtype_hybrid_dss_c,
231 	OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R, },
232 #endif
233 };
234 
235 static struct dh_algorithm oakley_dhdef[] = {
236 { "modp768",	algtype_modp768,	OAKLEY_ATTR_GRP_DESC_MODP768,
237 		&dh_modp768, },
238 { "modp1024",	algtype_modp1024,	OAKLEY_ATTR_GRP_DESC_MODP1024,
239 		&dh_modp1024, },
240 { "modp1536",	algtype_modp1536,	OAKLEY_ATTR_GRP_DESC_MODP1536,
241 		&dh_modp1536, },
242 { "modp2048",	algtype_modp2048,	OAKLEY_ATTR_GRP_DESC_MODP2048,
243 		&dh_modp2048, },
244 { "modp3072",	algtype_modp3072,	OAKLEY_ATTR_GRP_DESC_MODP3072,
245 		&dh_modp3072, },
246 { "modp4096",	algtype_modp4096,	OAKLEY_ATTR_GRP_DESC_MODP4096,
247 		&dh_modp4096, },
248 { "modp6144",	algtype_modp6144,	OAKLEY_ATTR_GRP_DESC_MODP6144,
249 		&dh_modp6144, },
250 { "modp8192",	algtype_modp8192,	OAKLEY_ATTR_GRP_DESC_MODP8192,
251 		&dh_modp8192, },
252 };
253 
254 static struct hash_algorithm *alg_oakley_hashdef __P((int));
255 static struct hmac_algorithm *alg_oakley_hmacdef __P((int));
256 static struct enc_algorithm *alg_oakley_encdef __P((int));
257 static struct enc_algorithm *alg_ipsec_encdef __P((int));
258 static struct hmac_algorithm *alg_ipsec_hmacdef __P((int));
259 static struct dh_algorithm *alg_oakley_dhdef __P((int));
260 
261 /* oakley hash algorithm */
262 static struct hash_algorithm *
263 alg_oakley_hashdef(doi)
264 	int doi;
265 {
266 	int i;
267 
268 	for (i = 0; i < ARRAYLEN(oakley_hashdef); i++)
269 		if (doi == oakley_hashdef[i].doi) {
270 			plog(LLV_DEBUG, LOCATION, NULL, "hash(%s)\n",
271 				oakley_hashdef[i].name);
272 			return &oakley_hashdef[i];
273 		}
274 	return NULL;
275 }
276 
277 int
278 alg_oakley_hashdef_ok(doi)
279 	int doi;
280 {
281 	struct hash_algorithm *f;
282 
283 	f = alg_oakley_hashdef(doi);
284 	if (f == NULL)
285 		return 0;
286 
287 	return 1;
288 }
289 
290 int
291 alg_oakley_hashdef_doi(type)
292 	int type;
293 {
294 	int i, res = -1;
295 
296 	for (i = 0; i < ARRAYLEN(oakley_hashdef); i++)
297 		if (type == oakley_hashdef[i].type) {
298 			res = oakley_hashdef[i].doi;
299 			break;
300 		}
301 	return res;
302 }
303 
304 int
305 alg_oakley_hashdef_hashlen(doi)
306 	int doi;
307 {
308 	struct hash_algorithm *f;
309 
310 	f = alg_oakley_hashdef(doi);
311 	if (f == NULL || f->hashlen == NULL)
312 		return 0;
313 
314 	return (f->hashlen)();
315 }
316 
317 const char *
318 alg_oakley_hashdef_name (doi)
319 	int doi;
320 {
321 	struct hash_algorithm *f;
322 
323 	f = alg_oakley_hashdef(doi);
324 	if (f == NULL)
325 		return "*UNKNOWN*";
326 
327 	return f->name;
328 }
329 
330 vchar_t *
331 alg_oakley_hashdef_one(doi, buf)
332 	int doi;
333 	vchar_t *buf;
334 {
335 	struct hash_algorithm *f;
336 
337 	f = alg_oakley_hashdef(doi);
338 	if (f == NULL || f->hashlen == NULL)
339 		return NULL;
340 
341 	return (f->one)(buf);
342 }
343 
344 /* oakley hmac algorithm */
345 static struct hmac_algorithm *
346 alg_oakley_hmacdef(doi)
347 	int doi;
348 {
349 	int i;
350 
351 	for (i = 0; i < ARRAYLEN(oakley_hmacdef); i++)
352 		if (doi == oakley_hmacdef[i].doi) {
353 			plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
354 				oakley_hmacdef[i].name);
355 			return &oakley_hmacdef[i];
356 		}
357 	return NULL;
358 }
359 
360 int
361 alg_oakley_hmacdef_doi(type)
362 	int type;
363 {
364 	int i, res = -1;
365 
366 	for (i = 0; i < ARRAYLEN(oakley_hmacdef); i++)
367 		if (type == oakley_hmacdef[i].type) {
368 			res = oakley_hmacdef[i].doi;
369 			break;
370 		}
371 	return res;
372 }
373 
374 vchar_t *
375 alg_oakley_hmacdef_one(doi, key, buf)
376 	int doi;
377 	vchar_t *key, *buf;
378 {
379 	struct hmac_algorithm *f;
380 	vchar_t *res;
381 #ifdef ENABLE_STATS
382 	struct timeval start, end;
383 #endif
384 
385 	f = alg_oakley_hmacdef(doi);
386 	if (f == NULL || f->one == NULL)
387 		return NULL;
388 
389 #ifdef ENABLE_STATS
390 	gettimeofday(&start, NULL);
391 #endif
392 
393 	res = (f->one)(key, buf);
394 
395 #ifdef ENABLE_STATS
396 	gettimeofday(&end, NULL);
397 	syslog(LOG_NOTICE, "%s(%s size=%d): %8.6f", __func__,
398 		f->name, buf->l, timedelta(&start, &end));
399 #endif
400 
401 	return res;
402 }
403 
404 /* oakley encryption algorithm */
405 static struct enc_algorithm *
406 alg_oakley_encdef(doi)
407 	int doi;
408 {
409 	int i;
410 
411 	for (i = 0; i < ARRAYLEN(oakley_encdef); i++)
412 		if (doi == oakley_encdef[i].doi) {
413 			plog(LLV_DEBUG, LOCATION, NULL, "encryption(%s)\n",
414 				oakley_encdef[i].name);
415 			return &oakley_encdef[i];
416 		}
417 	return NULL;
418 }
419 
420 int
421 alg_oakley_encdef_ok(doi)
422 	int doi;
423 {
424 	struct enc_algorithm *f;
425 
426 	f = alg_oakley_encdef(doi);
427 	if (f == NULL)
428 		return 0;
429 
430 	return 1;
431 }
432 
433 int
434 alg_oakley_encdef_doi(type)
435 	int type;
436 {
437 	int i, res = -1;
438 
439 	for (i = 0; i < ARRAYLEN(oakley_encdef); i++)
440 		if (type == oakley_encdef[i].type) {
441 			res = oakley_encdef[i].doi;
442 			break;
443 		}
444 	return res;
445 }
446 
447 int
448 alg_oakley_encdef_keylen(doi, len)
449 	int doi, len;
450 {
451 	struct enc_algorithm *f;
452 
453 	f = alg_oakley_encdef(doi);
454 	if (f == NULL || f->keylen == NULL)
455 		return -1;
456 
457 	return (f->keylen)(len);
458 }
459 
460 int
461 alg_oakley_encdef_blocklen(doi)
462 	int doi;
463 {
464 	struct enc_algorithm *f;
465 
466 	f = alg_oakley_encdef(doi);
467 	if (f == NULL)
468 		return -1;
469 
470 	return f->blocklen;
471 }
472 
473 const char *
474 alg_oakley_encdef_name (doi)
475 	int doi;
476 {
477 	struct enc_algorithm *f;
478 
479 	f = alg_oakley_encdef(doi);
480 	if (f == NULL)
481 		return "*UNKNOWN*";
482 
483 	return f->name;
484 }
485 
486 vchar_t *
487 alg_oakley_encdef_decrypt(doi, buf, key, iv)
488 	int doi;
489 	vchar_t *buf, *key, *iv;
490 {
491 	vchar_t *res;
492 	struct enc_algorithm *f;
493 #ifdef ENABLE_STATS
494 	struct timeval start, end;
495 #endif
496 
497 	f = alg_oakley_encdef(doi);
498 	if (f == NULL || f->decrypt == NULL)
499 		return NULL;
500 
501 #ifdef ENABLE_STATS
502 	gettimeofday(&start, NULL);
503 #endif
504 
505 	res = (f->decrypt)(buf, key, iv);
506 
507 #ifdef ENABLE_STATS
508 	gettimeofday(&end, NULL);
509 	syslog(LOG_NOTICE, "%s(%s klen=%d size=%d): %8.6f", __func__,
510 		f->name, key->l << 3, buf->l, timedelta(&start, &end));
511 #endif
512 	return res;
513 }
514 
515 vchar_t *
516 alg_oakley_encdef_encrypt(doi, buf, key, iv)
517 	int doi;
518 	vchar_t *buf, *key, *iv;
519 {
520 	vchar_t *res;
521 	struct enc_algorithm *f;
522 #ifdef ENABLE_STATS
523 	struct timeval start, end;
524 #endif
525 
526 	f = alg_oakley_encdef(doi);
527 	if (f == NULL || f->encrypt == NULL)
528 		return NULL;
529 
530 #ifdef ENABLE_STATS
531 	gettimeofday(&start, NULL);
532 #endif
533 
534 	res = (f->encrypt)(buf, key, iv);
535 
536 #ifdef ENABLE_STATS
537 	gettimeofday(&end, NULL);
538 	syslog(LOG_NOTICE, "%s(%s klen=%d size=%d): %8.6f", __func__,
539 		f->name, key->l << 3, buf->l, timedelta(&start, &end));
540 #endif
541 	return res;
542 }
543 
544 /* ipsec encryption algorithm */
545 static struct enc_algorithm *
546 alg_ipsec_encdef(doi)
547 	int doi;
548 {
549 	int i;
550 
551 	for (i = 0; i < ARRAYLEN(ipsec_encdef); i++)
552 		if (doi == ipsec_encdef[i].doi) {
553 			plog(LLV_DEBUG, LOCATION, NULL, "encryption(%s)\n",
554 				ipsec_encdef[i].name);
555 			return &ipsec_encdef[i];
556 		}
557 	return NULL;
558 }
559 
560 int
561 alg_ipsec_encdef_doi(type)
562 	int type;
563 {
564 	int i, res = -1;
565 
566 	for (i = 0; i < ARRAYLEN(ipsec_encdef); i++)
567 		if (type == ipsec_encdef[i].type) {
568 			res = ipsec_encdef[i].doi;
569 			break;
570 		}
571 	return res;
572 }
573 
574 int
575 alg_ipsec_encdef_keylen(doi, len)
576 	int doi, len;
577 {
578 	struct enc_algorithm *f;
579 
580 	f = alg_ipsec_encdef(doi);
581 	if (f == NULL || f->keylen == NULL)
582 		return -1;
583 
584 	return (f->keylen)(len);
585 }
586 
587 /* ipsec hmac algorithm */
588 static struct hmac_algorithm *
589 alg_ipsec_hmacdef(doi)
590 	int doi;
591 {
592 	int i;
593 
594 	for (i = 0; i < ARRAYLEN(ipsec_hmacdef); i++)
595 		if (doi == ipsec_hmacdef[i].doi) {
596 			plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
597 				oakley_hmacdef[i].name);
598 			return &ipsec_hmacdef[i];
599 		}
600 	return NULL;
601 }
602 
603 int
604 alg_ipsec_hmacdef_doi(type)
605 	int type;
606 {
607 	int i, res = -1;
608 
609 	for (i = 0; i < ARRAYLEN(ipsec_hmacdef); i++)
610 		if (type == ipsec_hmacdef[i].type) {
611 			res = ipsec_hmacdef[i].doi;
612 			break;
613 		}
614 	return res;
615 }
616 
617 int
618 alg_ipsec_hmacdef_hashlen(doi)
619 	int doi;
620 {
621 	struct hmac_algorithm *f;
622 
623 	f = alg_ipsec_hmacdef(doi);
624 	if (f == NULL || f->hashlen == NULL)
625 		return -1;
626 
627 	return (f->hashlen)();
628 }
629 
630 /* ip compression */
631 int
632 alg_ipsec_compdef_doi(type)
633 	int type;
634 {
635 	int i, res = -1;
636 
637 	for (i = 0; i < ARRAYLEN(ipsec_compdef); i++)
638 		if (type == ipsec_compdef[i].type) {
639 			res = ipsec_compdef[i].doi;
640 			break;
641 		}
642 	return res;
643 }
644 
645 /* dh algorithm */
646 static struct dh_algorithm *
647 alg_oakley_dhdef(doi)
648 	int doi;
649 {
650 	int i;
651 
652 	for (i = 0; i < ARRAYLEN(oakley_dhdef); i++)
653 		if (doi == oakley_dhdef[i].doi) {
654 			plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
655 				oakley_dhdef[i].name);
656 			return &oakley_dhdef[i];
657 		}
658 	return NULL;
659 }
660 
661 int
662 alg_oakley_dhdef_ok(doi)
663 	int doi;
664 {
665 	struct dh_algorithm *f;
666 
667 	f = alg_oakley_dhdef(doi);
668 	if (f == NULL)
669 		return 0;
670 
671 	return 1;
672 }
673 
674 int
675 alg_oakley_dhdef_doi(type)
676 	int type;
677 {
678 	int i, res = -1;
679 
680 	for (i = 0; i < ARRAYLEN(oakley_dhdef); i++)
681 		if (type == oakley_dhdef[i].type) {
682 			res = oakley_dhdef[i].doi;
683 			break;
684 		}
685 	return res;
686 }
687 
688 struct dhgroup *
689 alg_oakley_dhdef_group(doi)
690 	int doi;
691 {
692 	struct dh_algorithm *f;
693 
694 	f = alg_oakley_dhdef(doi);
695 	if (f == NULL || f->dhgroup == NULL)
696 		return NULL;
697 
698 	return f->dhgroup;
699 }
700 
701 const char *
702 alg_oakley_dhdef_name (doi)
703 	int doi;
704 {
705 	struct dh_algorithm *f;
706 
707 	f = alg_oakley_dhdef(doi);
708 	if (f == NULL)
709 		return "*UNKNOWN*";
710 	return f->name;
711 }
712 
713 /* authentication method */
714 int
715 alg_oakley_authdef_doi(type)
716 	int type;
717 {
718 	int i, res = -1;
719 
720 	for (i = 0; i < ARRAYLEN(oakley_authdef); i++)
721 		if (type == oakley_authdef[i].type) {
722 			res = oakley_authdef[i].doi;
723 			break;
724 		}
725 	return res;
726 }
727 
728 const char *
729 alg_oakley_authdef_name (doi)
730 	int doi;
731 {
732 	int i;
733 
734 	for (i = 0; i < ARRAYLEN(oakley_authdef); i++)
735 		if (doi == oakley_authdef[i].doi) {
736 			return oakley_authdef[i].name;
737 		}
738 	return "*UNKNOWN*";
739 }
740 
741 /*
742  * give the default key length
743  * OUT:	-1:		NG
744  *	0:		fixed key cipher, key length not allowed
745  *	positive:	default key length
746  */
747 int
748 default_keylen(class, type)
749 	int class, type;
750 {
751 
752 	switch (class) {
753 	case algclass_isakmp_enc:
754 	case algclass_ipsec_enc:
755 		break;
756 	default:
757 		return 0;
758 	}
759 
760 	switch (type) {
761 	case algtype_blowfish:
762 	case algtype_rc5:
763 	case algtype_cast128:
764 	case algtype_aes:
765 	case algtype_twofish:
766 		return 128;
767 	default:
768 		return 0;
769 	}
770 }
771 
772 /*
773  * check key length
774  * OUT:	-1:	NG
775  *	0:	OK
776  */
777 int
778 check_keylen(class, type, len)
779 	int class, type, len;
780 {
781 	int badrange;
782 
783 	switch (class) {
784 	case algclass_isakmp_enc:
785 	case algclass_ipsec_enc:
786 		break;
787 	default:
788 		/* unknown class, punt */
789 		plog(LLV_ERROR, LOCATION, NULL,
790 			"unknown algclass %d\n", class);
791 		return -1;
792 	}
793 
794 	/* key length must be multiple of 8 bytes - RFC2451 2.2 */
795 	switch (type) {
796 	case algtype_blowfish:
797 	case algtype_rc5:
798 	case algtype_cast128:
799 	case algtype_aes:
800 	case algtype_twofish:
801 		if (len % 8 != 0) {
802 			plog(LLV_ERROR, LOCATION, NULL,
803 				"key length %d is not multiple of 8\n", len);
804 			return -1;
805 		}
806 		break;
807 	}
808 
809 	/* key length range */
810 	badrange = 0;
811 	switch (type) {
812 	case algtype_blowfish:
813 		if (len < 40 || 448 < len)
814 			badrange++;
815 		break;
816 	case algtype_rc5:
817 		if (len < 40 || 2040 < len)
818 			badrange++;
819 		break;
820 	case algtype_cast128:
821 		if (len < 40 || 128 < len)
822 			badrange++;
823 		break;
824 	case algtype_aes:
825 		if (!(len == 128 || len == 192 || len == 256))
826 			badrange++;
827 		break;
828 	case algtype_twofish:
829 		if (len < 40 || 256 < len)
830 			badrange++;
831 		break;
832 	default:
833 		if (len) {
834 			plog(LLV_ERROR, LOCATION, NULL,
835 				"key length is not allowed");
836 			return -1;
837 		}
838 		break;
839 	}
840 	if (badrange) {
841 		plog(LLV_ERROR, LOCATION, NULL,
842 			"key length out of range\n");
843 		return -1;
844 	}
845 
846 	return 0;
847 }
848 
849 /*
850  * convert algorithm type to DOI value.
851  * OUT	-1   : NG
852  *	other: converted.
853  */
854 int
855 algtype2doi(class, type)
856 	int class, type;
857 {
858 	int res = -1;
859 
860 	switch (class) {
861 	case algclass_ipsec_enc:
862 		res = alg_ipsec_encdef_doi(type);
863 		break;
864 	case algclass_ipsec_auth:
865 		res = alg_ipsec_hmacdef_doi(type);
866 		break;
867 	case algclass_ipsec_comp:
868 		res = alg_ipsec_compdef_doi(type);
869 		break;
870 	case algclass_isakmp_enc:
871 		res =  alg_oakley_encdef_doi(type);
872 		break;
873 	case algclass_isakmp_hash:
874 		res = alg_oakley_hashdef_doi(type);
875 		break;
876 	case algclass_isakmp_dh:
877 		res = alg_oakley_dhdef_doi(type);
878 		break;
879 	case algclass_isakmp_ameth:
880 		res = alg_oakley_authdef_doi(type);
881 		break;
882 	}
883 	return res;
884 }
885 
886 /*
887  * convert algorithm class to DOI value.
888  * OUT	-1   : NG
889  *	other: converted.
890  */
891 int
892 algclass2doi(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 }
916