Home | History | Annotate | Download | only in racoon
      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 *
    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
    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
    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
    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 *
    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 *
    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 *
    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
    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 *
    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 *
    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
    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
    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
    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
    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 *
    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 *
    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 *
    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 *
    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
    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
    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 *
    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
    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
    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
    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 *
    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
    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
    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 *
    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 *
    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
    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 *
    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
    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
    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
    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
    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