File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon / algorithm.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:39:10 2012 UTC (12 years, 4 months ago) by misho
Branches: ipsec-tools, MAIN
CVS tags: v0_8_2p2, v0_8_1p0, v0_8_1, v0_8_0p0, v0_8_0, HEAD
ipsec-tools

    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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>