Home | History | Annotate | Line # | Download | only in racoon
      1 /*	$NetBSD: algorithm.c,v 1.12 2025/03/08 16:39:08 christos 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(int);
    294 static struct hmac_algorithm *alg_oakley_hmacdef(int);
    295 static struct enc_algorithm *alg_oakley_encdef(int);
    296 static struct enc_algorithm *alg_ipsec_encdef(int);
    297 static struct hmac_algorithm *alg_ipsec_hmacdef(int);
    298 static struct dh_algorithm *alg_oakley_dhdef(int);
    299 
    300 /* oakley hash algorithm */
    301 static struct hash_algorithm *
    302 alg_oakley_hashdef(int doi)
    303 {
    304 
    305 	for (size_t i = 0; i < ARRAYLEN(oakley_hashdef); i++)
    306 		if (doi == oakley_hashdef[i].doi) {
    307 			plog(LLV_DEBUG, LOCATION, NULL, "hash(%s)\n",
    308 				oakley_hashdef[i].name);
    309 			return &oakley_hashdef[i];
    310 		}
    311 	return NULL;
    312 }
    313 
    314 int
    315 alg_oakley_hashdef_ok(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(int type)
    328 {
    329 	int res = -1;
    330 
    331 	for (size_t i = 0; i < ARRAYLEN(oakley_hashdef); i++)
    332 		if (type == oakley_hashdef[i].type) {
    333 			res = oakley_hashdef[i].doi;
    334 			break;
    335 		}
    336 	return res;
    337 }
    338 
    339 int
    340 alg_oakley_hashdef_hashlen(int doi)
    341 {
    342 	struct hash_algorithm *f;
    343 
    344 	f = alg_oakley_hashdef(doi);
    345 	if (f == NULL || f->hashlen == NULL)
    346 		return 0;
    347 
    348 	return (f->hashlen)();
    349 }
    350 
    351 const char *
    352 alg_oakley_hashdef_name(int doi)
    353 {
    354 	struct hash_algorithm *f;
    355 
    356 	f = alg_oakley_hashdef(doi);
    357 	if (f == NULL)
    358 		return "*UNKNOWN*";
    359 
    360 	return f->name;
    361 }
    362 
    363 vchar_t *
    364 alg_oakley_hashdef_one(int doi, vchar_t *buf)
    365 {
    366 	struct hash_algorithm *f;
    367 
    368 	f = alg_oakley_hashdef(doi);
    369 	if (f == NULL || f->hashlen == NULL)
    370 		return NULL;
    371 
    372 	return (f->one)(buf);
    373 }
    374 
    375 /* oakley hmac algorithm */
    376 static struct hmac_algorithm *
    377 alg_oakley_hmacdef(int doi)
    378 {
    379 
    380 	for (size_t i = 0; i < ARRAYLEN(oakley_hmacdef); i++)
    381 		if (doi == oakley_hmacdef[i].doi) {
    382 			plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
    383 				oakley_hmacdef[i].name);
    384 			return &oakley_hmacdef[i];
    385 		}
    386 	return NULL;
    387 }
    388 
    389 int
    390 alg_oakley_hmacdef_doi(int type)
    391 {
    392 	int res = -1;
    393 
    394 	for (size_t i = 0; i < ARRAYLEN(oakley_hmacdef); i++)
    395 		if (type == oakley_hmacdef[i].type) {
    396 			res = oakley_hmacdef[i].doi;
    397 			break;
    398 		}
    399 	return res;
    400 }
    401 
    402 vchar_t *
    403 alg_oakley_hmacdef_one(int doi, vchar_t *key, vchar_t *buf)
    404 {
    405 	struct hmac_algorithm *f;
    406 	vchar_t *res;
    407 #ifdef ENABLE_STATS
    408 	struct timeval start, end;
    409 #endif
    410 
    411 	f = alg_oakley_hmacdef(doi);
    412 	if (f == NULL || f->one == NULL)
    413 		return NULL;
    414 
    415 #ifdef ENABLE_STATS
    416 	gettimeofday(&start, NULL);
    417 #endif
    418 
    419 	res = (f->one)(key, buf);
    420 
    421 #ifdef ENABLE_STATS
    422 	gettimeofday(&end, NULL);
    423 	syslog(LOG_NOTICE, "%s(%s size=%zu): %8.6f", __func__,
    424 		f->name, buf->l, timedelta(&start, &end));
    425 #endif
    426 
    427 	return res;
    428 }
    429 
    430 /* oakley encryption algorithm */
    431 static struct enc_algorithm *
    432 alg_oakley_encdef(int doi)
    433 {
    434 
    435 	for (size_t i = 0; i < ARRAYLEN(oakley_encdef); i++)
    436 		if (doi == oakley_encdef[i].doi) {
    437 			plog(LLV_DEBUG, LOCATION, NULL, "encryption(%s)\n",
    438 				oakley_encdef[i].name);
    439 			return &oakley_encdef[i];
    440 		}
    441 	return NULL;
    442 }
    443 
    444 int
    445 alg_oakley_encdef_ok(int doi)
    446 {
    447 	struct enc_algorithm *f;
    448 
    449 	f = alg_oakley_encdef(doi);
    450 	if (f == NULL)
    451 		return 0;
    452 
    453 	return 1;
    454 }
    455 
    456 int
    457 alg_oakley_encdef_doi(int type)
    458 {
    459 	int res = -1;
    460 
    461 	for (size_t i = 0; i < ARRAYLEN(oakley_encdef); i++)
    462 		if (type == oakley_encdef[i].type) {
    463 			res = oakley_encdef[i].doi;
    464 			break;
    465 		}
    466 	return res;
    467 }
    468 
    469 int
    470 alg_oakley_encdef_keylen(int doi, int len)
    471 {
    472 	struct enc_algorithm *f;
    473 
    474 	f = alg_oakley_encdef(doi);
    475 	if (f == NULL || f->keylen == NULL)
    476 		return -1;
    477 
    478 	return (f->keylen)(len);
    479 }
    480 
    481 int
    482 alg_oakley_encdef_blocklen(int doi)
    483 {
    484 	struct enc_algorithm *f;
    485 
    486 	f = alg_oakley_encdef(doi);
    487 	if (f == NULL)
    488 		return -1;
    489 
    490 	return f->blocklen;
    491 }
    492 
    493 const char *
    494 alg_oakley_encdef_name(int doi)
    495 {
    496 	struct enc_algorithm *f;
    497 
    498 	f = alg_oakley_encdef(doi);
    499 	if (f == NULL)
    500 		return "*UNKNOWN*";
    501 
    502 	return f->name;
    503 }
    504 
    505 vchar_t *
    506 alg_oakley_encdef_decrypt(int doi, vchar_t *buf, vchar_t *key, vchar_t *iv)
    507 {
    508 	vchar_t *res;
    509 	struct enc_algorithm *f;
    510 #ifdef ENABLE_STATS
    511 	struct timeval start, end;
    512 #endif
    513 
    514 	f = alg_oakley_encdef(doi);
    515 	if (f == NULL || f->decrypt == NULL)
    516 		return NULL;
    517 
    518 #ifdef ENABLE_STATS
    519 	gettimeofday(&start, NULL);
    520 #endif
    521 
    522 	res = (f->decrypt)(buf, key, iv);
    523 
    524 #ifdef ENABLE_STATS
    525 	gettimeofday(&end, NULL);
    526 	syslog(LOG_NOTICE, "%s(%s klen=%zu size=%zu): %8.6f", __func__,
    527 		f->name, key->l << 3, buf->l, timedelta(&start, &end));
    528 #endif
    529 	return res;
    530 }
    531 
    532 vchar_t *
    533 alg_oakley_encdef_encrypt(int doi, vchar_t *buf, vchar_t *key, vchar_t *iv)
    534 {
    535 	vchar_t *res;
    536 	struct enc_algorithm *f;
    537 #ifdef ENABLE_STATS
    538 	struct timeval start, end;
    539 #endif
    540 
    541 	f = alg_oakley_encdef(doi);
    542 	if (f == NULL || f->encrypt == NULL)
    543 		return NULL;
    544 
    545 #ifdef ENABLE_STATS
    546 	gettimeofday(&start, NULL);
    547 #endif
    548 
    549 	res = (f->encrypt)(buf, key, iv);
    550 
    551 #ifdef ENABLE_STATS
    552 	gettimeofday(&end, NULL);
    553 	syslog(LOG_NOTICE, "%s(%s klen=%zu size=%zu): %8.6f", __func__,
    554 		f->name, key->l << 3, buf->l, timedelta(&start, &end));
    555 #endif
    556 	return res;
    557 }
    558 
    559 /* ipsec encryption algorithm */
    560 static struct enc_algorithm *
    561 alg_ipsec_encdef(int doi)
    562 {
    563 
    564 	for (size_t i = 0; i < ARRAYLEN(ipsec_encdef); i++)
    565 		if (doi == ipsec_encdef[i].doi) {
    566 			plog(LLV_DEBUG, LOCATION, NULL, "encryption(%s)\n",
    567 				ipsec_encdef[i].name);
    568 			return &ipsec_encdef[i];
    569 		}
    570 	return NULL;
    571 }
    572 
    573 int
    574 alg_ipsec_encdef_doi(int type)
    575 {
    576 	int res = -1;
    577 
    578 	for (size_t i = 0; i < ARRAYLEN(ipsec_encdef); i++)
    579 		if (type == ipsec_encdef[i].type) {
    580 			res = ipsec_encdef[i].doi;
    581 			break;
    582 		}
    583 	return res;
    584 }
    585 
    586 int
    587 alg_ipsec_encdef_keylen(int doi, int len)
    588 {
    589 	struct enc_algorithm *f;
    590 
    591 	f = alg_ipsec_encdef(doi);
    592 	if (f == NULL || f->keylen == NULL)
    593 		return -1;
    594 
    595 	return (f->keylen)(len);
    596 }
    597 
    598 /* ipsec hmac algorithm */
    599 static struct hmac_algorithm *
    600 alg_ipsec_hmacdef(int doi)
    601 {
    602 
    603 	for (size_t i = 0; i < ARRAYLEN(ipsec_hmacdef); i++)
    604 		if (doi == ipsec_hmacdef[i].doi) {
    605 			plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
    606 				ipsec_hmacdef[i].name);
    607 			return &ipsec_hmacdef[i];
    608 		}
    609 	return NULL;
    610 }
    611 
    612 int
    613 alg_ipsec_hmacdef_doi(int type)
    614 {
    615 	int res = -1;
    616 
    617 	for (size_t i = 0; i < ARRAYLEN(ipsec_hmacdef); i++)
    618 		if (type == ipsec_hmacdef[i].type) {
    619 			res = ipsec_hmacdef[i].doi;
    620 			break;
    621 		}
    622 	return res;
    623 }
    624 
    625 int
    626 alg_ipsec_hmacdef_hashlen(int doi)
    627 {
    628 	struct hmac_algorithm *f;
    629 
    630 	f = alg_ipsec_hmacdef(doi);
    631 	if (f == NULL || f->hashlen == NULL)
    632 		return -1;
    633 
    634 	return (f->hashlen)();
    635 }
    636 
    637 /* ip compression */
    638 int
    639 alg_ipsec_compdef_doi(int type)
    640 {
    641 	int res = -1;
    642 
    643 	for (size_t i = 0; i < ARRAYLEN(ipsec_compdef); i++)
    644 		if (type == ipsec_compdef[i].type) {
    645 			res = ipsec_compdef[i].doi;
    646 			break;
    647 		}
    648 	return res;
    649 }
    650 
    651 /* dh algorithm */
    652 static struct dh_algorithm *
    653 alg_oakley_dhdef(int doi)
    654 {
    655 
    656 	for (size_t i = 0; i < ARRAYLEN(oakley_dhdef); i++)
    657 		if (doi == oakley_dhdef[i].doi) {
    658 			plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
    659 				oakley_dhdef[i].name);
    660 			return &oakley_dhdef[i];
    661 		}
    662 	return NULL;
    663 }
    664 
    665 int
    666 alg_oakley_dhdef_ok(int doi)
    667 {
    668 	struct dh_algorithm *f;
    669 
    670 	f = alg_oakley_dhdef(doi);
    671 	if (f == NULL)
    672 		return 0;
    673 
    674 	return 1;
    675 }
    676 
    677 int
    678 alg_oakley_dhdef_doi(int type)
    679 {
    680 	int res = -1;
    681 
    682 	for (size_t i = 0; i < ARRAYLEN(oakley_dhdef); i++)
    683 		if (type == oakley_dhdef[i].type) {
    684 			res = oakley_dhdef[i].doi;
    685 			break;
    686 		}
    687 	return res;
    688 }
    689 
    690 struct dhgroup *
    691 alg_oakley_dhdef_group(int doi)
    692 {
    693 	struct dh_algorithm *f;
    694 
    695 	f = alg_oakley_dhdef(doi);
    696 	if (f == NULL || f->dhgroup == NULL)
    697 		return NULL;
    698 
    699 	return f->dhgroup;
    700 }
    701 
    702 const char *
    703 alg_oakley_dhdef_name(int doi)
    704 {
    705 	struct dh_algorithm *f;
    706 
    707 	f = alg_oakley_dhdef(doi);
    708 	if (f == NULL)
    709 		return "*UNKNOWN*";
    710 	return f->name;
    711 }
    712 
    713 /* authentication method */
    714 int
    715 alg_oakley_authdef_doi(int type)
    716 {
    717 	int res = -1;
    718 
    719 	for (size_t i = 0; i < ARRAYLEN(oakley_authdef); i++)
    720 		if (type == oakley_authdef[i].type) {
    721 			res = oakley_authdef[i].doi;
    722 			break;
    723 		}
    724 	return res;
    725 }
    726 
    727 const char *
    728 alg_oakley_authdef_name(int doi)
    729 {
    730 
    731 	for (size_t 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  */
    744 int
    745 default_keylen(int class, int type)
    746 {
    747 
    748 	switch (class) {
    749 	case algclass_isakmp_enc:
    750 	case algclass_ipsec_enc:
    751 		break;
    752 	default:
    753 		return 0;
    754 	}
    755 
    756 	switch (type) {
    757 	case algtype_blowfish:
    758 	case algtype_rc5:
    759 	case algtype_cast128:
    760 	case algtype_aes:
    761 	case algtype_aesgcm16:
    762 	case algtype_twofish:
    763 	case algtype_camellia:
    764 		return 128;
    765 	default:
    766 		return 0;
    767 	}
    768 }
    769 
    770 /*
    771  * check key length
    772  * OUT:	-1:	NG
    773  *	0:	OK
    774  */
    775 int
    776 check_keylen(int class, int type, int 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(LLV_ERROR, LOCATION, NULL,
    787 			"unknown algclass %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_aesgcm16:
    798 	case algtype_twofish:
    799 	case algtype_camellia:
    800 		if (len % 8 != 0) {
    801 			plog(LLV_ERROR, LOCATION, NULL,
    802 				"key length %d is not multiple of 8\n", len);
    803 			return -1;
    804 		}
    805 		break;
    806 	}
    807 
    808 	/* key length range */
    809 	badrange = 0;
    810 	switch (type) {
    811 	case algtype_blowfish:
    812 		if (len < 40 || 448 < len)
    813 			badrange++;
    814 		break;
    815 	case algtype_rc5:
    816 		if (len < 40 || 2040 < len)
    817 			badrange++;
    818 		break;
    819 	case algtype_cast128:
    820 		if (len < 40 || 128 < len)
    821 			badrange++;
    822 		break;
    823 	case algtype_aes:
    824 		if (!(len == 128 || len == 192 || len == 256))
    825 			badrange++;
    826 		break;
    827 	case algtype_aesgcm16:
    828 		if (!(len == 128 || len == 192 || len == 256))
    829 			badrange++;
    830 		break;
    831 	case algtype_twofish:
    832 		if (len < 40 || 256 < len)
    833 			badrange++;
    834 		break;
    835 	case algtype_camellia:
    836 		if (!(len == 128 || len == 192 || len == 256))
    837 			badrange++;
    838 		break;
    839 	default:
    840 		if (len) {
    841 			plog(LLV_ERROR, LOCATION, NULL,
    842 				"key length is not allowed");
    843 			return -1;
    844 		}
    845 		break;
    846 	}
    847 	if (badrange) {
    848 		plog(LLV_ERROR, LOCATION, NULL,
    849 			"key length out of range\n");
    850 		return -1;
    851 	}
    852 
    853 	return 0;
    854 }
    855 
    856 /*
    857  * convert algorithm type to DOI value.
    858  * OUT	-1   : NG
    859  *	other: converted.
    860  */
    861 int
    862 algtype2doi(int class, int type)
    863 {
    864 	int res = -1;
    865 
    866 	switch (class) {
    867 	case algclass_ipsec_enc:
    868 		res = alg_ipsec_encdef_doi(type);
    869 		break;
    870 	case algclass_ipsec_auth:
    871 		res = alg_ipsec_hmacdef_doi(type);
    872 		break;
    873 	case algclass_ipsec_comp:
    874 		res = alg_ipsec_compdef_doi(type);
    875 		break;
    876 	case algclass_isakmp_enc:
    877 		res =  alg_oakley_encdef_doi(type);
    878 		break;
    879 	case algclass_isakmp_hash:
    880 		res = alg_oakley_hashdef_doi(type);
    881 		break;
    882 	case algclass_isakmp_dh:
    883 		res = alg_oakley_dhdef_doi(type);
    884 		break;
    885 	case algclass_isakmp_ameth:
    886 		res = alg_oakley_authdef_doi(type);
    887 		break;
    888 	}
    889 	return res;
    890 }
    891 
    892 /*
    893  * convert algorithm class to DOI value.
    894  * OUT	-1   : NG
    895  *	other: converted.
    896  */
    897 int
    898 algclass2doi(int class)
    899 {
    900 	switch (class) {
    901 	case algclass_ipsec_enc:
    902 		return IPSECDOI_PROTO_IPSEC_ESP;
    903 	case algclass_ipsec_auth:
    904 		return IPSECDOI_ATTR_AUTH;
    905 	case algclass_ipsec_comp:
    906 		return IPSECDOI_PROTO_IPCOMP;
    907 	case algclass_isakmp_enc:
    908 		return OAKLEY_ATTR_ENC_ALG;
    909 	case algclass_isakmp_hash:
    910 		return OAKLEY_ATTR_HASH_ALG;
    911 	case algclass_isakmp_dh:
    912 		return OAKLEY_ATTR_GRP_DESC;
    913 	case algclass_isakmp_ameth:
    914 		return OAKLEY_ATTR_AUTH_METHOD;
    915 	default:
    916 		return -1;
    917 	}
    918 	/*NOTREACHED*/
    919 	return -1;
    920 }
    921