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