Annotation of embedaddon/ipsec-tools/src/racoon/oakley.c, revision 1.1
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:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>