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