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>