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