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 
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 #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 
138 static 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 
189 static 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 
222 static 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  */
234 static 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 
271 static 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 
290 static struct hash_algorithm *alg_oakley_hashdef __P((int));
291 static struct hmac_algorithm *alg_oakley_hmacdef __P((int));
292 static struct enc_algorithm *alg_oakley_encdef __P((int));
293 static struct enc_algorithm *alg_ipsec_encdef __P((int));
294 static struct hmac_algorithm *alg_ipsec_hmacdef __P((int));
295 static struct dh_algorithm *alg_oakley_dhdef __P((int));
296 
297 /* oakley hash algorithm */
298 static struct hash_algorithm *
alg_oakley_hashdef(doi)299 alg_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 
313 int
alg_oakley_hashdef_ok(doi)314 alg_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 
326 int
alg_oakley_hashdef_doi(type)327 alg_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 
340 int
alg_oakley_hashdef_hashlen(doi)341 alg_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 
353 const char *
alg_oakley_hashdef_name(doi)354 alg_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 
366 vchar_t *
alg_oakley_hashdef_one(doi,buf)367 alg_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 */
381 static struct hmac_algorithm *
alg_oakley_hmacdef(doi)382 alg_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 
396 int
alg_oakley_hmacdef_doi(type)397 alg_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 
410 vchar_t *
alg_oakley_hmacdef_one(doi,key,buf)411 alg_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 */
441 static struct enc_algorithm *
alg_oakley_encdef(doi)442 alg_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 
456 int
alg_oakley_encdef_ok(doi)457 alg_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 
469 int
alg_oakley_encdef_doi(type)470 alg_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 
483 int
alg_oakley_encdef_keylen(doi,len)484 alg_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 
496 int
alg_oakley_encdef_blocklen(doi)497 alg_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 
509 const char *
alg_oakley_encdef_name(doi)510 alg_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 
522 vchar_t *
alg_oakley_encdef_decrypt(doi,buf,key,iv)523 alg_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 
551 vchar_t *
alg_oakley_encdef_encrypt(doi,buf,key,iv)552 alg_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 */
581 static struct enc_algorithm *
alg_ipsec_encdef(doi)582 alg_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 
596 int
alg_ipsec_encdef_doi(type)597 alg_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 
610 int
alg_ipsec_encdef_keylen(doi,len)611 alg_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 */
624 static struct hmac_algorithm *
alg_ipsec_hmacdef(doi)625 alg_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 
639 int
alg_ipsec_hmacdef_doi(type)640 alg_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 
653 int
alg_ipsec_hmacdef_hashlen(doi)654 alg_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 */
667 int
alg_ipsec_compdef_doi(type)668 alg_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 */
682 static struct dh_algorithm *
alg_oakley_dhdef(doi)683 alg_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 
697 int
alg_oakley_dhdef_ok(doi)698 alg_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 
710 int
alg_oakley_dhdef_doi(type)711 alg_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 
724 struct dhgroup *
alg_oakley_dhdef_group(doi)725 alg_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 
737 const char *
alg_oakley_dhdef_name(doi)738 alg_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 */
750 int
alg_oakley_authdef_doi(type)751 alg_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 
764 const char *
alg_oakley_authdef_name(doi)765 alg_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  */
783 int
default_keylen(class,type)784 default_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  */
814 int
check_keylen(class,type,len)815 check_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  */
896 int
algtype2doi(class,type)897 algtype2doi(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  */
933 int
algclass2doi(class)934 algclass2doi(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