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