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

Annotation of sys/netinet/ip_ah.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: ip_ah.c,v 1.89 2007/02/14 00:53:48 jsg 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 and Niklas Hallqvist.
                     17:  *
                     18:  * Copyright (c) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
                     19:  * Angelos D. Keromytis and Niels Provos.
                     20:  * Copyright (c) 1999 Niklas Hallqvist.
                     21:  * Copyright (c) 2001 Angelos D. Keromytis.
                     22:  *
                     23:  * Permission to use, copy, and modify this software with or without fee
                     24:  * is hereby granted, provided that this entire notice is included in
                     25:  * all copies of any software which is or includes a copy or
                     26:  * modification of this software.
                     27:  * You may use this code under the GNU public license if you so wish. Please
                     28:  * contribute changes back to the authors under this freer than GPL license
                     29:  * so that we may further the use of strong encryption without limitations to
                     30:  * all.
                     31:  *
                     32:  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
                     33:  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
                     34:  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
                     35:  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
                     36:  * PURPOSE.
                     37:  */
                     38:
                     39: #include "pfsync.h"
                     40:
                     41: #include <sys/param.h>
                     42: #include <sys/systm.h>
                     43: #include <sys/mbuf.h>
                     44: #include <sys/socket.h>
                     45:
                     46: #include <net/if.h>
                     47: #include <net/bpf.h>
                     48:
                     49: #ifdef INET
                     50: #include <netinet/in.h>
                     51: #include <netinet/in_systm.h>
                     52: #include <netinet/ip.h>
                     53: #include <netinet/ip_var.h>
                     54: #endif /* INET */
                     55:
                     56: #ifdef INET6
                     57: #ifndef INET
                     58: #include <netinet/in.h>
                     59: #endif /* INET */
                     60: #include <netinet/ip6.h>
                     61: #endif /* INET6 */
                     62:
                     63: #include <netinet/ip_ipsp.h>
                     64: #include <netinet/ip_ah.h>
                     65: #include <net/pfkeyv2.h>
                     66: #include <net/if_enc.h>
                     67:
                     68: #if NPFSYNC > 0
                     69: #include <net/pfvar.h>
                     70: #include <net/if_pfsync.h>
                     71: #endif /* NPFSYNC > 0 */
                     72:
                     73: #include <crypto/cryptodev.h>
                     74: #include <crypto/xform.h>
                     75:
                     76: #include "bpfilter.h"
                     77:
                     78: #ifdef ENCDEBUG
                     79: #define DPRINTF(x)     if (encdebug) printf x
                     80: #else
                     81: #define DPRINTF(x)
                     82: #endif
                     83:
                     84: struct ahstat ahstat;
                     85:
                     86: /*
                     87:  * ah_attach() is called from the transformation initialization code.
                     88:  */
                     89: int
                     90: ah_attach()
                     91: {
                     92:        return 0;
                     93: }
                     94:
                     95: /*
                     96:  * ah_init() is called when an SPI is being set up.
                     97:  */
                     98: int
                     99: ah_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
                    100: {
                    101:        struct auth_hash *thash = NULL;
                    102:        struct cryptoini cria;
                    103:
                    104:        /* Authentication operation. */
                    105:        switch (ii->ii_authalg) {
                    106:        case SADB_AALG_MD5HMAC:
                    107:                thash = &auth_hash_hmac_md5_96;
                    108:                break;
                    109:
                    110:        case SADB_AALG_SHA1HMAC:
                    111:                thash = &auth_hash_hmac_sha1_96;
                    112:                break;
                    113:
                    114:        case SADB_X_AALG_RIPEMD160HMAC:
                    115:                thash = &auth_hash_hmac_ripemd_160_96;
                    116:                break;
                    117:
                    118:        case SADB_X_AALG_SHA2_256:
                    119:                thash = &auth_hash_hmac_sha2_256_96;
                    120:                break;
                    121:
                    122:        case SADB_X_AALG_SHA2_384:
                    123:                thash = &auth_hash_hmac_sha2_384_96;
                    124:                break;
                    125:
                    126:        case SADB_X_AALG_SHA2_512:
                    127:                thash = &auth_hash_hmac_sha2_512_96;
                    128:                break;
                    129:
                    130:        case SADB_X_AALG_MD5:
                    131:                thash = &auth_hash_key_md5;
                    132:                break;
                    133:
                    134:        case SADB_X_AALG_SHA1:
                    135:                thash = &auth_hash_key_sha1;
                    136:                break;
                    137:
                    138:        default:
                    139:                DPRINTF(("ah_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg));
                    140:                return EINVAL;
                    141:        }
                    142:
                    143:        if (ii->ii_authkeylen != thash->keysize && thash->keysize != 0) {
                    144:                DPRINTF(("ah_init(): keylength %d doesn't match algorithm "
                    145:                    "%s keysize (%d)\n", ii->ii_authkeylen, thash->name,
                    146:                    thash->keysize));
                    147:                return EINVAL;
                    148:        }
                    149:
                    150:        tdbp->tdb_xform = xsp;
                    151:        tdbp->tdb_authalgxform = thash;
                    152:        tdbp->tdb_bitmap = 0;
                    153:        tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL;
                    154:
                    155:        DPRINTF(("ah_init(): initialized TDB with hash algorithm %s\n",
                    156:            thash->name));
                    157:
                    158:        tdbp->tdb_amxkeylen = ii->ii_authkeylen;
                    159:        MALLOC(tdbp->tdb_amxkey, u_int8_t *, tdbp->tdb_amxkeylen, M_XDATA,
                    160:            M_WAITOK);
                    161:
                    162:        bcopy(ii->ii_authkey, tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
                    163:
                    164:        /* Initialize crypto session. */
                    165:        bzero(&cria, sizeof(cria));
                    166:        cria.cri_alg = tdbp->tdb_authalgxform->type;
                    167:        cria.cri_klen = ii->ii_authkeylen * 8;
                    168:        cria.cri_key = ii->ii_authkey;
                    169:
                    170:        return crypto_newsession(&tdbp->tdb_cryptoid, &cria, 0);
                    171: }
                    172:
                    173: /*
                    174:  * Paranoia.
                    175:  */
                    176: int
                    177: ah_zeroize(struct tdb *tdbp)
                    178: {
                    179:        int err;
                    180:
                    181:        if (tdbp->tdb_amxkey) {
                    182:                bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
                    183:                FREE(tdbp->tdb_amxkey, M_XDATA);
                    184:                tdbp->tdb_amxkey = NULL;
                    185:        }
                    186:
                    187:        err = crypto_freesession(tdbp->tdb_cryptoid);
                    188:        tdbp->tdb_cryptoid = 0;
                    189:        return err;
                    190: }
                    191:
                    192: /*
                    193:  * Massage IPv4/IPv6 headers for AH processing.
                    194:  */
                    195: int
                    196: ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out)
                    197: {
                    198:        struct mbuf *m = *m0;
                    199:        unsigned char *ptr;
                    200:        int off, count;
                    201:
                    202: #ifdef INET
                    203:        struct ip *ip;
                    204: #endif /* INET */
                    205:
                    206: #ifdef INET6
                    207:        struct ip6_ext *ip6e;
                    208:        struct ip6_hdr ip6;
                    209:        int ad, alloc, nxt;
                    210: #endif /* INET6 */
                    211:
                    212:        switch (proto) {
                    213: #ifdef INET
                    214:        case AF_INET:
                    215:                /*
                    216:                 * This is the least painful way of dealing with IPv4 header
                    217:                 * and option processing -- just make sure they're in
                    218:                 * contiguous memory.
                    219:                 */
                    220:                *m0 = m = m_pullup(m, skip);
                    221:                if (m == NULL) {
                    222:                        DPRINTF(("ah_massage_headers(): m_pullup() failed\n"));
                    223:                        ahstat.ahs_hdrops++;
                    224:                        return ENOBUFS;
                    225:                }
                    226:
                    227:                /* Fix the IP header */
                    228:                ip = mtod(m, struct ip *);
                    229:                ip->ip_tos = 0;
                    230:                ip->ip_ttl = 0;
                    231:                ip->ip_sum = 0;
                    232:
                    233:                /*
                    234:                 * On input, fix ip_len which has been byte-swapped
                    235:                 * at ip_input().
                    236:                 */
                    237:                if (alg == CRYPTO_MD5_KPDK || alg == CRYPTO_SHA1_KPDK)
                    238:                        ip->ip_off &= htons(IP_DF);
                    239:                else
                    240:                        ip->ip_off = 0;
                    241:
                    242:                ptr = mtod(m, unsigned char *) + sizeof(struct ip);
                    243:
                    244:                /* IPv4 option processing */
                    245:                for (off = sizeof(struct ip); off < skip;) {
                    246:                        if (ptr[off] == IPOPT_EOL || ptr[off] == IPOPT_NOP ||
                    247:                            off + 1 < skip)
                    248:                                ;
                    249:                        else {
                    250:                                DPRINTF(("ah_massage_headers(): illegal IPv4 "
                    251:                                    "option length for option %d\n",
                    252:                                    ptr[off]));
                    253:
                    254:                                ahstat.ahs_hdrops++;
                    255:                                m_freem(m);
                    256:                                return EINVAL;
                    257:                        }
                    258:
                    259:                        switch (ptr[off]) {
                    260:                        case IPOPT_EOL:
                    261:                                off = skip;  /* End the loop. */
                    262:                                break;
                    263:
                    264:                        case IPOPT_NOP:
                    265:                                off++;
                    266:                                break;
                    267:
                    268:                        case IPOPT_SECURITY:    /* 0x82 */
                    269:                        case 0x85:      /* Extended security. */
                    270:                        case 0x86:      /* Commercial security. */
                    271:                        case 0x94:      /* Router alert */
                    272:                        case 0x95:      /* RFC1770 */
                    273:                                /* Sanity check for option length. */
                    274:                                if (ptr[off + 1] < 2) {
                    275:                                        DPRINTF(("ah_massage_headers(): "
                    276:                                            "illegal IPv4 option length for "
                    277:                                            "option %d\n", ptr[off]));
                    278:
                    279:                                        ahstat.ahs_hdrops++;
                    280:                                        m_freem(m);
                    281:                                        return EINVAL;
                    282:                                }
                    283:
                    284:                                off += ptr[off + 1];
                    285:                                break;
                    286:
                    287:                        case IPOPT_LSRR:
                    288:                        case IPOPT_SSRR:
                    289:                                /* Sanity check for option length. */
                    290:                                if (ptr[off + 1] < 2) {
                    291:                                        DPRINTF(("ah_massage_headers(): "
                    292:                                            "illegal IPv4 option length for "
                    293:                                            "option %d\n", ptr[off]));
                    294:
                    295:                                        ahstat.ahs_hdrops++;
                    296:                                        m_freem(m);
                    297:                                        return EINVAL;
                    298:                                }
                    299:
                    300:                                /*
                    301:                                 * On output, if we have either of the
                    302:                                 * source routing options, we should
                    303:                                 * swap the destination address of the
                    304:                                 * IP header with the last address
                    305:                                 * specified in the option, as that is
                    306:                                 * what the destination's IP header
                    307:                                 * will look like.
                    308:                                 */
                    309:                                if (out)
                    310:                                        bcopy(ptr + off + ptr[off + 1] -
                    311:                                            sizeof(struct in_addr),
                    312:                                            &(ip->ip_dst), sizeof(struct in_addr));
                    313:
                    314:                                /* FALLTHROUGH */
                    315:                        default:
                    316:                                /* Sanity check for option length. */
                    317:                                if (ptr[off + 1] < 2) {
                    318:                                        DPRINTF(("ah_massage_headers(): "
                    319:                                            "illegal IPv4 option length for "
                    320:                                            "option %d\n", ptr[off]));
                    321:                                        ahstat.ahs_hdrops++;
                    322:                                        m_freem(m);
                    323:                                        return EINVAL;
                    324:                                }
                    325:
                    326:                                /* Zeroize all other options. */
                    327:                                count = ptr[off + 1];
                    328:                                bcopy(ipseczeroes, ptr, count);
                    329:                                off += count;
                    330:                                break;
                    331:                        }
                    332:
                    333:                        /* Sanity check. */
                    334:                        if (off > skip) {
                    335:                                DPRINTF(("ah_massage_headers(): malformed "
                    336:                                    "IPv4 options header\n"));
                    337:
                    338:                                ahstat.ahs_hdrops++;
                    339:                                m_freem(m);
                    340:                                return EINVAL;
                    341:                        }
                    342:                }
                    343:
                    344:                break;
                    345: #endif /* INET */
                    346:
                    347: #ifdef INET6
                    348:        case AF_INET6:  /* Ugly... */
                    349:                /* Copy and "cook" the IPv6 header. */
                    350:                m_copydata(m, 0, sizeof(ip6), (caddr_t) &ip6);
                    351:
                    352:                /* We don't do IPv6 Jumbograms. */
                    353:                if (ip6.ip6_plen == 0) {
                    354:                        DPRINTF(("ah_massage_headers(): unsupported IPv6 "
                    355:                            "jumbogram"));
                    356:                        ahstat.ahs_hdrops++;
                    357:                        m_freem(m);
                    358:                        return EMSGSIZE;
                    359:                }
                    360:
                    361:                ip6.ip6_flow = 0;
                    362:                ip6.ip6_hlim = 0;
                    363:                ip6.ip6_vfc &= ~IPV6_VERSION_MASK;
                    364:                ip6.ip6_vfc |= IPV6_VERSION;
                    365:
                    366:                /* Scoped address handling. */
                    367:                if (IN6_IS_SCOPE_EMBED(&ip6.ip6_src))
                    368:                        ip6.ip6_src.s6_addr16[1] = 0;
                    369:                if (IN6_IS_SCOPE_EMBED(&ip6.ip6_dst))
                    370:                        ip6.ip6_dst.s6_addr16[1] = 0;
                    371:
                    372:                /* Done with IPv6 header. */
                    373:                m_copyback(m, 0, sizeof(struct ip6_hdr), &ip6);
                    374:
                    375:                /* Let's deal with the remaining headers (if any). */
                    376:                if (skip - sizeof(struct ip6_hdr) > 0) {
                    377:                        if (m->m_len <= skip) {
                    378:                                MALLOC(ptr, unsigned char *,
                    379:                                    skip - sizeof(struct ip6_hdr),
                    380:                                    M_XDATA, M_NOWAIT);
                    381:                                if (ptr == NULL) {
                    382:                                        DPRINTF(("ah_massage_headers(): failed to allocate memory for IPv6 headers\n"));
                    383:                                        ahstat.ahs_hdrops++;
                    384:                                        m_freem(m);
                    385:                                        return ENOBUFS;
                    386:                                }
                    387:
                    388:                                /*
                    389:                                 * Copy all the protocol headers after
                    390:                                 * the IPv6 header.
                    391:                                 */
                    392:                                m_copydata(m, sizeof(struct ip6_hdr),
                    393:                                    skip - sizeof(struct ip6_hdr), ptr);
                    394:                                alloc = 1;
                    395:                        } else {
                    396:                                /* No need to allocate memory. */
                    397:                                ptr = mtod(m, unsigned char *) +
                    398:                                    sizeof(struct ip6_hdr);
                    399:                                alloc = 0;
                    400:                        }
                    401:                } else
                    402:                        break;
                    403:
                    404:                nxt = ip6.ip6_nxt & 0xff; /* Next header type. */
                    405:
                    406:                for (off = 0; off < skip - sizeof(struct ip6_hdr);) {
                    407:                        switch (nxt) {
                    408:                        case IPPROTO_HOPOPTS:
                    409:                        case IPPROTO_DSTOPTS:
                    410:                                ip6e = (struct ip6_ext *) (ptr + off);
                    411:
                    412:                                /*
                    413:                                 * Process the mutable/immutable
                    414:                                 * options -- borrows heavily from the
                    415:                                 * KAME code.
                    416:                                 */
                    417:                                for (count = off + sizeof(struct ip6_ext);
                    418:                                     count < off + ((ip6e->ip6e_len + 1) << 3);) {
                    419:                                        if (ptr[count] == IP6OPT_PAD1) {
                    420:                                                count++;
                    421:                                                continue; /* Skip padding. */
                    422:                                        }
                    423:
                    424:                                        /* Sanity check. */
                    425:                                        if (count > off +
                    426:                                            ((ip6e->ip6e_len + 1) << 3)) {
                    427:                                                ahstat.ahs_hdrops++;
                    428:                                                m_freem(m);
                    429:
                    430:                                                /* Free, if we allocated. */
                    431:                                                if (alloc)
                    432:                                                        FREE(ptr, M_XDATA);
                    433:                                                return EINVAL;
                    434:                                        }
                    435:
                    436:                                        ad = ptr[count + 1];
                    437:
                    438:                                        /* If mutable option, zeroize. */
                    439:                                        if (ptr[count] & IP6OPT_MUTABLE)
                    440:                                                bcopy(ipseczeroes, ptr + count,
                    441:                                                    ptr[count + 1]);
                    442:
                    443:                                        count += ad;
                    444:
                    445:                                        /* Sanity check. */
                    446:                                        if (count >
                    447:                                            skip - sizeof(struct ip6_hdr)) {
                    448:                                                ahstat.ahs_hdrops++;
                    449:                                                m_freem(m);
                    450:
                    451:                                                /* Free, if we allocated. */
                    452:                                                if (alloc)
                    453:                                                        FREE(ptr, M_XDATA);
                    454:                                                return EINVAL;
                    455:                                        }
                    456:                                }
                    457:
                    458:                                /* Advance. */
                    459:                                off += ((ip6e->ip6e_len + 1) << 3);
                    460:                                nxt = ip6e->ip6e_nxt;
                    461:                                break;
                    462:
                    463:                        case IPPROTO_ROUTING:
                    464:                                /*
                    465:                                 * Always include routing headers in
                    466:                                 * computation.
                    467:                                 */
                    468:                            {
                    469:                                struct ip6_rthdr *rh;
                    470:
                    471:                                ip6e = (struct ip6_ext *) (ptr + off);
                    472:                                rh = (struct ip6_rthdr *)(ptr + off);
                    473:                                /*
                    474:                                 * must adjust content to make it look like
                    475:                                 * its final form (as seen at the final
                    476:                                 * destination).
                    477:                                 * we only know how to massage type 0 routing
                    478:                                 * header.
                    479:                                 */
                    480:                                if (out && rh->ip6r_type == IPV6_RTHDR_TYPE_0) {
                    481:                                        struct ip6_rthdr0 *rh0;
                    482:                                        struct in6_addr *addr, finaldst;
                    483:                                        int i;
                    484:
                    485:                                        rh0 = (struct ip6_rthdr0 *)rh;
                    486:                                        addr = (struct in6_addr *)(rh0 + 1);
                    487:
                    488:                                        for (i = 0; i < rh0->ip6r0_segleft; i++)
                    489:                                                if (IN6_IS_SCOPE_EMBED(&addr[i]))
                    490:                                                        addr[i].s6_addr16[1] = 0;
                    491:
                    492:                                        finaldst = addr[rh0->ip6r0_segleft - 1];
                    493:                                        ovbcopy(&addr[0], &addr[1],
                    494:                                            sizeof(struct in6_addr) *
                    495:                                            (rh0->ip6r0_segleft - 1));
                    496:
                    497:                                        m_copydata(m, 0, sizeof(ip6),
                    498:                                            (caddr_t)&ip6);
                    499:                                        addr[0] = ip6.ip6_dst;
                    500:                                        ip6.ip6_dst = finaldst;
                    501:                                        m_copyback(m, 0, sizeof(ip6), &ip6);
                    502:
                    503:                                        rh0->ip6r0_segleft = 0;
                    504:                                }
                    505:
                    506:                                /* advance */
                    507:                                off += ((ip6e->ip6e_len + 1) << 3);
                    508:                                nxt = ip6e->ip6e_nxt;
                    509:                                break;
                    510:                            }
                    511:
                    512:                        default:
                    513:                                DPRINTF(("ah_massage_headers(): unexpected "
                    514:                                    "IPv6 header type %d\n", off));
                    515:                                if (alloc)
                    516:                                        FREE(ptr, M_XDATA);
                    517:                                ahstat.ahs_hdrops++;
                    518:                                m_freem(m);
                    519:                                return EINVAL;
                    520:                        }
                    521:                }
                    522:
                    523:                /* Copyback and free, if we allocated. */
                    524:                if (alloc) {
                    525:                        m_copyback(m, sizeof(struct ip6_hdr),
                    526:                            skip - sizeof(struct ip6_hdr), ptr);
                    527:                        FREE(ptr, M_XDATA);
                    528:                }
                    529:
                    530:                break;
                    531: #endif /* INET6 */
                    532:        }
                    533:
                    534:        return 0;
                    535: }
                    536:
                    537: /*
                    538:  * ah_input() gets called to verify that an input packet
                    539:  * passes authentication.
                    540:  */
                    541: int
                    542: ah_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
                    543: {
                    544:        struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
                    545:        struct tdb_crypto *tc;
                    546:        struct m_tag *mtag;
                    547:        u_int32_t btsx;
                    548:        u_int8_t hl;
                    549:        int rplen;
                    550:
                    551:        struct cryptodesc *crda = NULL;
                    552:        struct cryptop *crp;
                    553:
                    554:        if (!(tdb->tdb_flags & TDBF_NOREPLAY))
                    555:                rplen = AH_FLENGTH + sizeof(u_int32_t);
                    556:        else
                    557:                rplen = AH_FLENGTH;
                    558:
                    559:        /* Save the AH header, we use it throughout. */
                    560:        m_copydata(m, skip + offsetof(struct ah, ah_hl), sizeof(u_int8_t),
                    561:            (caddr_t) &hl);
                    562:
                    563:        /* Replay window checking, if applicable. */
                    564:        if ((tdb->tdb_wnd > 0) && (!(tdb->tdb_flags & TDBF_NOREPLAY))) {
                    565:                m_copydata(m, skip + offsetof(struct ah, ah_rpl),
                    566:                    sizeof(u_int32_t), (caddr_t) &btsx);
                    567:                btsx = ntohl(btsx);
                    568:
                    569:                switch (checkreplaywindow32(btsx, 0, &(tdb->tdb_rpl),
                    570:                    tdb->tdb_wnd, &(tdb->tdb_bitmap), 0)) {
                    571:                case 0: /* All's well. */
                    572:                        break;
                    573:
                    574:                case 1:
                    575:                        DPRINTF(("ah_input(): replay counter wrapped for "
                    576:                            "SA %s/%08x\n", ipsp_address(tdb->tdb_dst),
                    577:                            ntohl(tdb->tdb_spi)));
                    578:
                    579:                        ahstat.ahs_wrap++;
                    580:                        m_freem(m);
                    581:                        return ENOBUFS;
                    582:
                    583:                case 2:
                    584:                case 3:
                    585:                        DPRINTF(("ah_input(): duplicate packet received in "
                    586:                            "SA %s/%08x\n", ipsp_address(tdb->tdb_dst),
                    587:                            ntohl(tdb->tdb_spi)));
                    588:
                    589:                        m_freem(m);
                    590:                        return ENOBUFS;
                    591:
                    592:                default:
                    593:                        DPRINTF(("ah_input(): bogus value from "
                    594:                            "checkreplaywindow32() in SA %s/%08x\n",
                    595:                            ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
                    596:
                    597:                        ahstat.ahs_replay++;
                    598:                        m_freem(m);
                    599:                        return ENOBUFS;
                    600:                }
                    601:        }
                    602:
                    603:        /* Verify AH header length. */
                    604:        if (hl * sizeof(u_int32_t) != ahx->authsize + rplen - AH_FLENGTH) {
                    605:                DPRINTF(("ah_input(): bad authenticator length %d for packet "
                    606:                    "in SA %s/%08x\n", hl * sizeof(u_int32_t),
                    607:                    ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
                    608:
                    609:                ahstat.ahs_badauthl++;
                    610:                m_freem(m);
                    611:                return EACCES;
                    612:        }
                    613:
                    614:        /* Update the counters. */
                    615:        tdb->tdb_cur_bytes +=
                    616:            (m->m_pkthdr.len - skip - hl * sizeof(u_int32_t));
                    617:        ahstat.ahs_ibytes += (m->m_pkthdr.len - skip - hl * sizeof(u_int32_t));
                    618:
                    619:        /* Hard expiration. */
                    620:        if (tdb->tdb_flags & TDBF_BYTES &&
                    621:            tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) {
                    622:                pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
                    623:                tdb_delete(tdb);
                    624:                m_freem(m);
                    625:                return ENXIO;
                    626:        }
                    627:
                    628:        /* Notify on expiration. */
                    629:        if (tdb->tdb_flags & TDBF_SOFT_BYTES &&
                    630:            tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes) {
                    631:                pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
                    632:                tdb->tdb_flags &= ~TDBF_SOFT_BYTES;  /* Turn off checking. */
                    633:        }
                    634:
                    635:        /* Get crypto descriptors. */
                    636:        crp = crypto_getreq(1);
                    637:        if (crp == NULL) {
                    638:                m_freem(m);
                    639:                DPRINTF(("ah_input(): failed to acquire crypto "
                    640:                    "descriptors\n"));
                    641:                ahstat.ahs_crypto++;
                    642:                return ENOBUFS;
                    643:        }
                    644:
                    645:        crda = crp->crp_desc;
                    646:
                    647:        crda->crd_skip = 0;
                    648:        crda->crd_len = m->m_pkthdr.len;
                    649:        crda->crd_inject = skip + rplen;
                    650:
                    651:        /* Authentication operation. */
                    652:        crda->crd_alg = ahx->type;
                    653:        crda->crd_key = tdb->tdb_amxkey;
                    654:        crda->crd_klen = tdb->tdb_amxkeylen * 8;
                    655:
                    656: #ifdef notyet
                    657:        /* Find out if we've already done crypto. */
                    658:        for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL);
                    659:             mtag != NULL;
                    660:             mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, mtag)) {
                    661:                struct tdb_ident *tdbi;
                    662:
                    663:                tdbi = (struct tdb_ident *) (mtag + 1);
                    664:                if (tdbi->proto == tdb->tdb_sproto &&
                    665:                    tdbi->spi == tdb->tdb_spi &&
                    666:                    !bcmp(&tdbi->dst, &tdb->tdb_dst,
                    667:                        sizeof(union sockaddr_union)))
                    668:                        break;
                    669:        }
                    670: #else
                    671:        mtag = NULL;
                    672: #endif
                    673:
                    674:        /* Allocate IPsec-specific opaque crypto info. */
                    675:        if (mtag == NULL)
                    676:                MALLOC(tc, struct tdb_crypto *,
                    677:                    sizeof(struct tdb_crypto) + skip +
                    678:                    rplen + ahx->authsize, M_XDATA, M_NOWAIT);
                    679:        else /* Hash verification has already been done successfully. */
                    680:                MALLOC(tc, struct tdb_crypto *, sizeof(struct tdb_crypto),
                    681:                    M_XDATA, M_NOWAIT);
                    682:        if (tc == NULL) {
                    683:                m_freem(m);
                    684:                crypto_freereq(crp);
                    685:                DPRINTF(("ah_input(): failed to allocate tdb_crypto\n"));
                    686:                ahstat.ahs_crypto++;
                    687:                return ENOBUFS;
                    688:        }
                    689:
                    690:        bzero(tc, sizeof(struct tdb_crypto));
                    691:
                    692:        /* Only save information if crypto processing is needed. */
                    693:        if (mtag == NULL) {
                    694:                /*
                    695:                 * Save the authenticator, the skipped portion of the packet,
                    696:                 * and the AH header.
                    697:                 */
                    698:                m_copydata(m, 0, skip + rplen + ahx->authsize,
                    699:                    (caddr_t) (tc + 1));
                    700:
                    701:                /* Zeroize the authenticator on the packet. */
                    702:                m_copyback(m, skip + rplen, ahx->authsize, ipseczeroes);
                    703:
                    704:                /* "Massage" the packet headers for crypto processing. */
                    705:                if ((btsx = ah_massage_headers(&m, tdb->tdb_dst.sa.sa_family,
                    706:                    skip, ahx->type, 0)) != 0) {
                    707:                        /* mbuf will be free'd by callee. */
                    708:                        FREE(tc, M_XDATA);
                    709:                        crypto_freereq(crp);
                    710:                        return btsx;
                    711:                }
                    712:        }
                    713:
                    714:        /* Crypto operation descriptor. */
                    715:        crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */
                    716:        crp->crp_flags = CRYPTO_F_IMBUF;
                    717:        crp->crp_buf = (caddr_t) m;
                    718:        crp->crp_callback = (int (*) (struct cryptop *)) ah_input_cb;
                    719:        crp->crp_sid = tdb->tdb_cryptoid;
                    720:        crp->crp_opaque = (caddr_t) tc;
                    721:
                    722:        /* These are passed as-is to the callback. */
                    723:        tc->tc_skip = skip;
                    724:        tc->tc_protoff = protoff;
                    725:        tc->tc_spi = tdb->tdb_spi;
                    726:        tc->tc_proto = tdb->tdb_sproto;
                    727:        tc->tc_ptr = (caddr_t) mtag; /* Save the mtag we've identified. */
                    728:        bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union));
                    729:
                    730:        if (mtag == NULL)
                    731:                return crypto_dispatch(crp);
                    732:        else
                    733:                return ah_input_cb(crp);
                    734: }
                    735:
                    736: /*
                    737:  * AH input callback, called directly by the crypto driver.
                    738:  */
                    739: int
                    740: ah_input_cb(void *op)
                    741: {
                    742:        int s, roff, rplen, error, skip, protoff;
                    743:        unsigned char calc[AH_ALEN_MAX];
                    744:        struct mbuf *m1, *m0, *m;
                    745:        struct cryptodesc *crd;
                    746:        struct auth_hash *ahx;
                    747:        struct tdb_crypto *tc;
                    748:        struct cryptop *crp;
                    749:        struct m_tag *mtag;
                    750:        struct tdb *tdb;
                    751:        u_int32_t btsx;
                    752:        u_int8_t prot;
                    753:        caddr_t ptr;
                    754:
                    755:        crp = (struct cryptop *) op;
                    756:        crd = crp->crp_desc;
                    757:
                    758:        tc = (struct tdb_crypto *) crp->crp_opaque;
                    759:        skip = tc->tc_skip;
                    760:        protoff = tc->tc_protoff;
                    761:        mtag = (struct m_tag *) tc->tc_ptr;
                    762:
                    763:        m = (struct mbuf *) crp->crp_buf;
                    764:        if (m == NULL) {
                    765:                /* Shouldn't happen... */
                    766:                FREE(tc, M_XDATA);
                    767:                crypto_freereq(crp);
                    768:                ahstat.ahs_crypto++;
                    769:                DPRINTF(("ah_input_cb(): bogus returned buffer from "
                    770:                    "crypto\n"));
                    771:                return (EINVAL);
                    772:        }
                    773:
                    774:        s = spltdb();
                    775:
                    776:        tdb = gettdb(tc->tc_spi, &tc->tc_dst, tc->tc_proto);
                    777:        if (tdb == NULL) {
                    778:                FREE(tc, M_XDATA);
                    779:                ahstat.ahs_notdb++;
                    780:                DPRINTF(("ah_input_cb(): TDB is expired while in crypto"));
                    781:                error = EPERM;
                    782:                goto baddone;
                    783:        }
                    784:
                    785:        ahx = (struct auth_hash *) tdb->tdb_authalgxform;
                    786:
                    787:        /* Check for crypto errors. */
                    788:        if (crp->crp_etype) {
                    789:                if (crp->crp_etype == EAGAIN) {
                    790:                        /* Reset the session ID */
                    791:                        if (tdb->tdb_cryptoid != 0)
                    792:                                tdb->tdb_cryptoid = crp->crp_sid;
                    793:                        splx(s);
                    794:                        return crypto_dispatch(crp);
                    795:                }
                    796:                FREE(tc, M_XDATA);
                    797:                ahstat.ahs_noxform++;
                    798:                DPRINTF(("ah_input_cb(): crypto error %d\n", crp->crp_etype));
                    799:                error = crp->crp_etype;
                    800:                goto baddone;
                    801:        } else {
                    802:                crypto_freereq(crp); /* No longer needed. */
                    803:                crp = NULL;
                    804:        }
                    805:
                    806:        if (!(tdb->tdb_flags & TDBF_NOREPLAY))
                    807:                rplen = AH_FLENGTH + sizeof(u_int32_t);
                    808:        else
                    809:                rplen = AH_FLENGTH;
                    810:
                    811:        /* Copy authenticator off the packet. */
                    812:        m_copydata(m, skip + rplen, ahx->authsize, calc);
                    813:
                    814:        /*
                    815:         * If we have an mtag, we don't need to verify the authenticator --
                    816:         * it has been verified by an IPsec-aware NIC.
                    817:         */
                    818:        if (mtag == NULL) {
                    819:                ptr = (caddr_t) (tc + 1);
                    820:
                    821:                /* Verify authenticator. */
                    822:                if (bcmp(ptr + skip + rplen, calc, ahx->authsize)) {
                    823:                        FREE(tc, M_XDATA);
                    824:
                    825:                        DPRINTF(("ah_input(): authentication failed for "
                    826:                            "packet in SA %s/%08x\n",
                    827:                            ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
                    828:
                    829:                        ahstat.ahs_badauth++;
                    830:                        error = EACCES;
                    831:                        goto baddone;
                    832:                }
                    833:
                    834:                /* Fix the Next Protocol field. */
                    835:                ((u_int8_t *) ptr)[protoff] = ((u_int8_t *) ptr)[skip];
                    836:
                    837:                /* Copyback the saved (uncooked) network headers. */
                    838:                m_copyback(m, 0, skip, ptr);
                    839:        } else {
                    840:                /* Fix the Next Protocol field. */
                    841:                m_copydata(m, skip, sizeof(u_int8_t), &prot);
                    842:                m_copyback(m, protoff, sizeof(u_int8_t), &prot);
                    843:        }
                    844:
                    845:        FREE(tc, M_XDATA);
                    846:
                    847:        /* Replay window checking, if applicable. */
                    848:        if ((tdb->tdb_wnd > 0) && (!(tdb->tdb_flags & TDBF_NOREPLAY))) {
                    849:                m_copydata(m, skip + offsetof(struct ah, ah_rpl),
                    850:                    sizeof(u_int32_t), (caddr_t) &btsx);
                    851:                btsx = ntohl(btsx);
                    852:
                    853:                switch (checkreplaywindow32(btsx, 0, &(tdb->tdb_rpl),
                    854:                    tdb->tdb_wnd, &(tdb->tdb_bitmap), 1)) {
                    855:                case 0: /* All's well. */
                    856: #if NPFSYNC > 0
                    857:                        pfsync_update_tdb(tdb,0);
                    858: #endif
                    859:                        break;
                    860:
                    861:                case 1:
                    862:                        DPRINTF(("ah_input(): replay counter wrapped for "
                    863:                            "SA %s/%08x\n", ipsp_address(tdb->tdb_dst),
                    864:                            ntohl(tdb->tdb_spi)));
                    865:
                    866:                        ahstat.ahs_wrap++;
                    867:                        error = ENOBUFS;
                    868:                        goto baddone;
                    869:
                    870:                case 2:
                    871:                case 3:
                    872:                        DPRINTF(("ah_input_cb(): duplicate packet received in "
                    873:                            "SA %s/%08x\n", ipsp_address(tdb->tdb_dst),
                    874:                            ntohl(tdb->tdb_spi)));
                    875:
                    876:                        error = ENOBUFS;
                    877:                        goto baddone;
                    878:
                    879:                default:
                    880:                        DPRINTF(("ah_input_cb(): bogus value from "
                    881:                            "checkreplaywindow32() in SA %s/%08x\n",
                    882:                            ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
                    883:
                    884:                        ahstat.ahs_replay++;
                    885:                        error = ENOBUFS;
                    886:                        goto baddone;
                    887:                }
                    888:        }
                    889:
                    890:        /* Record the beginning of the AH header. */
                    891:        m1 = m_getptr(m, skip, &roff);
                    892:        if (m1 == NULL) {
                    893:                ahstat.ahs_hdrops++;
                    894:                splx(s);
                    895:                m_freem(m);
                    896:
                    897:                DPRINTF(("ah_input(): bad mbuf chain for packet in SA "
                    898:                    "%s/%08x\n", ipsp_address(tdb->tdb_dst),
                    899:                    ntohl(tdb->tdb_spi)));
                    900:
                    901:                return EINVAL;
                    902:        }
                    903:
                    904:        /* Remove the AH header from the mbuf. */
                    905:        if (roff == 0) {
                    906:                /*
                    907:                 * The AH header was conveniently at the beginning of
                    908:                 * the mbuf.
                    909:                 */
                    910:                m_adj(m1, rplen + ahx->authsize);
                    911:                if (!(m1->m_flags & M_PKTHDR))
                    912:                        m->m_pkthdr.len -= rplen + ahx->authsize;
                    913:        } else
                    914:                if (roff + rplen + ahx->authsize >= m1->m_len) {
                    915:                        /*
                    916:                         * Part or all of the AH header is at the end
                    917:                         * of this mbuf, so first let's remove the
                    918:                         * remainder of the AH header from the
                    919:                         * beginning of the remainder of the mbuf
                    920:                         * chain, if any.
                    921:                         */
                    922:                        if (roff + rplen + ahx->authsize > m1->m_len) {
                    923:                                /* Adjust the next mbuf by the remainder. */
                    924:                                m_adj(m1->m_next, roff + rplen +
                    925:                                    ahx->authsize - m1->m_len);
                    926:
                    927:                                /*
                    928:                                 * The second mbuf is guaranteed not
                    929:                                 * to have a pkthdr...
                    930:                                 */
                    931:                                m->m_pkthdr.len -=
                    932:                                    (roff + rplen + ahx->authsize - m1->m_len);
                    933:                        }
                    934:
                    935:                        /* Now, let's unlink the mbuf chain for a second... */
                    936:                        m0 = m1->m_next;
                    937:                        m1->m_next = NULL;
                    938:
                    939:                        /*
                    940:                         * ...and trim the end of the first part of
                    941:                         * the chain...sick
                    942:                         */
                    943:                        m_adj(m1, -(m1->m_len - roff));
                    944:                        if (!(m1->m_flags & M_PKTHDR))
                    945:                                m->m_pkthdr.len -= (m1->m_len - roff);
                    946:
                    947:                        /* Finally, let's relink. */
                    948:                        m1->m_next = m0;
                    949:                } else {
                    950:                        /*
                    951:                         * The AH header lies in the "middle" of the
                    952:                         * mbuf...do an overlapping copy of the
                    953:                         * remainder of the mbuf over the ESP header.
                    954:                         */
                    955:                        bcopy(mtod(m1, u_char *) + roff + rplen +
                    956:                            ahx->authsize, mtod(m1, u_char *) + roff,
                    957:                            m1->m_len - (roff + rplen + ahx->authsize));
                    958:                        m1->m_len -= rplen + ahx->authsize;
                    959:                        m->m_pkthdr.len -= rplen + ahx->authsize;
                    960:                }
                    961:
                    962:        error = ipsec_common_input_cb(m, tdb, skip, protoff, mtag);
                    963:        splx(s);
                    964:        return (error);
                    965:
                    966:  baddone:
                    967:        splx(s);
                    968:
                    969:        if (m != NULL)
                    970:                m_freem(m);
                    971:
                    972:        if (crp != NULL)
                    973:                crypto_freereq(crp);
                    974:
                    975:        return (error);
                    976: }
                    977:
                    978: /*
                    979:  * AH output routine, called by ipsp_process_packet().
                    980:  */
                    981: int
                    982: ah_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
                    983:     int protoff)
                    984: {
                    985:        struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
                    986:        struct cryptodesc *crda;
                    987:        struct tdb_crypto *tc;
                    988:        struct mbuf *mo, *mi;
                    989:        struct cryptop *crp;
                    990:        u_int16_t iplen;
                    991:        int len, rplen;
                    992:        u_int8_t prot;
                    993:        struct ah *ah;
                    994: #if NBPFILTER > 0
                    995:        struct ifnet *ifn = &(encif[0].sc_if);
                    996:
                    997:        ifn->if_opackets++;
                    998:        ifn->if_obytes += m->m_pkthdr.len;
                    999:
                   1000:        if (ifn->if_bpf) {
                   1001:                struct enchdr hdr;
                   1002:
                   1003:                bzero (&hdr, sizeof(hdr));
                   1004:
                   1005:                hdr.af = tdb->tdb_dst.sa.sa_family;
                   1006:                hdr.spi = tdb->tdb_spi;
                   1007:                hdr.flags |= M_AUTH | M_AUTH_AH;
                   1008:
                   1009:                bpf_mtap_hdr(ifn->if_bpf, (char *)&hdr, ENC_HDRLEN, m,
                   1010:                    BPF_DIRECTION_OUT);
                   1011:        }
                   1012: #endif
                   1013:
                   1014:        ahstat.ahs_output++;
                   1015:
                   1016:        /*
                   1017:         * Check for replay counter wrap-around in automatic (not
                   1018:         * manual) keying.
                   1019:         */
                   1020:        if ((tdb->tdb_rpl == 0) && (tdb->tdb_wnd > 0) &&
                   1021:            (!(tdb->tdb_flags & TDBF_NOREPLAY))) {
                   1022:                DPRINTF(("ah_output(): SA %s/%08x should have expired\n",
                   1023:                    ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
                   1024:                m_freem(m);
                   1025:                ahstat.ahs_wrap++;
                   1026:                return EINVAL;
                   1027:        }
                   1028:
                   1029:        if (!(tdb->tdb_flags & TDBF_NOREPLAY))
                   1030:                rplen = AH_FLENGTH + sizeof(u_int32_t);
                   1031:        else
                   1032:                rplen = AH_FLENGTH;
                   1033:
                   1034:        switch (tdb->tdb_dst.sa.sa_family) {
                   1035: #ifdef INET
                   1036:        case AF_INET:
                   1037:                /* Check for IP maximum packet size violations. */
                   1038:                if (rplen + ahx->authsize + m->m_pkthdr.len > IP_MAXPACKET) {
                   1039:                        DPRINTF(("ah_output(): packet in SA %s/%08x got too "
                   1040:                            "big\n",
                   1041:                            ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
                   1042:                        m_freem(m);
                   1043:                        ahstat.ahs_toobig++;
                   1044:                        return EMSGSIZE;
                   1045:                }
                   1046:                break;
                   1047: #endif /* INET */
                   1048:
                   1049: #ifdef INET6
                   1050:        case AF_INET6:
                   1051:                /* Check for IPv6 maximum packet size violations. */
                   1052:                if (rplen + ahx->authsize + m->m_pkthdr.len > IPV6_MAXPACKET) {
                   1053:                        DPRINTF(("ah_output(): packet in SA %s/%08x "
                   1054:                            "got too big\n", ipsp_address(tdb->tdb_dst),
                   1055:                            ntohl(tdb->tdb_spi)));
                   1056:                        m_freem(m);
                   1057:                        ahstat.ahs_toobig++;
                   1058:                        return EMSGSIZE;
                   1059:                }
                   1060:                break;
                   1061: #endif /* INET6 */
                   1062:
                   1063:        default:
                   1064:                DPRINTF(("ah_output(): unknown/unsupported protocol "
                   1065:                    "family %d, SA %s/%08x\n", tdb->tdb_dst.sa.sa_family,
                   1066:                    ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
                   1067:                m_freem(m);
                   1068:                ahstat.ahs_nopf++;
                   1069:                return EPFNOSUPPORT;
                   1070:        }
                   1071:
                   1072:        /* Update the counters. */
                   1073:        tdb->tdb_cur_bytes += m->m_pkthdr.len - skip;
                   1074:        ahstat.ahs_obytes += m->m_pkthdr.len - skip;
                   1075:
                   1076:        /* Hard expiration. */
                   1077:        if (tdb->tdb_flags & TDBF_BYTES &&
                   1078:            tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) {
                   1079:                pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
                   1080:                tdb_delete(tdb);
                   1081:                m_freem(m);
                   1082:                return EINVAL;
                   1083:        }
                   1084:
                   1085:        /* Notify on expiration. */
                   1086:        if (tdb->tdb_flags & TDBF_SOFT_BYTES &&
                   1087:            tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes) {
                   1088:                pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
                   1089:                tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */
                   1090:        }
                   1091:
                   1092:        /*
                   1093:         * Loop through mbuf chain; if we find a readonly mbuf,
                   1094:         * replace the rest of the chain.
                   1095:         */
                   1096:        mo = NULL;
                   1097:        mi = m;
                   1098:        while (mi != NULL && !M_READONLY(mi)) {
                   1099:                mo = mi;
                   1100:                mi = mi->m_next;
                   1101:        }
                   1102:
                   1103:        if (mi != NULL) {
                   1104:                /* Replace the rest of the mbuf chain. */
                   1105:                struct mbuf *n = m_copym2(mi, 0, M_COPYALL, M_DONTWAIT);
                   1106:
                   1107:                if (n == NULL) {
                   1108:                        ahstat.ahs_hdrops++;
                   1109:                        m_freem(m);
                   1110:                        return ENOBUFS;
                   1111:                }
                   1112:
                   1113:                if (mo != NULL)
                   1114:                        mo->m_next = n;
                   1115:                else
                   1116:                        m = n;
                   1117:
                   1118:                m_freem(mi);
                   1119:        }
                   1120:
                   1121:        /* Inject AH header. */
                   1122:        mi = m_inject(m, skip, rplen + ahx->authsize, M_DONTWAIT);
                   1123:        if (mi == NULL) {
                   1124:                DPRINTF(("ah_output(): failed to inject AH header for SA "
                   1125:                    "%s/%08x\n", ipsp_address(tdb->tdb_dst),
                   1126:                    ntohl(tdb->tdb_spi)));
                   1127:
                   1128:                m_freem(m);
                   1129:                ahstat.ahs_hdrops++;
                   1130:                return ENOBUFS;
                   1131:        }
                   1132:
                   1133:        /*
                   1134:         * The AH header is guaranteed by m_inject() to be in
                   1135:         * contiguous memory, at the beginning of the returned mbuf.
                   1136:         */
                   1137:        ah = mtod(mi, struct ah *);
                   1138:
                   1139:        /* Initialize the AH header. */
                   1140:        m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &ah->ah_nh);
                   1141:        ah->ah_hl = (rplen + ahx->authsize - AH_FLENGTH) / sizeof(u_int32_t);
                   1142:        ah->ah_rv = 0;
                   1143:        ah->ah_spi = tdb->tdb_spi;
                   1144:
                   1145:        /* Zeroize authenticator. */
                   1146:        m_copyback(m, skip + rplen, ahx->authsize, ipseczeroes);
                   1147:
                   1148:        if (!(tdb->tdb_flags & TDBF_NOREPLAY)) {
                   1149:                ah->ah_rpl = htonl(tdb->tdb_rpl++);
                   1150: #if NPFSYNC > 0
                   1151:                pfsync_update_tdb(tdb,1);
                   1152: #endif
                   1153:        }
                   1154:
                   1155:        /* Get crypto descriptors. */
                   1156:        crp = crypto_getreq(1);
                   1157:        if (crp == NULL) {
                   1158:                m_freem(m);
                   1159:                DPRINTF(("ah_output(): failed to acquire crypto "
                   1160:                    "descriptors\n"));
                   1161:                ahstat.ahs_crypto++;
                   1162:                return ENOBUFS;
                   1163:        }
                   1164:
                   1165:        crda = crp->crp_desc;
                   1166:
                   1167:        crda->crd_skip = 0;
                   1168:        crda->crd_inject = skip + rplen;
                   1169:        crda->crd_len = m->m_pkthdr.len;
                   1170:
                   1171:        /* Authentication operation. */
                   1172:        crda->crd_alg = ahx->type;
                   1173:        crda->crd_key = tdb->tdb_amxkey;
                   1174:        crda->crd_klen = tdb->tdb_amxkeylen * 8;
                   1175:
                   1176:        /* Allocate IPsec-specific opaque crypto info. */
                   1177:        if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0)
                   1178:                MALLOC(tc, struct tdb_crypto *,
                   1179:                    sizeof(struct tdb_crypto) + skip, M_XDATA, M_NOWAIT);
                   1180:        else
                   1181:                MALLOC(tc, struct tdb_crypto *,
                   1182:                    sizeof(struct tdb_crypto), M_XDATA, M_NOWAIT);
                   1183:        if (tc == NULL) {
                   1184:                m_freem(m);
                   1185:                crypto_freereq(crp);
                   1186:                DPRINTF(("ah_output(): failed to allocate tdb_crypto\n"));
                   1187:                ahstat.ahs_crypto++;
                   1188:                return ENOBUFS;
                   1189:        }
                   1190:
                   1191:        bzero(tc, sizeof(struct tdb_crypto));
                   1192:
                   1193:        /* Save the skipped portion of the packet. */
                   1194:        if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0) {
                   1195:                m_copydata(m, 0, skip, (caddr_t) (tc + 1));
                   1196:
                   1197:                /*
                   1198:                 * Fix IP header length on the header used for
                   1199:                 * authentication. We don't need to fix the original
                   1200:                 * header length as it will be fixed by our caller.
                   1201:                 */
                   1202:                switch (tdb->tdb_dst.sa.sa_family) {
                   1203: #ifdef INET
                   1204:                case AF_INET:
                   1205:                        bcopy(((caddr_t)(tc + 1)) +
                   1206:                            offsetof(struct ip, ip_len),
                   1207:                            (caddr_t) &iplen, sizeof(u_int16_t));
                   1208:                        iplen = htons(ntohs(iplen) + rplen + ahx->authsize);
                   1209:                        m_copyback(m, offsetof(struct ip, ip_len),
                   1210:                            sizeof(u_int16_t), &iplen);
                   1211:                        break;
                   1212: #endif /* INET */
                   1213:
                   1214: #ifdef INET6
                   1215:                case AF_INET6:
                   1216:                        bcopy(((caddr_t)(tc + 1)) +
                   1217:                            offsetof(struct ip6_hdr, ip6_plen),
                   1218:                            (caddr_t) &iplen, sizeof(u_int16_t));
                   1219:                        iplen = htons(ntohs(iplen) + rplen + ahx->authsize);
                   1220:                        m_copyback(m, offsetof(struct ip6_hdr, ip6_plen),
                   1221:                            sizeof(u_int16_t), &iplen);
                   1222:                        break;
                   1223: #endif /* INET6 */
                   1224:                }
                   1225:
                   1226:                /* Fix the Next Header field in saved header. */
                   1227:                ((u_int8_t *) (tc + 1))[protoff] = IPPROTO_AH;
                   1228:
                   1229:                /* Update the Next Protocol field in the IP header. */
                   1230:                prot = IPPROTO_AH;
                   1231:                m_copyback(m, protoff, sizeof(u_int8_t), &prot);
                   1232:
                   1233:                /* "Massage" the packet headers for crypto processing. */
                   1234:                if ((len = ah_massage_headers(&m, tdb->tdb_dst.sa.sa_family,
                   1235:                    skip, ahx->type, 1)) != 0) {
                   1236:                        /* mbuf will be free'd by callee. */
                   1237:                        FREE(tc, M_XDATA);
                   1238:                        crypto_freereq(crp);
                   1239:                        return len;
                   1240:                }
                   1241:        } else {
                   1242:                /* Update the Next Protocol field in the IP header. */
                   1243:                prot = IPPROTO_AH;
                   1244:                m_copyback(m, protoff, sizeof(u_int8_t), &prot);
                   1245:        }
                   1246:
                   1247:        /* Crypto operation descriptor. */
                   1248:        crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */
                   1249:        crp->crp_flags = CRYPTO_F_IMBUF;
                   1250:        crp->crp_buf = (caddr_t) m;
                   1251:        crp->crp_callback = (int (*) (struct cryptop *)) ah_output_cb;
                   1252:        crp->crp_sid = tdb->tdb_cryptoid;
                   1253:        crp->crp_opaque = (caddr_t) tc;
                   1254:
                   1255:        /* These are passed as-is to the callback. */
                   1256:        tc->tc_skip = skip;
                   1257:        tc->tc_protoff = protoff;
                   1258:        tc->tc_spi = tdb->tdb_spi;
                   1259:        tc->tc_proto = tdb->tdb_sproto;
                   1260:        bcopy(&tdb->tdb_dst, &tc->tc_dst, sizeof(union sockaddr_union));
                   1261:
                   1262:        if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0)
                   1263:                return crypto_dispatch(crp);
                   1264:        else
                   1265:                return ah_output_cb(crp);
                   1266: }
                   1267:
                   1268: /*
                   1269:  * AH output callback, called directly from the crypto handler.
                   1270:  */
                   1271: int
                   1272: ah_output_cb(void *op)
                   1273: {
                   1274:        int skip, protoff, error;
                   1275:        struct tdb_crypto *tc;
                   1276:        struct cryptop *crp;
                   1277:        struct tdb *tdb;
                   1278:        struct mbuf *m;
                   1279:        caddr_t ptr;
                   1280:        int err, s;
                   1281:
                   1282:        crp = (struct cryptop *) op;
                   1283:        tc = (struct tdb_crypto *) crp->crp_opaque;
                   1284:        skip = tc->tc_skip;
                   1285:        protoff = tc->tc_protoff;
                   1286:        ptr = (caddr_t) (tc + 1);
                   1287:
                   1288:        m = (struct mbuf *) crp->crp_buf;
                   1289:        if (m == NULL) {
                   1290:                /* Shouldn't happen... */
                   1291:                FREE(tc, M_XDATA);
                   1292:                crypto_freereq(crp);
                   1293:                ahstat.ahs_crypto++;
                   1294:                DPRINTF(("ah_output_cb(): bogus returned buffer from "
                   1295:                    "crypto\n"));
                   1296:                return (EINVAL);
                   1297:        }
                   1298:
                   1299:        s = spltdb();
                   1300:
                   1301:        tdb = gettdb(tc->tc_spi, &tc->tc_dst, tc->tc_proto);
                   1302:        if (tdb == NULL) {
                   1303:                FREE(tc, M_XDATA);
                   1304:                ahstat.ahs_notdb++;
                   1305:                DPRINTF(("ah_output_cb(): TDB is expired while in crypto\n"));
                   1306:                error = EPERM;
                   1307:                goto baddone;
                   1308:        }
                   1309:
                   1310:        /* Check for crypto errors. */
                   1311:        if (crp->crp_etype) {
                   1312:                if (crp->crp_etype == EAGAIN) {
                   1313:                        /* Reset the session ID */
                   1314:                        if (tdb->tdb_cryptoid != 0)
                   1315:                                tdb->tdb_cryptoid = crp->crp_sid;
                   1316:                        splx(s);
                   1317:                        return crypto_dispatch(crp);
                   1318:                }
                   1319:                FREE(tc, M_XDATA);
                   1320:                ahstat.ahs_noxform++;
                   1321:                DPRINTF(("ah_output_cb(): crypto error %d\n", crp->crp_etype));
                   1322:                error = crp->crp_etype;
                   1323:                goto baddone;
                   1324:        }
                   1325:
                   1326:        /*
                   1327:         * Copy original headers (with the new protocol number) back
                   1328:         * in place.
                   1329:         */
                   1330:        if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0)
                   1331:                m_copyback(m, 0, skip, ptr);
                   1332:
                   1333:        FREE(tc, M_XDATA);
                   1334:
                   1335:        /* No longer needed. */
                   1336:        crypto_freereq(crp);
                   1337:
                   1338:        err =  ipsp_process_done(m, tdb);
                   1339:        splx(s);
                   1340:        return err;
                   1341:
                   1342:  baddone:
                   1343:        splx(s);
                   1344:
                   1345:        if (m != NULL)
                   1346:                m_freem(m);
                   1347:
                   1348:        crypto_freereq(crp);
                   1349:
                   1350:        return error;
                   1351: }

CVSweb