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