root/netinet/ip_ah.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ah_attach
  2. ah_init
  3. ah_zeroize
  4. ah_massage_headers
  5. ah_input
  6. ah_input_cb
  7. ah_output
  8. ah_output_cb

    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 }

/* [<][>][^][v][top][bottom][index][help] */