LCOV - code coverage report
Current view: top level - netinet - ip_ah.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 450 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 8 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ip_ah.c,v 1.143 2018/08/28 15:15:02 mpi 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/if_var.h>
      48             : #include <net/bpf.h>
      49             : 
      50             : #include <netinet/in.h>
      51             : #include <netinet/ip.h>
      52             : #include <netinet/ip_var.h>
      53             : 
      54             : #ifdef INET6
      55             : #include <netinet/ip6.h>
      56             : #endif /* INET6 */
      57             : 
      58             : #include <netinet/ip_ipsp.h>
      59             : #include <netinet/ip_ah.h>
      60             : #include <net/pfkeyv2.h>
      61             : #include <net/if_enc.h>
      62             : 
      63             : #if NPFSYNC > 0
      64             : #include <net/pfvar.h>
      65             : #include <net/if_pfsync.h>
      66             : #endif /* NPFSYNC > 0 */
      67             : 
      68             : #include <crypto/cryptodev.h>
      69             : #include <crypto/xform.h>
      70             : 
      71             : #include "bpfilter.h"
      72             : 
      73             : #ifdef ENCDEBUG
      74             : #define DPRINTF(x)      if (encdebug) printf x
      75             : #else
      76             : #define DPRINTF(x)
      77             : #endif
      78             : 
      79             : int     ah_massage_headers(struct mbuf **, int, int, int, int);
      80             : 
      81             : const unsigned char ipseczeroes[IPSEC_ZEROES_SIZE]; /* zeroes! */
      82             : 
      83             : 
      84             : /*
      85             :  * ah_attach() is called from the transformation initialization code.
      86             :  */
      87             : int
      88           0 : ah_attach(void)
      89             : {
      90           0 :         return 0;
      91             : }
      92             : 
      93             : /*
      94             :  * ah_init() is called when an SPI is being set up.
      95             :  */
      96             : int
      97           0 : ah_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
      98             : {
      99             :         struct auth_hash *thash = NULL;
     100           0 :         struct cryptoini cria, crin;
     101             : 
     102             :         /* Authentication operation. */
     103           0 :         switch (ii->ii_authalg) {
     104             :         case SADB_AALG_MD5HMAC:
     105             :                 thash = &auth_hash_hmac_md5_96;
     106           0 :                 break;
     107             : 
     108             :         case SADB_AALG_SHA1HMAC:
     109             :                 thash = &auth_hash_hmac_sha1_96;
     110           0 :                 break;
     111             : 
     112             :         case SADB_X_AALG_RIPEMD160HMAC:
     113             :                 thash = &auth_hash_hmac_ripemd_160_96;
     114           0 :                 break;
     115             : 
     116             :         case SADB_X_AALG_SHA2_256:
     117             :                 thash = &auth_hash_hmac_sha2_256_128;
     118           0 :                 break;
     119             : 
     120             :         case SADB_X_AALG_SHA2_384:
     121             :                 thash = &auth_hash_hmac_sha2_384_192;
     122           0 :                 break;
     123             : 
     124             :         case SADB_X_AALG_SHA2_512:
     125             :                 thash = &auth_hash_hmac_sha2_512_256;
     126           0 :                 break;
     127             : 
     128             :         default:
     129             :                 DPRINTF(("%s: unsupported authentication algorithm %d"
     130             :                     " specified\n", __func__, ii->ii_authalg));
     131           0 :                 return EINVAL;
     132             :         }
     133             : 
     134           0 :         if (ii->ii_authkeylen != thash->keysize && thash->keysize != 0) {
     135             :                 DPRINTF(("ah_init(): keylength %d doesn't match algorithm "
     136             :                     "%s keysize (%d)\n", ii->ii_authkeylen, thash->name,
     137             :                     thash->keysize));
     138           0 :                 return EINVAL;
     139             :         }
     140             : 
     141           0 :         tdbp->tdb_xform = xsp;
     142           0 :         tdbp->tdb_authalgxform = thash;
     143           0 :         tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL;
     144             : 
     145             :         DPRINTF(("%s: initialized TDB with hash algorithm %s\n", __func__,
     146             :             thash->name));
     147             : 
     148           0 :         tdbp->tdb_amxkeylen = ii->ii_authkeylen;
     149           0 :         tdbp->tdb_amxkey = malloc(tdbp->tdb_amxkeylen, M_XDATA, M_WAITOK);
     150             : 
     151           0 :         memcpy(tdbp->tdb_amxkey, ii->ii_authkey, tdbp->tdb_amxkeylen);
     152             : 
     153             :         /* Initialize crypto session. */
     154           0 :         memset(&cria, 0, sizeof(cria));
     155           0 :         cria.cri_alg = tdbp->tdb_authalgxform->type;
     156           0 :         cria.cri_klen = ii->ii_authkeylen * 8;
     157           0 :         cria.cri_key = ii->ii_authkey;
     158             : 
     159           0 :         if ((tdbp->tdb_wnd > 0) && (tdbp->tdb_flags & TDBF_ESN)) {
     160           0 :                 memset(&crin, 0, sizeof(crin));
     161           0 :                 crin.cri_alg = CRYPTO_ESN;
     162           0 :                 cria.cri_next = &crin;
     163           0 :         }
     164             : 
     165           0 :         return crypto_newsession(&tdbp->tdb_cryptoid, &cria, 0);
     166           0 : }
     167             : 
     168             : /*
     169             :  * Paranoia.
     170             :  */
     171             : int
     172           0 : ah_zeroize(struct tdb *tdbp)
     173             : {
     174             :         int err;
     175             : 
     176           0 :         if (tdbp->tdb_amxkey) {
     177           0 :                 explicit_bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
     178           0 :                 free(tdbp->tdb_amxkey, M_XDATA, tdbp->tdb_amxkeylen);
     179           0 :                 tdbp->tdb_amxkey = NULL;
     180           0 :         }
     181             : 
     182           0 :         err = crypto_freesession(tdbp->tdb_cryptoid);
     183           0 :         tdbp->tdb_cryptoid = 0;
     184           0 :         return err;
     185             : }
     186             : 
     187             : /*
     188             :  * Massage IPv4/IPv6 headers for AH processing.
     189             :  */
     190             : int
     191           0 : ah_massage_headers(struct mbuf **m0, int af, int skip, int alg, int out)
     192             : {
     193           0 :         struct mbuf *m = *m0;
     194             :         unsigned char *ptr;
     195             :         int off, count;
     196             :         struct ip *ip;
     197             : #ifdef INET6
     198             :         struct ip6_ext *ip6e;
     199           0 :         struct ip6_hdr ip6;
     200             :         int ad, alloc, nxt, noff, error;
     201             : #endif /* INET6 */
     202             : 
     203           0 :         switch (af) {
     204             :         case AF_INET:
     205             :                 /*
     206             :                  * This is the least painful way of dealing with IPv4 header
     207             :                  * and option processing -- just make sure they're in
     208             :                  * contiguous memory.
     209             :                  */
     210           0 :                 *m0 = m = m_pullup(m, skip);
     211           0 :                 if (m == NULL) {
     212             :                         DPRINTF(("%s: m_pullup() failed\n", __func__));
     213           0 :                         ahstat_inc(ahs_hdrops);
     214           0 :                         return ENOBUFS;
     215             :                 }
     216             : 
     217             :                 /* Fix the IP header */
     218           0 :                 ip = mtod(m, struct ip *);
     219           0 :                 ip->ip_tos = 0;
     220           0 :                 ip->ip_ttl = 0;
     221           0 :                 ip->ip_sum = 0;
     222           0 :                 ip->ip_off = 0;
     223             : 
     224           0 :                 ptr = mtod(m, unsigned char *);
     225             : 
     226             :                 /* IPv4 option processing */
     227           0 :                 for (off = sizeof(struct ip); off < skip;) {
     228           0 :                         if (ptr[off] != IPOPT_EOL && ptr[off] != IPOPT_NOP &&
     229           0 :                             off + 1 >= skip) {
     230             :                                 DPRINTF(("%s: illegal IPv4 option length for"
     231             :                                     " option %d\n", __func__, ptr[off]));
     232             : 
     233           0 :                                 ahstat_inc(ahs_hdrops);
     234           0 :                                 m_freem(m);
     235           0 :                                 return EINVAL;
     236             :                         }
     237             : 
     238           0 :                         switch (ptr[off]) {
     239             :                         case IPOPT_EOL:
     240             :                                 off = skip;  /* End the loop. */
     241           0 :                                 break;
     242             : 
     243             :                         case IPOPT_NOP:
     244           0 :                                 off++;
     245           0 :                                 break;
     246             : 
     247             :                         case IPOPT_SECURITY:    /* 0x82 */
     248             :                         case 0x85:      /* Extended security. */
     249             :                         case 0x86:      /* Commercial security. */
     250             :                         case 0x94:      /* Router alert */
     251             :                         case 0x95:      /* RFC1770 */
     252             :                                 /* Sanity check for option length. */
     253           0 :                                 if (ptr[off + 1] < 2) {
     254             :                                         DPRINTF(("%s: illegal IPv4 option"
     255             :                                             " length for option %d\n", __func__,
     256             :                                             ptr[off]));
     257             : 
     258           0 :                                         ahstat_inc(ahs_hdrops);
     259           0 :                                         m_freem(m);
     260           0 :                                         return EINVAL;
     261             :                                 }
     262             : 
     263           0 :                                 off += ptr[off + 1];
     264           0 :                                 break;
     265             : 
     266             :                         case IPOPT_LSRR:
     267             :                         case IPOPT_SSRR:
     268             :                                 /* Sanity check for option length. */
     269           0 :                                 if (ptr[off + 1] < 2) {
     270             :                                         DPRINTF(("%s: illegal IPv4 option"
     271             :                                             " length for option %d\n", __func__,
     272             :                                             ptr[off]));
     273             : 
     274           0 :                                         ahstat_inc(ahs_hdrops);
     275           0 :                                         m_freem(m);
     276           0 :                                         return EINVAL;
     277             :                                 }
     278             : 
     279             :                                 /*
     280             :                                  * On output, if we have either of the
     281             :                                  * source routing options, we should
     282             :                                  * swap the destination address of the
     283             :                                  * IP header with the last address
     284             :                                  * specified in the option, as that is
     285             :                                  * what the destination's IP header
     286             :                                  * will look like.
     287             :                                  */
     288           0 :                                 if (out &&
     289           0 :                                     ptr[off + 1] >= 2 + sizeof(struct in_addr))
     290           0 :                                         memcpy(&ip->ip_dst,
     291             :                                             ptr + off + ptr[off + 1] -
     292             :                                             sizeof(struct in_addr),
     293             :                                             sizeof(struct in_addr));
     294             : 
     295             :                                 /* FALLTHROUGH */
     296             :                         default:
     297             :                                 /* Sanity check for option length. */
     298           0 :                                 if (ptr[off + 1] < 2) {
     299             :                                         DPRINTF(("%s: illegal IPv4 option"
     300             :                                             " length for option %d\n", __func__,
     301             :                                             ptr[off]));
     302           0 :                                         ahstat_inc(ahs_hdrops);
     303           0 :                                         m_freem(m);
     304           0 :                                         return EINVAL;
     305             :                                 }
     306             : 
     307             :                                 /* Zeroize all other options. */
     308             :                                 count = ptr[off + 1];
     309           0 :                                 memset(ptr + off, 0, count);
     310           0 :                                 off += count;
     311           0 :                                 break;
     312             :                         }
     313             : 
     314             :                         /* Sanity check. */
     315           0 :                         if (off > skip)      {
     316             :                                 DPRINTF(("%s: malformed IPv4 options header\n",
     317             :                                     __func__));
     318             : 
     319           0 :                                 ahstat_inc(ahs_hdrops);
     320           0 :                                 m_freem(m);
     321           0 :                                 return EINVAL;
     322             :                         }
     323             :                 }
     324             : 
     325             :                 break;
     326             : 
     327             : #ifdef INET6
     328             :         case AF_INET6:  /* Ugly... */
     329             :                 /* Copy and "cook" the IPv6 header. */
     330           0 :                 m_copydata(m, 0, sizeof(ip6), (caddr_t) &ip6);
     331             : 
     332             :                 /* We don't do IPv6 Jumbograms. */
     333           0 :                 if (ip6.ip6_plen == 0) {
     334             :                         DPRINTF(("%s: unsupported IPv6 jumbogram", __func__));
     335           0 :                         ahstat_inc(ahs_hdrops);
     336           0 :                         m_freem(m);
     337           0 :                         return EMSGSIZE;
     338             :                 }
     339             : 
     340           0 :                 ip6.ip6_flow = 0;
     341           0 :                 ip6.ip6_hlim = 0;
     342           0 :                 ip6.ip6_vfc &= ~IPV6_VERSION_MASK;
     343           0 :                 ip6.ip6_vfc |= IPV6_VERSION;
     344             : 
     345             :                 /* Scoped address handling. */
     346           0 :                 if (IN6_IS_SCOPE_EMBED(&ip6.ip6_src))
     347           0 :                         ip6.ip6_src.s6_addr16[1] = 0;
     348           0 :                 if (IN6_IS_SCOPE_EMBED(&ip6.ip6_dst))
     349           0 :                         ip6.ip6_dst.s6_addr16[1] = 0;
     350             : 
     351             :                 /* Done with IPv6 header. */
     352           0 :                 error = m_copyback(m, 0, sizeof(struct ip6_hdr), &ip6,
     353             :                     M_NOWAIT);
     354           0 :                 if (error) {
     355             :                         DPRINTF(("%s: m_copyback no memory", __func__));
     356           0 :                         ahstat_inc(ahs_hdrops);
     357           0 :                         m_freem(m);
     358           0 :                         return error;
     359             :                 }
     360             : 
     361             :                 /* Let's deal with the remaining headers (if any). */
     362           0 :                 if (skip - sizeof(struct ip6_hdr) > 0) {
     363           0 :                         if (m->m_len <= skip) {
     364           0 :                                 ptr = malloc(skip - sizeof(struct ip6_hdr),
     365             :                                     M_XDATA, M_NOWAIT);
     366           0 :                                 if (ptr == NULL) {
     367             :                                         DPRINTF(("%s: failed to allocate memory"
     368             :                                             " for IPv6 headers\n", __func__));
     369           0 :                                         ahstat_inc(ahs_hdrops);
     370           0 :                                         m_freem(m);
     371           0 :                                         return ENOBUFS;
     372             :                                 }
     373             : 
     374             :                                 /*
     375             :                                  * Copy all the protocol headers after
     376             :                                  * the IPv6 header.
     377             :                                  */
     378           0 :                                 m_copydata(m, sizeof(struct ip6_hdr),
     379           0 :                                     skip - sizeof(struct ip6_hdr), ptr);
     380             :                                 alloc = 1;
     381           0 :                         } else {
     382             :                                 /* No need to allocate memory. */
     383           0 :                                 ptr = mtod(m, unsigned char *) +
     384             :                                     sizeof(struct ip6_hdr);
     385             :                                 alloc = 0;
     386             :                         }
     387             :                 } else
     388             :                         break;
     389             : 
     390           0 :                 nxt = ip6.ip6_nxt;  /* Next header type. */
     391             : 
     392           0 :                 for (off = 0; off < skip - sizeof(struct ip6_hdr);) {
     393           0 :                         if (off + sizeof(struct ip6_ext) >
     394             :                             skip - sizeof(struct ip6_hdr))
     395             :                                 goto error6;
     396           0 :                         ip6e = (struct ip6_ext *)(ptr + off);
     397             : 
     398           0 :                         switch (nxt) {
     399             :                         case IPPROTO_HOPOPTS:
     400             :                         case IPPROTO_DSTOPTS:
     401           0 :                                 noff = off + ((ip6e->ip6e_len + 1) << 3);
     402             : 
     403             :                                 /* Sanity check. */
     404           0 :                                 if (noff > skip - sizeof(struct ip6_hdr))
     405             :                                         goto error6;
     406             : 
     407             :                                 /*
     408             :                                  * Zero out mutable options.
     409             :                                  */
     410           0 :                                 for (count = off + sizeof(struct ip6_ext);
     411           0 :                                      count < noff;) {
     412           0 :                                         if (ptr[count] == IP6OPT_PAD1) {
     413           0 :                                                 count++;
     414           0 :                                                 continue; /* Skip padding. */
     415             :                                         }
     416             : 
     417           0 :                                         if (count + 2 > noff)
     418             :                                                 goto error6;
     419           0 :                                         ad = ptr[count + 1] + 2;
     420           0 :                                         if (count + ad > noff)
     421             :                                                 goto error6;
     422             : 
     423             :                                         /* If mutable option, zeroize. */
     424           0 :                                         if (ptr[count] & IP6OPT_MUTABLE)
     425           0 :                                                 memset(ptr + count, 0, ad);
     426             : 
     427             :                                         count += ad;
     428             :                                 }
     429             : 
     430           0 :                                 if (count != noff)
     431             :                                         goto error6;
     432             :                                 break;
     433             : 
     434             :                         case IPPROTO_ROUTING:
     435             :                                 /*
     436             :                                  * Always include routing headers in
     437             :                                  * computation.
     438             :                                  */
     439             :                             {
     440             :                                 struct ip6_rthdr *rh;
     441             : 
     442           0 :                                 rh = (struct ip6_rthdr *)(ptr + off);
     443             :                                 /*
     444             :                                  * must adjust content to make it look like
     445             :                                  * its final form (as seen at the final
     446             :                                  * destination).
     447             :                                  * we only know how to massage type 0 routing
     448             :                                  * header.
     449             :                                  */
     450           0 :                                 if (out && rh->ip6r_type == IPV6_RTHDR_TYPE_0) {
     451             :                                         struct ip6_rthdr0 *rh0;
     452           0 :                                         struct in6_addr *addr, finaldst;
     453             :                                         int i;
     454             : 
     455           0 :                                         rh0 = (struct ip6_rthdr0 *)rh;
     456           0 :                                         addr = (struct in6_addr *)(rh0 + 1);
     457             : 
     458           0 :                                         for (i = 0; i < rh0->ip6r0_segleft; i++)
     459           0 :                                                 if (IN6_IS_SCOPE_EMBED(&addr[i]))
     460           0 :                                                         addr[i].s6_addr16[1] = 0;
     461             : 
     462           0 :                                         finaldst = addr[rh0->ip6r0_segleft - 1];
     463           0 :                                         memmove(&addr[1], &addr[0],
     464             :                                             sizeof(struct in6_addr) *
     465             :                                             (rh0->ip6r0_segleft - 1));
     466             : 
     467           0 :                                         m_copydata(m, 0, sizeof(ip6),
     468             :                                             (caddr_t)&ip6);
     469           0 :                                         addr[0] = ip6.ip6_dst;
     470           0 :                                         ip6.ip6_dst = finaldst;
     471           0 :                                         error = m_copyback(m, 0, sizeof(ip6),
     472             :                                             &ip6, M_NOWAIT);
     473           0 :                                         if (error) {
     474           0 :                                                 if (alloc)
     475           0 :                                                         free(ptr, M_XDATA, 0);
     476           0 :                                                 ahstat_inc(ahs_hdrops);
     477           0 :                                                 m_freem(m);
     478           0 :                                                 return error;
     479             :                                         }
     480           0 :                                         rh0->ip6r0_segleft = 0;
     481           0 :                                 }
     482           0 :                                 break;
     483             :                             }
     484             : 
     485             :                         default:
     486             :                                 DPRINTF(("%s: unexpected IPv6 header type %d\n",
     487             :                                     __func__, off));
     488             : error6:
     489           0 :                                 if (alloc)
     490           0 :                                         free(ptr, M_XDATA, 0);
     491           0 :                                 ahstat_inc(ahs_hdrops);
     492           0 :                                 m_freem(m);
     493           0 :                                 return EINVAL;
     494             :                         }
     495             : 
     496             :                         /* Advance. */
     497           0 :                         off += ((ip6e->ip6e_len + 1) << 3);
     498           0 :                         nxt = ip6e->ip6e_nxt;
     499             :                 }
     500             : 
     501             :                 /* Copyback and free, if we allocated. */
     502           0 :                 if (alloc) {
     503           0 :                         error = m_copyback(m, sizeof(struct ip6_hdr),
     504           0 :                             skip - sizeof(struct ip6_hdr), ptr, M_NOWAIT);
     505           0 :                         free(ptr, M_XDATA, 0);
     506           0 :                         if (error) {
     507           0 :                                 ahstat_inc(ahs_hdrops);
     508           0 :                                 m_freem(m);
     509           0 :                                 return error;
     510             :                         }
     511             :                 }
     512             : 
     513             :                 break;
     514             : #endif /* INET6 */
     515             :         }
     516             : 
     517           0 :         return 0;
     518           0 : }
     519             : 
     520             : /*
     521             :  * ah_input() gets called to verify that an input packet
     522             :  * passes authentication.
     523             :  */
     524             : int
     525           0 : ah_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
     526             : {
     527           0 :         struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
     528             :         struct tdb_crypto *tc = NULL;
     529           0 :         u_int32_t btsx, esn;
     530           0 :         u_int8_t hl;
     531             :         int error, rplen;
     532             :         u_int64_t ibytes;
     533             : #ifdef ENCDEBUG
     534             :         char buf[INET6_ADDRSTRLEN];
     535             : #endif
     536             :         struct cryptodesc *crda = NULL;
     537             :         struct cryptop *crp = NULL;
     538             : 
     539             :         rplen = AH_FLENGTH + sizeof(u_int32_t);
     540             : 
     541             :         /* Save the AH header, we use it throughout. */
     542           0 :         m_copydata(m, skip + offsetof(struct ah, ah_hl), sizeof(u_int8_t),
     543             :             (caddr_t) &hl);
     544             : 
     545             :         /* Replay window checking, if applicable. */
     546           0 :         if (tdb->tdb_wnd > 0) {
     547           0 :                 m_copydata(m, skip + offsetof(struct ah, ah_rpl),
     548             :                     sizeof(u_int32_t), (caddr_t) &btsx);
     549           0 :                 btsx = ntohl(btsx);
     550             : 
     551           0 :                 switch (checkreplaywindow(tdb, btsx, &esn, 0)) {
     552             :                 case 0: /* All's well. */
     553             :                         break;
     554             :                 case 1:
     555             :                         DPRINTF(("%s: replay counter wrapped for SA %s/%08x\n",
     556             :                             __func__, ipsp_address(&tdb->tdb_dst, buf,
     557             :                             sizeof(buf)), ntohl(tdb->tdb_spi)));
     558           0 :                         ahstat_inc(ahs_wrap);
     559             :                         error = ENOBUFS;
     560           0 :                         goto drop;
     561             :                 case 2:
     562             :                         DPRINTF(("%s: old packet received in SA %s/%08x\n",
     563             :                             __func__, ipsp_address(&tdb->tdb_dst, buf,
     564             :                             sizeof(buf)), ntohl(tdb->tdb_spi)));
     565           0 :                         ahstat_inc(ahs_replay);
     566             :                         error = ENOBUFS;
     567           0 :                         goto drop;
     568             :                 case 3:
     569             :                         DPRINTF(("%s: duplicate packet received in SA "
     570             :                             "%s/%08x\n", __func__,
     571             :                             ipsp_address(&tdb->tdb_dst, buf,
     572             :                             sizeof(buf)), ntohl(tdb->tdb_spi)));
     573           0 :                         ahstat_inc(ahs_replay);
     574             :                         error = ENOBUFS;
     575           0 :                         goto drop;
     576             :                 default:
     577             :                         DPRINTF(("%s: bogus value from "
     578             :                             "checkreplaywindow() in SA %s/%08x\n", __func__,
     579             :                             ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
     580             :                             ntohl(tdb->tdb_spi)));
     581           0 :                         ahstat_inc(ahs_replay);
     582             :                         error = ENOBUFS;
     583           0 :                         goto drop;
     584             :                 }
     585             :         }
     586             : 
     587             :         /* Verify AH header length. */
     588           0 :         if (hl * sizeof(u_int32_t) != ahx->authsize + rplen - AH_FLENGTH) {
     589             :                 DPRINTF(("%s: bad authenticator length %ld for packet "
     590             :                     "in SA %s/%08x\n", __func__, hl * sizeof(u_int32_t),
     591             :                     ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
     592             :                     ntohl(tdb->tdb_spi)));
     593           0 :                 ahstat_inc(ahs_badauthl);
     594             :                 error = EACCES;
     595           0 :                 goto drop;
     596             :         }
     597           0 :         if (skip + ahx->authsize + rplen > m->m_pkthdr.len) {
     598             :                 DPRINTF(("%s: bad mbuf length %d (expecting %d) "
     599             :                     "for packet in SA %s/%08x\n", __func__,
     600             :                     m->m_pkthdr.len, skip + ahx->authsize + rplen,
     601             :                     ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
     602             :                     ntohl(tdb->tdb_spi)));
     603           0 :                 ahstat_inc(ahs_badauthl);
     604             :                 error = EACCES;
     605           0 :                 goto drop;
     606             :         }
     607             : 
     608             :         /* Update the counters. */
     609           0 :         ibytes = (m->m_pkthdr.len - skip - hl * sizeof(u_int32_t));
     610           0 :         tdb->tdb_cur_bytes += ibytes;
     611           0 :         tdb->tdb_ibytes += ibytes;
     612           0 :         ahstat_add(ahs_ibytes, ibytes);
     613             : 
     614             :         /* Hard expiration. */
     615           0 :         if (tdb->tdb_flags & TDBF_BYTES &&
     616           0 :             tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) {
     617           0 :                 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
     618           0 :                 tdb_delete(tdb);
     619             :                 error = ENXIO;
     620           0 :                 goto drop;
     621             :         }
     622             : 
     623             :         /* Notify on expiration. */
     624           0 :         if (tdb->tdb_flags & TDBF_SOFT_BYTES &&
     625           0 :             tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes) {
     626           0 :                 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
     627           0 :                 tdb->tdb_flags &= ~TDBF_SOFT_BYTES;  /* Turn off checking. */
     628           0 :         }
     629             : 
     630             :         /* Get crypto descriptors. */
     631           0 :         crp = crypto_getreq(1);
     632           0 :         if (crp == NULL) {
     633             :                 DPRINTF(("%s: failed to acquire crypto descriptors\n",
     634             :                     __func__));
     635           0 :                 ahstat_inc(ahs_crypto);
     636             :                 error = ENOBUFS;
     637           0 :                 goto drop;
     638             :         }
     639             : 
     640           0 :         crda = &crp->crp_desc[0];
     641             : 
     642           0 :         crda->crd_skip = 0;
     643           0 :         crda->crd_len = m->m_pkthdr.len;
     644           0 :         crda->crd_inject = skip + rplen;
     645             : 
     646             :         /* Authentication operation. */
     647           0 :         crda->crd_alg = ahx->type;
     648           0 :         crda->crd_key = tdb->tdb_amxkey;
     649           0 :         crda->crd_klen = tdb->tdb_amxkeylen * 8;
     650             : 
     651           0 :         if ((tdb->tdb_wnd > 0) && (tdb->tdb_flags & TDBF_ESN)) {
     652           0 :                 esn = htonl(esn);
     653           0 :                 memcpy(crda->crd_esn, &esn, 4);
     654           0 :                 crda->crd_flags |= CRD_F_ESN;
     655           0 :         }
     656             : 
     657             :         /* Allocate IPsec-specific opaque crypto info. */
     658           0 :         tc = malloc(sizeof(*tc) + skip + rplen + ahx->authsize, M_XDATA,
     659             :             M_NOWAIT | M_ZERO);
     660           0 :         if (tc == NULL) {
     661             :                 DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__));
     662           0 :                 ahstat_inc(ahs_crypto);
     663             :                 error = ENOBUFS;
     664           0 :                 goto drop;
     665             :         }
     666             : 
     667             :         /*
     668             :          * Save the authenticator, the skipped portion of the packet,
     669             :          * and the AH header.
     670             :          */
     671           0 :         m_copydata(m, 0, skip + rplen + ahx->authsize, (caddr_t) (tc + 1));
     672             : 
     673             :         /* Zeroize the authenticator on the packet. */
     674           0 :         m_copyback(m, skip + rplen, ahx->authsize, ipseczeroes, M_NOWAIT);
     675             : 
     676             :         /* "Massage" the packet headers for crypto processing. */
     677           0 :         error = ah_massage_headers(&m, tdb->tdb_dst.sa.sa_family, skip,
     678           0 :             ahx->type, 0);
     679           0 :         if (error) {
     680             :                 /* mbuf was freed by callee. */
     681           0 :                 m = NULL;
     682           0 :                 goto drop;
     683             :         }
     684             : 
     685             :         /* Crypto operation descriptor. */
     686           0 :         crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */
     687           0 :         crp->crp_flags = CRYPTO_F_IMBUF;
     688           0 :         crp->crp_buf = (caddr_t)m;
     689           0 :         crp->crp_callback = ipsec_input_cb;
     690           0 :         crp->crp_sid = tdb->tdb_cryptoid;
     691           0 :         crp->crp_opaque = (caddr_t)tc;
     692             : 
     693             :         /* These are passed as-is to the callback. */
     694           0 :         tc->tc_skip = skip;
     695           0 :         tc->tc_protoff = protoff;
     696           0 :         tc->tc_spi = tdb->tdb_spi;
     697           0 :         tc->tc_proto = tdb->tdb_sproto;
     698           0 :         tc->tc_rdomain = tdb->tdb_rdomain;
     699           0 :         memcpy(&tc->tc_dst, &tdb->tdb_dst, sizeof(union sockaddr_union));
     700             : 
     701           0 :         return crypto_dispatch(crp);
     702             : 
     703             :  drop:
     704           0 :         m_freem(m);
     705           0 :         crypto_freereq(crp);
     706           0 :         free(tc, M_XDATA, 0);
     707           0 :         return error;
     708           0 : }
     709             : 
     710             : int
     711           0 : ah_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m, int clen)
     712             : {
     713           0 :         struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
     714           0 :         int roff, rplen, skip, protoff;
     715           0 :         u_int32_t btsx, esn;
     716             :         caddr_t ptr;
     717           0 :         unsigned char calc[AH_ALEN_MAX];
     718             :         struct mbuf *m1, *m0;
     719             : #ifdef ENCDEBUG
     720             :         char buf[INET6_ADDRSTRLEN];
     721             : #endif
     722             : 
     723           0 :         NET_ASSERT_LOCKED();
     724             : 
     725           0 :         skip = tc->tc_skip;
     726           0 :         protoff = tc->tc_protoff;
     727             : 
     728             :         rplen = AH_FLENGTH + sizeof(u_int32_t);
     729             : 
     730             :         /* Copy authenticator off the packet. */
     731           0 :         m_copydata(m, skip + rplen, ahx->authsize, calc);
     732             : 
     733           0 :         ptr = (caddr_t) (tc + 1);
     734             : 
     735             :         /* Verify authenticator. */
     736           0 :         if (timingsafe_bcmp(ptr + skip + rplen, calc, ahx->authsize)) {
     737             :                 DPRINTF(("%s: authentication failed for packet in SA %s/%08x\n",
     738             :                     __func__, ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
     739             :                     ntohl(tdb->tdb_spi)));
     740             : 
     741           0 :                 ahstat_inc(ahs_badauth);
     742           0 :                 goto baddone;
     743             :         }
     744             : 
     745             :         /* Fix the Next Protocol field. */
     746           0 :         ((u_int8_t *) ptr)[protoff] = ((u_int8_t *) ptr)[skip];
     747             : 
     748             :         /* Copyback the saved (uncooked) network headers. */
     749           0 :         m_copyback(m, 0, skip, ptr, M_NOWAIT);
     750             : 
     751             :         /* Replay window checking, if applicable. */
     752           0 :         if (tdb->tdb_wnd > 0) {
     753           0 :                 m_copydata(m, skip + offsetof(struct ah, ah_rpl),
     754             :                     sizeof(u_int32_t), (caddr_t) &btsx);
     755           0 :                 btsx = ntohl(btsx);
     756             : 
     757           0 :                 switch (checkreplaywindow(tdb, btsx, &esn, 1)) {
     758             :                 case 0: /* All's well. */
     759             : #if NPFSYNC > 0
     760           0 :                         pfsync_update_tdb(tdb,0);
     761             : #endif
     762             :                         break;
     763             :                 case 1:
     764             :                         DPRINTF(("%s: replay counter wrapped for SA %s/%08x\n",
     765             :                             __func__, ipsp_address(&tdb->tdb_dst, buf,
     766             :                             sizeof(buf)), ntohl(tdb->tdb_spi)));
     767           0 :                         ahstat_inc(ahs_wrap);
     768           0 :                         goto baddone;
     769             :                 case 2:
     770             :                         DPRINTF(("%s: old packet received in SA %s/%08x\n",
     771             :                             __func__, ipsp_address(&tdb->tdb_dst, buf,
     772             :                             sizeof(buf)), ntohl(tdb->tdb_spi)));
     773           0 :                         ahstat_inc(ahs_replay);
     774           0 :                         goto baddone;
     775             :                 case 3:
     776             :                         DPRINTF(("%s): duplicate packet received in "
     777             :                             "SA %s/%08x\n", __func__,
     778             :                             ipsp_address(&tdb->tdb_dst, buf,
     779             :                             sizeof(buf)), ntohl(tdb->tdb_spi)));
     780           0 :                         ahstat_inc(ahs_replay);
     781           0 :                         goto baddone;
     782             :                 default:
     783             :                         DPRINTF(("%s: bogus value from "
     784             :                             "checkreplaywindow() in SA %s/%08x\n", __func__,
     785             :                             ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
     786             :                             ntohl(tdb->tdb_spi)));
     787           0 :                         ahstat_inc(ahs_replay);
     788           0 :                         goto baddone;
     789             :                 }
     790           0 :         }
     791             : 
     792             :         /* Record the beginning of the AH header. */
     793           0 :         m1 = m_getptr(m, skip, &roff);
     794           0 :         if (m1 == NULL) {
     795             :                 DPRINTF(("%s: bad mbuf chain for packet in SA %s/%08x\n",
     796             :                     __func__, ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
     797             :                     ntohl(tdb->tdb_spi)));
     798           0 :                 ahstat_inc(ahs_hdrops);
     799           0 :                 goto baddone;
     800             :         }
     801             : 
     802             :         /* Remove the AH header from the mbuf. */
     803           0 :         if (roff == 0) {
     804             :                 /*
     805             :                  * The AH header was conveniently at the beginning of
     806             :                  * the mbuf.
     807             :                  */
     808           0 :                 m_adj(m1, rplen + ahx->authsize);
     809             :                 /*
     810             :                  * If m1 is the first mbuf, it has set M_PKTHDR and m_adj()
     811             :                  * has already adjusted the packet header length for us.
     812             :                  */
     813           0 :                 if (m1 != m)
     814           0 :                         m->m_pkthdr.len -= rplen + ahx->authsize;
     815             :         } else
     816           0 :                 if (roff + rplen + ahx->authsize >= m1->m_len) {
     817             :                         int adjlen;
     818             : 
     819             :                         /*
     820             :                          * Part or all of the AH header is at the end
     821             :                          * of this mbuf, so first let's remove the
     822             :                          * remainder of the AH header from the
     823             :                          * beginning of the remainder of the mbuf
     824             :                          * chain, if any.
     825             :                          */
     826           0 :                         if (roff + rplen + ahx->authsize > m1->m_len) {
     827           0 :                                 adjlen = roff + rplen + ahx->authsize -
     828             :                                     m1->m_len;
     829             :                                 /* Adjust the next mbuf by the remainder. */
     830           0 :                                 m_adj(m1->m_next, adjlen);
     831             : 
     832             :                                 /*
     833             :                                  * The second mbuf is guaranteed not
     834             :                                  * to have a pkthdr...
     835             :                                  */
     836           0 :                                 m->m_pkthdr.len -= adjlen;
     837           0 :                         }
     838             : 
     839             :                         /* Now, let's unlink the mbuf chain for a second... */
     840           0 :                         m0 = m1->m_next;
     841           0 :                         m1->m_next = NULL;
     842             : 
     843             :                         /*
     844             :                          * ...and trim the end of the first part of
     845             :                          * the chain...sick
     846             :                          */
     847           0 :                         adjlen = m1->m_len - roff;
     848           0 :                         m_adj(m1, -adjlen);
     849             :                         /*
     850             :                          * If m1 is the first mbuf, it has set M_PKTHDR and
     851             :                          * m_adj() has already adjusted the packet header len.
     852             :                          */
     853           0 :                         if (m1 != m)
     854           0 :                                 m->m_pkthdr.len -= adjlen;
     855             : 
     856             :                         /* Finally, let's relink. */
     857           0 :                         m1->m_next = m0;
     858           0 :                 } else {
     859             :                         /*
     860             :                          * The AH header lies in the "middle" of the
     861             :                          * mbuf...do an overlapping copy of the
     862             :                          * remainder of the mbuf over the ESP header.
     863             :                          */
     864           0 :                         bcopy(mtod(m1, u_char *) + roff + rplen +
     865             :                             ahx->authsize, mtod(m1, u_char *) + roff,
     866           0 :                             m1->m_len - (roff + rplen + ahx->authsize));
     867           0 :                         m1->m_len -= rplen + ahx->authsize;
     868           0 :                         m->m_pkthdr.len -= rplen + ahx->authsize;
     869             :                 }
     870             : 
     871           0 :         free(tc, M_XDATA, 0);
     872             : 
     873           0 :         return ipsec_common_input_cb(m, tdb, skip, protoff);
     874             : 
     875             :  baddone:
     876           0 :         m_freem(m);
     877           0 :         free(tc, M_XDATA, 0);
     878           0 :         return -1;
     879           0 : }
     880             : 
     881             : /*
     882             :  * AH output routine, called by ipsp_process_packet().
     883             :  */
     884             : int
     885           0 : ah_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
     886             :     int protoff)
     887             : {
     888           0 :         struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
     889             :         struct cryptodesc *crda;
     890             :         struct tdb_crypto *tc = NULL;
     891             :         struct mbuf *mi;
     892             :         struct cryptop *crp = NULL;
     893           0 :         u_int16_t iplen;
     894           0 :         int error, rplen, roff;
     895           0 :         u_int8_t prot;
     896             :         struct ah *ah;
     897             : #if NBPFILTER > 0
     898             :         struct ifnet *encif;
     899             : #ifdef ENCDEBUG
     900             :         char buf[INET6_ADDRSTRLEN];
     901             : #endif
     902             : 
     903           0 :         if ((encif = enc_getif(tdb->tdb_rdomain, tdb->tdb_tap)) != NULL) {
     904           0 :                 encif->if_opackets++;
     905           0 :                 encif->if_obytes += m->m_pkthdr.len;
     906             : 
     907           0 :                 if (encif->if_bpf) {
     908           0 :                         struct enchdr hdr;
     909             : 
     910           0 :                         memset(&hdr, 0, sizeof(hdr));
     911             : 
     912           0 :                         hdr.af = tdb->tdb_dst.sa.sa_family;
     913           0 :                         hdr.spi = tdb->tdb_spi;
     914           0 :                         hdr.flags |= M_AUTH;
     915             : 
     916           0 :                         bpf_mtap_hdr(encif->if_bpf, (char *)&hdr,
     917           0 :                             ENC_HDRLEN, m, BPF_DIRECTION_OUT, NULL);
     918           0 :                 }
     919             :         }
     920             : #endif
     921             : 
     922           0 :         ahstat_inc(ahs_output);
     923             : 
     924             :         /*
     925             :          * Check for replay counter wrap-around in automatic (not
     926             :          * manual) keying.
     927             :          */
     928           0 :         if ((tdb->tdb_rpl == 0) && (tdb->tdb_wnd > 0)) {
     929             :                 DPRINTF(("%s: SA %s/%08x should have expired\n", __func__,
     930             :                     ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
     931             :                     ntohl(tdb->tdb_spi)));
     932           0 :                 ahstat_inc(ahs_wrap);
     933             :                 error = EINVAL;
     934           0 :                 goto drop;
     935             :         }
     936             : 
     937             :         rplen = AH_FLENGTH + sizeof(u_int32_t);
     938             : 
     939           0 :         switch (tdb->tdb_dst.sa.sa_family) {
     940             :         case AF_INET:
     941             :                 /* Check for IP maximum packet size violations. */
     942           0 :                 if (rplen + ahx->authsize + m->m_pkthdr.len > IP_MAXPACKET) {
     943             :                         DPRINTF(("%s: packet in SA %s/%08x got too big\n",
     944             :                             __func__,
     945             :                             ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
     946             :                             ntohl(tdb->tdb_spi)));
     947           0 :                         ahstat_inc(ahs_toobig);
     948             :                         error = EMSGSIZE;
     949           0 :                         goto drop;
     950             :                 }
     951             :                 break;
     952             : 
     953             : #ifdef INET6
     954             :         case AF_INET6:
     955             :                 /* Check for IPv6 maximum packet size violations. */
     956           0 :                 if (rplen + ahx->authsize + m->m_pkthdr.len > IPV6_MAXPACKET) {
     957             :                         DPRINTF(("%s: packet in SA %s/%08x got too big\n",
     958             :                             __func__, ipsp_address(&tdb->tdb_dst, buf,
     959             :                             sizeof(buf)), ntohl(tdb->tdb_spi)));
     960           0 :                         ahstat_inc(ahs_toobig);
     961             :                         error = EMSGSIZE;
     962           0 :                         goto drop;
     963             :                 }
     964             :                 break;
     965             : #endif /* INET6 */
     966             : 
     967             :         default:
     968             :                 DPRINTF(("%s: unknown/unsupported protocol family %d, "
     969             :                     "SA %s/%08x\n", __func__, tdb->tdb_dst.sa.sa_family,
     970             :                     ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
     971             :                     ntohl(tdb->tdb_spi)));
     972           0 :                 ahstat_inc(ahs_nopf);
     973             :                 error = EPFNOSUPPORT;
     974           0 :                 goto drop;
     975             :         }
     976             : 
     977             :         /* Update the counters. */
     978           0 :         tdb->tdb_cur_bytes += m->m_pkthdr.len - skip;
     979           0 :         ahstat_add(ahs_obytes, m->m_pkthdr.len - skip);
     980             : 
     981             :         /* Hard expiration. */
     982           0 :         if (tdb->tdb_flags & TDBF_BYTES &&
     983           0 :             tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) {
     984           0 :                 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
     985           0 :                 tdb_delete(tdb);
     986             :                 error = EINVAL;
     987           0 :                 goto drop;
     988             :         }
     989             : 
     990             :         /* Notify on expiration. */
     991           0 :         if (tdb->tdb_flags & TDBF_SOFT_BYTES &&
     992           0 :             tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes) {
     993           0 :                 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
     994           0 :                 tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */
     995           0 :         }
     996             : 
     997             :         /*
     998             :          * Loop through mbuf chain; if we find a readonly mbuf,
     999             :          * copy the packet.
    1000             :          */
    1001           0 :         mi = m;
    1002           0 :         while (mi != NULL && !M_READONLY(mi))
    1003           0 :                 mi = mi->m_next;
    1004             : 
    1005           0 :         if (mi != NULL) {
    1006           0 :                 struct mbuf *n = m_dup_pkt(m, 0, M_DONTWAIT);
    1007             : 
    1008           0 :                 if (n == NULL) {
    1009           0 :                         ahstat_inc(ahs_hdrops);
    1010             :                         error = ENOBUFS;
    1011           0 :                         goto drop;
    1012             :                 }
    1013             : 
    1014           0 :                 m_freem(m);
    1015           0 :                 m = n;
    1016           0 :         }
    1017             : 
    1018             :         /* Inject AH header. */
    1019           0 :         mi = m_makespace(m, skip, rplen + ahx->authsize, &roff);
    1020           0 :         if (mi == NULL) {
    1021             :                 DPRINTF(("%s: failed to inject AH header for SA %s/%08x\n",
    1022             :                     __func__, ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
    1023             :                     ntohl(tdb->tdb_spi)));
    1024           0 :                 ahstat_inc(ahs_hdrops);
    1025             :                 error = ENOBUFS;
    1026           0 :                 goto drop;
    1027             :         }
    1028             : 
    1029             :         /*
    1030             :          * The AH header is guaranteed by m_makespace() to be in
    1031             :          * contiguous memory, at 'roff' of the returned mbuf.
    1032             :          */
    1033           0 :         ah = (struct ah *)(mtod(mi, caddr_t) + roff);
    1034             : 
    1035             :         /* Initialize the AH header. */
    1036           0 :         m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &ah->ah_nh);
    1037           0 :         ah->ah_hl = (rplen + ahx->authsize - AH_FLENGTH) / sizeof(u_int32_t);
    1038           0 :         ah->ah_rv = 0;
    1039           0 :         ah->ah_spi = tdb->tdb_spi;
    1040             : 
    1041             :         /* Zeroize authenticator. */
    1042           0 :         m_copyback(m, skip + rplen, ahx->authsize, ipseczeroes, M_NOWAIT);
    1043             : 
    1044           0 :         tdb->tdb_rpl++;
    1045           0 :         ah->ah_rpl = htonl((u_int32_t)(tdb->tdb_rpl & 0xffffffff));
    1046             : #if NPFSYNC > 0
    1047           0 :         pfsync_update_tdb(tdb,1);
    1048             : #endif
    1049             : 
    1050             :         /* Get crypto descriptors. */
    1051           0 :         crp = crypto_getreq(1);
    1052           0 :         if (crp == NULL) {
    1053             :                 DPRINTF(("%s: failed to acquire crypto descriptors\n",
    1054             :                     __func__));
    1055           0 :                 ahstat_inc(ahs_crypto);
    1056             :                 error = ENOBUFS;
    1057           0 :                 goto drop;
    1058             :         }
    1059             : 
    1060           0 :         crda = &crp->crp_desc[0];
    1061             : 
    1062           0 :         crda->crd_skip = 0;
    1063           0 :         crda->crd_inject = skip + rplen;
    1064           0 :         crda->crd_len = m->m_pkthdr.len;
    1065             : 
    1066             :         /* Authentication operation. */
    1067           0 :         crda->crd_alg = ahx->type;
    1068           0 :         crda->crd_key = tdb->tdb_amxkey;
    1069           0 :         crda->crd_klen = tdb->tdb_amxkeylen * 8;
    1070             : 
    1071           0 :         if ((tdb->tdb_wnd > 0) && (tdb->tdb_flags & TDBF_ESN)) {
    1072             :                 u_int32_t esn;
    1073             : 
    1074           0 :                 esn = htonl((u_int32_t)(tdb->tdb_rpl >> 32));
    1075           0 :                 memcpy(crda->crd_esn, &esn, 4);
    1076           0 :                 crda->crd_flags |= CRD_F_ESN;
    1077           0 :         }
    1078             : 
    1079             :         /* Allocate IPsec-specific opaque crypto info. */
    1080           0 :         tc = malloc(sizeof(*tc) + skip, M_XDATA, M_NOWAIT | M_ZERO);
    1081           0 :         if (tc == NULL) {
    1082             :                 DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__));
    1083           0 :                 ahstat_inc(ahs_crypto);
    1084             :                 error = ENOBUFS;
    1085           0 :                 goto drop;
    1086             :         }
    1087             : 
    1088             :         /* Save the skipped portion of the packet. */
    1089           0 :         m_copydata(m, 0, skip, (caddr_t) (tc + 1));
    1090             : 
    1091             :         /*
    1092             :          * Fix IP header length on the header used for
    1093             :          * authentication. We don't need to fix the original
    1094             :          * header length as it will be fixed by our caller.
    1095             :          */
    1096           0 :         switch (tdb->tdb_dst.sa.sa_family) {
    1097             :         case AF_INET:
    1098           0 :                 memcpy((caddr_t) &iplen, ((caddr_t)(tc + 1)) +
    1099             :                     offsetof(struct ip, ip_len), sizeof(u_int16_t));
    1100           0 :                 iplen = htons(ntohs(iplen) + rplen + ahx->authsize);
    1101           0 :                 m_copyback(m, offsetof(struct ip, ip_len),
    1102             :                     sizeof(u_int16_t), &iplen, M_NOWAIT);
    1103           0 :                 break;
    1104             : 
    1105             : #ifdef INET6
    1106             :         case AF_INET6:
    1107           0 :                 memcpy((caddr_t) &iplen, ((caddr_t)(tc + 1)) +
    1108             :                     offsetof(struct ip6_hdr, ip6_plen), sizeof(u_int16_t));
    1109           0 :                 iplen = htons(ntohs(iplen) + rplen + ahx->authsize);
    1110           0 :                 m_copyback(m, offsetof(struct ip6_hdr, ip6_plen),
    1111             :                     sizeof(u_int16_t), &iplen, M_NOWAIT);
    1112           0 :                 break;
    1113             : #endif /* INET6 */
    1114             :         }
    1115             : 
    1116             :         /* Fix the Next Header field in saved header. */
    1117           0 :         ((u_int8_t *) (tc + 1))[protoff] = IPPROTO_AH;
    1118             : 
    1119             :         /* Update the Next Protocol field in the IP header. */
    1120           0 :         prot = IPPROTO_AH;
    1121           0 :         m_copyback(m, protoff, sizeof(u_int8_t), &prot, M_NOWAIT);
    1122             : 
    1123             :         /* "Massage" the packet headers for crypto processing. */
    1124           0 :         error = ah_massage_headers(&m, tdb->tdb_dst.sa.sa_family, skip,
    1125           0 :             ahx->type, 1);
    1126           0 :         if (error) {
    1127             :                 /* mbuf was freed by callee. */
    1128           0 :                 m = NULL;
    1129           0 :                 goto drop;
    1130             :         }
    1131             : 
    1132             :         /* Crypto operation descriptor. */
    1133           0 :         crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */
    1134           0 :         crp->crp_flags = CRYPTO_F_IMBUF;
    1135           0 :         crp->crp_buf = (caddr_t)m;
    1136           0 :         crp->crp_callback = ipsec_output_cb;
    1137           0 :         crp->crp_sid = tdb->tdb_cryptoid;
    1138           0 :         crp->crp_opaque = (caddr_t)tc;
    1139             : 
    1140             :         /* These are passed as-is to the callback. */
    1141           0 :         tc->tc_skip = skip;
    1142           0 :         tc->tc_protoff = protoff;
    1143           0 :         tc->tc_spi = tdb->tdb_spi;
    1144           0 :         tc->tc_proto = tdb->tdb_sproto;
    1145           0 :         tc->tc_rdomain = tdb->tdb_rdomain;
    1146           0 :         memcpy(&tc->tc_dst, &tdb->tdb_dst, sizeof(union sockaddr_union));
    1147             : 
    1148           0 :         return crypto_dispatch(crp);
    1149             : 
    1150             :  drop:
    1151           0 :         m_freem(m);
    1152           0 :         crypto_freereq(crp);
    1153           0 :         free(tc, M_XDATA, 0);
    1154           0 :         return error;
    1155           0 : }
    1156             : 
    1157             : /*
    1158             :  * AH output callback.
    1159             :  */
    1160             : int
    1161           0 : ah_output_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m, int ilen,
    1162             :     int olen)
    1163             : {
    1164           0 :         int skip = tc->tc_skip;
    1165           0 :         caddr_t ptr = (caddr_t) (tc + 1);
    1166             : 
    1167             :         /*
    1168             :          * Copy original headers (with the new protocol number) back
    1169             :          * in place.
    1170             :          */
    1171           0 :         m_copyback(m, 0, skip, ptr, M_NOWAIT);
    1172             : 
    1173             :         /* No longer needed. */
    1174           0 :         free(tc, M_XDATA, 0);
    1175             : 
    1176             :         /* Call the IPsec input callback. */
    1177           0 :         if (ipsp_process_done(m, tdb)) {
    1178           0 :                 ahstat_inc(ahs_outfail);
    1179           0 :                 return -1;
    1180             :         }
    1181             : 
    1182           0 :         return 0;
    1183           0 : }

Generated by: LCOV version 1.13