Return to oakley.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon |
1.1 ! misho 1: /* $NetBSD: oakley.c,v 1.22 2011/03/17 14:42:58 vanhu Exp $ */ ! 2: ! 3: /* Id: oakley.c,v 1.32 2006/05/26 12:19:46 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/types.h> ! 37: #include <sys/param.h> ! 38: #include <sys/socket.h> /* XXX for subjectaltname */ ! 39: #include <netinet/in.h> /* XXX for subjectaltname */ ! 40: ! 41: #include <openssl/pkcs7.h> ! 42: #include <openssl/x509.h> ! 43: ! 44: #include <stdlib.h> ! 45: #include <stdio.h> ! 46: #include <string.h> ! 47: #include <errno.h> ! 48: ! 49: #if TIME_WITH_SYS_TIME ! 50: # include <sys/time.h> ! 51: # include <time.h> ! 52: #else ! 53: # if HAVE_SYS_TIME_H ! 54: # include <sys/time.h> ! 55: # else ! 56: # include <time.h> ! 57: # endif ! 58: #endif ! 59: #ifdef ENABLE_HYBRID ! 60: #include <resolv.h> ! 61: #endif ! 62: ! 63: #include "var.h" ! 64: #include "misc.h" ! 65: #include "vmbuf.h" ! 66: #include "str2val.h" ! 67: #include "plog.h" ! 68: #include "debug.h" ! 69: ! 70: #include "isakmp_var.h" ! 71: #include "isakmp.h" ! 72: #ifdef ENABLE_HYBRID ! 73: #include "isakmp_xauth.h" ! 74: #include "isakmp_cfg.h" ! 75: #endif ! 76: #include "oakley.h" ! 77: #include "admin.h" ! 78: #include "privsep.h" ! 79: #include "localconf.h" ! 80: #include "remoteconf.h" ! 81: #include "policy.h" ! 82: #include "handler.h" ! 83: #include "ipsec_doi.h" ! 84: #include "algorithm.h" ! 85: #include "dhgroup.h" ! 86: #include "sainfo.h" ! 87: #include "proposal.h" ! 88: #include "crypto_openssl.h" ! 89: #include "dnssec.h" ! 90: #include "sockmisc.h" ! 91: #include "strnames.h" ! 92: #include "gcmalloc.h" ! 93: #include "rsalist.h" ! 94: ! 95: #ifdef HAVE_GSSAPI ! 96: #include "gssapi.h" ! 97: #endif ! 98: ! 99: #define OUTBOUND_SA 0 ! 100: #define INBOUND_SA 1 ! 101: ! 102: #define INITDHVAL(a, s, d, t) \ ! 103: do { \ ! 104: vchar_t buf; \ ! 105: buf.v = str2val((s), 16, &buf.l); \ ! 106: memset(&a, 0, sizeof(struct dhgroup)); \ ! 107: a.type = (t); \ ! 108: a.prime = vdup(&buf); \ ! 109: a.gen1 = 2; \ ! 110: a.gen2 = 0; \ ! 111: racoon_free(buf.v); \ ! 112: } while(0); ! 113: ! 114: struct dhgroup dh_modp768; ! 115: struct dhgroup dh_modp1024; ! 116: struct dhgroup dh_modp1536; ! 117: struct dhgroup dh_modp2048; ! 118: struct dhgroup dh_modp3072; ! 119: struct dhgroup dh_modp4096; ! 120: struct dhgroup dh_modp6144; ! 121: struct dhgroup dh_modp8192; ! 122: ! 123: ! 124: static int oakley_check_dh_pub __P((vchar_t *, vchar_t **)); ! 125: static int oakley_compute_keymat_x __P((struct ph2handle *, int, int)); ! 126: static int oakley_check_certid __P((struct ph1handle *iph1)); ! 127: static int check_typeofcertname __P((int, int)); ! 128: static int oakley_padlen __P((int, int)); ! 129: static int get_plainrsa_fromlocal __P((struct ph1handle *, int)); ! 130: ! 131: int oakley_get_certtype(cert) ! 132: vchar_t *cert; ! 133: { ! 134: if (cert == NULL) ! 135: return ISAKMP_CERT_NONE; ! 136: ! 137: return cert->v[0]; ! 138: } ! 139: ! 140: static vchar_t * ! 141: dump_isakmp_payload(gen) ! 142: struct isakmp_gen *gen; ! 143: { ! 144: vchar_t p; ! 145: ! 146: if (ntohs(gen->len) <= sizeof(*gen)) { ! 147: plog(LLV_ERROR, LOCATION, NULL, ! 148: "Len is too small !!.\n"); ! 149: return NULL; ! 150: } ! 151: ! 152: p.v = (caddr_t) (gen + 1); ! 153: p.l = ntohs(gen->len) - sizeof(*gen); ! 154: ! 155: return vdup(&p); ! 156: } ! 157: ! 158: static vchar_t * ! 159: dump_x509(cert) ! 160: X509 *cert; ! 161: { ! 162: vchar_t *pl; ! 163: u_char *bp; ! 164: int len; ! 165: ! 166: len = i2d_X509(cert, NULL); ! 167: ! 168: pl = vmalloc(len + 1); ! 169: if (pl == NULL) { ! 170: plog(LLV_ERROR, LOCATION, NULL, ! 171: "Failed to copy CERT from packet.\n"); ! 172: return NULL; ! 173: } ! 174: ! 175: pl->v[0] = ISAKMP_CERT_X509SIGN; ! 176: bp = (u_char *) &pl->v[1]; ! 177: i2d_X509(cert, &bp); ! 178: ! 179: return pl; ! 180: } ! 181: ! 182: ! 183: ! 184: int ! 185: oakley_get_defaultlifetime() ! 186: { ! 187: return OAKLEY_ATTR_SA_LD_SEC_DEFAULT; ! 188: } ! 189: ! 190: int ! 191: oakley_dhinit() ! 192: { ! 193: /* set DH MODP */ ! 194: INITDHVAL(dh_modp768, OAKLEY_PRIME_MODP768, ! 195: OAKLEY_ATTR_GRP_DESC_MODP768, OAKLEY_ATTR_GRP_TYPE_MODP); ! 196: INITDHVAL(dh_modp1024, OAKLEY_PRIME_MODP1024, ! 197: OAKLEY_ATTR_GRP_DESC_MODP1024, OAKLEY_ATTR_GRP_TYPE_MODP); ! 198: INITDHVAL(dh_modp1536, OAKLEY_PRIME_MODP1536, ! 199: OAKLEY_ATTR_GRP_DESC_MODP1536, OAKLEY_ATTR_GRP_TYPE_MODP); ! 200: INITDHVAL(dh_modp2048, OAKLEY_PRIME_MODP2048, ! 201: OAKLEY_ATTR_GRP_DESC_MODP2048, OAKLEY_ATTR_GRP_TYPE_MODP); ! 202: INITDHVAL(dh_modp3072, OAKLEY_PRIME_MODP3072, ! 203: OAKLEY_ATTR_GRP_DESC_MODP3072, OAKLEY_ATTR_GRP_TYPE_MODP); ! 204: INITDHVAL(dh_modp4096, OAKLEY_PRIME_MODP4096, ! 205: OAKLEY_ATTR_GRP_DESC_MODP4096, OAKLEY_ATTR_GRP_TYPE_MODP); ! 206: INITDHVAL(dh_modp6144, OAKLEY_PRIME_MODP6144, ! 207: OAKLEY_ATTR_GRP_DESC_MODP6144, OAKLEY_ATTR_GRP_TYPE_MODP); ! 208: INITDHVAL(dh_modp8192, OAKLEY_PRIME_MODP8192, ! 209: OAKLEY_ATTR_GRP_DESC_MODP8192, OAKLEY_ATTR_GRP_TYPE_MODP); ! 210: ! 211: return 0; ! 212: } ! 213: ! 214: void ! 215: oakley_dhgrp_free(dhgrp) ! 216: struct dhgroup *dhgrp; ! 217: { ! 218: if (dhgrp->prime) ! 219: vfree(dhgrp->prime); ! 220: if (dhgrp->curve_a) ! 221: vfree(dhgrp->curve_a); ! 222: if (dhgrp->curve_b) ! 223: vfree(dhgrp->curve_b); ! 224: if (dhgrp->order) ! 225: vfree(dhgrp->order); ! 226: racoon_free(dhgrp); ! 227: } ! 228: ! 229: /* ! 230: * RFC2409 5 ! 231: * The length of the Diffie-Hellman public value MUST be equal to the ! 232: * length of the prime modulus over which the exponentiation was ! 233: * performed, prepending zero bits to the value if necessary. ! 234: */ ! 235: static int ! 236: oakley_check_dh_pub(prime, pub0) ! 237: vchar_t *prime, **pub0; ! 238: { ! 239: vchar_t *tmp; ! 240: vchar_t *pub = *pub0; ! 241: ! 242: if (prime->l == pub->l) ! 243: return 0; ! 244: ! 245: if (prime->l < pub->l) { ! 246: /* what should i do ? */ ! 247: plog(LLV_ERROR, LOCATION, NULL, ! 248: "invalid public information was generated.\n"); ! 249: return -1; ! 250: } ! 251: ! 252: /* prime->l > pub->l */ ! 253: tmp = vmalloc(prime->l); ! 254: if (tmp == NULL) { ! 255: plog(LLV_ERROR, LOCATION, NULL, ! 256: "failed to get DH buffer.\n"); ! 257: return -1; ! 258: } ! 259: memcpy(tmp->v + prime->l - pub->l, pub->v, pub->l); ! 260: ! 261: vfree(*pub0); ! 262: *pub0 = tmp; ! 263: ! 264: return 0; ! 265: } ! 266: ! 267: /* ! 268: * compute sharing secret of DH ! 269: * IN: *dh, *pub, *priv, *pub_p ! 270: * OUT: **gxy ! 271: */ ! 272: int ! 273: oakley_dh_compute(dh, pub, priv, pub_p, gxy) ! 274: const struct dhgroup *dh; ! 275: vchar_t *pub, *priv, *pub_p, **gxy; ! 276: { ! 277: #ifdef ENABLE_STATS ! 278: struct timeval start, end; ! 279: #endif ! 280: if ((*gxy = vmalloc(dh->prime->l)) == NULL) { ! 281: plog(LLV_ERROR, LOCATION, NULL, ! 282: "failed to get DH buffer.\n"); ! 283: return -1; ! 284: } ! 285: ! 286: #ifdef ENABLE_STATS ! 287: gettimeofday(&start, NULL); ! 288: #endif ! 289: switch (dh->type) { ! 290: case OAKLEY_ATTR_GRP_TYPE_MODP: ! 291: if (eay_dh_compute(dh->prime, dh->gen1, pub, priv, pub_p, gxy) < 0) { ! 292: plog(LLV_ERROR, LOCATION, NULL, ! 293: "failed to compute dh value.\n"); ! 294: return -1; ! 295: } ! 296: break; ! 297: case OAKLEY_ATTR_GRP_TYPE_ECP: ! 298: case OAKLEY_ATTR_GRP_TYPE_EC2N: ! 299: plog(LLV_ERROR, LOCATION, NULL, ! 300: "dh type %d isn't supported.\n", dh->type); ! 301: return -1; ! 302: default: ! 303: plog(LLV_ERROR, LOCATION, NULL, ! 304: "invalid dh type %d.\n", dh->type); ! 305: return -1; ! 306: } ! 307: ! 308: #ifdef ENABLE_STATS ! 309: gettimeofday(&end, NULL); ! 310: syslog(LOG_NOTICE, "%s(%s%zu): %8.6f", __func__, ! 311: s_attr_isakmp_group(dh->type), dh->prime->l << 3, ! 312: timedelta(&start, &end)); ! 313: #endif ! 314: ! 315: plog(LLV_DEBUG, LOCATION, NULL, "compute DH's shared.\n"); ! 316: plogdump(LLV_DEBUG, (*gxy)->v, (*gxy)->l); ! 317: ! 318: return 0; ! 319: } ! 320: ! 321: /* ! 322: * generate values of DH ! 323: * IN: *dh ! 324: * OUT: **pub, **priv ! 325: */ ! 326: int ! 327: oakley_dh_generate(dh, pub, priv) ! 328: const struct dhgroup *dh; ! 329: vchar_t **pub, **priv; ! 330: { ! 331: #ifdef ENABLE_STATS ! 332: struct timeval start, end; ! 333: gettimeofday(&start, NULL); ! 334: #endif ! 335: switch (dh->type) { ! 336: case OAKLEY_ATTR_GRP_TYPE_MODP: ! 337: if (eay_dh_generate(dh->prime, dh->gen1, dh->gen2, pub, priv) < 0) { ! 338: plog(LLV_ERROR, LOCATION, NULL, ! 339: "failed to compute dh value.\n"); ! 340: return -1; ! 341: } ! 342: break; ! 343: ! 344: case OAKLEY_ATTR_GRP_TYPE_ECP: ! 345: case OAKLEY_ATTR_GRP_TYPE_EC2N: ! 346: plog(LLV_ERROR, LOCATION, NULL, ! 347: "dh type %d isn't supported.\n", dh->type); ! 348: return -1; ! 349: default: ! 350: plog(LLV_ERROR, LOCATION, NULL, ! 351: "invalid dh type %d.\n", dh->type); ! 352: return -1; ! 353: } ! 354: ! 355: #ifdef ENABLE_STATS ! 356: gettimeofday(&end, NULL); ! 357: syslog(LOG_NOTICE, "%s(%s%zu): %8.6f", __func__, ! 358: s_attr_isakmp_group(dh->type), dh->prime->l << 3, ! 359: timedelta(&start, &end)); ! 360: #endif ! 361: ! 362: if (oakley_check_dh_pub(dh->prime, pub) != 0) ! 363: return -1; ! 364: ! 365: plog(LLV_DEBUG, LOCATION, NULL, "compute DH's private.\n"); ! 366: plogdump(LLV_DEBUG, (*priv)->v, (*priv)->l); ! 367: plog(LLV_DEBUG, LOCATION, NULL, "compute DH's public.\n"); ! 368: plogdump(LLV_DEBUG, (*pub)->v, (*pub)->l); ! 369: ! 370: return 0; ! 371: } ! 372: ! 373: /* ! 374: * copy pre-defined dhgroup values. ! 375: */ ! 376: int ! 377: oakley_setdhgroup(group, dhgrp) ! 378: int group; ! 379: struct dhgroup **dhgrp; ! 380: { ! 381: struct dhgroup *g; ! 382: ! 383: *dhgrp = NULL; /* just make sure, initialize */ ! 384: ! 385: g = alg_oakley_dhdef_group(group); ! 386: if (g == NULL) { ! 387: plog(LLV_ERROR, LOCATION, NULL, ! 388: "invalid DH parameter grp=%d.\n", group); ! 389: return -1; ! 390: } ! 391: ! 392: if (!g->type || !g->prime || !g->gen1) { ! 393: /* unsuported */ ! 394: plog(LLV_ERROR, LOCATION, NULL, ! 395: "unsupported DH parameters grp=%d.\n", group); ! 396: return -1; ! 397: } ! 398: ! 399: *dhgrp = racoon_calloc(1, sizeof(struct dhgroup)); ! 400: if (*dhgrp == NULL) { ! 401: plog(LLV_ERROR, LOCATION, NULL, ! 402: "failed to get DH buffer.\n"); ! 403: return 0; ! 404: } ! 405: ! 406: /* set defined dh vlaues */ ! 407: memcpy(*dhgrp, g, sizeof(*g)); ! 408: (*dhgrp)->prime = vdup(g->prime); ! 409: ! 410: return 0; ! 411: } ! 412: ! 413: /* ! 414: * PRF ! 415: * ! 416: * NOTE: we do not support prf with different input/output bitwidth, ! 417: * so we do not implement RFC2409 Appendix B (DOORAK-MAC example) in ! 418: * oakley_compute_keymat(). If you add support for such prf function, ! 419: * modify oakley_compute_keymat() accordingly. ! 420: */ ! 421: vchar_t * ! 422: oakley_prf(key, buf, iph1) ! 423: vchar_t *key, *buf; ! 424: struct ph1handle *iph1; ! 425: { ! 426: vchar_t *res = NULL; ! 427: int type; ! 428: ! 429: if (iph1->approval == NULL) { ! 430: /* ! 431: * it's before negotiating hash algorithm. ! 432: * We use md5 as default. ! 433: */ ! 434: type = OAKLEY_ATTR_HASH_ALG_MD5; ! 435: } else ! 436: type = iph1->approval->hashtype; ! 437: ! 438: res = alg_oakley_hmacdef_one(type, key, buf); ! 439: if (res == NULL) { ! 440: plog(LLV_ERROR, LOCATION, NULL, ! 441: "invalid hmac algorithm %d.\n", type); ! 442: return NULL; ! 443: } ! 444: ! 445: return res; ! 446: } ! 447: ! 448: /* ! 449: * hash ! 450: */ ! 451: vchar_t * ! 452: oakley_hash(buf, iph1) ! 453: vchar_t *buf; ! 454: struct ph1handle *iph1; ! 455: { ! 456: vchar_t *res = NULL; ! 457: int type; ! 458: ! 459: if (iph1->approval == NULL) { ! 460: /* ! 461: * it's before negotiating hash algorithm. ! 462: * We use md5 as default. ! 463: */ ! 464: type = OAKLEY_ATTR_HASH_ALG_MD5; ! 465: } else ! 466: type = iph1->approval->hashtype; ! 467: ! 468: res = alg_oakley_hashdef_one(type, buf); ! 469: if (res == NULL) { ! 470: plog(LLV_ERROR, LOCATION, NULL, ! 471: "invalid hash algorithm %d.\n", type); ! 472: return NULL; ! 473: } ! 474: ! 475: return res; ! 476: } ! 477: ! 478: /* ! 479: * compute KEYMAT ! 480: * see seciton 5.5 Phase 2 - Quick Mode in isakmp-oakley-05. ! 481: */ ! 482: int ! 483: oakley_compute_keymat(iph2, side) ! 484: struct ph2handle *iph2; ! 485: int side; ! 486: { ! 487: int error = -1; ! 488: ! 489: /* compute sharing secret of DH when PFS */ ! 490: if (iph2->approval->pfs_group && iph2->dhpub_p) { ! 491: if (oakley_dh_compute(iph2->pfsgrp, iph2->dhpub, ! 492: iph2->dhpriv, iph2->dhpub_p, &iph2->dhgxy) < 0) ! 493: goto end; ! 494: } ! 495: ! 496: /* compute keymat */ ! 497: if (oakley_compute_keymat_x(iph2, side, INBOUND_SA) < 0 ! 498: || oakley_compute_keymat_x(iph2, side, OUTBOUND_SA) < 0) ! 499: goto end; ! 500: ! 501: plog(LLV_DEBUG, LOCATION, NULL, "KEYMAT computed.\n"); ! 502: ! 503: error = 0; ! 504: ! 505: end: ! 506: return error; ! 507: } ! 508: ! 509: /* ! 510: * compute KEYMAT. ! 511: * KEYMAT = prf(SKEYID_d, protocol | SPI | Ni_b | Nr_b). ! 512: * If PFS is desired and KE payloads were exchanged, ! 513: * KEYMAT = prf(SKEYID_d, g(qm)^xy | protocol | SPI | Ni_b | Nr_b) ! 514: * ! 515: * NOTE: we do not support prf with different input/output bitwidth, ! 516: * so we do not implement RFC2409 Appendix B (DOORAK-MAC example). ! 517: */ ! 518: static int ! 519: oakley_compute_keymat_x(iph2, side, sa_dir) ! 520: struct ph2handle *iph2; ! 521: int side; ! 522: int sa_dir; ! 523: { ! 524: vchar_t *buf = NULL, *res = NULL, *bp; ! 525: char *p; ! 526: int len; ! 527: int error = -1; ! 528: int pfs = 0; ! 529: int dupkeymat; /* generate K[1-dupkeymat] */ ! 530: struct saproto *pr; ! 531: struct satrns *tr; ! 532: int encklen, authklen, l; ! 533: ! 534: pfs = ((iph2->approval->pfs_group && iph2->dhgxy) ? 1 : 0); ! 535: ! 536: len = pfs ? iph2->dhgxy->l : 0; ! 537: len += (1 ! 538: + sizeof(u_int32_t) /* XXX SPI size */ ! 539: + iph2->nonce->l ! 540: + iph2->nonce_p->l); ! 541: buf = vmalloc(len); ! 542: if (buf == NULL) { ! 543: plog(LLV_ERROR, LOCATION, NULL, ! 544: "failed to get keymat buffer.\n"); ! 545: goto end; ! 546: } ! 547: ! 548: for (pr = iph2->approval->head; pr != NULL; pr = pr->next) { ! 549: p = buf->v; ! 550: ! 551: /* if PFS */ ! 552: if (pfs) { ! 553: memcpy(p, iph2->dhgxy->v, iph2->dhgxy->l); ! 554: p += iph2->dhgxy->l; ! 555: } ! 556: ! 557: p[0] = pr->proto_id; ! 558: p += 1; ! 559: ! 560: memcpy(p, (sa_dir == INBOUND_SA ? &pr->spi : &pr->spi_p), ! 561: sizeof(pr->spi)); ! 562: p += sizeof(pr->spi); ! 563: ! 564: bp = (side == INITIATOR ? iph2->nonce : iph2->nonce_p); ! 565: memcpy(p, bp->v, bp->l); ! 566: p += bp->l; ! 567: ! 568: bp = (side == INITIATOR ? iph2->nonce_p : iph2->nonce); ! 569: memcpy(p, bp->v, bp->l); ! 570: p += bp->l; ! 571: ! 572: /* compute IV */ ! 573: plog(LLV_DEBUG, LOCATION, NULL, "KEYMAT compute with\n"); ! 574: plogdump(LLV_DEBUG, buf->v, buf->l); ! 575: ! 576: /* res = K1 */ ! 577: res = oakley_prf(iph2->ph1->skeyid_d, buf, iph2->ph1); ! 578: if (res == NULL) ! 579: goto end; ! 580: ! 581: /* compute key length needed */ ! 582: encklen = authklen = 0; ! 583: switch (pr->proto_id) { ! 584: case IPSECDOI_PROTO_IPSEC_ESP: ! 585: for (tr = pr->head; tr; tr = tr->next) { ! 586: l = alg_ipsec_encdef_keylen(tr->trns_id, ! 587: tr->encklen); ! 588: if (l > encklen) ! 589: encklen = l; ! 590: ! 591: l = alg_ipsec_hmacdef_hashlen(tr->authtype); ! 592: if (l > authklen) ! 593: authklen = l; ! 594: } ! 595: break; ! 596: case IPSECDOI_PROTO_IPSEC_AH: ! 597: for (tr = pr->head; tr; tr = tr->next) { ! 598: l = alg_ipsec_hmacdef_hashlen(tr->trns_id); ! 599: if (l > authklen) ! 600: authklen = l; ! 601: } ! 602: break; ! 603: default: ! 604: break; ! 605: } ! 606: plog(LLV_DEBUG, LOCATION, NULL, "encklen=%d authklen=%d\n", ! 607: encklen, authklen); ! 608: ! 609: dupkeymat = (encklen + authklen) / 8 / res->l; ! 610: dupkeymat += 2; /* safety mergin */ ! 611: if (dupkeymat < 3) ! 612: dupkeymat = 3; ! 613: plog(LLV_DEBUG, LOCATION, NULL, ! 614: "generating %zu bits of key (dupkeymat=%d)\n", ! 615: dupkeymat * 8 * res->l, dupkeymat); ! 616: if (0 < --dupkeymat) { ! 617: vchar_t *prev = res; /* K(n-1) */ ! 618: vchar_t *seed = NULL; /* seed for Kn */ ! 619: size_t l; ! 620: ! 621: /* ! 622: * generating long key (isakmp-oakley-08 5.5) ! 623: * KEYMAT = K1 | K2 | K3 | ... ! 624: * where ! 625: * src = [ g(qm)^xy | ] protocol | SPI | Ni_b | Nr_b ! 626: * K1 = prf(SKEYID_d, src) ! 627: * K2 = prf(SKEYID_d, K1 | src) ! 628: * K3 = prf(SKEYID_d, K2 | src) ! 629: * Kn = prf(SKEYID_d, K(n-1) | src) ! 630: */ ! 631: plog(LLV_DEBUG, LOCATION, NULL, ! 632: "generating K1...K%d for KEYMAT.\n", ! 633: dupkeymat + 1); ! 634: ! 635: seed = vmalloc(prev->l + buf->l); ! 636: if (seed == NULL) { ! 637: plog(LLV_ERROR, LOCATION, NULL, ! 638: "failed to get keymat buffer.\n"); ! 639: if (prev && prev != res) ! 640: vfree(prev); ! 641: goto end; ! 642: } ! 643: ! 644: while (dupkeymat--) { ! 645: vchar_t *this = NULL; /* Kn */ ! 646: int update_prev; ! 647: ! 648: memcpy(seed->v, prev->v, prev->l); ! 649: memcpy(seed->v + prev->l, buf->v, buf->l); ! 650: this = oakley_prf(iph2->ph1->skeyid_d, seed, ! 651: iph2->ph1); ! 652: if (!this) { ! 653: plog(LLV_ERROR, LOCATION, NULL, ! 654: "oakley_prf memory overflow\n"); ! 655: if (prev && prev != res) ! 656: vfree(prev); ! 657: vfree(this); ! 658: vfree(seed); ! 659: goto end; ! 660: } ! 661: ! 662: update_prev = (prev && prev == res) ? 1 : 0; ! 663: ! 664: l = res->l; ! 665: res = vrealloc(res, l + this->l); ! 666: ! 667: if (update_prev) ! 668: prev = res; ! 669: ! 670: if (res == NULL) { ! 671: plog(LLV_ERROR, LOCATION, NULL, ! 672: "failed to get keymat buffer.\n"); ! 673: if (prev && prev != res) ! 674: vfree(prev); ! 675: vfree(this); ! 676: vfree(seed); ! 677: goto end; ! 678: } ! 679: memcpy(res->v + l, this->v, this->l); ! 680: ! 681: if (prev && prev != res) ! 682: vfree(prev); ! 683: prev = this; ! 684: this = NULL; ! 685: } ! 686: ! 687: if (prev && prev != res) ! 688: vfree(prev); ! 689: vfree(seed); ! 690: } ! 691: ! 692: plogdump(LLV_DEBUG, res->v, res->l); ! 693: ! 694: if (sa_dir == INBOUND_SA) ! 695: pr->keymat = res; ! 696: else ! 697: pr->keymat_p = res; ! 698: res = NULL; ! 699: } ! 700: ! 701: error = 0; ! 702: ! 703: end: ! 704: if (error) { ! 705: for (pr = iph2->approval->head; pr != NULL; pr = pr->next) { ! 706: if (pr->keymat) { ! 707: vfree(pr->keymat); ! 708: pr->keymat = NULL; ! 709: } ! 710: if (pr->keymat_p) { ! 711: vfree(pr->keymat_p); ! 712: pr->keymat_p = NULL; ! 713: } ! 714: } ! 715: } ! 716: ! 717: if (buf != NULL) ! 718: vfree(buf); ! 719: if (res) ! 720: vfree(res); ! 721: ! 722: return error; ! 723: } ! 724: ! 725: #if notyet ! 726: /* ! 727: * NOTE: Must terminate by NULL. ! 728: */ ! 729: vchar_t * ! 730: oakley_compute_hashx(struct ph1handle *iph1, ...) ! 731: { ! 732: vchar_t *buf, *res; ! 733: vchar_t *s; ! 734: caddr_t p; ! 735: int len; ! 736: ! 737: va_list ap; ! 738: ! 739: /* get buffer length */ ! 740: va_start(ap, iph1); ! 741: len = 0; ! 742: while ((s = va_arg(ap, vchar_t *)) != NULL) { ! 743: len += s->l ! 744: } ! 745: va_end(ap); ! 746: ! 747: buf = vmalloc(len); ! 748: if (buf == NULL) { ! 749: plog(LLV_ERROR, LOCATION, NULL, ! 750: "failed to get hash buffer\n"); ! 751: return NULL; ! 752: } ! 753: ! 754: /* set buffer */ ! 755: va_start(ap, iph1); ! 756: p = buf->v; ! 757: while ((s = va_arg(ap, char *)) != NULL) { ! 758: memcpy(p, s->v, s->l); ! 759: p += s->l; ! 760: } ! 761: va_end(ap); ! 762: ! 763: plog(LLV_DEBUG, LOCATION, NULL, "HASH with: \n"); ! 764: plogdump(LLV_DEBUG, buf->v, buf->l); ! 765: ! 766: /* compute HASH */ ! 767: res = oakley_prf(iph1->skeyid_a, buf, iph1); ! 768: vfree(buf); ! 769: if (res == NULL) ! 770: return NULL; ! 771: ! 772: plog(LLV_DEBUG, LOCATION, NULL, "HASH computed:\n"); ! 773: plogdump(LLV_DEBUG, res->v, res->l); ! 774: ! 775: return res; ! 776: } ! 777: #endif ! 778: ! 779: /* ! 780: * compute HASH(3) prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b) ! 781: * see seciton 5.5 Phase 2 - Quick Mode in isakmp-oakley-05. ! 782: */ ! 783: vchar_t * ! 784: oakley_compute_hash3(iph1, msgid, body) ! 785: struct ph1handle *iph1; ! 786: u_int32_t msgid; ! 787: vchar_t *body; ! 788: { ! 789: vchar_t *buf = 0, *res = 0; ! 790: int len; ! 791: int error = -1; ! 792: ! 793: /* create buffer */ ! 794: len = 1 + sizeof(u_int32_t) + body->l; ! 795: buf = vmalloc(len); ! 796: if (buf == NULL) { ! 797: plog(LLV_DEBUG, LOCATION, NULL, ! 798: "failed to get hash buffer\n"); ! 799: goto end; ! 800: } ! 801: ! 802: buf->v[0] = 0; ! 803: ! 804: memcpy(buf->v + 1, (char *)&msgid, sizeof(msgid)); ! 805: ! 806: memcpy(buf->v + 1 + sizeof(u_int32_t), body->v, body->l); ! 807: ! 808: plog(LLV_DEBUG, LOCATION, NULL, "HASH with: \n"); ! 809: plogdump(LLV_DEBUG, buf->v, buf->l); ! 810: ! 811: /* compute HASH */ ! 812: res = oakley_prf(iph1->skeyid_a, buf, iph1); ! 813: if (res == NULL) ! 814: goto end; ! 815: ! 816: error = 0; ! 817: ! 818: plog(LLV_DEBUG, LOCATION, NULL, "HASH computed:\n"); ! 819: plogdump(LLV_DEBUG, res->v, res->l); ! 820: ! 821: end: ! 822: if (buf != NULL) ! 823: vfree(buf); ! 824: return res; ! 825: } ! 826: ! 827: /* ! 828: * compute HASH type of prf(SKEYID_a, M-ID | buffer) ! 829: * e.g. ! 830: * for quick mode HASH(1): ! 831: * prf(SKEYID_a, M-ID | SA | Ni [ | KE ] [ | IDci | IDcr ]) ! 832: * for quick mode HASH(2): ! 833: * prf(SKEYID_a, M-ID | Ni_b | SA | Nr [ | KE ] [ | IDci | IDcr ]) ! 834: * for Informational exchange: ! 835: * prf(SKEYID_a, M-ID | N/D) ! 836: */ ! 837: vchar_t * ! 838: oakley_compute_hash1(iph1, msgid, body) ! 839: struct ph1handle *iph1; ! 840: u_int32_t msgid; ! 841: vchar_t *body; ! 842: { ! 843: vchar_t *buf = NULL, *res = NULL; ! 844: char *p; ! 845: int len; ! 846: int error = -1; ! 847: ! 848: /* create buffer */ ! 849: len = sizeof(u_int32_t) + body->l; ! 850: buf = vmalloc(len); ! 851: if (buf == NULL) { ! 852: plog(LLV_DEBUG, LOCATION, NULL, ! 853: "failed to get hash buffer\n"); ! 854: goto end; ! 855: } ! 856: ! 857: p = buf->v; ! 858: ! 859: memcpy(buf->v, (char *)&msgid, sizeof(msgid)); ! 860: p += sizeof(u_int32_t); ! 861: ! 862: memcpy(p, body->v, body->l); ! 863: ! 864: plog(LLV_DEBUG, LOCATION, NULL, "HASH with:\n"); ! 865: plogdump(LLV_DEBUG, buf->v, buf->l); ! 866: ! 867: /* compute HASH */ ! 868: res = oakley_prf(iph1->skeyid_a, buf, iph1); ! 869: if (res == NULL) ! 870: goto end; ! 871: ! 872: error = 0; ! 873: ! 874: plog(LLV_DEBUG, LOCATION, NULL, "HASH computed:\n"); ! 875: plogdump(LLV_DEBUG, res->v, res->l); ! 876: ! 877: end: ! 878: if (buf != NULL) ! 879: vfree(buf); ! 880: return res; ! 881: } ! 882: ! 883: /* ! 884: * compute phase1 HASH ! 885: * main/aggressive ! 886: * I-digest = prf(SKEYID, g^i | g^r | CKY-I | CKY-R | SAi_b | ID_i1_b) ! 887: * R-digest = prf(SKEYID, g^r | g^i | CKY-R | CKY-I | SAi_b | ID_r1_b) ! 888: * for gssapi, also include all GSS tokens, and call gss_wrap on the result ! 889: */ ! 890: vchar_t * ! 891: oakley_ph1hash_common(iph1, sw) ! 892: struct ph1handle *iph1; ! 893: int sw; ! 894: { ! 895: vchar_t *buf = NULL, *res = NULL, *bp; ! 896: char *p, *bp2; ! 897: int len, bl; ! 898: int error = -1; ! 899: #ifdef HAVE_GSSAPI ! 900: vchar_t *gsstokens = NULL; ! 901: #endif ! 902: ! 903: /* create buffer */ ! 904: len = iph1->dhpub->l ! 905: + iph1->dhpub_p->l ! 906: + sizeof(cookie_t) * 2 ! 907: + iph1->sa->l ! 908: + (sw == GENERATE ? iph1->id->l : iph1->id_p->l); ! 909: ! 910: #ifdef HAVE_GSSAPI ! 911: if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) { ! 912: if (iph1->gi_i != NULL && iph1->gi_r != NULL) { ! 913: bp = (sw == GENERATE ? iph1->gi_i : iph1->gi_r); ! 914: len += bp->l; ! 915: } ! 916: if (sw == GENERATE) ! 917: gssapi_get_itokens(iph1, &gsstokens); ! 918: else ! 919: gssapi_get_rtokens(iph1, &gsstokens); ! 920: if (gsstokens == NULL) ! 921: return NULL; ! 922: len += gsstokens->l; ! 923: } ! 924: #endif ! 925: ! 926: buf = vmalloc(len); ! 927: if (buf == NULL) { ! 928: plog(LLV_ERROR, LOCATION, NULL, ! 929: "failed to get hash buffer\n"); ! 930: goto end; ! 931: } ! 932: ! 933: p = buf->v; ! 934: ! 935: bp = (sw == GENERATE ? iph1->dhpub : iph1->dhpub_p); ! 936: memcpy(p, bp->v, bp->l); ! 937: p += bp->l; ! 938: ! 939: bp = (sw == GENERATE ? iph1->dhpub_p : iph1->dhpub); ! 940: memcpy(p, bp->v, bp->l); ! 941: p += bp->l; ! 942: ! 943: if (iph1->side == INITIATOR) ! 944: bp2 = (sw == GENERATE ? ! 945: (char *)&iph1->index.i_ck : (char *)&iph1->index.r_ck); ! 946: else ! 947: bp2 = (sw == GENERATE ? ! 948: (char *)&iph1->index.r_ck : (char *)&iph1->index.i_ck); ! 949: bl = sizeof(cookie_t); ! 950: memcpy(p, bp2, bl); ! 951: p += bl; ! 952: ! 953: if (iph1->side == INITIATOR) ! 954: bp2 = (sw == GENERATE ? ! 955: (char *)&iph1->index.r_ck : (char *)&iph1->index.i_ck); ! 956: else ! 957: bp2 = (sw == GENERATE ? ! 958: (char *)&iph1->index.i_ck : (char *)&iph1->index.r_ck); ! 959: bl = sizeof(cookie_t); ! 960: memcpy(p, bp2, bl); ! 961: p += bl; ! 962: ! 963: bp = iph1->sa; ! 964: memcpy(p, bp->v, bp->l); ! 965: p += bp->l; ! 966: ! 967: bp = (sw == GENERATE ? iph1->id : iph1->id_p); ! 968: memcpy(p, bp->v, bp->l); ! 969: p += bp->l; ! 970: ! 971: #ifdef HAVE_GSSAPI ! 972: if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) { ! 973: if (iph1->gi_i != NULL && iph1->gi_r != NULL) { ! 974: bp = (sw == GENERATE ? iph1->gi_i : iph1->gi_r); ! 975: memcpy(p, bp->v, bp->l); ! 976: p += bp->l; ! 977: } ! 978: memcpy(p, gsstokens->v, gsstokens->l); ! 979: p += gsstokens->l; ! 980: } ! 981: #endif ! 982: ! 983: plog(LLV_DEBUG, LOCATION, NULL, "HASH with:\n"); ! 984: plogdump(LLV_DEBUG, buf->v, buf->l); ! 985: ! 986: /* compute HASH */ ! 987: res = oakley_prf(iph1->skeyid, buf, iph1); ! 988: if (res == NULL) ! 989: goto end; ! 990: ! 991: error = 0; ! 992: ! 993: plog(LLV_DEBUG, LOCATION, NULL, "HASH (%s) computed:\n", ! 994: iph1->side == INITIATOR ? "init" : "resp"); ! 995: plogdump(LLV_DEBUG, res->v, res->l); ! 996: ! 997: end: ! 998: if (buf != NULL) ! 999: vfree(buf); ! 1000: #ifdef HAVE_GSSAPI ! 1001: if (gsstokens != NULL) ! 1002: vfree(gsstokens); ! 1003: #endif ! 1004: return res; ! 1005: } ! 1006: ! 1007: /* ! 1008: * compute HASH_I on base mode. ! 1009: * base:psk,rsa ! 1010: * HASH_I = prf(SKEYID, g^xi | CKY-I | CKY-R | SAi_b | IDii_b) ! 1011: * base:sig ! 1012: * HASH_I = prf(hash(Ni_b | Nr_b), g^xi | CKY-I | CKY-R | SAi_b | IDii_b) ! 1013: */ ! 1014: vchar_t * ! 1015: oakley_ph1hash_base_i(iph1, sw) ! 1016: struct ph1handle *iph1; ! 1017: int sw; ! 1018: { ! 1019: vchar_t *buf = NULL, *res = NULL, *bp; ! 1020: vchar_t *hashkey = NULL; ! 1021: vchar_t *hash = NULL; /* for signature mode */ ! 1022: char *p; ! 1023: int len; ! 1024: int error = -1; ! 1025: ! 1026: /* sanity check */ ! 1027: if (iph1->etype != ISAKMP_ETYPE_BASE) { ! 1028: plog(LLV_ERROR, LOCATION, NULL, ! 1029: "invalid etype for this hash function\n"); ! 1030: return NULL; ! 1031: } ! 1032: ! 1033: switch (iph1->approval->authmethod) { ! 1034: case OAKLEY_ATTR_AUTH_METHOD_PSKEY: ! 1035: case OAKLEY_ATTR_AUTH_METHOD_RSAENC: ! 1036: case OAKLEY_ATTR_AUTH_METHOD_RSAREV: ! 1037: #ifdef ENABLE_HYBRID ! 1038: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I: ! 1039: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R: ! 1040: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I: ! 1041: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R: ! 1042: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I: ! 1043: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R: ! 1044: #endif ! 1045: if (iph1->skeyid == NULL) { ! 1046: plog(LLV_ERROR, LOCATION, NULL, "no SKEYID found.\n"); ! 1047: return NULL; ! 1048: } ! 1049: hashkey = iph1->skeyid; ! 1050: break; ! 1051: ! 1052: case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: ! 1053: case OAKLEY_ATTR_AUTH_METHOD_RSASIG: ! 1054: #ifdef HAVE_GSSAPI ! 1055: case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB: ! 1056: #endif ! 1057: #ifdef ENABLE_HYBRID ! 1058: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: ! 1059: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R: ! 1060: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: ! 1061: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R: ! 1062: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I: ! 1063: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: ! 1064: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I: ! 1065: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: ! 1066: #endif ! 1067: /* make hash for seed */ ! 1068: len = iph1->nonce->l + iph1->nonce_p->l; ! 1069: buf = vmalloc(len); ! 1070: if (buf == NULL) { ! 1071: plog(LLV_ERROR, LOCATION, NULL, ! 1072: "failed to get hash buffer\n"); ! 1073: goto end; ! 1074: } ! 1075: p = buf->v; ! 1076: ! 1077: bp = (sw == GENERATE ? iph1->nonce_p : iph1->nonce); ! 1078: memcpy(p, bp->v, bp->l); ! 1079: p += bp->l; ! 1080: ! 1081: bp = (sw == GENERATE ? iph1->nonce : iph1->nonce_p); ! 1082: memcpy(p, bp->v, bp->l); ! 1083: p += bp->l; ! 1084: ! 1085: hash = oakley_hash(buf, iph1); ! 1086: if (hash == NULL) ! 1087: goto end; ! 1088: vfree(buf); ! 1089: buf = NULL; ! 1090: ! 1091: hashkey = hash; ! 1092: break; ! 1093: ! 1094: default: ! 1095: plog(LLV_ERROR, LOCATION, NULL, ! 1096: "not supported authentication method %d\n", ! 1097: iph1->approval->authmethod); ! 1098: return NULL; ! 1099: ! 1100: } ! 1101: ! 1102: len = (sw == GENERATE ? iph1->dhpub->l : iph1->dhpub_p->l) ! 1103: + sizeof(cookie_t) * 2 ! 1104: + iph1->sa->l ! 1105: + (sw == GENERATE ? iph1->id->l : iph1->id_p->l); ! 1106: buf = vmalloc(len); ! 1107: if (buf == NULL) { ! 1108: plog(LLV_ERROR, LOCATION, NULL, ! 1109: "failed to get hash buffer\n"); ! 1110: goto end; ! 1111: } ! 1112: p = buf->v; ! 1113: ! 1114: bp = (sw == GENERATE ? iph1->dhpub : iph1->dhpub_p); ! 1115: memcpy(p, bp->v, bp->l); ! 1116: p += bp->l; ! 1117: ! 1118: memcpy(p, &iph1->index.i_ck, sizeof(cookie_t)); ! 1119: p += sizeof(cookie_t); ! 1120: memcpy(p, &iph1->index.r_ck, sizeof(cookie_t)); ! 1121: p += sizeof(cookie_t); ! 1122: ! 1123: memcpy(p, iph1->sa->v, iph1->sa->l); ! 1124: p += iph1->sa->l; ! 1125: ! 1126: bp = (sw == GENERATE ? iph1->id : iph1->id_p); ! 1127: memcpy(p, bp->v, bp->l); ! 1128: p += bp->l; ! 1129: ! 1130: plog(LLV_DEBUG, LOCATION, NULL, "HASH_I with:\n"); ! 1131: plogdump(LLV_DEBUG, buf->v, buf->l); ! 1132: ! 1133: /* compute HASH */ ! 1134: res = oakley_prf(hashkey, buf, iph1); ! 1135: if (res == NULL) ! 1136: goto end; ! 1137: ! 1138: error = 0; ! 1139: ! 1140: plog(LLV_DEBUG, LOCATION, NULL, "HASH_I computed:\n"); ! 1141: plogdump(LLV_DEBUG, res->v, res->l); ! 1142: ! 1143: end: ! 1144: if (hash != NULL) ! 1145: vfree(hash); ! 1146: if (buf != NULL) ! 1147: vfree(buf); ! 1148: return res; ! 1149: } ! 1150: ! 1151: /* ! 1152: * compute HASH_R on base mode for signature method. ! 1153: * base: ! 1154: * HASH_R = prf(hash(Ni_b | Nr_b), g^xi | g^xr | CKY-I | CKY-R | SAi_b | IDii_b) ! 1155: */ ! 1156: vchar_t * ! 1157: oakley_ph1hash_base_r(iph1, sw) ! 1158: struct ph1handle *iph1; ! 1159: int sw; ! 1160: { ! 1161: vchar_t *buf = NULL, *res = NULL, *bp; ! 1162: vchar_t *hash = NULL; ! 1163: char *p; ! 1164: int len; ! 1165: int error = -1; ! 1166: ! 1167: /* sanity check */ ! 1168: if (iph1->etype != ISAKMP_ETYPE_BASE) { ! 1169: plog(LLV_ERROR, LOCATION, NULL, ! 1170: "invalid etype for this hash function\n"); ! 1171: return NULL; ! 1172: } ! 1173: ! 1174: switch (iph1->approval->authmethod) { ! 1175: case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: ! 1176: case OAKLEY_ATTR_AUTH_METHOD_RSASIG: ! 1177: #ifdef ENABLE_HYBRID ! 1178: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: ! 1179: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R: ! 1180: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: ! 1181: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R: ! 1182: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I: ! 1183: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: ! 1184: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I: ! 1185: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: ! 1186: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I: ! 1187: #endif ! 1188: break; ! 1189: default: ! 1190: plog(LLV_ERROR, LOCATION, NULL, ! 1191: "not supported authentication method %d\n", ! 1192: iph1->approval->authmethod); ! 1193: return NULL; ! 1194: break; ! 1195: } ! 1196: ! 1197: /* make hash for seed */ ! 1198: len = iph1->nonce->l + iph1->nonce_p->l; ! 1199: buf = vmalloc(len); ! 1200: if (buf == NULL) { ! 1201: plog(LLV_ERROR, LOCATION, NULL, ! 1202: "failed to get hash buffer\n"); ! 1203: goto end; ! 1204: } ! 1205: p = buf->v; ! 1206: ! 1207: bp = (sw == GENERATE ? iph1->nonce_p : iph1->nonce); ! 1208: memcpy(p, bp->v, bp->l); ! 1209: p += bp->l; ! 1210: ! 1211: bp = (sw == GENERATE ? iph1->nonce : iph1->nonce_p); ! 1212: memcpy(p, bp->v, bp->l); ! 1213: p += bp->l; ! 1214: ! 1215: hash = oakley_hash(buf, iph1); ! 1216: if (hash == NULL) ! 1217: goto end; ! 1218: vfree(buf); ! 1219: buf = NULL; ! 1220: ! 1221: /* make really hash */ ! 1222: len = (sw == GENERATE ? iph1->dhpub_p->l : iph1->dhpub->l) ! 1223: + (sw == GENERATE ? iph1->dhpub->l : iph1->dhpub_p->l) ! 1224: + sizeof(cookie_t) * 2 ! 1225: + iph1->sa->l ! 1226: + (sw == GENERATE ? iph1->id_p->l : iph1->id->l); ! 1227: buf = vmalloc(len); ! 1228: if (buf == NULL) { ! 1229: plog(LLV_ERROR, LOCATION, NULL, ! 1230: "failed to get hash buffer\n"); ! 1231: goto end; ! 1232: } ! 1233: p = buf->v; ! 1234: ! 1235: ! 1236: bp = (sw == GENERATE ? iph1->dhpub_p : iph1->dhpub); ! 1237: memcpy(p, bp->v, bp->l); ! 1238: p += bp->l; ! 1239: ! 1240: bp = (sw == GENERATE ? iph1->dhpub : iph1->dhpub_p); ! 1241: memcpy(p, bp->v, bp->l); ! 1242: p += bp->l; ! 1243: ! 1244: memcpy(p, &iph1->index.i_ck, sizeof(cookie_t)); ! 1245: p += sizeof(cookie_t); ! 1246: memcpy(p, &iph1->index.r_ck, sizeof(cookie_t)); ! 1247: p += sizeof(cookie_t); ! 1248: ! 1249: memcpy(p, iph1->sa->v, iph1->sa->l); ! 1250: p += iph1->sa->l; ! 1251: ! 1252: bp = (sw == GENERATE ? iph1->id_p : iph1->id); ! 1253: memcpy(p, bp->v, bp->l); ! 1254: p += bp->l; ! 1255: ! 1256: plog(LLV_DEBUG, LOCATION, NULL, "HASH_R with:\n"); ! 1257: plogdump(LLV_DEBUG, buf->v, buf->l); ! 1258: ! 1259: /* compute HASH */ ! 1260: res = oakley_prf(hash, buf, iph1); ! 1261: if (res == NULL) ! 1262: goto end; ! 1263: ! 1264: error = 0; ! 1265: ! 1266: plog(LLV_DEBUG, LOCATION, NULL, "HASH_R computed:\n"); ! 1267: plogdump(LLV_DEBUG, res->v, res->l); ! 1268: ! 1269: end: ! 1270: if (buf != NULL) ! 1271: vfree(buf); ! 1272: if (hash) ! 1273: vfree(hash); ! 1274: return res; ! 1275: } ! 1276: ! 1277: /* ! 1278: * compute each authentication method in phase 1. ! 1279: * OUT: ! 1280: * 0: OK ! 1281: * -1: error ! 1282: * other: error to be reply with notification. ! 1283: * the value is notification type. ! 1284: */ ! 1285: int ! 1286: oakley_validate_auth(iph1) ! 1287: struct ph1handle *iph1; ! 1288: { ! 1289: vchar_t *my_hash = NULL; ! 1290: int result; ! 1291: #ifdef HAVE_GSSAPI ! 1292: vchar_t *gsshash = NULL; ! 1293: #endif ! 1294: #ifdef ENABLE_STATS ! 1295: struct timeval start, end; ! 1296: #endif ! 1297: ! 1298: #ifdef ENABLE_STATS ! 1299: gettimeofday(&start, NULL); ! 1300: #endif ! 1301: ! 1302: switch (iph1->approval->authmethod) { ! 1303: case OAKLEY_ATTR_AUTH_METHOD_PSKEY: ! 1304: #ifdef ENABLE_HYBRID ! 1305: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I: ! 1306: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R: ! 1307: #endif ! 1308: /* validate HASH */ ! 1309: { ! 1310: char *r_hash; ! 1311: ! 1312: if (iph1->id_p == NULL || iph1->pl_hash == NULL) { ! 1313: plog(LLV_ERROR, LOCATION, iph1->remote, ! 1314: "few isakmp message received.\n"); ! 1315: return ISAKMP_NTYPE_PAYLOAD_MALFORMED; ! 1316: } ! 1317: #ifdef ENABLE_HYBRID ! 1318: if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I && ! 1319: ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0)) ! 1320: { ! 1321: plog(LLV_ERROR, LOCATION, NULL, "No SIG was passed, " ! 1322: "hybrid auth is enabled, " ! 1323: "but peer is no Xauth compliant\n"); ! 1324: return ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED; ! 1325: break; ! 1326: } ! 1327: #endif ! 1328: r_hash = (caddr_t)(iph1->pl_hash + 1); ! 1329: ! 1330: plog(LLV_DEBUG, LOCATION, NULL, "HASH received:\n"); ! 1331: plogdump(LLV_DEBUG, r_hash, ! 1332: ntohs(iph1->pl_hash->h.len) - sizeof(*iph1->pl_hash)); ! 1333: ! 1334: switch (iph1->etype) { ! 1335: case ISAKMP_ETYPE_IDENT: ! 1336: case ISAKMP_ETYPE_AGG: ! 1337: my_hash = oakley_ph1hash_common(iph1, VALIDATE); ! 1338: break; ! 1339: case ISAKMP_ETYPE_BASE: ! 1340: if (iph1->side == INITIATOR) ! 1341: my_hash = oakley_ph1hash_common(iph1, VALIDATE); ! 1342: else ! 1343: my_hash = oakley_ph1hash_base_i(iph1, VALIDATE); ! 1344: break; ! 1345: default: ! 1346: plog(LLV_ERROR, LOCATION, NULL, ! 1347: "invalid etype %d\n", iph1->etype); ! 1348: return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE; ! 1349: } ! 1350: if (my_hash == NULL) ! 1351: return ISAKMP_INTERNAL_ERROR; ! 1352: ! 1353: result = memcmp(my_hash->v, r_hash, my_hash->l); ! 1354: vfree(my_hash); ! 1355: ! 1356: if (result) { ! 1357: plog(LLV_ERROR, LOCATION, NULL, "HASH mismatched\n"); ! 1358: return ISAKMP_NTYPE_INVALID_HASH_INFORMATION; ! 1359: } ! 1360: ! 1361: plog(LLV_DEBUG, LOCATION, NULL, "HASH for PSK validated.\n"); ! 1362: } ! 1363: break; ! 1364: case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: ! 1365: case OAKLEY_ATTR_AUTH_METHOD_RSASIG: ! 1366: #ifdef ENABLE_HYBRID ! 1367: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: ! 1368: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: ! 1369: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I: ! 1370: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: ! 1371: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I: ! 1372: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: ! 1373: #endif ! 1374: { ! 1375: int error = 0; ! 1376: int certtype; ! 1377: ! 1378: /* validation */ ! 1379: if (iph1->id_p == NULL) { ! 1380: plog(LLV_ERROR, LOCATION, iph1->remote, ! 1381: "no ID payload was passed.\n"); ! 1382: return ISAKMP_NTYPE_PAYLOAD_MALFORMED; ! 1383: } ! 1384: if (iph1->sig_p == NULL) { ! 1385: plog(LLV_ERROR, LOCATION, iph1->remote, ! 1386: "no SIG payload was passed.\n"); ! 1387: return ISAKMP_NTYPE_PAYLOAD_MALFORMED; ! 1388: } ! 1389: ! 1390: plog(LLV_DEBUG, LOCATION, NULL, "SIGN passed:\n"); ! 1391: plogdump(LLV_DEBUG, iph1->sig_p->v, iph1->sig_p->l); ! 1392: ! 1393: /* get peer's cert */ ! 1394: certtype = oakley_get_certtype(iph1->rmconf->peerscert); ! 1395: switch (certtype) { ! 1396: case ISAKMP_CERT_NONE: ! 1397: /* expect to receive one from peer */ ! 1398: if (iph1->cert_p == NULL) { ! 1399: plog(LLV_ERROR, LOCATION, NULL, ! 1400: "no peer's CERT payload found.\n"); ! 1401: return ISAKMP_INTERNAL_ERROR; ! 1402: } ! 1403: /* verify the cert if needed */ ! 1404: if (!iph1->rmconf->verify_cert) ! 1405: break; ! 1406: ! 1407: switch (oakley_get_certtype(iph1->cert_p)) { ! 1408: case ISAKMP_CERT_X509SIGN: { ! 1409: char path[MAXPATHLEN]; ! 1410: char *ca; ! 1411: ! 1412: if (iph1->rmconf->cacertfile != NULL) { ! 1413: getpathname(path, sizeof(path), ! 1414: LC_PATHTYPE_CERT, ! 1415: iph1->rmconf->cacertfile); ! 1416: ca = path; ! 1417: } else { ! 1418: ca = NULL; ! 1419: } ! 1420: ! 1421: error = eay_check_x509cert( ! 1422: iph1->cert_p, ! 1423: lcconf->pathinfo[LC_PATHTYPE_CERT], ! 1424: ca, 0); ! 1425: break; ! 1426: } ! 1427: default: ! 1428: plog(LLV_ERROR, LOCATION, NULL, ! 1429: "peers_cert certtype %d was not expected\n", ! 1430: certtype); ! 1431: return ISAKMP_INTERNAL_ERROR; ! 1432: } ! 1433: ! 1434: if (error != 0) { ! 1435: plog(LLV_ERROR, LOCATION, NULL, ! 1436: "the peer's certificate is not verified.\n"); ! 1437: return ISAKMP_NTYPE_INVALID_CERT_AUTHORITY; ! 1438: } ! 1439: break; ! 1440: case ISAKMP_CERT_X509SIGN: ! 1441: if (iph1->rmconf->peerscert == NULL) { ! 1442: plog(LLV_ERROR, LOCATION, NULL, ! 1443: "no peer's CERT file found.\n"); ! 1444: return ISAKMP_INTERNAL_ERROR; ! 1445: } ! 1446: /* don't use received cert */ ! 1447: if (iph1->cert_p != NULL) { ! 1448: vfree(iph1->cert_p); ! 1449: iph1->cert_p = NULL; ! 1450: } ! 1451: /* copy from remoteconf instead */ ! 1452: iph1->cert_p = vdup(iph1->rmconf->peerscert); ! 1453: break; ! 1454: case ISAKMP_CERT_PLAINRSA: ! 1455: if (get_plainrsa_fromlocal(iph1, 0)) ! 1456: return ISAKMP_INTERNAL_ERROR; ! 1457: break; ! 1458: case ISAKMP_CERT_DNS: ! 1459: /* don't use received cert */ ! 1460: if (iph1->cert_p != NULL) { ! 1461: vfree(iph1->cert_p); ! 1462: iph1->cert_p = NULL; ! 1463: } ! 1464: ! 1465: iph1->cert_p = dnssec_getcert(iph1->id_p); ! 1466: if (iph1->cert_p == NULL) { ! 1467: plog(LLV_ERROR, LOCATION, NULL, ! 1468: "no CERT RR found.\n"); ! 1469: return ISAKMP_INTERNAL_ERROR; ! 1470: } ! 1471: break; ! 1472: default: ! 1473: plog(LLV_ERROR, LOCATION, NULL, ! 1474: "invalid certificate type: %d\n", ! 1475: oakley_get_certtype(iph1->rmconf->peerscert)); ! 1476: return ISAKMP_INTERNAL_ERROR; ! 1477: } ! 1478: ! 1479: /* compare ID payload and certificate name */ ! 1480: if ((error = oakley_check_certid(iph1)) != 0) ! 1481: return error; ! 1482: ! 1483: /* Generate a warning if verify_cert */ ! 1484: if (iph1->rmconf->verify_cert) { ! 1485: plog(LLV_DEBUG, LOCATION, NULL, ! 1486: "CERT validated\n"); ! 1487: } else { ! 1488: plog(LLV_WARNING, LOCATION, NULL, ! 1489: "CERT validation disabled by configuration\n"); ! 1490: } ! 1491: ! 1492: /* compute hash */ ! 1493: switch (iph1->etype) { ! 1494: case ISAKMP_ETYPE_IDENT: ! 1495: case ISAKMP_ETYPE_AGG: ! 1496: my_hash = oakley_ph1hash_common(iph1, VALIDATE); ! 1497: break; ! 1498: case ISAKMP_ETYPE_BASE: ! 1499: if (iph1->side == INITIATOR) ! 1500: my_hash = oakley_ph1hash_base_r(iph1, VALIDATE); ! 1501: else ! 1502: my_hash = oakley_ph1hash_base_i(iph1, VALIDATE); ! 1503: break; ! 1504: default: ! 1505: plog(LLV_ERROR, LOCATION, NULL, ! 1506: "invalid etype %d\n", iph1->etype); ! 1507: return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE; ! 1508: } ! 1509: if (my_hash == NULL) ! 1510: return ISAKMP_INTERNAL_ERROR; ! 1511: ! 1512: /* check signature */ ! 1513: certtype = oakley_get_certtype(iph1->cert_p); ! 1514: if (certtype == ISAKMP_CERT_NONE) ! 1515: certtype = oakley_get_certtype(iph1->rmconf->peerscert); ! 1516: switch (certtype) { ! 1517: case ISAKMP_CERT_X509SIGN: ! 1518: case ISAKMP_CERT_DNS: ! 1519: error = eay_check_x509sign(my_hash, ! 1520: iph1->sig_p, ! 1521: iph1->cert_p); ! 1522: break; ! 1523: case ISAKMP_CERT_PLAINRSA: ! 1524: iph1->rsa_p = rsa_try_check_rsasign(my_hash, ! 1525: iph1->sig_p, iph1->rsa_candidates); ! 1526: error = iph1->rsa_p ? 0 : -1; ! 1527: genlist_free(iph1->rsa_candidates, NULL); ! 1528: iph1->rsa_candidates = NULL; ! 1529: break; ! 1530: default: ! 1531: plog(LLV_ERROR, LOCATION, NULL, ! 1532: "cannot check signature for certtype %d\n", ! 1533: certtype); ! 1534: vfree(my_hash); ! 1535: return ISAKMP_INTERNAL_ERROR; ! 1536: } ! 1537: ! 1538: vfree(my_hash); ! 1539: if (error != 0) { ! 1540: plog(LLV_ERROR, LOCATION, NULL, ! 1541: "Invalid SIG.\n"); ! 1542: return ISAKMP_NTYPE_INVALID_SIGNATURE; ! 1543: } ! 1544: plog(LLV_DEBUG, LOCATION, NULL, "SIG authenticated\n"); ! 1545: } ! 1546: break; ! 1547: #ifdef ENABLE_HYBRID ! 1548: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R: ! 1549: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R: ! 1550: { ! 1551: if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) { ! 1552: plog(LLV_ERROR, LOCATION, NULL, "No SIG was passed, " ! 1553: "hybrid auth is enabled, " ! 1554: "but peer is no Xauth compliant\n"); ! 1555: return ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED; ! 1556: break; ! 1557: } ! 1558: plog(LLV_INFO, LOCATION, NULL, "No SIG was passed, " ! 1559: "but hybrid auth is enabled\n"); ! 1560: ! 1561: return 0; ! 1562: break; ! 1563: } ! 1564: #endif ! 1565: #ifdef HAVE_GSSAPI ! 1566: case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB: ! 1567: /* check if we're not into XAUTH_PSKEY_I instead */ ! 1568: #ifdef ENABLE_HYBRID ! 1569: if (iph1->rmconf->xauth) ! 1570: break; ! 1571: #endif ! 1572: switch (iph1->etype) { ! 1573: case ISAKMP_ETYPE_IDENT: ! 1574: case ISAKMP_ETYPE_AGG: ! 1575: my_hash = oakley_ph1hash_common(iph1, VALIDATE); ! 1576: break; ! 1577: default: ! 1578: plog(LLV_ERROR, LOCATION, NULL, ! 1579: "invalid etype %d\n", iph1->etype); ! 1580: return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE; ! 1581: } ! 1582: ! 1583: if (my_hash == NULL) { ! 1584: if (gssapi_more_tokens(iph1)) ! 1585: return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE; ! 1586: else ! 1587: return ISAKMP_NTYPE_INVALID_HASH_INFORMATION; ! 1588: } ! 1589: ! 1590: gsshash = gssapi_unwraphash(iph1); ! 1591: if (gsshash == NULL) { ! 1592: vfree(my_hash); ! 1593: return ISAKMP_NTYPE_INVALID_HASH_INFORMATION; ! 1594: } ! 1595: ! 1596: result = memcmp(my_hash->v, gsshash->v, my_hash->l); ! 1597: vfree(my_hash); ! 1598: vfree(gsshash); ! 1599: ! 1600: if (result) { ! 1601: plog(LLV_ERROR, LOCATION, NULL, "HASH mismatched\n"); ! 1602: return ISAKMP_NTYPE_INVALID_HASH_INFORMATION; ! 1603: } ! 1604: plog(LLV_DEBUG, LOCATION, NULL, "hash compared OK\n"); ! 1605: break; ! 1606: #endif ! 1607: case OAKLEY_ATTR_AUTH_METHOD_RSAENC: ! 1608: case OAKLEY_ATTR_AUTH_METHOD_RSAREV: ! 1609: #ifdef ENABLE_HYBRID ! 1610: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I: ! 1611: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R: ! 1612: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I: ! 1613: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R: ! 1614: #endif ! 1615: if (iph1->id_p == NULL || iph1->pl_hash == NULL) { ! 1616: plog(LLV_ERROR, LOCATION, iph1->remote, ! 1617: "few isakmp message received.\n"); ! 1618: return ISAKMP_NTYPE_PAYLOAD_MALFORMED; ! 1619: } ! 1620: plog(LLV_ERROR, LOCATION, iph1->remote, ! 1621: "not supported authmethod type %s\n", ! 1622: s_oakley_attr_method(iph1->approval->authmethod)); ! 1623: return ISAKMP_INTERNAL_ERROR; ! 1624: default: ! 1625: plog(LLV_ERROR, LOCATION, iph1->remote, ! 1626: "invalid authmethod %d why ?\n", ! 1627: iph1->approval->authmethod); ! 1628: return ISAKMP_INTERNAL_ERROR; ! 1629: } ! 1630: #ifdef ENABLE_STATS ! 1631: gettimeofday(&end, NULL); ! 1632: syslog(LOG_NOTICE, "%s(%s): %8.6f", __func__, ! 1633: s_oakley_attr_method(iph1->approval->authmethod), ! 1634: timedelta(&start, &end)); ! 1635: #endif ! 1636: ! 1637: return 0; ! 1638: } ! 1639: ! 1640: /* get my certificate ! 1641: * NOTE: include certificate type. ! 1642: */ ! 1643: int ! 1644: oakley_getmycert(iph1) ! 1645: struct ph1handle *iph1; ! 1646: { ! 1647: switch (oakley_get_certtype(iph1->rmconf->mycert)) { ! 1648: case ISAKMP_CERT_X509SIGN: ! 1649: if (iph1->cert) ! 1650: return 0; ! 1651: iph1->cert = vdup(iph1->rmconf->mycert); ! 1652: break; ! 1653: case ISAKMP_CERT_PLAINRSA: ! 1654: if (iph1->rsa) ! 1655: return 0; ! 1656: return get_plainrsa_fromlocal(iph1, 1); ! 1657: default: ! 1658: plog(LLV_ERROR, LOCATION, NULL, ! 1659: "Unknown certtype #%d\n", ! 1660: oakley_get_certtype(iph1->rmconf->mycert)); ! 1661: return -1; ! 1662: } ! 1663: ! 1664: return 0; ! 1665: } ! 1666: ! 1667: static int ! 1668: get_plainrsa_fromlocal(iph1, my) ! 1669: struct ph1handle *iph1; ! 1670: int my; ! 1671: { ! 1672: char path[MAXPATHLEN]; ! 1673: vchar_t *cert = NULL; ! 1674: char *certfile; ! 1675: int error = -1; ! 1676: ! 1677: iph1->rsa_candidates = rsa_lookup_keys(iph1, my); ! 1678: if (!iph1->rsa_candidates || ! 1679: rsa_list_count(iph1->rsa_candidates) == 0) { ! 1680: plog(LLV_ERROR, LOCATION, NULL, ! 1681: "%s RSA key not found for %s\n", ! 1682: my ? "Private" : "Public", ! 1683: saddr2str_fromto("%s <-> %s", ! 1684: iph1->local, iph1->remote)); ! 1685: goto end; ! 1686: } ! 1687: ! 1688: if (my && rsa_list_count(iph1->rsa_candidates) > 1) { ! 1689: plog(LLV_WARNING, LOCATION, NULL, ! 1690: "More than one (=%lu) private " ! 1691: "PlainRSA key found for %s\n", ! 1692: rsa_list_count(iph1->rsa_candidates), ! 1693: saddr2str_fromto("%s <-> %s", ! 1694: iph1->local, iph1->remote)); ! 1695: plog(LLV_WARNING, LOCATION, NULL, ! 1696: "This may have unpredictable results, " ! 1697: "i.e. wrong key could be used!\n"); ! 1698: plog(LLV_WARNING, LOCATION, NULL, ! 1699: "Consider using only one single private " ! 1700: "key for all peers...\n"); ! 1701: } ! 1702: if (my) { ! 1703: iph1->rsa = ((struct rsa_key *) ! 1704: genlist_next(iph1->rsa_candidates, NULL))->rsa; ! 1705: ! 1706: genlist_free(iph1->rsa_candidates, NULL); ! 1707: iph1->rsa_candidates = NULL; ! 1708: ! 1709: if (iph1->rsa == NULL) ! 1710: goto end; ! 1711: } ! 1712: ! 1713: error = 0; ! 1714: ! 1715: end: ! 1716: return error; ! 1717: } ! 1718: ! 1719: /* get signature */ ! 1720: int ! 1721: oakley_getsign(iph1) ! 1722: struct ph1handle *iph1; ! 1723: { ! 1724: char path[MAXPATHLEN]; ! 1725: vchar_t *privkey = NULL; ! 1726: int error = -1; ! 1727: ! 1728: switch (oakley_get_certtype(iph1->rmconf->mycert)) { ! 1729: case ISAKMP_CERT_X509SIGN: ! 1730: case ISAKMP_CERT_DNS: ! 1731: if (iph1->rmconf->myprivfile == NULL) { ! 1732: plog(LLV_ERROR, LOCATION, NULL, "no cert defined.\n"); ! 1733: goto end; ! 1734: } ! 1735: ! 1736: /* make private file name */ ! 1737: getpathname(path, sizeof(path), ! 1738: LC_PATHTYPE_CERT, ! 1739: iph1->rmconf->myprivfile); ! 1740: privkey = privsep_eay_get_pkcs1privkey(path); ! 1741: if (privkey == NULL) { ! 1742: plog(LLV_ERROR, LOCATION, NULL, ! 1743: "failed to get private key.\n"); ! 1744: goto end; ! 1745: } ! 1746: plog(LLV_DEBUG2, LOCATION, NULL, "private key:\n"); ! 1747: plogdump(LLV_DEBUG2, privkey->v, privkey->l); ! 1748: iph1->sig = eay_get_x509sign(iph1->hash, privkey); ! 1749: break; ! 1750: case ISAKMP_CERT_PLAINRSA: ! 1751: iph1->sig = eay_get_rsasign(iph1->hash, iph1->rsa); ! 1752: break; ! 1753: default: ! 1754: plog(LLV_ERROR, LOCATION, NULL, ! 1755: "Unknown certtype #%d\n", ! 1756: oakley_get_certtype(iph1->rmconf->mycert)); ! 1757: goto end; ! 1758: } ! 1759: ! 1760: if (iph1->sig == NULL) { ! 1761: plog(LLV_ERROR, LOCATION, NULL, "failed to sign.\n"); ! 1762: goto end; ! 1763: } ! 1764: ! 1765: plog(LLV_DEBUG, LOCATION, NULL, "SIGN computed:\n"); ! 1766: plogdump(LLV_DEBUG, iph1->sig->v, iph1->sig->l); ! 1767: ! 1768: error = 0; ! 1769: ! 1770: end: ! 1771: if (privkey != NULL) ! 1772: vfree(privkey); ! 1773: ! 1774: return error; ! 1775: } ! 1776: ! 1777: /* ! 1778: * compare certificate name and ID value. ! 1779: */ ! 1780: static int ! 1781: oakley_check_certid(iph1) ! 1782: struct ph1handle *iph1; ! 1783: { ! 1784: struct ipsecdoi_id_b *id_b; ! 1785: vchar_t *name = NULL; ! 1786: char *altname = NULL; ! 1787: int idlen, type; ! 1788: int error; ! 1789: ! 1790: if (iph1->rmconf == NULL || iph1->rmconf->verify_cert == FALSE) ! 1791: return 0; ! 1792: ! 1793: if (iph1->id_p == NULL || iph1->cert_p == NULL) { ! 1794: plog(LLV_ERROR, LOCATION, iph1->remote, "no ID nor CERT found.\n"); ! 1795: return ISAKMP_NTYPE_INVALID_ID_INFORMATION; ! 1796: } ! 1797: ! 1798: id_b = (struct ipsecdoi_id_b *)iph1->id_p->v; ! 1799: idlen = iph1->id_p->l - sizeof(*id_b); ! 1800: ! 1801: switch (id_b->type) { ! 1802: case IPSECDOI_ID_DER_ASN1_DN: ! 1803: name = eay_get_x509asn1subjectname(iph1->cert_p); ! 1804: if (!name) { ! 1805: plog(LLV_ERROR, LOCATION, iph1->remote, ! 1806: "failed to get subjectName\n"); ! 1807: return ISAKMP_NTYPE_INVALID_CERTIFICATE; ! 1808: } ! 1809: if (idlen != name->l) { ! 1810: plog(LLV_ERROR, LOCATION, iph1->remote, ! 1811: "Invalid ID length in phase 1.\n"); ! 1812: vfree(name); ! 1813: return ISAKMP_NTYPE_INVALID_ID_INFORMATION; ! 1814: } ! 1815: error = memcmp(id_b + 1, name->v, idlen); ! 1816: if (error != 0) { ! 1817: plog(LLV_ERROR, LOCATION, iph1->remote, ! 1818: "ID mismatched with ASN1 SubjectName.\n"); ! 1819: plogdump(LLV_DEBUG, id_b + 1, idlen); ! 1820: plogdump(LLV_DEBUG, name->v, idlen); ! 1821: if (iph1->rmconf->verify_identifier) { ! 1822: vfree(name); ! 1823: return ISAKMP_NTYPE_INVALID_ID_INFORMATION; ! 1824: } ! 1825: } ! 1826: vfree(name); ! 1827: return 0; ! 1828: case IPSECDOI_ID_IPV4_ADDR: ! 1829: case IPSECDOI_ID_IPV6_ADDR: ! 1830: { ! 1831: /* ! 1832: * converting to binary from string because openssl return ! 1833: * a string even if object is a binary. ! 1834: * XXX fix it ! access by ASN.1 directly without. ! 1835: */ ! 1836: struct addrinfo hints, *res; ! 1837: caddr_t a = NULL; ! 1838: int pos; ! 1839: ! 1840: for (pos = 1; ; pos++) { ! 1841: if (eay_get_x509subjectaltname(iph1->cert_p, ! 1842: &altname, &type, pos) !=0) { ! 1843: plog(LLV_ERROR, LOCATION, NULL, ! 1844: "failed to get subjectAltName\n"); ! 1845: return ISAKMP_NTYPE_INVALID_CERTIFICATE; ! 1846: } ! 1847: ! 1848: /* it's the end condition of the loop. */ ! 1849: if (!altname) { ! 1850: plog(LLV_ERROR, LOCATION, NULL, ! 1851: "no proper subjectAltName.\n"); ! 1852: return ISAKMP_NTYPE_INVALID_CERTIFICATE; ! 1853: } ! 1854: ! 1855: if (check_typeofcertname(id_b->type, type) == 0) ! 1856: break; ! 1857: ! 1858: /* next name */ ! 1859: racoon_free(altname); ! 1860: altname = NULL; ! 1861: } ! 1862: memset(&hints, 0, sizeof(hints)); ! 1863: hints.ai_family = PF_UNSPEC; ! 1864: hints.ai_socktype = SOCK_RAW; ! 1865: hints.ai_flags = AI_NUMERICHOST; ! 1866: error = getaddrinfo(altname, NULL, &hints, &res); ! 1867: racoon_free(altname); ! 1868: altname = NULL; ! 1869: if (error != 0) { ! 1870: plog(LLV_ERROR, LOCATION, NULL, ! 1871: "no proper subjectAltName.\n"); ! 1872: return ISAKMP_NTYPE_INVALID_CERTIFICATE; ! 1873: } ! 1874: switch (res->ai_family) { ! 1875: case AF_INET: ! 1876: a = (caddr_t)&((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr; ! 1877: break; ! 1878: #ifdef INET6 ! 1879: case AF_INET6: ! 1880: a = (caddr_t)&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr.s6_addr; ! 1881: break; ! 1882: #endif ! 1883: default: ! 1884: plog(LLV_ERROR, LOCATION, NULL, ! 1885: "family not supported: %d.\n", res->ai_family); ! 1886: freeaddrinfo(res); ! 1887: return ISAKMP_NTYPE_INVALID_CERTIFICATE; ! 1888: } ! 1889: error = memcmp(id_b + 1, a, idlen); ! 1890: freeaddrinfo(res); ! 1891: vfree(name); ! 1892: if (error != 0) { ! 1893: plog(LLV_ERROR, LOCATION, NULL, ! 1894: "ID mismatched with subjectAltName.\n"); ! 1895: plogdump(LLV_DEBUG, id_b + 1, idlen); ! 1896: plogdump(LLV_DEBUG, a, idlen); ! 1897: if (iph1->rmconf->verify_identifier) ! 1898: return ISAKMP_NTYPE_INVALID_ID_INFORMATION; ! 1899: } ! 1900: return 0; ! 1901: } ! 1902: case IPSECDOI_ID_FQDN: ! 1903: case IPSECDOI_ID_USER_FQDN: ! 1904: { ! 1905: int pos; ! 1906: ! 1907: for (pos = 1; ; pos++) { ! 1908: if (eay_get_x509subjectaltname(iph1->cert_p, ! 1909: &altname, &type, pos) != 0){ ! 1910: plog(LLV_ERROR, LOCATION, NULL, ! 1911: "failed to get subjectAltName\n"); ! 1912: return ISAKMP_NTYPE_INVALID_CERTIFICATE; ! 1913: } ! 1914: ! 1915: /* it's the end condition of the loop. */ ! 1916: if (!altname) { ! 1917: plog(LLV_ERROR, LOCATION, NULL, ! 1918: "no proper subjectAltName.\n"); ! 1919: return ISAKMP_NTYPE_INVALID_CERTIFICATE; ! 1920: } ! 1921: ! 1922: if (check_typeofcertname(id_b->type, type) == 0) ! 1923: break; ! 1924: ! 1925: /* next name */ ! 1926: racoon_free(altname); ! 1927: altname = NULL; ! 1928: } ! 1929: if (idlen != strlen(altname)) { ! 1930: plog(LLV_ERROR, LOCATION, NULL, ! 1931: "Invalid ID length in phase 1.\n"); ! 1932: racoon_free(altname); ! 1933: return ISAKMP_NTYPE_INVALID_ID_INFORMATION; ! 1934: } ! 1935: if (check_typeofcertname(id_b->type, type) != 0) { ! 1936: plog(LLV_ERROR, LOCATION, NULL, ! 1937: "ID type mismatched. ID: %s CERT: %s.\n", ! 1938: s_ipsecdoi_ident(id_b->type), ! 1939: s_ipsecdoi_ident(type)); ! 1940: racoon_free(altname); ! 1941: return ISAKMP_NTYPE_INVALID_ID_INFORMATION; ! 1942: } ! 1943: error = memcmp(id_b + 1, altname, idlen); ! 1944: if (error) { ! 1945: plog(LLV_ERROR, LOCATION, NULL, "ID mismatched.\n"); ! 1946: plogdump(LLV_DEBUG, id_b + 1, idlen); ! 1947: plogdump(LLV_DEBUG, altname, idlen); ! 1948: racoon_free(altname); ! 1949: return ISAKMP_NTYPE_INVALID_ID_INFORMATION; ! 1950: } ! 1951: racoon_free(altname); ! 1952: return 0; ! 1953: } ! 1954: default: ! 1955: plog(LLV_ERROR, LOCATION, NULL, ! 1956: "Inpropper ID type passed: %s.\n", ! 1957: s_ipsecdoi_ident(id_b->type)); ! 1958: return ISAKMP_NTYPE_INVALID_ID_INFORMATION; ! 1959: } ! 1960: /*NOTREACHED*/ ! 1961: } ! 1962: ! 1963: static int ! 1964: check_typeofcertname(doi, genid) ! 1965: int doi, genid; ! 1966: { ! 1967: switch (doi) { ! 1968: case IPSECDOI_ID_IPV4_ADDR: ! 1969: case IPSECDOI_ID_IPV4_ADDR_SUBNET: ! 1970: case IPSECDOI_ID_IPV6_ADDR: ! 1971: case IPSECDOI_ID_IPV6_ADDR_SUBNET: ! 1972: case IPSECDOI_ID_IPV4_ADDR_RANGE: ! 1973: case IPSECDOI_ID_IPV6_ADDR_RANGE: ! 1974: if (genid != GENT_IPADD) ! 1975: return -1; ! 1976: return 0; ! 1977: case IPSECDOI_ID_FQDN: ! 1978: if (genid != GENT_DNS) ! 1979: return -1; ! 1980: return 0; ! 1981: case IPSECDOI_ID_USER_FQDN: ! 1982: if (genid != GENT_EMAIL) ! 1983: return -1; ! 1984: return 0; ! 1985: case IPSECDOI_ID_DER_ASN1_DN: /* should not be passed to this function*/ ! 1986: case IPSECDOI_ID_DER_ASN1_GN: ! 1987: case IPSECDOI_ID_KEY_ID: ! 1988: default: ! 1989: return -1; ! 1990: } ! 1991: /*NOTREACHED*/ ! 1992: } ! 1993: ! 1994: /* ! 1995: * save certificate including certificate type. ! 1996: */ ! 1997: int ! 1998: oakley_savecert(iph1, gen) ! 1999: struct ph1handle *iph1; ! 2000: struct isakmp_gen *gen; ! 2001: { ! 2002: vchar_t **c; ! 2003: u_int8_t type; ! 2004: STACK_OF(X509) *certs=NULL; ! 2005: PKCS7 *p7; ! 2006: ! 2007: type = *(u_int8_t *)(gen + 1) & 0xff; ! 2008: ! 2009: switch (type) { ! 2010: case ISAKMP_CERT_DNS: ! 2011: plog(LLV_WARNING, LOCATION, NULL, ! 2012: "CERT payload is unnecessary in DNSSEC. " ! 2013: "ignore this CERT payload.\n"); ! 2014: return 0; ! 2015: case ISAKMP_CERT_PKCS7: ! 2016: case ISAKMP_CERT_PGP: ! 2017: case ISAKMP_CERT_X509SIGN: ! 2018: case ISAKMP_CERT_KERBEROS: ! 2019: case ISAKMP_CERT_SPKI: ! 2020: c = &iph1->cert_p; ! 2021: break; ! 2022: case ISAKMP_CERT_CRL: ! 2023: c = &iph1->crl_p; ! 2024: break; ! 2025: case ISAKMP_CERT_X509KE: ! 2026: case ISAKMP_CERT_X509ATTR: ! 2027: case ISAKMP_CERT_ARL: ! 2028: plog(LLV_ERROR, LOCATION, NULL, ! 2029: "No supported such CERT type %d\n", type); ! 2030: return -1; ! 2031: default: ! 2032: plog(LLV_ERROR, LOCATION, NULL, ! 2033: "Invalid CERT type %d\n", type); ! 2034: return -1; ! 2035: } ! 2036: ! 2037: /* XXX choice the 1th cert, ignore after the cert. */ ! 2038: /* XXX should be processed. */ ! 2039: if (*c) { ! 2040: plog(LLV_WARNING, LOCATION, NULL, ! 2041: "ignore 2nd CERT payload.\n"); ! 2042: return 0; ! 2043: } ! 2044: ! 2045: if (type == ISAKMP_CERT_PKCS7) { ! 2046: u_char *bp; ! 2047: int i; ! 2048: ! 2049: /* Skip the header */ ! 2050: bp = (u_char *)(gen + 1); ! 2051: /* And the first byte is the certificate type, ! 2052: * we know that already ! 2053: */ ! 2054: bp++; ! 2055: p7 = d2i_PKCS7(NULL, (void *)&bp, ! 2056: ntohs(gen->len) - sizeof(*gen) - 1); ! 2057: ! 2058: if (!p7) { ! 2059: plog(LLV_ERROR, LOCATION, NULL, ! 2060: "Failed to parse PKCS#7 CERT.\n"); ! 2061: return -1; ! 2062: } ! 2063: ! 2064: /* Copied this from the openssl pkcs7 application; ! 2065: * there"s little by way of documentation for any of ! 2066: * it. I can only presume it"s correct. ! 2067: */ ! 2068: ! 2069: i = OBJ_obj2nid(p7->type); ! 2070: switch (i) { ! 2071: case NID_pkcs7_signed: ! 2072: certs=p7->d.sign->cert; ! 2073: break; ! 2074: case NID_pkcs7_signedAndEnveloped: ! 2075: certs=p7->d.signed_and_enveloped->cert; ! 2076: break; ! 2077: default: ! 2078: break; ! 2079: } ! 2080: ! 2081: if (!certs) { ! 2082: plog(LLV_ERROR, LOCATION, NULL, ! 2083: "CERT PKCS#7 bundle contains no certs.\n"); ! 2084: PKCS7_free(p7); ! 2085: return -1; ! 2086: } ! 2087: ! 2088: for (i = 0; i < sk_X509_num(certs); i++) { ! 2089: int len; ! 2090: u_char *bp; ! 2091: X509 *cert = sk_X509_value(certs,i); ! 2092: ! 2093: plog(LLV_DEBUG, LOCATION, NULL, ! 2094: "Trying PKCS#7 cert %d.\n", i); ! 2095: ! 2096: /* We'll just try each cert in turn */ ! 2097: *c = dump_x509(cert); ! 2098: ! 2099: if (!*c) { ! 2100: plog(LLV_ERROR, LOCATION, NULL, ! 2101: "Failed to get CERT buffer.\n"); ! 2102: continue; ! 2103: } ! 2104: ! 2105: /* Ignore cert if it doesn't match identity ! 2106: * XXX If verify cert is disabled, we still just take ! 2107: * the first certificate.... ! 2108: */ ! 2109: if (oakley_check_certid(iph1)) { ! 2110: plog(LLV_DEBUG, LOCATION, NULL, ! 2111: "Discarding CERT: does not match ID.\n"); ! 2112: vfree((*c)); ! 2113: *c = NULL; ! 2114: continue; ! 2115: } ! 2116: ! 2117: { ! 2118: char *p = eay_get_x509text(*c); ! 2119: plog(LLV_DEBUG, LOCATION, NULL, "CERT saved:\n"); ! 2120: plogdump(LLV_DEBUG, (*c)->v, (*c)->l); ! 2121: plog(LLV_DEBUG, LOCATION, NULL, "%s", ! 2122: p ? p : "\n"); ! 2123: racoon_free(p); ! 2124: } ! 2125: break; ! 2126: } ! 2127: PKCS7_free(p7); ! 2128: } else { ! 2129: *c = dump_isakmp_payload(gen); ! 2130: if (!*c) { ! 2131: plog(LLV_ERROR, LOCATION, NULL, ! 2132: "Failed to get CERT buffer.\n"); ! 2133: return -1; ! 2134: } ! 2135: ! 2136: switch (type) { ! 2137: case ISAKMP_CERT_PGP: ! 2138: case ISAKMP_CERT_X509SIGN: ! 2139: case ISAKMP_CERT_KERBEROS: ! 2140: case ISAKMP_CERT_SPKI: ! 2141: /* Ignore cert if it doesn't match identity ! 2142: * XXX If verify cert is disabled, we still just take ! 2143: * the first certificate.... ! 2144: */ ! 2145: if (oakley_check_certid(iph1)){ ! 2146: plog(LLV_DEBUG, LOCATION, NULL, ! 2147: "Discarding CERT: does not match ID.\n"); ! 2148: vfree((*c)); ! 2149: *c = NULL; ! 2150: return 0; ! 2151: } ! 2152: ! 2153: { ! 2154: char *p = eay_get_x509text(*c); ! 2155: plog(LLV_DEBUG, LOCATION, NULL, "CERT saved:\n"); ! 2156: plogdump(LLV_DEBUG, (*c)->v, (*c)->l); ! 2157: plog(LLV_DEBUG, LOCATION, NULL, "%s", p ? p : "\n"); ! 2158: racoon_free(p); ! 2159: } ! 2160: break; ! 2161: case ISAKMP_CERT_CRL: ! 2162: plog(LLV_DEBUG, LOCATION, NULL, "CRL saved:\n"); ! 2163: plogdump(LLV_DEBUG, (*c)->v, (*c)->l); ! 2164: break; ! 2165: case ISAKMP_CERT_X509KE: ! 2166: case ISAKMP_CERT_X509ATTR: ! 2167: case ISAKMP_CERT_ARL: ! 2168: default: ! 2169: /* XXX */ ! 2170: vfree(*c); ! 2171: *c = NULL; ! 2172: return 0; ! 2173: } ! 2174: } ! 2175: ! 2176: return 0; ! 2177: } ! 2178: ! 2179: /* ! 2180: * save certificate including certificate type. ! 2181: */ ! 2182: int ! 2183: oakley_savecr(iph1, gen) ! 2184: struct ph1handle *iph1; ! 2185: struct isakmp_gen *gen; ! 2186: { ! 2187: vchar_t *cert; ! 2188: vchar_t **c; ! 2189: u_int8_t type; ! 2190: ! 2191: type = *(u_int8_t *)(gen + 1) & 0xff; ! 2192: switch (type) { ! 2193: case ISAKMP_CERT_DNS: ! 2194: plog(LLV_WARNING, LOCATION, NULL, ! 2195: "CERT payload is unnecessary in DNSSEC\n"); ! 2196: /*FALLTHRU*/ ! 2197: case ISAKMP_CERT_PKCS7: ! 2198: case ISAKMP_CERT_PGP: ! 2199: case ISAKMP_CERT_X509SIGN: ! 2200: case ISAKMP_CERT_KERBEROS: ! 2201: case ISAKMP_CERT_SPKI: ! 2202: c = &iph1->cr_p; ! 2203: break; ! 2204: case ISAKMP_CERT_X509KE: ! 2205: case ISAKMP_CERT_X509ATTR: ! 2206: case ISAKMP_CERT_ARL: ! 2207: plog(LLV_ERROR, LOCATION, NULL, ! 2208: "No supported such CR type %d\n", type); ! 2209: return -1; ! 2210: case ISAKMP_CERT_CRL: ! 2211: default: ! 2212: plog(LLV_ERROR, LOCATION, NULL, ! 2213: "Invalid CR type %d\n", type); ! 2214: return -1; ! 2215: } ! 2216: ! 2217: /* Already found an acceptable CR? */ ! 2218: if (*c != NULL) ! 2219: return 0; ! 2220: ! 2221: cert = dump_isakmp_payload(gen); ! 2222: if (cert == NULL) { ! 2223: plog(LLV_ERROR, LOCATION, NULL, ! 2224: "Failed to get CR buffer.\n"); ! 2225: return -1; ! 2226: } ! 2227: ! 2228: plog(LLV_DEBUG, LOCATION, NULL, "CR received:\n"); ! 2229: plogdump(LLV_DEBUG, cert->v, cert->l); ! 2230: ! 2231: *c = cert; ! 2232: if (resolveph1rmconf(iph1) == 0) { ! 2233: /* Found unique match */ ! 2234: plog(LLV_DEBUG, LOCATION, NULL, "CR saved.\n"); ! 2235: } else { ! 2236: /* Still ambiguous or matches nothing, ignore this CR */ ! 2237: *c = NULL; ! 2238: vfree(cert); ! 2239: } ! 2240: return 0; ! 2241: } ! 2242: ! 2243: /* ! 2244: * Add a single CR. ! 2245: */ ! 2246: struct append_cr_ctx { ! 2247: struct ph1handle *iph1; ! 2248: struct payload_list *plist; ! 2249: }; ! 2250: ! 2251: static int ! 2252: oakley_append_rmconf_cr(rmconf, ctx) ! 2253: struct remoteconf *rmconf; ! 2254: void *ctx; ! 2255: { ! 2256: struct append_cr_ctx *actx = (struct append_cr_ctx *) ctx; ! 2257: vchar_t *buf, *asn1dn = NULL; ! 2258: int type; ! 2259: ! 2260: /* Do we want to send CR about this? */ ! 2261: if (rmconf->send_cr == FALSE) ! 2262: return 0; ! 2263: ! 2264: if (rmconf->peerscert != NULL) { ! 2265: type = oakley_get_certtype(rmconf->peerscert); ! 2266: asn1dn = eay_get_x509asn1issuername(rmconf->peerscert); ! 2267: } else if (rmconf->cacert != NULL) { ! 2268: type = oakley_get_certtype(rmconf->cacert); ! 2269: asn1dn = eay_get_x509asn1subjectname(rmconf->cacert); ! 2270: } else ! 2271: return 0; ! 2272: ! 2273: if (asn1dn == NULL) { ! 2274: plog(LLV_ERROR, LOCATION, actx->iph1->remote, ! 2275: "Failed to get CR ASN1 DN from certificate\n"); ! 2276: return 0; ! 2277: } ! 2278: ! 2279: buf = vmalloc(1 + asn1dn->l); ! 2280: if (buf == NULL) ! 2281: goto err; ! 2282: ! 2283: buf->v[0] = type; ! 2284: memcpy(&buf->v[1], asn1dn->v, asn1dn->l); ! 2285: ! 2286: plog(LLV_DEBUG, LOCATION, actx->iph1->remote, ! 2287: "appending CR: %s\n", ! 2288: s_isakmp_certtype(buf->v[0])); ! 2289: plogdump(LLV_DEBUG, buf->v, buf->l); ! 2290: ! 2291: actx->plist = isakmp_plist_append_full(actx->plist, buf, ISAKMP_NPTYPE_CR, 1); ! 2292: ! 2293: err: ! 2294: vfree(asn1dn); ! 2295: return 0; ! 2296: } ! 2297: ! 2298: /* ! 2299: * Append list of acceptable CRs. ! 2300: * RFC2048 3.10 ! 2301: */ ! 2302: struct payload_list * ! 2303: oakley_append_cr(plist, iph1) ! 2304: struct payload_list *plist; ! 2305: struct ph1handle *iph1; ! 2306: { ! 2307: struct append_cr_ctx ctx; ! 2308: struct rmconfselector sel; ! 2309: ! 2310: ctx.iph1 = iph1; ! 2311: ctx.plist = plist; ! 2312: if (iph1->rmconf == NULL) { ! 2313: rmconf_selector_from_ph1(&sel, iph1); ! 2314: enumrmconf(&sel, oakley_append_rmconf_cr, &ctx); ! 2315: } else { ! 2316: oakley_append_rmconf_cr(iph1->rmconf, &ctx); ! 2317: } ! 2318: ! 2319: return ctx.plist; ! 2320: } ! 2321: ! 2322: /* ! 2323: * check peer's CR. ! 2324: */ ! 2325: int ! 2326: oakley_checkcr(iph1) ! 2327: struct ph1handle *iph1; ! 2328: { ! 2329: int type; ! 2330: ! 2331: if (iph1->cr_p == NULL) ! 2332: return 0; ! 2333: ! 2334: plog(LLV_DEBUG, LOCATION, iph1->remote, ! 2335: "peer transmitted CR: %s\n", ! 2336: s_isakmp_certtype(oakley_get_certtype(iph1->cr_p))); ! 2337: ! 2338: type = oakley_get_certtype(iph1->cr_p); ! 2339: if (type != oakley_get_certtype(iph1->rmconf->mycert)) { ! 2340: plog(LLV_ERROR, LOCATION, iph1->remote, ! 2341: "such a cert type isn't supported: %d\n", ! 2342: type); ! 2343: return -1; ! 2344: } ! 2345: ! 2346: return 0; ! 2347: } ! 2348: ! 2349: /* ! 2350: * check to need CR payload. ! 2351: */ ! 2352: int ! 2353: oakley_needcr(type) ! 2354: int type; ! 2355: { ! 2356: switch (type) { ! 2357: case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: ! 2358: case OAKLEY_ATTR_AUTH_METHOD_RSASIG: ! 2359: #ifdef ENABLE_HYBRID ! 2360: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: ! 2361: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: ! 2362: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I: ! 2363: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: ! 2364: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I: ! 2365: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: ! 2366: #endif ! 2367: return 1; ! 2368: default: ! 2369: return 0; ! 2370: } ! 2371: /*NOTREACHED*/ ! 2372: } ! 2373: ! 2374: /* ! 2375: * compute SKEYID ! 2376: * see seciton 5. Exchanges in RFC 2409 ! 2377: * psk: SKEYID = prf(pre-shared-key, Ni_b | Nr_b) ! 2378: * sig: SKEYID = prf(Ni_b | Nr_b, g^ir) ! 2379: * enc: SKEYID = prf(H(Ni_b | Nr_b), CKY-I | CKY-R) ! 2380: */ ! 2381: int ! 2382: oakley_skeyid(iph1) ! 2383: struct ph1handle *iph1; ! 2384: { ! 2385: vchar_t *buf = NULL, *bp; ! 2386: char *p; ! 2387: int len; ! 2388: int error = -1; ! 2389: ! 2390: /* SKEYID */ ! 2391: switch (iph1->approval->authmethod) { ! 2392: case OAKLEY_ATTR_AUTH_METHOD_PSKEY: ! 2393: #ifdef ENABLE_HYBRID ! 2394: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I: ! 2395: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R: ! 2396: #endif ! 2397: if (iph1->etype != ISAKMP_ETYPE_IDENT) { ! 2398: iph1->authstr = getpskbyname(iph1->id_p); ! 2399: if (iph1->authstr == NULL) { ! 2400: if (iph1->rmconf->verify_identifier) { ! 2401: plog(LLV_ERROR, LOCATION, iph1->remote, ! 2402: "couldn't find the pskey.\n"); ! 2403: goto end; ! 2404: } ! 2405: plog(LLV_NOTIFY, LOCATION, iph1->remote, ! 2406: "couldn't find the proper pskey, " ! 2407: "try to get one by the peer's address.\n"); ! 2408: } ! 2409: } ! 2410: if (iph1->authstr == NULL) { ! 2411: /* ! 2412: * If the exchange type is the main mode or if it's ! 2413: * failed to get the psk by ID, racoon try to get ! 2414: * the psk by remote IP address. ! 2415: * It may be nonsense. ! 2416: */ ! 2417: iph1->authstr = getpskbyaddr(iph1->remote); ! 2418: if (iph1->authstr == NULL) { ! 2419: plog(LLV_ERROR, LOCATION, iph1->remote, ! 2420: "couldn't find the pskey for %s.\n", ! 2421: saddrwop2str(iph1->remote)); ! 2422: goto end; ! 2423: } ! 2424: } ! 2425: plog(LLV_DEBUG, LOCATION, NULL, "the psk found.\n"); ! 2426: /* should be secret PSK */ ! 2427: plog(LLV_DEBUG2, LOCATION, NULL, "psk: "); ! 2428: plogdump(LLV_DEBUG2, iph1->authstr->v, iph1->authstr->l); ! 2429: ! 2430: len = iph1->nonce->l + iph1->nonce_p->l; ! 2431: buf = vmalloc(len); ! 2432: if (buf == NULL) { ! 2433: plog(LLV_ERROR, LOCATION, NULL, ! 2434: "failed to get skeyid buffer\n"); ! 2435: goto end; ! 2436: } ! 2437: p = buf->v; ! 2438: ! 2439: bp = (iph1->side == INITIATOR ? iph1->nonce : iph1->nonce_p); ! 2440: plog(LLV_DEBUG, LOCATION, NULL, "nonce 1: "); ! 2441: plogdump(LLV_DEBUG, bp->v, bp->l); ! 2442: memcpy(p, bp->v, bp->l); ! 2443: p += bp->l; ! 2444: ! 2445: bp = (iph1->side == INITIATOR ? iph1->nonce_p : iph1->nonce); ! 2446: plog(LLV_DEBUG, LOCATION, NULL, "nonce 2: "); ! 2447: plogdump(LLV_DEBUG, bp->v, bp->l); ! 2448: memcpy(p, bp->v, bp->l); ! 2449: p += bp->l; ! 2450: ! 2451: iph1->skeyid = oakley_prf(iph1->authstr, buf, iph1); ! 2452: if (iph1->skeyid == NULL) ! 2453: goto end; ! 2454: break; ! 2455: ! 2456: case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: ! 2457: case OAKLEY_ATTR_AUTH_METHOD_RSASIG: ! 2458: #ifdef ENABLE_HYBRID ! 2459: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: ! 2460: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: ! 2461: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R: ! 2462: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R: ! 2463: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I: ! 2464: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: ! 2465: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I: ! 2466: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: ! 2467: #endif ! 2468: #ifdef HAVE_GSSAPI ! 2469: case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB: ! 2470: #endif ! 2471: len = iph1->nonce->l + iph1->nonce_p->l; ! 2472: buf = vmalloc(len); ! 2473: if (buf == NULL) { ! 2474: plog(LLV_ERROR, LOCATION, NULL, ! 2475: "failed to get nonce buffer\n"); ! 2476: goto end; ! 2477: } ! 2478: p = buf->v; ! 2479: ! 2480: bp = (iph1->side == INITIATOR ? iph1->nonce : iph1->nonce_p); ! 2481: plog(LLV_DEBUG, LOCATION, NULL, "nonce1: "); ! 2482: plogdump(LLV_DEBUG, bp->v, bp->l); ! 2483: memcpy(p, bp->v, bp->l); ! 2484: p += bp->l; ! 2485: ! 2486: bp = (iph1->side == INITIATOR ? iph1->nonce_p : iph1->nonce); ! 2487: plog(LLV_DEBUG, LOCATION, NULL, "nonce2: "); ! 2488: plogdump(LLV_DEBUG, bp->v, bp->l); ! 2489: memcpy(p, bp->v, bp->l); ! 2490: p += bp->l; ! 2491: ! 2492: iph1->skeyid = oakley_prf(buf, iph1->dhgxy, iph1); ! 2493: if (iph1->skeyid == NULL) ! 2494: goto end; ! 2495: break; ! 2496: case OAKLEY_ATTR_AUTH_METHOD_RSAENC: ! 2497: case OAKLEY_ATTR_AUTH_METHOD_RSAREV: ! 2498: #ifdef ENABLE_HYBRID ! 2499: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I: ! 2500: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R: ! 2501: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I: ! 2502: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R: ! 2503: #endif ! 2504: plog(LLV_WARNING, LOCATION, NULL, ! 2505: "not supported authentication method %s\n", ! 2506: s_oakley_attr_method(iph1->approval->authmethod)); ! 2507: goto end; ! 2508: default: ! 2509: plog(LLV_ERROR, LOCATION, NULL, ! 2510: "invalid authentication method %d\n", ! 2511: iph1->approval->authmethod); ! 2512: goto end; ! 2513: } ! 2514: ! 2515: plog(LLV_DEBUG, LOCATION, NULL, "SKEYID computed:\n"); ! 2516: plogdump(LLV_DEBUG, iph1->skeyid->v, iph1->skeyid->l); ! 2517: ! 2518: error = 0; ! 2519: ! 2520: end: ! 2521: if (buf != NULL) ! 2522: vfree(buf); ! 2523: return error; ! 2524: } ! 2525: ! 2526: /* ! 2527: * compute SKEYID_[dae] ! 2528: * see seciton 5. Exchanges in RFC 2409 ! 2529: * SKEYID_d = prf(SKEYID, g^ir | CKY-I | CKY-R | 0) ! 2530: * SKEYID_a = prf(SKEYID, SKEYID_d | g^ir | CKY-I | CKY-R | 1) ! 2531: * SKEYID_e = prf(SKEYID, SKEYID_a | g^ir | CKY-I | CKY-R | 2) ! 2532: */ ! 2533: int ! 2534: oakley_skeyid_dae(iph1) ! 2535: struct ph1handle *iph1; ! 2536: { ! 2537: vchar_t *buf = NULL; ! 2538: char *p; ! 2539: int len; ! 2540: int error = -1; ! 2541: ! 2542: if (iph1->skeyid == NULL) { ! 2543: plog(LLV_ERROR, LOCATION, NULL, "no SKEYID found.\n"); ! 2544: goto end; ! 2545: } ! 2546: ! 2547: /* SKEYID D */ ! 2548: /* SKEYID_d = prf(SKEYID, g^xy | CKY-I | CKY-R | 0) */ ! 2549: len = iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1; ! 2550: buf = vmalloc(len); ! 2551: if (buf == NULL) { ! 2552: plog(LLV_ERROR, LOCATION, NULL, ! 2553: "failed to get skeyid buffer\n"); ! 2554: goto end; ! 2555: } ! 2556: p = buf->v; ! 2557: ! 2558: memcpy(p, iph1->dhgxy->v, iph1->dhgxy->l); ! 2559: p += iph1->dhgxy->l; ! 2560: memcpy(p, (caddr_t)&iph1->index.i_ck, sizeof(cookie_t)); ! 2561: p += sizeof(cookie_t); ! 2562: memcpy(p, (caddr_t)&iph1->index.r_ck, sizeof(cookie_t)); ! 2563: p += sizeof(cookie_t); ! 2564: *p = 0; ! 2565: iph1->skeyid_d = oakley_prf(iph1->skeyid, buf, iph1); ! 2566: if (iph1->skeyid_d == NULL) ! 2567: goto end; ! 2568: ! 2569: vfree(buf); ! 2570: buf = NULL; ! 2571: ! 2572: plog(LLV_DEBUG, LOCATION, NULL, "SKEYID_d computed:\n"); ! 2573: plogdump(LLV_DEBUG, iph1->skeyid_d->v, iph1->skeyid_d->l); ! 2574: ! 2575: /* SKEYID A */ ! 2576: /* SKEYID_a = prf(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1) */ ! 2577: len = iph1->skeyid_d->l + iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1; ! 2578: buf = vmalloc(len); ! 2579: if (buf == NULL) { ! 2580: plog(LLV_ERROR, LOCATION, NULL, ! 2581: "failed to get skeyid buffer\n"); ! 2582: goto end; ! 2583: } ! 2584: p = buf->v; ! 2585: memcpy(p, iph1->skeyid_d->v, iph1->skeyid_d->l); ! 2586: p += iph1->skeyid_d->l; ! 2587: memcpy(p, iph1->dhgxy->v, iph1->dhgxy->l); ! 2588: p += iph1->dhgxy->l; ! 2589: memcpy(p, (caddr_t)&iph1->index.i_ck, sizeof(cookie_t)); ! 2590: p += sizeof(cookie_t); ! 2591: memcpy(p, (caddr_t)&iph1->index.r_ck, sizeof(cookie_t)); ! 2592: p += sizeof(cookie_t); ! 2593: *p = 1; ! 2594: iph1->skeyid_a = oakley_prf(iph1->skeyid, buf, iph1); ! 2595: if (iph1->skeyid_a == NULL) ! 2596: goto end; ! 2597: ! 2598: vfree(buf); ! 2599: buf = NULL; ! 2600: ! 2601: plog(LLV_DEBUG, LOCATION, NULL, "SKEYID_a computed:\n"); ! 2602: plogdump(LLV_DEBUG, iph1->skeyid_a->v, iph1->skeyid_a->l); ! 2603: ! 2604: /* SKEYID E */ ! 2605: /* SKEYID_e = prf(SKEYID, SKEYID_a | g^xy | CKY-I | CKY-R | 2) */ ! 2606: len = iph1->skeyid_a->l + iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1; ! 2607: buf = vmalloc(len); ! 2608: if (buf == NULL) { ! 2609: plog(LLV_ERROR, LOCATION, NULL, ! 2610: "failed to get skeyid buffer\n"); ! 2611: goto end; ! 2612: } ! 2613: p = buf->v; ! 2614: memcpy(p, iph1->skeyid_a->v, iph1->skeyid_a->l); ! 2615: p += iph1->skeyid_a->l; ! 2616: memcpy(p, iph1->dhgxy->v, iph1->dhgxy->l); ! 2617: p += iph1->dhgxy->l; ! 2618: memcpy(p, (caddr_t)&iph1->index.i_ck, sizeof(cookie_t)); ! 2619: p += sizeof(cookie_t); ! 2620: memcpy(p, (caddr_t)&iph1->index.r_ck, sizeof(cookie_t)); ! 2621: p += sizeof(cookie_t); ! 2622: *p = 2; ! 2623: iph1->skeyid_e = oakley_prf(iph1->skeyid, buf, iph1); ! 2624: if (iph1->skeyid_e == NULL) ! 2625: goto end; ! 2626: ! 2627: vfree(buf); ! 2628: buf = NULL; ! 2629: ! 2630: plog(LLV_DEBUG, LOCATION, NULL, "SKEYID_e computed:\n"); ! 2631: plogdump(LLV_DEBUG, iph1->skeyid_e->v, iph1->skeyid_e->l); ! 2632: ! 2633: error = 0; ! 2634: ! 2635: end: ! 2636: if (buf != NULL) ! 2637: vfree(buf); ! 2638: return error; ! 2639: } ! 2640: ! 2641: /* ! 2642: * compute final encryption key. ! 2643: * see Appendix B. ! 2644: */ ! 2645: int ! 2646: oakley_compute_enckey(iph1) ! 2647: struct ph1handle *iph1; ! 2648: { ! 2649: u_int keylen, prflen; ! 2650: int error = -1; ! 2651: ! 2652: /* RFC2409 p39 */ ! 2653: keylen = alg_oakley_encdef_keylen(iph1->approval->enctype, ! 2654: iph1->approval->encklen); ! 2655: if (keylen == -1) { ! 2656: plog(LLV_ERROR, LOCATION, NULL, ! 2657: "invalid encryption algorithm %d, " ! 2658: "or invalid key length %d.\n", ! 2659: iph1->approval->enctype, ! 2660: iph1->approval->encklen); ! 2661: goto end; ! 2662: } ! 2663: iph1->key = vmalloc(keylen >> 3); ! 2664: if (iph1->key == NULL) { ! 2665: plog(LLV_ERROR, LOCATION, NULL, ! 2666: "failed to get key buffer\n"); ! 2667: goto end; ! 2668: } ! 2669: ! 2670: /* set prf length */ ! 2671: prflen = alg_oakley_hashdef_hashlen(iph1->approval->hashtype); ! 2672: if (prflen == -1) { ! 2673: plog(LLV_ERROR, LOCATION, NULL, ! 2674: "invalid hash type %d.\n", iph1->approval->hashtype); ! 2675: goto end; ! 2676: } ! 2677: ! 2678: /* see isakmp-oakley-08 5.3. */ ! 2679: if (iph1->key->l <= iph1->skeyid_e->l) { ! 2680: /* ! 2681: * if length(Ka) <= length(SKEYID_e) ! 2682: * Ka = first length(K) bit of SKEYID_e ! 2683: */ ! 2684: memcpy(iph1->key->v, iph1->skeyid_e->v, iph1->key->l); ! 2685: } else { ! 2686: vchar_t *buf = NULL, *res = NULL; ! 2687: u_char *p, *ep; ! 2688: int cplen; ! 2689: int subkey; ! 2690: ! 2691: /* ! 2692: * otherwise, ! 2693: * Ka = K1 | K2 | K3 ! 2694: * where ! 2695: * K1 = prf(SKEYID_e, 0) ! 2696: * K2 = prf(SKEYID_e, K1) ! 2697: * K3 = prf(SKEYID_e, K2) ! 2698: */ ! 2699: plog(LLV_DEBUG, LOCATION, NULL, ! 2700: "len(SKEYID_e) < len(Ka) (%zu < %zu), " ! 2701: "generating long key (Ka = K1 | K2 | ...)\n", ! 2702: iph1->skeyid_e->l, iph1->key->l); ! 2703: ! 2704: if ((buf = vmalloc(prflen >> 3)) == 0) { ! 2705: plog(LLV_ERROR, LOCATION, NULL, ! 2706: "failed to get key buffer\n"); ! 2707: goto end; ! 2708: } ! 2709: p = (u_char *)iph1->key->v; ! 2710: ep = p + iph1->key->l; ! 2711: ! 2712: subkey = 1; ! 2713: while (p < ep) { ! 2714: if (p == (u_char *)iph1->key->v) { ! 2715: /* just for computing K1 */ ! 2716: buf->v[0] = 0; ! 2717: buf->l = 1; ! 2718: } ! 2719: res = oakley_prf(iph1->skeyid_e, buf, iph1); ! 2720: if (res == NULL) { ! 2721: vfree(buf); ! 2722: goto end; ! 2723: } ! 2724: plog(LLV_DEBUG, LOCATION, NULL, ! 2725: "compute intermediate encryption key K%d\n", ! 2726: subkey); ! 2727: plogdump(LLV_DEBUG, buf->v, buf->l); ! 2728: plogdump(LLV_DEBUG, res->v, res->l); ! 2729: ! 2730: cplen = (res->l < ep - p) ? res->l : ep - p; ! 2731: memcpy(p, res->v, cplen); ! 2732: p += cplen; ! 2733: ! 2734: buf->l = prflen >> 3; /* to cancel K1 speciality */ ! 2735: if (res->l != buf->l) { ! 2736: plog(LLV_ERROR, LOCATION, NULL, ! 2737: "internal error: res->l=%zu buf->l=%zu\n", ! 2738: res->l, buf->l); ! 2739: vfree(res); ! 2740: vfree(buf); ! 2741: goto end; ! 2742: } ! 2743: memcpy(buf->v, res->v, res->l); ! 2744: vfree(res); ! 2745: subkey++; ! 2746: } ! 2747: ! 2748: vfree(buf); ! 2749: } ! 2750: ! 2751: /* ! 2752: * don't check any weak key or not. ! 2753: * draft-ietf-ipsec-ike-01.txt Appendix B. ! 2754: * draft-ietf-ipsec-ciph-aes-cbc-00.txt Section 2.3. ! 2755: */ ! 2756: #if 0 ! 2757: /* weakkey check */ ! 2758: if (iph1->approval->enctype > ARRAYLEN(oakley_encdef) ! 2759: || oakley_encdef[iph1->approval->enctype].weakkey == NULL) { ! 2760: plog(LLV_ERROR, LOCATION, NULL, ! 2761: "encryption algorithm %d isn't supported.\n", ! 2762: iph1->approval->enctype); ! 2763: goto end; ! 2764: } ! 2765: if ((oakley_encdef[iph1->approval->enctype].weakkey)(iph1->key)) { ! 2766: plog(LLV_ERROR, LOCATION, NULL, ! 2767: "weakkey was generated.\n"); ! 2768: goto end; ! 2769: } ! 2770: #endif ! 2771: ! 2772: plog(LLV_DEBUG, LOCATION, NULL, "final encryption key computed:\n"); ! 2773: plogdump(LLV_DEBUG, iph1->key->v, iph1->key->l); ! 2774: ! 2775: error = 0; ! 2776: ! 2777: end: ! 2778: return error; ! 2779: } ! 2780: ! 2781: /* ! 2782: * compute IV and set to ph1handle ! 2783: * IV = hash(g^xi | g^xr) ! 2784: * see 4.1 Phase 1 state in draft-ietf-ipsec-ike. ! 2785: */ ! 2786: int ! 2787: oakley_newiv(iph1) ! 2788: struct ph1handle *iph1; ! 2789: { ! 2790: struct isakmp_ivm *newivm = NULL; ! 2791: vchar_t *buf = NULL, *bp; ! 2792: char *p; ! 2793: int len; ! 2794: ! 2795: /* create buffer */ ! 2796: len = iph1->dhpub->l + iph1->dhpub_p->l; ! 2797: buf = vmalloc(len); ! 2798: if (buf == NULL) { ! 2799: plog(LLV_ERROR, LOCATION, NULL, ! 2800: "failed to get iv buffer\n"); ! 2801: return -1; ! 2802: } ! 2803: ! 2804: p = buf->v; ! 2805: ! 2806: bp = (iph1->side == INITIATOR ? iph1->dhpub : iph1->dhpub_p); ! 2807: memcpy(p, bp->v, bp->l); ! 2808: p += bp->l; ! 2809: ! 2810: bp = (iph1->side == INITIATOR ? iph1->dhpub_p : iph1->dhpub); ! 2811: memcpy(p, bp->v, bp->l); ! 2812: p += bp->l; ! 2813: ! 2814: /* allocate IVm */ ! 2815: newivm = racoon_calloc(1, sizeof(struct isakmp_ivm)); ! 2816: if (newivm == NULL) { ! 2817: plog(LLV_ERROR, LOCATION, NULL, ! 2818: "failed to get iv buffer\n"); ! 2819: vfree(buf); ! 2820: return -1; ! 2821: } ! 2822: ! 2823: /* compute IV */ ! 2824: newivm->iv = oakley_hash(buf, iph1); ! 2825: if (newivm->iv == NULL) { ! 2826: vfree(buf); ! 2827: oakley_delivm(newivm); ! 2828: return -1; ! 2829: } ! 2830: ! 2831: /* adjust length of iv */ ! 2832: newivm->iv->l = alg_oakley_encdef_blocklen(iph1->approval->enctype); ! 2833: if (newivm->iv->l == -1) { ! 2834: plog(LLV_ERROR, LOCATION, NULL, ! 2835: "invalid encryption algorithm %d.\n", ! 2836: iph1->approval->enctype); ! 2837: vfree(buf); ! 2838: oakley_delivm(newivm); ! 2839: return -1; ! 2840: } ! 2841: ! 2842: /* create buffer to save iv */ ! 2843: if ((newivm->ive = vdup(newivm->iv)) == NULL) { ! 2844: plog(LLV_ERROR, LOCATION, NULL, ! 2845: "vdup (%s)\n", strerror(errno)); ! 2846: vfree(buf); ! 2847: oakley_delivm(newivm); ! 2848: return -1; ! 2849: } ! 2850: ! 2851: vfree(buf); ! 2852: ! 2853: plog(LLV_DEBUG, LOCATION, NULL, "IV computed:\n"); ! 2854: plogdump(LLV_DEBUG, newivm->iv->v, newivm->iv->l); ! 2855: ! 2856: iph1->ivm = newivm; ! 2857: ! 2858: return 0; ! 2859: } ! 2860: ! 2861: /* ! 2862: * compute IV for the payload after phase 1. ! 2863: * It's not limited for phase 2. ! 2864: * if pahse 1 was encrypted. ! 2865: * IV = hash(last CBC block of Phase 1 | M-ID) ! 2866: * if phase 1 was not encrypted. ! 2867: * IV = hash(phase 1 IV | M-ID) ! 2868: * see 4.2 Phase 2 state in draft-ietf-ipsec-ike. ! 2869: */ ! 2870: struct isakmp_ivm * ! 2871: oakley_newiv2(iph1, msgid) ! 2872: struct ph1handle *iph1; ! 2873: u_int32_t msgid; ! 2874: { ! 2875: struct isakmp_ivm *newivm = NULL; ! 2876: vchar_t *buf = NULL; ! 2877: char *p; ! 2878: int len; ! 2879: int error = -1; ! 2880: ! 2881: /* create buffer */ ! 2882: len = iph1->ivm->iv->l + sizeof(msgid_t); ! 2883: buf = vmalloc(len); ! 2884: if (buf == NULL) { ! 2885: plog(LLV_ERROR, LOCATION, NULL, ! 2886: "failed to get iv buffer\n"); ! 2887: goto end; ! 2888: } ! 2889: ! 2890: p = buf->v; ! 2891: ! 2892: memcpy(p, iph1->ivm->iv->v, iph1->ivm->iv->l); ! 2893: p += iph1->ivm->iv->l; ! 2894: ! 2895: memcpy(p, &msgid, sizeof(msgid)); ! 2896: ! 2897: plog(LLV_DEBUG, LOCATION, NULL, "compute IV for phase2\n"); ! 2898: plog(LLV_DEBUG, LOCATION, NULL, "phase1 last IV:\n"); ! 2899: plogdump(LLV_DEBUG, buf->v, buf->l); ! 2900: ! 2901: /* allocate IVm */ ! 2902: newivm = racoon_calloc(1, sizeof(struct isakmp_ivm)); ! 2903: if (newivm == NULL) { ! 2904: plog(LLV_ERROR, LOCATION, NULL, ! 2905: "failed to get iv buffer\n"); ! 2906: goto end; ! 2907: } ! 2908: ! 2909: /* compute IV */ ! 2910: if ((newivm->iv = oakley_hash(buf, iph1)) == NULL) ! 2911: goto end; ! 2912: ! 2913: /* adjust length of iv */ ! 2914: newivm->iv->l = alg_oakley_encdef_blocklen(iph1->approval->enctype); ! 2915: if (newivm->iv->l == -1) { ! 2916: plog(LLV_ERROR, LOCATION, NULL, ! 2917: "invalid encryption algorithm %d.\n", ! 2918: iph1->approval->enctype); ! 2919: goto end; ! 2920: } ! 2921: ! 2922: /* create buffer to save new iv */ ! 2923: if ((newivm->ive = vdup(newivm->iv)) == NULL) { ! 2924: plog(LLV_ERROR, LOCATION, NULL, "vdup (%s)\n", strerror(errno)); ! 2925: goto end; ! 2926: } ! 2927: ! 2928: error = 0; ! 2929: ! 2930: plog(LLV_DEBUG, LOCATION, NULL, "phase2 IV computed:\n"); ! 2931: plogdump(LLV_DEBUG, newivm->iv->v, newivm->iv->l); ! 2932: ! 2933: end: ! 2934: if (error && newivm != NULL){ ! 2935: oakley_delivm(newivm); ! 2936: newivm=NULL; ! 2937: } ! 2938: if (buf != NULL) ! 2939: vfree(buf); ! 2940: return newivm; ! 2941: } ! 2942: ! 2943: void ! 2944: oakley_delivm(ivm) ! 2945: struct isakmp_ivm *ivm; ! 2946: { ! 2947: if (ivm == NULL) ! 2948: return; ! 2949: ! 2950: if (ivm->iv != NULL) ! 2951: vfree(ivm->iv); ! 2952: if (ivm->ive != NULL) ! 2953: vfree(ivm->ive); ! 2954: racoon_free(ivm); ! 2955: plog(LLV_DEBUG, LOCATION, NULL, "IV freed\n"); ! 2956: ! 2957: return; ! 2958: } ! 2959: ! 2960: /* ! 2961: * decrypt packet. ! 2962: * save new iv and old iv. ! 2963: */ ! 2964: vchar_t * ! 2965: oakley_do_decrypt(iph1, msg, ivdp, ivep) ! 2966: struct ph1handle *iph1; ! 2967: vchar_t *msg, *ivdp, *ivep; ! 2968: { ! 2969: vchar_t *buf = NULL, *new = NULL; ! 2970: char *pl; ! 2971: int len; ! 2972: u_int8_t padlen; ! 2973: int blen; ! 2974: int error = -1; ! 2975: ! 2976: plog(LLV_DEBUG, LOCATION, NULL, "begin decryption.\n"); ! 2977: ! 2978: blen = alg_oakley_encdef_blocklen(iph1->approval->enctype); ! 2979: if (blen == -1) { ! 2980: plog(LLV_ERROR, LOCATION, NULL, ! 2981: "invalid encryption algorithm %d.\n", ! 2982: iph1->approval->enctype); ! 2983: goto end; ! 2984: } ! 2985: ! 2986: /* save IV for next, but not sync. */ ! 2987: memset(ivep->v, 0, ivep->l); ! 2988: memcpy(ivep->v, (caddr_t)&msg->v[msg->l - blen], blen); ! 2989: ! 2990: plog(LLV_DEBUG, LOCATION, NULL, ! 2991: "IV was saved for next processing:\n"); ! 2992: plogdump(LLV_DEBUG, ivep->v, ivep->l); ! 2993: ! 2994: pl = msg->v + sizeof(struct isakmp); ! 2995: ! 2996: len = msg->l - sizeof(struct isakmp); ! 2997: ! 2998: /* create buffer */ ! 2999: buf = vmalloc(len); ! 3000: if (buf == NULL) { ! 3001: plog(LLV_ERROR, LOCATION, NULL, ! 3002: "failed to get buffer to decrypt.\n"); ! 3003: goto end; ! 3004: } ! 3005: memcpy(buf->v, pl, len); ! 3006: ! 3007: /* do decrypt */ ! 3008: new = alg_oakley_encdef_decrypt(iph1->approval->enctype, ! 3009: buf, iph1->key, ivdp); ! 3010: if (new == NULL || new->v == NULL || new->l == 0) { ! 3011: plog(LLV_ERROR, LOCATION, NULL, ! 3012: "decryption %d failed.\n", iph1->approval->enctype); ! 3013: goto end; ! 3014: } ! 3015: plog(LLV_DEBUG, LOCATION, NULL, "with key:\n"); ! 3016: plogdump(LLV_DEBUG, iph1->key->v, iph1->key->l); ! 3017: ! 3018: vfree(buf); ! 3019: buf = NULL; ! 3020: ! 3021: plog(LLV_DEBUG, LOCATION, NULL, "decrypted payload by IV:\n"); ! 3022: plogdump(LLV_DEBUG, ivdp->v, ivdp->l); ! 3023: ! 3024: plog(LLV_DEBUG, LOCATION, NULL, ! 3025: "decrypted payload, but not trimed.\n"); ! 3026: plogdump(LLV_DEBUG, new->v, new->l); ! 3027: ! 3028: /* get padding length */ ! 3029: if (lcconf->pad_excltail) ! 3030: padlen = new->v[new->l - 1] + 1; ! 3031: else ! 3032: padlen = new->v[new->l - 1]; ! 3033: plog(LLV_DEBUG, LOCATION, NULL, "padding len=%u\n", padlen); ! 3034: ! 3035: /* trim padding */ ! 3036: if (lcconf->pad_strict) { ! 3037: if (padlen > new->l) { ! 3038: plog(LLV_ERROR, LOCATION, NULL, ! 3039: "invalied padding len=%u, buflen=%zu.\n", ! 3040: padlen, new->l); ! 3041: plogdump(LLV_ERROR, new->v, new->l); ! 3042: goto end; ! 3043: } ! 3044: new->l -= padlen; ! 3045: plog(LLV_DEBUG, LOCATION, NULL, "trimmed padding\n"); ! 3046: } else { ! 3047: plog(LLV_DEBUG, LOCATION, NULL, "skip to trim padding.\n"); ! 3048: } ! 3049: ! 3050: /* create new buffer */ ! 3051: len = sizeof(struct isakmp) + new->l; ! 3052: buf = vmalloc(len); ! 3053: if (buf == NULL) { ! 3054: plog(LLV_ERROR, LOCATION, NULL, ! 3055: "failed to get buffer to decrypt.\n"); ! 3056: goto end; ! 3057: } ! 3058: memcpy(buf->v, msg->v, sizeof(struct isakmp)); ! 3059: memcpy(buf->v + sizeof(struct isakmp), new->v, new->l); ! 3060: ((struct isakmp *)buf->v)->len = htonl(buf->l); ! 3061: ! 3062: plog(LLV_DEBUG, LOCATION, NULL, "decrypted.\n"); ! 3063: plogdump(LLV_DEBUG, buf->v, buf->l); ! 3064: ! 3065: #ifdef HAVE_PRINT_ISAKMP_C ! 3066: isakmp_printpacket(buf, iph1->remote, iph1->local, 1); ! 3067: #endif ! 3068: ! 3069: error = 0; ! 3070: ! 3071: end: ! 3072: if (error && buf != NULL) { ! 3073: vfree(buf); ! 3074: buf = NULL; ! 3075: } ! 3076: if (new != NULL) ! 3077: vfree(new); ! 3078: ! 3079: return buf; ! 3080: } ! 3081: ! 3082: /* ! 3083: * encrypt packet. ! 3084: */ ! 3085: vchar_t * ! 3086: oakley_do_encrypt(iph1, msg, ivep, ivp) ! 3087: struct ph1handle *iph1; ! 3088: vchar_t *msg, *ivep, *ivp; ! 3089: { ! 3090: vchar_t *buf = 0, *new = 0; ! 3091: char *pl; ! 3092: int len; ! 3093: u_int padlen; ! 3094: int blen; ! 3095: int error = -1; ! 3096: ! 3097: plog(LLV_DEBUG, LOCATION, NULL, "begin encryption.\n"); ! 3098: ! 3099: /* set cbc block length */ ! 3100: blen = alg_oakley_encdef_blocklen(iph1->approval->enctype); ! 3101: if (blen == -1) { ! 3102: plog(LLV_ERROR, LOCATION, NULL, ! 3103: "invalid encryption algorithm %d.\n", ! 3104: iph1->approval->enctype); ! 3105: goto end; ! 3106: } ! 3107: ! 3108: pl = msg->v + sizeof(struct isakmp); ! 3109: len = msg->l - sizeof(struct isakmp); ! 3110: ! 3111: /* add padding */ ! 3112: padlen = oakley_padlen(len, blen); ! 3113: plog(LLV_DEBUG, LOCATION, NULL, "pad length = %u\n", padlen); ! 3114: ! 3115: /* create buffer */ ! 3116: buf = vmalloc(len + padlen); ! 3117: if (buf == NULL) { ! 3118: plog(LLV_ERROR, LOCATION, NULL, ! 3119: "failed to get buffer to encrypt.\n"); ! 3120: goto end; ! 3121: } ! 3122: if (padlen) { ! 3123: int i; ! 3124: char *p = &buf->v[len]; ! 3125: if (lcconf->pad_random) { ! 3126: for (i = 0; i < padlen; i++) ! 3127: *p++ = eay_random() & 0xff; ! 3128: } ! 3129: } ! 3130: memcpy(buf->v, pl, len); ! 3131: ! 3132: /* make pad into tail */ ! 3133: if (lcconf->pad_excltail) ! 3134: buf->v[len + padlen - 1] = padlen - 1; ! 3135: else ! 3136: buf->v[len + padlen - 1] = padlen; ! 3137: ! 3138: plogdump(LLV_DEBUG, buf->v, buf->l); ! 3139: ! 3140: /* do encrypt */ ! 3141: new = alg_oakley_encdef_encrypt(iph1->approval->enctype, ! 3142: buf, iph1->key, ivep); ! 3143: if (new == NULL) { ! 3144: plog(LLV_ERROR, LOCATION, NULL, ! 3145: "encryption %d failed.\n", iph1->approval->enctype); ! 3146: goto end; ! 3147: } ! 3148: plog(LLV_DEBUG, LOCATION, NULL, "with key:\n"); ! 3149: plogdump(LLV_DEBUG, iph1->key->v, iph1->key->l); ! 3150: ! 3151: vfree(buf); ! 3152: buf = NULL; ! 3153: ! 3154: plog(LLV_DEBUG, LOCATION, NULL, "encrypted payload by IV:\n"); ! 3155: plogdump(LLV_DEBUG, ivep->v, ivep->l); ! 3156: ! 3157: /* save IV for next */ ! 3158: memset(ivp->v, 0, ivp->l); ! 3159: memcpy(ivp->v, (caddr_t)&new->v[new->l - blen], blen); ! 3160: ! 3161: plog(LLV_DEBUG, LOCATION, NULL, "save IV for next:\n"); ! 3162: plogdump(LLV_DEBUG, ivp->v, ivp->l); ! 3163: ! 3164: /* create new buffer */ ! 3165: len = sizeof(struct isakmp) + new->l; ! 3166: buf = vmalloc(len); ! 3167: if (buf == NULL) { ! 3168: plog(LLV_ERROR, LOCATION, NULL, ! 3169: "failed to get buffer to encrypt.\n"); ! 3170: goto end; ! 3171: } ! 3172: memcpy(buf->v, msg->v, sizeof(struct isakmp)); ! 3173: memcpy(buf->v + sizeof(struct isakmp), new->v, new->l); ! 3174: ((struct isakmp *)buf->v)->len = htonl(buf->l); ! 3175: ! 3176: error = 0; ! 3177: ! 3178: plog(LLV_DEBUG, LOCATION, NULL, "encrypted.\n"); ! 3179: ! 3180: end: ! 3181: if (error && buf != NULL) { ! 3182: vfree(buf); ! 3183: buf = NULL; ! 3184: } ! 3185: if (new != NULL) ! 3186: vfree(new); ! 3187: ! 3188: return buf; ! 3189: } ! 3190: ! 3191: /* culculate padding length */ ! 3192: static int ! 3193: oakley_padlen(len, base) ! 3194: int len, base; ! 3195: { ! 3196: int padlen; ! 3197: ! 3198: padlen = base - len % base; ! 3199: ! 3200: if (lcconf->pad_randomlen) ! 3201: padlen += ((eay_random() % (lcconf->pad_maxsize + 1) + 1) * ! 3202: base); ! 3203: ! 3204: return padlen; ! 3205: } ! 3206: