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