[BACK]Return to ip_esp.c CVS log [TXT][DIR] Up to [local] / sys / netinet

Annotation of sys/netinet/ip_esp.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: ip_esp.c,v 1.100 2006/12/15 09:32:30 otto Exp $ */
        !             2: /*
        !             3:  * The authors of this code are John Ioannidis (ji@tla.org),
        !             4:  * Angelos D. Keromytis (kermit@csd.uch.gr) and
        !             5:  * Niels Provos (provos@physnet.uni-hamburg.de).
        !             6:  *
        !             7:  * The original version of this code was written by John Ioannidis
        !             8:  * for BSD/OS in Athens, Greece, in November 1995.
        !             9:  *
        !            10:  * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
        !            11:  * by Angelos D. Keromytis.
        !            12:  *
        !            13:  * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
        !            14:  * and Niels Provos.
        !            15:  *
        !            16:  * Additional features in 1999 by Angelos D. Keromytis.
        !            17:  *
        !            18:  * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
        !            19:  * Angelos D. Keromytis and Niels Provos.
        !            20:  * Copyright (c) 2001 Angelos D. Keromytis.
        !            21:  *
        !            22:  * Permission to use, copy, and modify this software with or without fee
        !            23:  * is hereby granted, provided that this entire notice is included in
        !            24:  * all copies of any software which is or includes a copy or
        !            25:  * modification of this software.
        !            26:  * You may use this code under the GNU public license if you so wish. Please
        !            27:  * contribute changes back to the authors under this freer than GPL license
        !            28:  * so that we may further the use of strong encryption without limitations to
        !            29:  * all.
        !            30:  *
        !            31:  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
        !            32:  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
        !            33:  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
        !            34:  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
        !            35:  * PURPOSE.
        !            36:  */
        !            37:
        !            38: #include "pfsync.h"
        !            39:
        !            40: #include <sys/param.h>
        !            41: #include <sys/systm.h>
        !            42: #include <sys/mbuf.h>
        !            43: #include <sys/socket.h>
        !            44:
        !            45: #include <net/if.h>
        !            46: #include <net/bpf.h>
        !            47:
        !            48: #include <dev/rndvar.h>
        !            49:
        !            50: #ifdef INET
        !            51: #include <netinet/in.h>
        !            52: #include <netinet/in_systm.h>
        !            53: #include <netinet/ip.h>
        !            54: #include <netinet/ip_var.h>
        !            55: #endif /* INET */
        !            56:
        !            57: #ifdef INET6
        !            58: #ifndef INET
        !            59: #include <netinet/in.h>
        !            60: #endif
        !            61: #include <netinet/ip6.h>
        !            62: #endif /* INET6 */
        !            63:
        !            64: #include <netinet/ip_ipsp.h>
        !            65: #include <netinet/ip_esp.h>
        !            66: #include <net/pfkeyv2.h>
        !            67: #include <net/if_enc.h>
        !            68:
        !            69: #if NPFSYNC > 0
        !            70: #include <net/pfvar.h>
        !            71: #include <net/if_pfsync.h>
        !            72: #endif /* NPFSYNC > 0 */
        !            73:
        !            74: #include <crypto/cryptodev.h>
        !            75: #include <crypto/xform.h>
        !            76:
        !            77: #include "bpfilter.h"
        !            78:
        !            79: #ifdef ENCDEBUG
        !            80: #define DPRINTF(x)     if (encdebug) printf x
        !            81: #else
        !            82: #define DPRINTF(x)
        !            83: #endif
        !            84:
        !            85: struct espstat espstat;
        !            86:
        !            87: /*
        !            88:  * esp_attach() is called from the transformation initialization code.
        !            89:  */
        !            90: int
        !            91: esp_attach()
        !            92: {
        !            93:        return 0;
        !            94: }
        !            95:
        !            96: /*
        !            97:  * esp_init() is called when an SPI is being set up.
        !            98:  */
        !            99: int
        !           100: esp_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
        !           101: {
        !           102:        struct enc_xform *txform = NULL;
        !           103:        struct auth_hash *thash = NULL;
        !           104:        struct cryptoini cria, crie;
        !           105:
        !           106:        if (!ii->ii_encalg && !ii->ii_authalg) {
        !           107:                DPRINTF(("esp_init(): neither authentication nor encryption "
        !           108:                    "algorithm given"));
        !           109:                return EINVAL;
        !           110:        }
        !           111:
        !           112:        if (ii->ii_encalg) {
        !           113:                switch (ii->ii_encalg) {
        !           114:                case SADB_EALG_NULL:
        !           115:                        txform = &enc_xform_null;
        !           116:                        break;
        !           117:
        !           118:                case SADB_EALG_DESCBC:
        !           119:                        txform = &enc_xform_des;
        !           120:                        break;
        !           121:
        !           122:                case SADB_EALG_3DESCBC:
        !           123:                        txform = &enc_xform_3des;
        !           124:                        break;
        !           125:
        !           126:                case SADB_X_EALG_AES:
        !           127:                        txform = &enc_xform_rijndael128;
        !           128:                        break;
        !           129:
        !           130:                case SADB_X_EALG_AESCTR:
        !           131:                        txform = &enc_xform_aes_ctr;
        !           132:                        break;
        !           133:
        !           134:                case SADB_X_EALG_BLF:
        !           135:                        txform = &enc_xform_blf;
        !           136:                        break;
        !           137:
        !           138:                case SADB_X_EALG_CAST:
        !           139:                        txform = &enc_xform_cast5;
        !           140:                        break;
        !           141:
        !           142:                case SADB_X_EALG_SKIPJACK:
        !           143:                        txform = &enc_xform_skipjack;
        !           144:                        break;
        !           145:
        !           146:                default:
        !           147:                        DPRINTF(("esp_init(): unsupported encryption algorithm %d specified\n", ii->ii_encalg));
        !           148:                        return EINVAL;
        !           149:                }
        !           150:
        !           151:                if (ii->ii_enckeylen < txform->minkey) {
        !           152:                        DPRINTF(("esp_init(): keylength %d too small (min length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->minkey, txform->name));
        !           153:                        return EINVAL;
        !           154:                }
        !           155:
        !           156:                if (ii->ii_enckeylen > txform->maxkey) {
        !           157:                        DPRINTF(("esp_init(): keylength %d too large (max length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->maxkey, txform->name));
        !           158:                        return EINVAL;
        !           159:                }
        !           160:
        !           161:                tdbp->tdb_encalgxform = txform;
        !           162:
        !           163:                DPRINTF(("esp_init(): initialized TDB with enc algorithm %s\n",
        !           164:                    txform->name));
        !           165:
        !           166:                tdbp->tdb_ivlen = txform->ivsize;
        !           167:                if (tdbp->tdb_flags & TDBF_HALFIV)
        !           168:                        tdbp->tdb_ivlen /= 2;
        !           169:        }
        !           170:
        !           171:        if (ii->ii_authalg) {
        !           172:                switch (ii->ii_authalg) {
        !           173:                case SADB_AALG_MD5HMAC:
        !           174:                        thash = &auth_hash_hmac_md5_96;
        !           175:                        break;
        !           176:
        !           177:                case SADB_AALG_SHA1HMAC:
        !           178:                        thash = &auth_hash_hmac_sha1_96;
        !           179:                        break;
        !           180:
        !           181:                case SADB_X_AALG_RIPEMD160HMAC:
        !           182:                        thash = &auth_hash_hmac_ripemd_160_96;
        !           183:                        break;
        !           184:
        !           185:                case SADB_X_AALG_SHA2_256:
        !           186:                        thash = &auth_hash_hmac_sha2_256_96;
        !           187:                        break;
        !           188:
        !           189:                case SADB_X_AALG_SHA2_384:
        !           190:                        thash = &auth_hash_hmac_sha2_384_96;
        !           191:                        break;
        !           192:
        !           193:                case SADB_X_AALG_SHA2_512:
        !           194:                        thash = &auth_hash_hmac_sha2_512_96;
        !           195:                        break;
        !           196:
        !           197:                default:
        !           198:                        DPRINTF(("esp_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg));
        !           199:                        return EINVAL;
        !           200:                }
        !           201:
        !           202:                if (ii->ii_authkeylen != thash->keysize) {
        !           203:                        DPRINTF(("esp_init(): keylength %d doesn't match algorithm %s keysize (%d)\n", ii->ii_authkeylen, thash->name, thash->keysize));
        !           204:                        return EINVAL;
        !           205:                }
        !           206:
        !           207:                tdbp->tdb_authalgxform = thash;
        !           208:
        !           209:                DPRINTF(("esp_init(): initialized TDB with hash algorithm %s\n",
        !           210:                    thash->name));
        !           211:        }
        !           212:
        !           213:        tdbp->tdb_xform = xsp;
        !           214:        tdbp->tdb_bitmap = 0;
        !           215:        tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL;
        !           216:
        !           217:        /* Initialize crypto session */
        !           218:        if (tdbp->tdb_encalgxform) {
        !           219:                /* Save the raw keys */
        !           220:                tdbp->tdb_emxkeylen = ii->ii_enckeylen;
        !           221:                MALLOC(tdbp->tdb_emxkey, u_int8_t *, tdbp->tdb_emxkeylen,
        !           222:                    M_XDATA, M_WAITOK);
        !           223:                bcopy(ii->ii_enckey, tdbp->tdb_emxkey, tdbp->tdb_emxkeylen);
        !           224:
        !           225:                bzero(&crie, sizeof(crie));
        !           226:
        !           227:                crie.cri_alg = tdbp->tdb_encalgxform->type;
        !           228:
        !           229:                if (tdbp->tdb_authalgxform)
        !           230:                        crie.cri_next = &cria;
        !           231:                else
        !           232:                        crie.cri_next = NULL;
        !           233:
        !           234:                crie.cri_klen = ii->ii_enckeylen * 8;
        !           235:                crie.cri_key = ii->ii_enckey;
        !           236:                /* XXX Rounds ? */
        !           237:        }
        !           238:
        !           239:        if (tdbp->tdb_authalgxform) {
        !           240:                /* Save the raw keys */
        !           241:                tdbp->tdb_amxkeylen = ii->ii_authkeylen;
        !           242:                MALLOC(tdbp->tdb_amxkey, u_int8_t *, tdbp->tdb_amxkeylen, M_XDATA,
        !           243:                    M_WAITOK);
        !           244:                bcopy(ii->ii_authkey, tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
        !           245:
        !           246:                bzero(&cria, sizeof(cria));
        !           247:
        !           248:                cria.cri_alg = tdbp->tdb_authalgxform->type;
        !           249:                cria.cri_next = NULL;
        !           250:                cria.cri_klen = ii->ii_authkeylen * 8;
        !           251:                cria.cri_key = ii->ii_authkey;
        !           252:        }
        !           253:
        !           254:        return crypto_newsession(&tdbp->tdb_cryptoid,
        !           255:            (tdbp->tdb_encalgxform ? &crie : &cria), 0);
        !           256: }
        !           257:
        !           258: /*
        !           259:  * Paranoia.
        !           260:  */
        !           261: int
        !           262: esp_zeroize(struct tdb *tdbp)
        !           263: {
        !           264:        int err;
        !           265:
        !           266:        if (tdbp->tdb_amxkey) {
        !           267:                bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
        !           268:                FREE(tdbp->tdb_amxkey, M_XDATA);
        !           269:                tdbp->tdb_amxkey = NULL;
        !           270:        }
        !           271:
        !           272:        if (tdbp->tdb_emxkey) {
        !           273:                bzero(tdbp->tdb_emxkey, tdbp->tdb_emxkeylen);
        !           274:                FREE(tdbp->tdb_emxkey, M_XDATA);
        !           275:                tdbp->tdb_emxkey = NULL;
        !           276:        }
        !           277:
        !           278:        err = crypto_freesession(tdbp->tdb_cryptoid);
        !           279:        tdbp->tdb_cryptoid = 0;
        !           280:        return err;
        !           281: }
        !           282:
        !           283: #define MAXBUFSIZ (AH_ALEN_MAX > ESP_MAX_IVS ? AH_ALEN_MAX : ESP_MAX_IVS)
        !           284:
        !           285: /*
        !           286:  * ESP input processing, called (eventually) through the protocol switch.
        !           287:  */
        !           288: int
        !           289: esp_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
        !           290: {
        !           291:        struct auth_hash *esph = (struct auth_hash *) tdb->tdb_authalgxform;
        !           292:        struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;
        !           293:        struct tdb_crypto *tc;
        !           294:        int plen, alen, hlen;
        !           295:        struct m_tag *mtag;
        !           296:        u_int32_t btsx;
        !           297:
        !           298:        struct cryptodesc *crde = NULL, *crda = NULL;
        !           299:        struct cryptop *crp;
        !           300:
        !           301:        /* Determine the ESP header length */
        !           302:        if (tdb->tdb_flags & TDBF_NOREPLAY)
        !           303:                hlen = sizeof(u_int32_t) + tdb->tdb_ivlen; /* "old" ESP */
        !           304:        else
        !           305:                hlen = 2 * sizeof(u_int32_t) + tdb->tdb_ivlen; /* "new" ESP */
        !           306:
        !           307:        if (esph)
        !           308:                alen = AH_HMAC_HASHLEN;
        !           309:        else
        !           310:                alen = 0;
        !           311:
        !           312:        plen = m->m_pkthdr.len - (skip + hlen + alen);
        !           313:        if (plen <= 0) {
        !           314:                DPRINTF(("esp_input: invalid payload length\n"));
        !           315:                espstat.esps_badilen++;
        !           316:                m_freem(m);
        !           317:                return EINVAL;
        !           318:        }
        !           319:
        !           320:        if (espx) {
        !           321:                /*
        !           322:                 * Verify payload length is multiple of encryption algorithm
        !           323:                 * block size.
        !           324:                 */
        !           325:                if (plen & (espx->blocksize - 1)) {
        !           326:                        DPRINTF(("esp_input(): payload of %d octets not a multiple of %d octets, SA %s/%08x\n", plen, espx->blocksize, ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
        !           327:                        espstat.esps_badilen++;
        !           328:                        m_freem(m);
        !           329:                        return EINVAL;
        !           330:                }
        !           331:        }
        !           332:
        !           333:        /* Replay window checking, if appropriate -- no value commitment. */
        !           334:        if ((tdb->tdb_wnd > 0) && (!(tdb->tdb_flags & TDBF_NOREPLAY))) {
        !           335:                m_copydata(m, skip + sizeof(u_int32_t), sizeof(u_int32_t),
        !           336:                    (unsigned char *) &btsx);
        !           337:                btsx = ntohl(btsx);
        !           338:
        !           339:                switch (checkreplaywindow32(btsx, 0, &(tdb->tdb_rpl),
        !           340:                    tdb->tdb_wnd, &(tdb->tdb_bitmap), 0)) {
        !           341:                case 0: /* All's well */
        !           342:                        break;
        !           343:
        !           344:                case 1:
        !           345:                        m_freem(m);
        !           346:                        DPRINTF(("esp_input(): replay counter wrapped for SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
        !           347:                        espstat.esps_wrap++;
        !           348:                        return EACCES;
        !           349:
        !           350:                case 2:
        !           351:                case 3:
        !           352:                        DPRINTF(("esp_input(): duplicate packet received in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
        !           353:                        m_freem(m);
        !           354:                        return EACCES;
        !           355:
        !           356:                default:
        !           357:                        m_freem(m);
        !           358:                        DPRINTF(("esp_input(): bogus value from checkreplaywindow32() in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
        !           359:                        espstat.esps_replay++;
        !           360:                        return EACCES;
        !           361:                }
        !           362:        }
        !           363:
        !           364:        /* Update the counters */
        !           365:        tdb->tdb_cur_bytes += m->m_pkthdr.len - skip - hlen - alen;
        !           366:        espstat.esps_ibytes += m->m_pkthdr.len - skip - hlen - alen;
        !           367:
        !           368:        /* Hard expiration */
        !           369:        if ((tdb->tdb_flags & TDBF_BYTES) &&
        !           370:            (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) {
        !           371:                pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
        !           372:                tdb_delete(tdb);
        !           373:                m_freem(m);
        !           374:                return ENXIO;
        !           375:        }
        !           376:
        !           377:        /* Notify on soft expiration */
        !           378:        if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
        !           379:            (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) {
        !           380:                pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
        !           381:                tdb->tdb_flags &= ~TDBF_SOFT_BYTES;       /* Turn off checking */
        !           382:        }
        !           383:
        !           384: #ifdef notyet
        !           385:        /* Find out if we've already done crypto */
        !           386:        for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL);
        !           387:             mtag != NULL;
        !           388:             mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, mtag)) {
        !           389:                struct tdb_ident *tdbi;
        !           390:
        !           391:                tdbi = (struct tdb_ident *) (mtag + 1);
        !           392:                if (tdbi->proto == tdb->tdb_sproto && tdbi->spi == tdb->tdb_spi &&
        !           393:                    !bcmp(&tdbi->dst, &tdb->tdb_dst, sizeof(union sockaddr_union)))
        !           394:                        break;
        !           395:        }
        !           396: #else
        !           397:        mtag = NULL;
        !           398: #endif
        !           399:
        !           400:        /* Get crypto descriptors */
        !           401:        crp = crypto_getreq(esph && espx ? 2 : 1);
        !           402:        if (crp == NULL) {
        !           403:                m_freem(m);
        !           404:                DPRINTF(("esp_input(): failed to acquire crypto descriptors\n"));
        !           405:                espstat.esps_crypto++;
        !           406:                return ENOBUFS;
        !           407:        }
        !           408:
        !           409:        /* Get IPsec-specific opaque pointer */
        !           410:        if (esph == NULL || mtag != NULL)
        !           411:                MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto),
        !           412:                    M_XDATA, M_NOWAIT);
        !           413:        else
        !           414:                MALLOC(tc, struct tdb_crypto *,
        !           415:                    sizeof(struct tdb_crypto) + alen, M_XDATA, M_NOWAIT);
        !           416:        if (tc == NULL) {
        !           417:                m_freem(m);
        !           418:                crypto_freereq(crp);
        !           419:                DPRINTF(("esp_input(): failed to allocate tdb_crypto\n"));
        !           420:                espstat.esps_crypto++;
        !           421:                return ENOBUFS;
        !           422:        }
        !           423:
        !           424:        bzero(tc, sizeof(struct tdb_crypto));
        !           425:        tc->tc_ptr = (caddr_t) mtag;
        !           426:
        !           427:        if (esph) {
        !           428:                crda = crp->crp_desc;
        !           429:                crde = crda->crd_next;
        !           430:
        !           431:                /* Authentication descriptor */
        !           432:                crda->crd_skip = skip;
        !           433:                crda->crd_len = m->m_pkthdr.len - (skip + alen);
        !           434:                crda->crd_inject = m->m_pkthdr.len - alen;
        !           435:
        !           436:                crda->crd_alg = esph->type;
        !           437:                crda->crd_key = tdb->tdb_amxkey;
        !           438:                crda->crd_klen = tdb->tdb_amxkeylen * 8;
        !           439:
        !           440:                /* Copy the authenticator */
        !           441:                if (mtag == NULL)
        !           442:                        m_copydata(m, m->m_pkthdr.len - alen, alen, (caddr_t) (tc + 1));
        !           443:        } else
        !           444:                crde = crp->crp_desc;
        !           445:
        !           446:        /* Crypto operation descriptor */
        !           447:        crp->crp_ilen = m->m_pkthdr.len; /* Total input length */
        !           448:        crp->crp_flags = CRYPTO_F_IMBUF;
        !           449:        crp->crp_buf = (caddr_t) m;
        !           450:        crp->crp_callback = (int (*) (struct cryptop *)) esp_input_cb;
        !           451:        crp->crp_sid = tdb->tdb_cryptoid;
        !           452:        crp->crp_opaque = (caddr_t) tc;
        !           453:
        !           454:        /* These are passed as-is to the callback */
        !           455:        tc->tc_skip = skip;
        !           456:        tc->tc_protoff = protoff;
        !           457:        tc->tc_spi = tdb->tdb_spi;
        !           458:        tc->tc_proto = tdb->tdb_sproto;
        !           459:        bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union));
        !           460:
        !           461:        /* Decryption descriptor */
        !           462:        if (espx) {
        !           463:                crde->crd_skip = skip + hlen;
        !           464:                crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen);
        !           465:                crde->crd_inject = skip + hlen - tdb->tdb_ivlen;
        !           466:
        !           467:                if (tdb->tdb_flags & TDBF_HALFIV) {
        !           468:                        /* Copy half-IV from packet */
        !           469:                        m_copydata(m, crde->crd_inject, tdb->tdb_ivlen, crde->crd_iv);
        !           470:
        !           471:                        /* Cook IV */
        !           472:                        for (btsx = 0; btsx < tdb->tdb_ivlen; btsx++)
        !           473:                                crde->crd_iv[tdb->tdb_ivlen + btsx] = ~crde->crd_iv[btsx];
        !           474:
        !           475:                        crde->crd_flags |= CRD_F_IV_EXPLICIT;
        !           476:                }
        !           477:
        !           478:                crde->crd_alg = espx->type;
        !           479:                crde->crd_key = tdb->tdb_emxkey;
        !           480:                crde->crd_klen = tdb->tdb_emxkeylen * 8;
        !           481:                /* XXX Rounds ? */
        !           482:        }
        !           483:
        !           484:        if (mtag == NULL)
        !           485:                return crypto_dispatch(crp);
        !           486:        else
        !           487:                return esp_input_cb(crp);
        !           488: }
        !           489:
        !           490: /*
        !           491:  * ESP input callback, called directly by the crypto driver.
        !           492:  */
        !           493: int
        !           494: esp_input_cb(void *op)
        !           495: {
        !           496:        u_int8_t lastthree[3], aalg[AH_HMAC_HASHLEN];
        !           497:        int s, hlen, roff, skip, protoff, error;
        !           498:        struct mbuf *m1, *mo, *m;
        !           499:        struct auth_hash *esph;
        !           500:        struct tdb_crypto *tc;
        !           501:        struct cryptop *crp;
        !           502:        struct m_tag *mtag;
        !           503:        struct tdb *tdb;
        !           504:        u_int32_t btsx;
        !           505:        caddr_t ptr;
        !           506:
        !           507:        crp = (struct cryptop *) op;
        !           508:
        !           509:        tc = (struct tdb_crypto *) crp->crp_opaque;
        !           510:        skip = tc->tc_skip;
        !           511:        protoff = tc->tc_protoff;
        !           512:        mtag = (struct m_tag *) tc->tc_ptr;
        !           513:
        !           514:        m = (struct mbuf *) crp->crp_buf;
        !           515:        if (m == NULL) {
        !           516:                /* Shouldn't happen... */
        !           517:                FREE(tc, M_XDATA);
        !           518:                crypto_freereq(crp);
        !           519:                espstat.esps_crypto++;
        !           520:                DPRINTF(("esp_input_cb(): bogus returned buffer from crypto\n"));
        !           521:                return (EINVAL);
        !           522:        }
        !           523:
        !           524:        s = spltdb();
        !           525:
        !           526:        tdb = gettdb(tc->tc_spi, &tc->tc_dst, tc->tc_proto);
        !           527:        if (tdb == NULL) {
        !           528:                FREE(tc, M_XDATA);
        !           529:                espstat.esps_notdb++;
        !           530:                DPRINTF(("esp_input_cb(): TDB is expired while in crypto"));
        !           531:                error = EPERM;
        !           532:                goto baddone;
        !           533:        }
        !           534:
        !           535:        esph = (struct auth_hash *) tdb->tdb_authalgxform;
        !           536:
        !           537:        /* Check for crypto errors */
        !           538:        if (crp->crp_etype) {
        !           539:                if (crp->crp_etype == EAGAIN) {
        !           540:                        /* Reset the session ID */
        !           541:                        if (tdb->tdb_cryptoid != 0)
        !           542:                                tdb->tdb_cryptoid = crp->crp_sid;
        !           543:                        splx(s);
        !           544:                        return crypto_dispatch(crp);
        !           545:                }
        !           546:                FREE(tc, M_XDATA);
        !           547:                espstat.esps_noxform++;
        !           548:                DPRINTF(("esp_input_cb(): crypto error %d\n", crp->crp_etype));
        !           549:                error = crp->crp_etype;
        !           550:                goto baddone;
        !           551:        }
        !           552:
        !           553:        /* If authentication was performed, check now. */
        !           554:        if (esph != NULL) {
        !           555:                /*
        !           556:                 * If we have a tag, it means an IPsec-aware NIC did the verification
        !           557:                 * for us.
        !           558:                 */
        !           559:                if (mtag == NULL) {
        !           560:                        /* Copy the authenticator from the packet */
        !           561:                        m_copydata(m, m->m_pkthdr.len - esph->authsize,
        !           562:                            esph->authsize, aalg);
        !           563:
        !           564:                        ptr = (caddr_t) (tc + 1);
        !           565:
        !           566:                        /* Verify authenticator */
        !           567:                        if (bcmp(ptr, aalg, esph->authsize)) {
        !           568:                                FREE(tc, M_XDATA);
        !           569:                                DPRINTF(("esp_input_cb(): authentication failed for packet in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
        !           570:                                espstat.esps_badauth++;
        !           571:                                error = EACCES;
        !           572:                                goto baddone;
        !           573:                        }
        !           574:                }
        !           575:
        !           576:                /* Remove trailing authenticator */
        !           577:                m_adj(m, -(esph->authsize));
        !           578:        }
        !           579:        FREE(tc, M_XDATA);
        !           580:
        !           581:        /* Replay window checking, if appropriate */
        !           582:        if ((tdb->tdb_wnd > 0) && (!(tdb->tdb_flags & TDBF_NOREPLAY))) {
        !           583:                m_copydata(m, skip + sizeof(u_int32_t), sizeof(u_int32_t),
        !           584:                    (unsigned char *) &btsx);
        !           585:                btsx = ntohl(btsx);
        !           586:
        !           587:                switch (checkreplaywindow32(btsx, 0, &(tdb->tdb_rpl),
        !           588:                    tdb->tdb_wnd, &(tdb->tdb_bitmap), 1)) {
        !           589:                case 0: /* All's well */
        !           590: #if NPFSYNC > 0
        !           591:                        pfsync_update_tdb(tdb,0);
        !           592: #endif
        !           593:                        break;
        !           594:
        !           595:                case 1:
        !           596:                        DPRINTF(("esp_input_cb(): replay counter wrapped for SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
        !           597:                        espstat.esps_wrap++;
        !           598:                        error = EACCES;
        !           599:                        goto baddone;
        !           600:
        !           601:                case 2:
        !           602:                case 3:
        !           603:                        DPRINTF(("esp_input_cb(): duplicate packet received in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
        !           604:                        error = EACCES;
        !           605:                        goto baddone;
        !           606:
        !           607:                default:
        !           608:                        DPRINTF(("esp_input_cb(): bogus value from checkreplaywindow32() in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
        !           609:                        espstat.esps_replay++;
        !           610:                        error = EACCES;
        !           611:                        goto baddone;
        !           612:                }
        !           613:        }
        !           614:
        !           615:        /* Release the crypto descriptors */
        !           616:        crypto_freereq(crp);
        !           617:
        !           618:        /* Determine the ESP header length */
        !           619:        if (tdb->tdb_flags & TDBF_NOREPLAY)
        !           620:                hlen = sizeof(u_int32_t) + tdb->tdb_ivlen; /* "old" ESP */
        !           621:        else
        !           622:                hlen = 2 * sizeof(u_int32_t) + tdb->tdb_ivlen; /* "new" ESP */
        !           623:
        !           624:        /* Find beginning of ESP header */
        !           625:        m1 = m_getptr(m, skip, &roff);
        !           626:        if (m1 == NULL) {
        !           627:                espstat.esps_hdrops++;
        !           628:                splx(s);
        !           629:                DPRINTF(("esp_input_cb(): bad mbuf chain, SA %s/%08x\n",
        !           630:                    ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
        !           631:                m_freem(m);
        !           632:                return EINVAL;
        !           633:        }
        !           634:
        !           635:        /* Remove the ESP header and IV from the mbuf. */
        !           636:        if (roff == 0) {
        !           637:                /* The ESP header was conveniently at the beginning of the mbuf */
        !           638:                m_adj(m1, hlen);
        !           639:                if (!(m1->m_flags & M_PKTHDR))
        !           640:                        m->m_pkthdr.len -= hlen;
        !           641:        } else if (roff + hlen >= m1->m_len) {
        !           642:                /*
        !           643:                 * Part or all of the ESP header is at the end of this mbuf, so
        !           644:                 * first let's remove the remainder of the ESP header from the
        !           645:                 * beginning of the remainder of the mbuf chain, if any.
        !           646:                 */
        !           647:                if (roff + hlen > m1->m_len) {
        !           648:                        /* Adjust the next mbuf by the remainder */
        !           649:                        m_adj(m1->m_next, roff + hlen - m1->m_len);
        !           650:
        !           651:                        /* The second mbuf is guaranteed not to have a pkthdr... */
        !           652:                        m->m_pkthdr.len -= (roff + hlen - m1->m_len);
        !           653:                }
        !           654:
        !           655:                /* Now, let's unlink the mbuf chain for a second...*/
        !           656:                mo = m1->m_next;
        !           657:                m1->m_next = NULL;
        !           658:
        !           659:                /* ...and trim the end of the first part of the chain...sick */
        !           660:                m_adj(m1, -(m1->m_len - roff));
        !           661:                if (!(m1->m_flags & M_PKTHDR))
        !           662:                        m->m_pkthdr.len -= (m1->m_len - roff);
        !           663:
        !           664:                /* Finally, let's relink */
        !           665:                m1->m_next = mo;
        !           666:        } else {
        !           667:                /*
        !           668:                 * The ESP header lies in the "middle" of the mbuf...do an
        !           669:                 * overlapping copy of the remainder of the mbuf over the ESP
        !           670:                 * header.
        !           671:                 */
        !           672:                bcopy(mtod(m1, u_char *) + roff + hlen,
        !           673:                    mtod(m1, u_char *) + roff, m1->m_len - (roff + hlen));
        !           674:                m1->m_len -= hlen;
        !           675:                m->m_pkthdr.len -= hlen;
        !           676:        }
        !           677:
        !           678:        /* Save the last three bytes of decrypted data */
        !           679:        m_copydata(m, m->m_pkthdr.len - 3, 3, lastthree);
        !           680:
        !           681:        /* Verify pad length */
        !           682:        if (lastthree[1] + 2 > m->m_pkthdr.len - skip) {
        !           683:                espstat.esps_badilen++;
        !           684:                splx(s);
        !           685:                DPRINTF(("esp_input_cb(): invalid padding length %d for packet in SA %s/%08x\n", lastthree[1], ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
        !           686:                m_freem(m);
        !           687:                return EINVAL;
        !           688:        }
        !           689:
        !           690:        /* Verify correct decryption by checking the last padding bytes */
        !           691:        if (!(tdb->tdb_flags & TDBF_RANDOMPADDING)) {
        !           692:                if ((lastthree[1] != lastthree[0]) && (lastthree[1] != 0)) {
        !           693:                        espstat.esps_badenc++;
        !           694:                        splx(s);
        !           695:                        DPRINTF(("esp_input(): decryption failed for packet in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
        !           696:                        m_freem(m);
        !           697:                        return EINVAL;
        !           698:                }
        !           699:        }
        !           700:
        !           701:        /* Trim the mbuf chain to remove the trailing authenticator and padding */
        !           702:        m_adj(m, -(lastthree[1] + 2));
        !           703:
        !           704:        /* Restore the Next Protocol field */
        !           705:        m_copyback(m, protoff, sizeof(u_int8_t), lastthree + 2);
        !           706:
        !           707:        /* Back to generic IPsec input processing */
        !           708:        error = ipsec_common_input_cb(m, tdb, skip, protoff, mtag);
        !           709:        splx(s);
        !           710:        return (error);
        !           711:
        !           712:  baddone:
        !           713:        splx(s);
        !           714:
        !           715:        if (m != NULL)
        !           716:                m_freem(m);
        !           717:
        !           718:        crypto_freereq(crp);
        !           719:
        !           720:        return (error);
        !           721: }
        !           722:
        !           723: /*
        !           724:  * ESP output routine, called by ipsp_process_packet().
        !           725:  */
        !           726: int
        !           727: esp_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
        !           728:     int protoff)
        !           729: {
        !           730:        struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;
        !           731:        struct auth_hash *esph = (struct auth_hash *) tdb->tdb_authalgxform;
        !           732:        int ilen, hlen, rlen, padding, blks, alen;
        !           733:        struct mbuf *mi, *mo = (struct mbuf *) NULL;
        !           734:        struct tdb_crypto *tc;
        !           735:        unsigned char *pad;
        !           736:        u_int8_t prot;
        !           737:
        !           738:        struct cryptodesc *crde = NULL, *crda = NULL;
        !           739:        struct cryptop *crp;
        !           740: #if NBPFILTER > 0
        !           741:        struct ifnet *ifn = &(encif[0].sc_if);
        !           742:
        !           743:        ifn->if_opackets++;
        !           744:        ifn->if_obytes += m->m_pkthdr.len;
        !           745:
        !           746:        if (ifn->if_bpf) {
        !           747:                struct enchdr hdr;
        !           748:
        !           749:                bzero (&hdr, sizeof(hdr));
        !           750:
        !           751:                hdr.af = tdb->tdb_dst.sa.sa_family;
        !           752:                hdr.spi = tdb->tdb_spi;
        !           753:                if (espx)
        !           754:                        hdr.flags |= M_CONF;
        !           755:                if (esph)
        !           756:                        hdr.flags |= M_AUTH;
        !           757:
        !           758:                bpf_mtap_hdr(ifn->if_bpf, (char *)&hdr, ENC_HDRLEN, m,
        !           759:                    BPF_DIRECTION_OUT);
        !           760:        }
        !           761: #endif
        !           762:
        !           763:        if (tdb->tdb_flags & TDBF_NOREPLAY)
        !           764:                hlen = sizeof(u_int32_t) + tdb->tdb_ivlen;
        !           765:        else
        !           766:                hlen = 2 * sizeof(u_int32_t) + tdb->tdb_ivlen;
        !           767:
        !           768:        rlen = m->m_pkthdr.len - skip; /* Raw payload length. */
        !           769:        if (espx)
        !           770:                blks = espx->blocksize;
        !           771:        else
        !           772:                blks = 4; /* If no encryption, we have to be 4-byte aligned. */
        !           773:
        !           774:        padding = ((blks - ((rlen + 2) % blks)) % blks) + 2;
        !           775:
        !           776:        if (esph)
        !           777:                alen = AH_HMAC_HASHLEN;
        !           778:        else
        !           779:                alen = 0;
        !           780:
        !           781:        espstat.esps_output++;
        !           782:
        !           783:        switch (tdb->tdb_dst.sa.sa_family) {
        !           784: #ifdef INET
        !           785:        case AF_INET:
        !           786:                /* Check for IP maximum packet size violations. */
        !           787:                if (skip + hlen + rlen + padding + alen > IP_MAXPACKET) {
        !           788:                        DPRINTF(("esp_output(): packet in SA %s/%08x got "
        !           789:                            "too big\n", ipsp_address(tdb->tdb_dst),
        !           790:                            ntohl(tdb->tdb_spi)));
        !           791:                        m_freem(m);
        !           792:                        espstat.esps_toobig++;
        !           793:                        return EMSGSIZE;
        !           794:                }
        !           795:                break;
        !           796: #endif /* INET */
        !           797:
        !           798: #ifdef INET6
        !           799:        case AF_INET6:
        !           800:                /* Check for IPv6 maximum packet size violations. */
        !           801:                if (skip + hlen + rlen + padding + alen > IPV6_MAXPACKET) {
        !           802:                        DPRINTF(("esp_output(): packet in SA %s/%08x got too "
        !           803:                            "big\n", ipsp_address(tdb->tdb_dst),
        !           804:                            ntohl(tdb->tdb_spi)));
        !           805:                        m_freem(m);
        !           806:                        espstat.esps_toobig++;
        !           807:                        return EMSGSIZE;
        !           808:                }
        !           809:                break;
        !           810: #endif /* INET6 */
        !           811:
        !           812:        default:
        !           813:                DPRINTF(("esp_output(): unknown/unsupported protocol "
        !           814:                    "family %d, SA %s/%08x\n", tdb->tdb_dst.sa.sa_family
        !           815:                    , ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
        !           816:                m_freem(m);
        !           817:                espstat.esps_nopf++;
        !           818:                return EPFNOSUPPORT;
        !           819:        }
        !           820:
        !           821:        /* Update the counters. */
        !           822:        tdb->tdb_cur_bytes += m->m_pkthdr.len - skip;
        !           823:        espstat.esps_obytes += m->m_pkthdr.len - skip;
        !           824:
        !           825:        /* Hard byte expiration. */
        !           826:        if (tdb->tdb_flags & TDBF_BYTES &&
        !           827:            tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) {
        !           828:                pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
        !           829:                tdb_delete(tdb);
        !           830:                m_freem(m);
        !           831:                return EINVAL;
        !           832:        }
        !           833:
        !           834:        /* Soft byte expiration. */
        !           835:        if (tdb->tdb_flags & TDBF_SOFT_BYTES &&
        !           836:            tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes) {
        !           837:                pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
        !           838:                tdb->tdb_flags &= ~TDBF_SOFT_BYTES;    /* Turn off checking. */
        !           839:        }
        !           840:
        !           841:        /*
        !           842:         * Loop through mbuf chain; if we find a readonly mbuf,
        !           843:         * replace the rest of the chain.
        !           844:         */
        !           845:        mo = NULL;
        !           846:        mi = m;
        !           847:        while (mi != NULL && !M_READONLY(mi)) {
        !           848:                mo = mi;
        !           849:                mi = mi->m_next;
        !           850:        }
        !           851:
        !           852:        if (mi != NULL) {
        !           853:                /* Replace the rest of the mbuf chain. */
        !           854:                struct mbuf *n = m_copym2(mi, 0, M_COPYALL, M_DONTWAIT);
        !           855:
        !           856:                if (n == NULL) {
        !           857:                        DPRINTF(("esp_output(): bad mbuf chain, SA %s/%08x\n",
        !           858:                            ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
        !           859:                        espstat.esps_hdrops++;
        !           860:                        m_freem(m);
        !           861:                        return ENOBUFS;
        !           862:                }
        !           863:
        !           864:                if (mo != NULL)
        !           865:                        mo->m_next = n;
        !           866:                else
        !           867:                        m = n;
        !           868:
        !           869:                m_freem(mi);
        !           870:        }
        !           871:
        !           872:        /* Inject ESP header. */
        !           873:        mo = m_inject(m, skip, hlen, M_DONTWAIT);
        !           874:        if (mo == NULL) {
        !           875:                DPRINTF(("esp_output(): failed to inject ESP header for "
        !           876:                    "SA %s/%08x\n", ipsp_address(tdb->tdb_dst),
        !           877:                    ntohl(tdb->tdb_spi)));
        !           878:                m_freem(m);
        !           879:                espstat.esps_hdrops++;
        !           880:                return ENOBUFS;
        !           881:        }
        !           882:
        !           883:        /* Initialize ESP header. */
        !           884:        bcopy((caddr_t) &tdb->tdb_spi, mtod(mo, caddr_t), sizeof(u_int32_t));
        !           885:        if (!(tdb->tdb_flags & TDBF_NOREPLAY)) {
        !           886:                u_int32_t replay = htonl(tdb->tdb_rpl++);
        !           887:                bcopy((caddr_t) &replay, mtod(mo, caddr_t) + sizeof(u_int32_t),
        !           888:                    sizeof(u_int32_t));
        !           889: #if NPFSYNC > 0
        !           890:                pfsync_update_tdb(tdb,1);
        !           891: #endif
        !           892:        }
        !           893:
        !           894:        /*
        !           895:         * Add padding -- better to do it ourselves than use the crypto engine,
        !           896:         * although if/when we support compression, we'd have to do that.
        !           897:         */
        !           898:        pad = (u_char *) m_pad(m, padding + alen);
        !           899:        if (pad == NULL) {
        !           900:                DPRINTF(("esp_output(): m_pad() failed for SA %s/%08x\n",
        !           901:                    ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
        !           902:                return ENOBUFS;
        !           903:        }
        !           904:
        !           905:        /* Self-describing or random padding ? */
        !           906:        if (!(tdb->tdb_flags & TDBF_RANDOMPADDING))
        !           907:                for (ilen = 0; ilen < padding - 2; ilen++)
        !           908:                        pad[ilen] = ilen + 1;
        !           909:        else
        !           910:                arc4random_bytes((void *) pad, padding - 2);
        !           911:
        !           912:        /* Fix padding length and Next Protocol in padding itself. */
        !           913:        pad[padding - 2] = padding - 2;
        !           914:        m_copydata(m, protoff, sizeof(u_int8_t), pad + padding - 1);
        !           915:
        !           916:        /* Fix Next Protocol in IPv4/IPv6 header. */
        !           917:        prot = IPPROTO_ESP;
        !           918:        m_copyback(m, protoff, sizeof(u_int8_t), &prot);
        !           919:
        !           920:        /* Get crypto descriptors. */
        !           921:        crp = crypto_getreq(esph && espx ? 2 : 1);
        !           922:        if (crp == NULL) {
        !           923:                m_freem(m);
        !           924:                DPRINTF(("esp_output(): failed to acquire crypto "
        !           925:                    "descriptors\n"));
        !           926:                espstat.esps_crypto++;
        !           927:                return ENOBUFS;
        !           928:        }
        !           929:
        !           930:        if (espx) {
        !           931:                crde = crp->crp_desc;
        !           932:                crda = crde->crd_next;
        !           933:
        !           934:                /* Encryption descriptor. */
        !           935:                crde->crd_skip = skip + hlen;
        !           936:                crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen);
        !           937:                crde->crd_flags = CRD_F_ENCRYPT;
        !           938:                crde->crd_inject = skip + hlen - tdb->tdb_ivlen;
        !           939:
        !           940:                if (tdb->tdb_flags & TDBF_HALFIV) {
        !           941:                        /* Copy half-iv in the packet. */
        !           942:                        m_copyback(m, crde->crd_inject, tdb->tdb_ivlen,
        !           943:                            tdb->tdb_iv);
        !           944:
        !           945:                        /* Cook half-iv. */
        !           946:                        bcopy(tdb->tdb_iv, crde->crd_iv, tdb->tdb_ivlen);
        !           947:                        for (ilen = 0; ilen < tdb->tdb_ivlen; ilen++)
        !           948:                                crde->crd_iv[tdb->tdb_ivlen + ilen] =
        !           949:                                    ~crde->crd_iv[ilen];
        !           950:
        !           951:                        crde->crd_flags |=
        !           952:                            CRD_F_IV_PRESENT | CRD_F_IV_EXPLICIT;
        !           953:                }
        !           954:
        !           955:                /* Encryption operation. */
        !           956:                crde->crd_alg = espx->type;
        !           957:                crde->crd_key = tdb->tdb_emxkey;
        !           958:                crde->crd_klen = tdb->tdb_emxkeylen * 8;
        !           959:                /* XXX Rounds ? */
        !           960:        } else
        !           961:                crda = crp->crp_desc;
        !           962:
        !           963:        /* IPsec-specific opaque crypto info. */
        !           964:        MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto),
        !           965:            M_XDATA, M_NOWAIT);
        !           966:        if (tc == NULL) {
        !           967:                m_freem(m);
        !           968:                crypto_freereq(crp);
        !           969:                DPRINTF(("esp_output(): failed to allocate tdb_crypto\n"));
        !           970:                espstat.esps_crypto++;
        !           971:                return ENOBUFS;
        !           972:        }
        !           973:
        !           974:        bzero(tc, sizeof(struct tdb_crypto));
        !           975:        tc->tc_spi = tdb->tdb_spi;
        !           976:        tc->tc_proto = tdb->tdb_sproto;
        !           977:        bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union));
        !           978:
        !           979:        /* Crypto operation descriptor. */
        !           980:        crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */
        !           981:        crp->crp_flags = CRYPTO_F_IMBUF;
        !           982:        crp->crp_buf = (caddr_t) m;
        !           983:        crp->crp_callback = (int (*) (struct cryptop *)) esp_output_cb;
        !           984:        crp->crp_opaque = (caddr_t) tc;
        !           985:        crp->crp_sid = tdb->tdb_cryptoid;
        !           986:
        !           987:        if (esph) {
        !           988:                /* Authentication descriptor. */
        !           989:                crda->crd_skip = skip;
        !           990:                crda->crd_len = m->m_pkthdr.len - (skip + alen);
        !           991:                crda->crd_inject = m->m_pkthdr.len - alen;
        !           992:
        !           993:                /* Authentication operation. */
        !           994:                crda->crd_alg = esph->type;
        !           995:                crda->crd_key = tdb->tdb_amxkey;
        !           996:                crda->crd_klen = tdb->tdb_amxkeylen * 8;
        !           997:        }
        !           998:
        !           999:        if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0)
        !          1000:                return crypto_dispatch(crp);
        !          1001:        else
        !          1002:                return esp_output_cb(crp);
        !          1003: }
        !          1004:
        !          1005: /*
        !          1006:  * ESP output callback, called directly by the crypto driver.
        !          1007:  */
        !          1008: int
        !          1009: esp_output_cb(void *op)
        !          1010: {
        !          1011:        struct cryptop *crp = (struct cryptop *) op;
        !          1012:        struct tdb_crypto *tc;
        !          1013:        struct tdb *tdb;
        !          1014:        struct mbuf *m;
        !          1015:        int error, s;
        !          1016:
        !          1017:        tc = (struct tdb_crypto *) crp->crp_opaque;
        !          1018:
        !          1019:        m = (struct mbuf *) crp->crp_buf;
        !          1020:        if (m == NULL) {
        !          1021:                /* Shouldn't happen... */
        !          1022:                FREE(tc, M_XDATA);
        !          1023:                crypto_freereq(crp);
        !          1024:                espstat.esps_crypto++;
        !          1025:                DPRINTF(("esp_output_cb(): bogus returned buffer from "
        !          1026:                    "crypto\n"));
        !          1027:                return (EINVAL);
        !          1028:        }
        !          1029:
        !          1030:
        !          1031:        s = spltdb();
        !          1032:
        !          1033:        tdb = gettdb(tc->tc_spi, &tc->tc_dst, tc->tc_proto);
        !          1034:        if (tdb == NULL) {
        !          1035:                FREE(tc, M_XDATA);
        !          1036:                espstat.esps_notdb++;
        !          1037:                DPRINTF(("esp_output_cb(): TDB is expired while in crypto\n"));
        !          1038:                error = EPERM;
        !          1039:                goto baddone;
        !          1040:        }
        !          1041:
        !          1042:        /* Check for crypto errors. */
        !          1043:        if (crp->crp_etype) {
        !          1044:                if (crp->crp_etype == EAGAIN) {
        !          1045:                        /* Reset the session ID */
        !          1046:                        if (tdb->tdb_cryptoid != 0)
        !          1047:                                tdb->tdb_cryptoid = crp->crp_sid;
        !          1048:                        splx(s);
        !          1049:                        return crypto_dispatch(crp);
        !          1050:                }
        !          1051:                FREE(tc, M_XDATA);
        !          1052:                espstat.esps_noxform++;
        !          1053:                DPRINTF(("esp_output_cb(): crypto error %d\n",
        !          1054:                    crp->crp_etype));
        !          1055:                error = crp->crp_etype;
        !          1056:                goto baddone;
        !          1057:        }
        !          1058:        FREE(tc, M_XDATA);
        !          1059:
        !          1060:        /* Release crypto descriptors. */
        !          1061:        crypto_freereq(crp);
        !          1062:
        !          1063:        /*
        !          1064:         * If we're doing half-iv, keep a copy of the last few bytes of the
        !          1065:         * encrypted part, for use as the next IV. Note that HALF-IV is only
        !          1066:         * supposed to be used without authentication (the old ESP specs).
        !          1067:         */
        !          1068:        if (tdb->tdb_flags & TDBF_HALFIV)
        !          1069:                m_copydata(m, m->m_pkthdr.len - tdb->tdb_ivlen, tdb->tdb_ivlen,
        !          1070:                    tdb->tdb_iv);
        !          1071:
        !          1072:        /* Call the IPsec input callback. */
        !          1073:        error = ipsp_process_done(m, tdb);
        !          1074:        splx(s);
        !          1075:        return error;
        !          1076:
        !          1077:  baddone:
        !          1078:        splx(s);
        !          1079:
        !          1080:        if (m != NULL)
        !          1081:                m_freem(m);
        !          1082:
        !          1083:        crypto_freereq(crp);
        !          1084:
        !          1085:        return error;
        !          1086: }
        !          1087:
        !          1088: /*
        !          1089:  * return 0 on success
        !          1090:  * return 1 for counter == 0
        !          1091:  * return 2 for very old packet
        !          1092:  * return 3 for packet within current window but already received
        !          1093:  */
        !          1094: int
        !          1095: checkreplaywindow32(u_int32_t seq, u_int32_t initial, u_int32_t *lastseq,
        !          1096:     u_int32_t window, u_int32_t *bitmap, int commit)
        !          1097: {
        !          1098:        u_int32_t diff, llseq, lbitmap;
        !          1099:
        !          1100:        /* Just do the checking, without "committing" any changes. */
        !          1101:        if (commit == 0) {
        !          1102:                llseq = *lastseq;
        !          1103:                lbitmap = *bitmap;
        !          1104:
        !          1105:                lastseq = &llseq;
        !          1106:                bitmap = &lbitmap;
        !          1107:        }
        !          1108:
        !          1109:        seq -= initial;
        !          1110:
        !          1111:        if (seq == 0)
        !          1112:                return 1;
        !          1113:
        !          1114:        if (seq > *lastseq - initial) {
        !          1115:                diff = seq - (*lastseq - initial);
        !          1116:                if (diff < window)
        !          1117:                        *bitmap = ((*bitmap) << diff) | 1;
        !          1118:                else
        !          1119:                        *bitmap = 1;
        !          1120:                *lastseq = seq + initial;
        !          1121:                return 0;
        !          1122:        }
        !          1123:
        !          1124:        diff = *lastseq - initial - seq;
        !          1125:        if (diff >= window) {
        !          1126:                espstat.esps_wrap++;
        !          1127:                return 2;
        !          1128:        }
        !          1129:
        !          1130:        if ((*bitmap) & (((u_int32_t) 1) << diff)) {
        !          1131:                espstat.esps_replay++;
        !          1132:                return 3;
        !          1133:        }
        !          1134:
        !          1135:        *bitmap |= (((u_int32_t) 1) << diff);
        !          1136:        return 0;
        !          1137: }
        !          1138:
        !          1139: /*
        !          1140:  * m_pad(m, n) pads <m> with <n> bytes at the end. The packet header
        !          1141:  * length is updated, and a pointer to the first byte of the padding
        !          1142:  * (which is guaranteed to be all in one mbuf) is returned.
        !          1143:  */
        !          1144:
        !          1145: caddr_t
        !          1146: m_pad(struct mbuf *m, int n)
        !          1147: {
        !          1148:        struct mbuf *m0, *m1;
        !          1149:        int len, pad;
        !          1150:        caddr_t retval;
        !          1151:
        !          1152:        if (n <= 0) {  /* No stupid arguments. */
        !          1153:                DPRINTF(("m_pad(): pad length invalid (%d)\n", n));
        !          1154:                m_freem(m);
        !          1155:                return NULL;
        !          1156:        }
        !          1157:
        !          1158:        len = m->m_pkthdr.len;
        !          1159:        pad = n;
        !          1160:        m0 = m;
        !          1161:
        !          1162:        while (m0->m_len < len) {
        !          1163:                len -= m0->m_len;
        !          1164:                m0 = m0->m_next;
        !          1165:        }
        !          1166:
        !          1167:        if (m0->m_len != len) {
        !          1168:                DPRINTF(("m_pad(): length mismatch (should be %d instead of "
        !          1169:                    "%d)\n", m->m_pkthdr.len,
        !          1170:                    m->m_pkthdr.len + m0->m_len - len));
        !          1171:
        !          1172:                m_freem(m);
        !          1173:                return NULL;
        !          1174:        }
        !          1175:
        !          1176:        /* Check for zero-length trailing mbufs, and find the last one. */
        !          1177:        for (m1 = m0; m1->m_next; m1 = m1->m_next) {
        !          1178:                if (m1->m_next->m_len != 0) {
        !          1179:                        DPRINTF(("m_pad(): length mismatch (should be %d "
        !          1180:                            "instead of %d)\n", m->m_pkthdr.len,
        !          1181:                            m->m_pkthdr.len + m1->m_next->m_len));
        !          1182:
        !          1183:                        m_freem(m);
        !          1184:                        return NULL;
        !          1185:                }
        !          1186:
        !          1187:                m0 = m1->m_next;
        !          1188:        }
        !          1189:
        !          1190:        if ((m0->m_flags & M_EXT) ||
        !          1191:            m0->m_data + m0->m_len + pad >= &(m0->m_dat[MLEN])) {
        !          1192:                /* Add an mbuf to the chain. */
        !          1193:                MGET(m1, M_DONTWAIT, MT_DATA);
        !          1194:                if (m1 == 0) {
        !          1195:                        m_freem(m0);
        !          1196:                        DPRINTF(("m_pad(): cannot append\n"));
        !          1197:                        return NULL;
        !          1198:                }
        !          1199:
        !          1200:                m0->m_next = m1;
        !          1201:                m0 = m1;
        !          1202:                m0->m_len = 0;
        !          1203:        }
        !          1204:
        !          1205:        retval = m0->m_data + m0->m_len;
        !          1206:        m0->m_len += pad;
        !          1207:        m->m_pkthdr.len += pad;
        !          1208:
        !          1209:        return retval;
        !          1210: }

CVSweb