1 /* $Id: algorithm.c,v 1.1.1.1 2005/02/12 11:11:39 manu Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include "config.h" 33 34 #include <sys/param.h> 35 #include <sys/types.h> 36 #include <stdlib.h> 37 38 #include "var.h" 39 #include "misc.h" 40 #include "vmbuf.h" 41 #include "plog.h" 42 #include "debug.h" 43 44 #include "crypto_openssl.h" 45 #include "dhgroup.h" 46 #include "algorithm.h" 47 #include "oakley.h" 48 #include "isakmp_var.h" 49 #include "isakmp.h" 50 #include "ipsec_doi.h" 51 #include "gcmalloc.h" 52 53 static struct hash_algorithm oakley_hashdef[] = { 54 { "md5", algtype_md5, OAKLEY_ATTR_HASH_ALG_MD5, 55 eay_md5_init, eay_md5_update, 56 eay_md5_final, eay_md5_hashlen, 57 eay_md5_one, }, 58 { "sha1", algtype_sha1, OAKLEY_ATTR_HASH_ALG_SHA, 59 eay_sha1_init, eay_sha1_update, 60 eay_sha1_final, eay_sha1_hashlen, 61 eay_sha1_one, }, 62 #ifdef WITH_SHA2 63 { "sha2_256", algtype_sha2_256, OAKLEY_ATTR_HASH_ALG_SHA2_256, 64 eay_sha2_256_init, eay_sha2_256_update, 65 eay_sha2_256_final, eay_sha2_256_hashlen, 66 eay_sha2_256_one, }, 67 { "sha2_384", algtype_sha2_384, OAKLEY_ATTR_HASH_ALG_SHA2_384, 68 eay_sha2_384_init, eay_sha2_384_update, 69 eay_sha2_384_final, eay_sha2_384_hashlen, 70 eay_sha2_384_one, }, 71 { "sha2_512", algtype_sha2_512, OAKLEY_ATTR_HASH_ALG_SHA2_512, 72 eay_sha2_512_init, eay_sha2_512_update, 73 eay_sha2_512_final, eay_sha2_512_hashlen, 74 eay_sha2_512_one, }, 75 #endif 76 }; 77 78 static struct hmac_algorithm oakley_hmacdef[] = { 79 { "hmac_md5", algtype_md5, OAKLEY_ATTR_HASH_ALG_MD5, 80 eay_hmacmd5_init, eay_hmacmd5_update, 81 eay_hmacmd5_final, NULL, 82 eay_hmacmd5_one, }, 83 { "hmac_sha1", algtype_sha1, OAKLEY_ATTR_HASH_ALG_SHA, 84 eay_hmacsha1_init, eay_hmacsha1_update, 85 eay_hmacsha1_final, NULL, 86 eay_hmacsha1_one, }, 87 #ifdef WITH_SHA2 88 { "hmac_sha2_256", algtype_sha2_256, OAKLEY_ATTR_HASH_ALG_SHA2_256, 89 eay_hmacsha2_256_init, eay_hmacsha2_256_update, 90 eay_hmacsha2_256_final, NULL, 91 eay_hmacsha2_256_one, }, 92 { "hmac_sha2_384", algtype_sha2_384, OAKLEY_ATTR_HASH_ALG_SHA2_384, 93 eay_hmacsha2_384_init, eay_hmacsha2_384_update, 94 eay_hmacsha2_384_final, NULL, 95 eay_hmacsha2_384_one, }, 96 { "hmac_sha2_512", algtype_sha2_512, OAKLEY_ATTR_HASH_ALG_SHA2_512, 97 eay_hmacsha2_512_init, eay_hmacsha2_512_update, 98 eay_hmacsha2_512_final, NULL, 99 eay_hmacsha2_512_one, }, 100 #endif 101 }; 102 103 static struct enc_algorithm oakley_encdef[] = { 104 { "des", algtype_des, OAKLEY_ATTR_ENC_ALG_DES, 8, 105 eay_des_encrypt, eay_des_decrypt, 106 eay_des_weakkey, eay_des_keylen, }, 107 #ifdef HAVE_OPENSSL_IDEA_H 108 { "idea", algtype_idea, OAKLEY_ATTR_ENC_ALG_IDEA, 8, 109 eay_idea_encrypt, eay_idea_decrypt, 110 eay_idea_weakkey, eay_idea_keylen, }, 111 #endif 112 { "blowfish", algtype_blowfish, OAKLEY_ATTR_ENC_ALG_BLOWFISH, 8, 113 eay_bf_encrypt, eay_bf_decrypt, 114 eay_bf_weakkey, eay_bf_keylen, }, 115 #ifdef HAVE_OPENSSL_RC5_H 116 { "rc5", algtype_rc5, OAKLEY_ATTR_ENC_ALG_RC5, 8, 117 eay_rc5_encrypt, eay_rc5_decrypt, 118 eay_rc5_weakkey, eay_rc5_keylen, }, 119 #endif 120 { "3des", algtype_3des, OAKLEY_ATTR_ENC_ALG_3DES, 8, 121 eay_3des_encrypt, eay_3des_decrypt, 122 eay_3des_weakkey, eay_3des_keylen, }, 123 { "cast", algtype_cast128, OAKLEY_ATTR_ENC_ALG_CAST, 8, 124 eay_cast_encrypt, eay_cast_decrypt, 125 eay_cast_weakkey, eay_cast_keylen, }, 126 { "aes", algtype_aes, OAKLEY_ATTR_ENC_ALG_AES, 16, 127 eay_aes_encrypt, eay_aes_decrypt, 128 eay_aes_weakkey, eay_aes_keylen, }, 129 }; 130 131 static struct enc_algorithm ipsec_encdef[] = { 132 { "des-iv64", algtype_des_iv64, IPSECDOI_ESP_DES_IV64, 8, 133 NULL, NULL, 134 NULL, eay_des_keylen, }, 135 { "des", algtype_des, IPSECDOI_ESP_DES, 8, 136 NULL, NULL, 137 NULL, eay_des_keylen, }, 138 { "3des", algtype_3des, IPSECDOI_ESP_3DES, 8, 139 NULL, NULL, 140 NULL, eay_3des_keylen, }, 141 #ifdef HAVE_OPENSSL_RC5_H 142 { "rc5", algtype_rc5, IPSECDOI_ESP_RC5, 8, 143 NULL, NULL, 144 NULL, eay_rc5_keylen, }, 145 #endif 146 { "cast", algtype_cast128, IPSECDOI_ESP_CAST, 8, 147 NULL, NULL, 148 NULL, eay_cast_keylen, }, 149 { "blowfish", algtype_blowfish, IPSECDOI_ESP_BLOWFISH, 8, 150 NULL, NULL, 151 NULL, eay_bf_keylen, }, 152 { "des-iv32", algtype_des_iv32, IPSECDOI_ESP_DES_IV32, 8, 153 NULL, NULL, 154 NULL, eay_des_keylen, }, 155 { "null", algtype_null_enc, IPSECDOI_ESP_NULL, 8, 156 NULL, NULL, 157 NULL, eay_null_keylen, }, 158 { "aes", algtype_aes, IPSECDOI_ESP_AES, 16, 159 NULL, NULL, 160 NULL, eay_aes_keylen, }, 161 { "twofish", algtype_twofish, IPSECDOI_ESP_TWOFISH, 16, 162 NULL, NULL, 163 NULL, eay_twofish_keylen, }, 164 #ifdef HAVE_OPENSSL_IDEA_H 165 { "3idea", algtype_3idea, IPSECDOI_ESP_3IDEA, 8, 166 NULL, NULL, 167 NULL, NULL, }, 168 { "idea", algtype_idea, IPSECDOI_ESP_IDEA, 8, 169 NULL, NULL, 170 NULL, NULL, }, 171 #endif 172 { "rc4", algtype_rc4, IPSECDOI_ESP_RC4, 8, 173 NULL, NULL, 174 NULL, NULL, }, 175 }; 176 177 static struct hmac_algorithm ipsec_hmacdef[] = { 178 { "md5", algtype_hmac_md5, IPSECDOI_ATTR_AUTH_HMAC_MD5, 179 NULL, NULL, 180 NULL, eay_md5_hashlen, 181 NULL, }, 182 { "sha1", algtype_hmac_sha1, IPSECDOI_ATTR_AUTH_HMAC_SHA1, 183 NULL, NULL, 184 NULL, eay_sha1_hashlen, 185 NULL, }, 186 { "kpdk", algtype_kpdk, IPSECDOI_ATTR_AUTH_KPDK, 187 NULL, NULL, 188 NULL, eay_kpdk_hashlen, 189 NULL, }, 190 { "null", algtype_non_auth, IPSECDOI_ATTR_AUTH_NONE, 191 NULL, NULL, 192 NULL, eay_null_hashlen, 193 NULL, }, 194 #ifdef WITH_SHA2 195 { "hmac_sha2_256", algtype_hmac_sha2_256, IPSECDOI_ATTR_SHA2_256, 196 NULL, NULL, 197 NULL, eay_sha2_256_hashlen, 198 NULL, }, 199 { "hmac_sha2_384", algtype_hmac_sha2_384, IPSECDOI_ATTR_SHA2_384, 200 NULL, NULL, 201 NULL, eay_sha2_384_hashlen, 202 NULL, }, 203 { "hmac_sha2_512", algtype_hmac_sha2_512, IPSECDOI_ATTR_SHA2_512, 204 NULL, NULL, 205 NULL, eay_sha2_512_hashlen, 206 NULL, }, 207 #endif 208 }; 209 210 static struct misc_algorithm ipsec_compdef[] = { 211 { "oui", algtype_oui, IPSECDOI_IPCOMP_OUI, }, 212 { "deflate", algtype_deflate, IPSECDOI_IPCOMP_DEFLATE, }, 213 { "lzs", algtype_lzs, IPSECDOI_IPCOMP_LZS, }, 214 }; 215 216 static struct misc_algorithm oakley_authdef[] = { 217 { "pre_shared_key", algtype_psk, OAKLEY_ATTR_AUTH_METHOD_PSKEY, }, 218 { "dsssig", algtype_dsssig, OAKLEY_ATTR_AUTH_METHOD_DSSSIG, }, 219 { "rsasig", algtype_rsasig, OAKLEY_ATTR_AUTH_METHOD_RSASIG, }, 220 { "rsaenc", algtype_rsaenc, OAKLEY_ATTR_AUTH_METHOD_RSAENC, }, 221 { "rsarev", algtype_rsarev, OAKLEY_ATTR_AUTH_METHOD_RSAREV, }, 222 { "gssapi_krb", algtype_gssapikrb, OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB, }, 223 #ifdef ENABLE_HYBRID 224 { "hybrid_rsa_server", algtype_hybrid_rsa_s, 225 OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I, }, 226 { "hybrid_dss_server", algtype_hybrid_dss_s, 227 OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I, }, 228 { "hybrid_rsa_client", algtype_hybrid_rsa_c, 229 OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R, }, 230 { "hybrid_dss_client", algtype_hybrid_dss_c, 231 OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R, }, 232 #endif 233 }; 234 235 static struct dh_algorithm oakley_dhdef[] = { 236 { "modp768", algtype_modp768, OAKLEY_ATTR_GRP_DESC_MODP768, 237 &dh_modp768, }, 238 { "modp1024", algtype_modp1024, OAKLEY_ATTR_GRP_DESC_MODP1024, 239 &dh_modp1024, }, 240 { "modp1536", algtype_modp1536, OAKLEY_ATTR_GRP_DESC_MODP1536, 241 &dh_modp1536, }, 242 { "modp2048", algtype_modp2048, OAKLEY_ATTR_GRP_DESC_MODP2048, 243 &dh_modp2048, }, 244 { "modp3072", algtype_modp3072, OAKLEY_ATTR_GRP_DESC_MODP3072, 245 &dh_modp3072, }, 246 { "modp4096", algtype_modp4096, OAKLEY_ATTR_GRP_DESC_MODP4096, 247 &dh_modp4096, }, 248 { "modp6144", algtype_modp6144, OAKLEY_ATTR_GRP_DESC_MODP6144, 249 &dh_modp6144, }, 250 { "modp8192", algtype_modp8192, OAKLEY_ATTR_GRP_DESC_MODP8192, 251 &dh_modp8192, }, 252 }; 253 254 static struct hash_algorithm *alg_oakley_hashdef __P((int)); 255 static struct hmac_algorithm *alg_oakley_hmacdef __P((int)); 256 static struct enc_algorithm *alg_oakley_encdef __P((int)); 257 static struct enc_algorithm *alg_ipsec_encdef __P((int)); 258 static struct hmac_algorithm *alg_ipsec_hmacdef __P((int)); 259 static struct dh_algorithm *alg_oakley_dhdef __P((int)); 260 261 /* oakley hash algorithm */ 262 static struct hash_algorithm * 263 alg_oakley_hashdef(doi) 264 int doi; 265 { 266 int i; 267 268 for (i = 0; i < ARRAYLEN(oakley_hashdef); i++) 269 if (doi == oakley_hashdef[i].doi) { 270 plog(LLV_DEBUG, LOCATION, NULL, "hash(%s)\n", 271 oakley_hashdef[i].name); 272 return &oakley_hashdef[i]; 273 } 274 return NULL; 275 } 276 277 int 278 alg_oakley_hashdef_ok(doi) 279 int doi; 280 { 281 struct hash_algorithm *f; 282 283 f = alg_oakley_hashdef(doi); 284 if (f == NULL) 285 return 0; 286 287 return 1; 288 } 289 290 int 291 alg_oakley_hashdef_doi(type) 292 int type; 293 { 294 int i, res = -1; 295 296 for (i = 0; i < ARRAYLEN(oakley_hashdef); i++) 297 if (type == oakley_hashdef[i].type) { 298 res = oakley_hashdef[i].doi; 299 break; 300 } 301 return res; 302 } 303 304 int 305 alg_oakley_hashdef_hashlen(doi) 306 int doi; 307 { 308 struct hash_algorithm *f; 309 310 f = alg_oakley_hashdef(doi); 311 if (f == NULL || f->hashlen == NULL) 312 return 0; 313 314 return (f->hashlen)(); 315 } 316 317 const char * 318 alg_oakley_hashdef_name (doi) 319 int doi; 320 { 321 struct hash_algorithm *f; 322 323 f = alg_oakley_hashdef(doi); 324 if (f == NULL) 325 return "*UNKNOWN*"; 326 327 return f->name; 328 } 329 330 vchar_t * 331 alg_oakley_hashdef_one(doi, buf) 332 int doi; 333 vchar_t *buf; 334 { 335 struct hash_algorithm *f; 336 337 f = alg_oakley_hashdef(doi); 338 if (f == NULL || f->hashlen == NULL) 339 return NULL; 340 341 return (f->one)(buf); 342 } 343 344 /* oakley hmac algorithm */ 345 static struct hmac_algorithm * 346 alg_oakley_hmacdef(doi) 347 int doi; 348 { 349 int i; 350 351 for (i = 0; i < ARRAYLEN(oakley_hmacdef); i++) 352 if (doi == oakley_hmacdef[i].doi) { 353 plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n", 354 oakley_hmacdef[i].name); 355 return &oakley_hmacdef[i]; 356 } 357 return NULL; 358 } 359 360 int 361 alg_oakley_hmacdef_doi(type) 362 int type; 363 { 364 int i, res = -1; 365 366 for (i = 0; i < ARRAYLEN(oakley_hmacdef); i++) 367 if (type == oakley_hmacdef[i].type) { 368 res = oakley_hmacdef[i].doi; 369 break; 370 } 371 return res; 372 } 373 374 vchar_t * 375 alg_oakley_hmacdef_one(doi, key, buf) 376 int doi; 377 vchar_t *key, *buf; 378 { 379 struct hmac_algorithm *f; 380 vchar_t *res; 381 #ifdef ENABLE_STATS 382 struct timeval start, end; 383 #endif 384 385 f = alg_oakley_hmacdef(doi); 386 if (f == NULL || f->one == NULL) 387 return NULL; 388 389 #ifdef ENABLE_STATS 390 gettimeofday(&start, NULL); 391 #endif 392 393 res = (f->one)(key, buf); 394 395 #ifdef ENABLE_STATS 396 gettimeofday(&end, NULL); 397 syslog(LOG_NOTICE, "%s(%s size=%d): %8.6f", __func__, 398 f->name, buf->l, timedelta(&start, &end)); 399 #endif 400 401 return res; 402 } 403 404 /* oakley encryption algorithm */ 405 static struct enc_algorithm * 406 alg_oakley_encdef(doi) 407 int doi; 408 { 409 int i; 410 411 for (i = 0; i < ARRAYLEN(oakley_encdef); i++) 412 if (doi == oakley_encdef[i].doi) { 413 plog(LLV_DEBUG, LOCATION, NULL, "encryption(%s)\n", 414 oakley_encdef[i].name); 415 return &oakley_encdef[i]; 416 } 417 return NULL; 418 } 419 420 int 421 alg_oakley_encdef_ok(doi) 422 int doi; 423 { 424 struct enc_algorithm *f; 425 426 f = alg_oakley_encdef(doi); 427 if (f == NULL) 428 return 0; 429 430 return 1; 431 } 432 433 int 434 alg_oakley_encdef_doi(type) 435 int type; 436 { 437 int i, res = -1; 438 439 for (i = 0; i < ARRAYLEN(oakley_encdef); i++) 440 if (type == oakley_encdef[i].type) { 441 res = oakley_encdef[i].doi; 442 break; 443 } 444 return res; 445 } 446 447 int 448 alg_oakley_encdef_keylen(doi, len) 449 int doi, len; 450 { 451 struct enc_algorithm *f; 452 453 f = alg_oakley_encdef(doi); 454 if (f == NULL || f->keylen == NULL) 455 return -1; 456 457 return (f->keylen)(len); 458 } 459 460 int 461 alg_oakley_encdef_blocklen(doi) 462 int doi; 463 { 464 struct enc_algorithm *f; 465 466 f = alg_oakley_encdef(doi); 467 if (f == NULL) 468 return -1; 469 470 return f->blocklen; 471 } 472 473 const char * 474 alg_oakley_encdef_name (doi) 475 int doi; 476 { 477 struct enc_algorithm *f; 478 479 f = alg_oakley_encdef(doi); 480 if (f == NULL) 481 return "*UNKNOWN*"; 482 483 return f->name; 484 } 485 486 vchar_t * 487 alg_oakley_encdef_decrypt(doi, buf, key, iv) 488 int doi; 489 vchar_t *buf, *key, *iv; 490 { 491 vchar_t *res; 492 struct enc_algorithm *f; 493 #ifdef ENABLE_STATS 494 struct timeval start, end; 495 #endif 496 497 f = alg_oakley_encdef(doi); 498 if (f == NULL || f->decrypt == NULL) 499 return NULL; 500 501 #ifdef ENABLE_STATS 502 gettimeofday(&start, NULL); 503 #endif 504 505 res = (f->decrypt)(buf, key, iv); 506 507 #ifdef ENABLE_STATS 508 gettimeofday(&end, NULL); 509 syslog(LOG_NOTICE, "%s(%s klen=%d size=%d): %8.6f", __func__, 510 f->name, key->l << 3, buf->l, timedelta(&start, &end)); 511 #endif 512 return res; 513 } 514 515 vchar_t * 516 alg_oakley_encdef_encrypt(doi, buf, key, iv) 517 int doi; 518 vchar_t *buf, *key, *iv; 519 { 520 vchar_t *res; 521 struct enc_algorithm *f; 522 #ifdef ENABLE_STATS 523 struct timeval start, end; 524 #endif 525 526 f = alg_oakley_encdef(doi); 527 if (f == NULL || f->encrypt == NULL) 528 return NULL; 529 530 #ifdef ENABLE_STATS 531 gettimeofday(&start, NULL); 532 #endif 533 534 res = (f->encrypt)(buf, key, iv); 535 536 #ifdef ENABLE_STATS 537 gettimeofday(&end, NULL); 538 syslog(LOG_NOTICE, "%s(%s klen=%d size=%d): %8.6f", __func__, 539 f->name, key->l << 3, buf->l, timedelta(&start, &end)); 540 #endif 541 return res; 542 } 543 544 /* ipsec encryption algorithm */ 545 static struct enc_algorithm * 546 alg_ipsec_encdef(doi) 547 int doi; 548 { 549 int i; 550 551 for (i = 0; i < ARRAYLEN(ipsec_encdef); i++) 552 if (doi == ipsec_encdef[i].doi) { 553 plog(LLV_DEBUG, LOCATION, NULL, "encryption(%s)\n", 554 ipsec_encdef[i].name); 555 return &ipsec_encdef[i]; 556 } 557 return NULL; 558 } 559 560 int 561 alg_ipsec_encdef_doi(type) 562 int type; 563 { 564 int i, res = -1; 565 566 for (i = 0; i < ARRAYLEN(ipsec_encdef); i++) 567 if (type == ipsec_encdef[i].type) { 568 res = ipsec_encdef[i].doi; 569 break; 570 } 571 return res; 572 } 573 574 int 575 alg_ipsec_encdef_keylen(doi, len) 576 int doi, len; 577 { 578 struct enc_algorithm *f; 579 580 f = alg_ipsec_encdef(doi); 581 if (f == NULL || f->keylen == NULL) 582 return -1; 583 584 return (f->keylen)(len); 585 } 586 587 /* ipsec hmac algorithm */ 588 static struct hmac_algorithm * 589 alg_ipsec_hmacdef(doi) 590 int doi; 591 { 592 int i; 593 594 for (i = 0; i < ARRAYLEN(ipsec_hmacdef); i++) 595 if (doi == ipsec_hmacdef[i].doi) { 596 plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n", 597 oakley_hmacdef[i].name); 598 return &ipsec_hmacdef[i]; 599 } 600 return NULL; 601 } 602 603 int 604 alg_ipsec_hmacdef_doi(type) 605 int type; 606 { 607 int i, res = -1; 608 609 for (i = 0; i < ARRAYLEN(ipsec_hmacdef); i++) 610 if (type == ipsec_hmacdef[i].type) { 611 res = ipsec_hmacdef[i].doi; 612 break; 613 } 614 return res; 615 } 616 617 int 618 alg_ipsec_hmacdef_hashlen(doi) 619 int doi; 620 { 621 struct hmac_algorithm *f; 622 623 f = alg_ipsec_hmacdef(doi); 624 if (f == NULL || f->hashlen == NULL) 625 return -1; 626 627 return (f->hashlen)(); 628 } 629 630 /* ip compression */ 631 int 632 alg_ipsec_compdef_doi(type) 633 int type; 634 { 635 int i, res = -1; 636 637 for (i = 0; i < ARRAYLEN(ipsec_compdef); i++) 638 if (type == ipsec_compdef[i].type) { 639 res = ipsec_compdef[i].doi; 640 break; 641 } 642 return res; 643 } 644 645 /* dh algorithm */ 646 static struct dh_algorithm * 647 alg_oakley_dhdef(doi) 648 int doi; 649 { 650 int i; 651 652 for (i = 0; i < ARRAYLEN(oakley_dhdef); i++) 653 if (doi == oakley_dhdef[i].doi) { 654 plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n", 655 oakley_dhdef[i].name); 656 return &oakley_dhdef[i]; 657 } 658 return NULL; 659 } 660 661 int 662 alg_oakley_dhdef_ok(doi) 663 int doi; 664 { 665 struct dh_algorithm *f; 666 667 f = alg_oakley_dhdef(doi); 668 if (f == NULL) 669 return 0; 670 671 return 1; 672 } 673 674 int 675 alg_oakley_dhdef_doi(type) 676 int type; 677 { 678 int i, res = -1; 679 680 for (i = 0; i < ARRAYLEN(oakley_dhdef); i++) 681 if (type == oakley_dhdef[i].type) { 682 res = oakley_dhdef[i].doi; 683 break; 684 } 685 return res; 686 } 687 688 struct dhgroup * 689 alg_oakley_dhdef_group(doi) 690 int doi; 691 { 692 struct dh_algorithm *f; 693 694 f = alg_oakley_dhdef(doi); 695 if (f == NULL || f->dhgroup == NULL) 696 return NULL; 697 698 return f->dhgroup; 699 } 700 701 const char * 702 alg_oakley_dhdef_name (doi) 703 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(type) 716 int type; 717 { 718 int i, res = -1; 719 720 for (i = 0; i < ARRAYLEN(oakley_authdef); i++) 721 if (type == oakley_authdef[i].type) { 722 res = oakley_authdef[i].doi; 723 break; 724 } 725 return res; 726 } 727 728 const char * 729 alg_oakley_authdef_name (doi) 730 int doi; 731 { 732 int i; 733 734 for (i = 0; i < ARRAYLEN(oakley_authdef); i++) 735 if (doi == oakley_authdef[i].doi) { 736 return oakley_authdef[i].name; 737 } 738 return "*UNKNOWN*"; 739 } 740 741 /* 742 * give the default key length 743 * OUT: -1: NG 744 * 0: fixed key cipher, key length not allowed 745 * positive: default key length 746 */ 747 int 748 default_keylen(class, type) 749 int class, type; 750 { 751 752 switch (class) { 753 case algclass_isakmp_enc: 754 case algclass_ipsec_enc: 755 break; 756 default: 757 return 0; 758 } 759 760 switch (type) { 761 case algtype_blowfish: 762 case algtype_rc5: 763 case algtype_cast128: 764 case algtype_aes: 765 case algtype_twofish: 766 return 128; 767 default: 768 return 0; 769 } 770 } 771 772 /* 773 * check key length 774 * OUT: -1: NG 775 * 0: OK 776 */ 777 int 778 check_keylen(class, type, len) 779 int class, type, len; 780 { 781 int badrange; 782 783 switch (class) { 784 case algclass_isakmp_enc: 785 case algclass_ipsec_enc: 786 break; 787 default: 788 /* unknown class, punt */ 789 plog(LLV_ERROR, LOCATION, NULL, 790 "unknown algclass %d\n", class); 791 return -1; 792 } 793 794 /* key length must be multiple of 8 bytes - RFC2451 2.2 */ 795 switch (type) { 796 case algtype_blowfish: 797 case algtype_rc5: 798 case algtype_cast128: 799 case algtype_aes: 800 case algtype_twofish: 801 if (len % 8 != 0) { 802 plog(LLV_ERROR, LOCATION, NULL, 803 "key length %d is not multiple of 8\n", len); 804 return -1; 805 } 806 break; 807 } 808 809 /* key length range */ 810 badrange = 0; 811 switch (type) { 812 case algtype_blowfish: 813 if (len < 40 || 448 < len) 814 badrange++; 815 break; 816 case algtype_rc5: 817 if (len < 40 || 2040 < len) 818 badrange++; 819 break; 820 case algtype_cast128: 821 if (len < 40 || 128 < len) 822 badrange++; 823 break; 824 case algtype_aes: 825 if (!(len == 128 || len == 192 || len == 256)) 826 badrange++; 827 break; 828 case algtype_twofish: 829 if (len < 40 || 256 < len) 830 badrange++; 831 break; 832 default: 833 if (len) { 834 plog(LLV_ERROR, LOCATION, NULL, 835 "key length is not allowed"); 836 return -1; 837 } 838 break; 839 } 840 if (badrange) { 841 plog(LLV_ERROR, LOCATION, NULL, 842 "key length out of range\n"); 843 return -1; 844 } 845 846 return 0; 847 } 848 849 /* 850 * convert algorithm type to DOI value. 851 * OUT -1 : NG 852 * other: converted. 853 */ 854 int 855 algtype2doi(class, type) 856 int class, type; 857 { 858 int res = -1; 859 860 switch (class) { 861 case algclass_ipsec_enc: 862 res = alg_ipsec_encdef_doi(type); 863 break; 864 case algclass_ipsec_auth: 865 res = alg_ipsec_hmacdef_doi(type); 866 break; 867 case algclass_ipsec_comp: 868 res = alg_ipsec_compdef_doi(type); 869 break; 870 case algclass_isakmp_enc: 871 res = alg_oakley_encdef_doi(type); 872 break; 873 case algclass_isakmp_hash: 874 res = alg_oakley_hashdef_doi(type); 875 break; 876 case algclass_isakmp_dh: 877 res = alg_oakley_dhdef_doi(type); 878 break; 879 case algclass_isakmp_ameth: 880 res = alg_oakley_authdef_doi(type); 881 break; 882 } 883 return res; 884 } 885 886 /* 887 * convert algorithm class to DOI value. 888 * OUT -1 : NG 889 * other: converted. 890 */ 891 int 892 algclass2doi(class) 893 int class; 894 { 895 switch (class) { 896 case algclass_ipsec_enc: 897 return IPSECDOI_PROTO_IPSEC_ESP; 898 case algclass_ipsec_auth: 899 return IPSECDOI_ATTR_AUTH; 900 case algclass_ipsec_comp: 901 return IPSECDOI_PROTO_IPCOMP; 902 case algclass_isakmp_enc: 903 return OAKLEY_ATTR_ENC_ALG; 904 case algclass_isakmp_hash: 905 return OAKLEY_ATTR_HASH_ALG; 906 case algclass_isakmp_dh: 907 return OAKLEY_ATTR_GRP_DESC; 908 case algclass_isakmp_ameth: 909 return OAKLEY_ATTR_AUTH_METHOD; 910 default: 911 return -1; 912 } 913 /*NOTREACHED*/ 914 return -1; 915 } 916