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