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