Return to algorithm.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon |
1.1 ! misho 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: }