The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netipsec/xform_ah.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $FreeBSD$       */
    2 /*      $OpenBSD: ip_ah.c,v 1.63 2001/06/26 06:18:58 angelos Exp $ */
    3 /*-
    4  * The authors of this code are John Ioannidis (ji@tla.org),
    5  * Angelos D. Keromytis (kermit@csd.uch.gr) and
    6  * Niels Provos (provos@physnet.uni-hamburg.de).
    7  *
    8  * The original version of this code was written by John Ioannidis
    9  * for BSD/OS in Athens, Greece, in November 1995.
   10  *
   11  * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
   12  * by Angelos D. Keromytis.
   13  *
   14  * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
   15  * and Niels Provos.
   16  *
   17  * Additional features in 1999 by Angelos D. Keromytis and Niklas Hallqvist.
   18  *
   19  * Copyright (c) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
   20  * Angelos D. Keromytis and Niels Provos.
   21  * Copyright (c) 1999 Niklas Hallqvist.
   22  * Copyright (c) 2001 Angelos D. Keromytis.
   23  *
   24  * Permission to use, copy, and modify this software with or without fee
   25  * is hereby granted, provided that this entire notice is included in
   26  * all copies of any software which is or includes a copy or
   27  * modification of this software.
   28  * You may use this code under the GNU public license if you so wish. Please
   29  * contribute changes back to the authors under this freer than GPL license
   30  * so that we may further the use of strong encryption without limitations to
   31  * all.
   32  *
   33  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
   34  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
   35  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
   36  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
   37  * PURPOSE.
   38  */
   39 #include "opt_inet.h"
   40 #include "opt_inet6.h"
   41 #include "opt_ipsec.h"
   42 
   43 #include <sys/param.h>
   44 #include <sys/systm.h>
   45 #include <sys/mbuf.h>
   46 #include <sys/socket.h>
   47 #include <sys/syslog.h>
   48 #include <sys/kernel.h>
   49 #include <sys/lock.h>
   50 #include <sys/mutex.h>
   51 #include <sys/sysctl.h>
   52 
   53 #include <net/if.h>
   54 #include <net/vnet.h>
   55 
   56 #include <netinet/in.h>
   57 #include <netinet/in_systm.h>
   58 #include <netinet/ip.h>
   59 #include <netinet/ip_ecn.h>
   60 #include <netinet/ip6.h>
   61 
   62 #include <netipsec/ipsec.h>
   63 #include <netipsec/ah.h>
   64 #include <netipsec/ah_var.h>
   65 #include <netipsec/xform.h>
   66 
   67 #ifdef INET6
   68 #include <netinet6/ip6_var.h>
   69 #include <netipsec/ipsec6.h>
   70 #include <netinet6/ip6_ecn.h>
   71 #endif
   72 
   73 #include <netipsec/key.h>
   74 #include <netipsec/key_debug.h>
   75 
   76 #include <opencrypto/cryptodev.h>
   77 
   78 /*
   79  * Return header size in bytes.  The old protocol did not support
   80  * the replay counter; the new protocol always includes the counter.
   81  */
   82 #define HDRSIZE(sav) \
   83         (((sav)->flags & SADB_X_EXT_OLD) ? \
   84                 sizeof (struct ah) : sizeof (struct ah) + sizeof (u_int32_t))
   85 /* 
   86  * Return authenticator size in bytes, based on a field in the
   87  * algorithm descriptor.
   88  */
   89 #define AUTHSIZE(sav)   ((sav->flags & SADB_X_EXT_OLD) ? 16 :   \
   90                          xform_ah_authsize((sav)->tdb_authalgxform))
   91 
   92 VNET_DEFINE(int, ah_enable) = 1;        /* control flow of packets with AH */
   93 VNET_DEFINE(int, ah_cleartos) = 1;      /* clear ip_tos when doing AH calc */
   94 VNET_PCPUSTAT_DEFINE(struct ahstat, ahstat);
   95 VNET_PCPUSTAT_SYSINIT(ahstat);
   96 
   97 #ifdef VIMAGE
   98 VNET_PCPUSTAT_SYSUNINIT(ahstat);
   99 #endif /* VIMAGE */
  100 
  101 #ifdef INET
  102 SYSCTL_DECL(_net_inet_ah);
  103 SYSCTL_INT(_net_inet_ah, OID_AUTO, ah_enable,
  104         CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ah_enable), 0, "");
  105 SYSCTL_INT(_net_inet_ah, OID_AUTO, ah_cleartos,
  106         CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ah_cleartos), 0, "");
  107 SYSCTL_VNET_PCPUSTAT(_net_inet_ah, IPSECCTL_STATS, stats, struct ahstat,
  108     ahstat, "AH statistics (struct ahstat, netipsec/ah_var.h)");
  109 #endif
  110 
  111 static unsigned char ipseczeroes[256];  /* larger than an ip6 extension hdr */
  112 static struct timeval md5warn, ripewarn, kpdkmd5warn, kpdksha1warn;
  113 
  114 static int ah_input_cb(struct cryptop*);
  115 static int ah_output_cb(struct cryptop*);
  116 
  117 int
  118 xform_ah_authsize(const struct auth_hash *esph)
  119 {
  120         int alen;
  121 
  122         if (esph == NULL)
  123                 return 0;
  124 
  125         switch (esph->type) {
  126         case CRYPTO_SHA2_256_HMAC:
  127         case CRYPTO_SHA2_384_HMAC:
  128         case CRYPTO_SHA2_512_HMAC:
  129                 alen = esph->hashsize / 2;      /* RFC4868 2.3 */
  130                 break;
  131 
  132         case CRYPTO_AES_128_NIST_GMAC:
  133         case CRYPTO_AES_192_NIST_GMAC:
  134         case CRYPTO_AES_256_NIST_GMAC:
  135                 alen = esph->hashsize;
  136                 break;
  137 
  138         default:
  139                 alen = AH_HMAC_HASHLEN;
  140                 break;
  141         }
  142 
  143         return alen;
  144 }
  145 
  146 size_t
  147 ah_hdrsiz(struct secasvar *sav)
  148 {
  149         size_t size;
  150 
  151         if (sav != NULL) {
  152                 int authsize, rplen, align;
  153 
  154                 IPSEC_ASSERT(sav->tdb_authalgxform != NULL, ("null xform"));
  155                 /*XXX not right for null algorithm--does it matter??*/
  156 
  157                 /* RFC4302: use the correct alignment. */
  158                 align = sizeof(uint32_t);
  159 #ifdef INET6
  160                 if (sav->sah->saidx.dst.sa.sa_family == AF_INET6) {
  161                         align = sizeof(uint64_t);
  162                 }
  163 #endif
  164                 rplen = HDRSIZE(sav);
  165                 authsize = AUTHSIZE(sav);
  166                 size = roundup(rplen + authsize, align);
  167         } else {
  168                 /* default guess */
  169                 size = sizeof (struct ah) + sizeof (u_int32_t) + 16;
  170         }
  171         return size;
  172 }
  173 
  174 /*
  175  * NB: public for use by esp_init.
  176  */
  177 int
  178 ah_init0(struct secasvar *sav, struct xformsw *xsp, struct cryptoini *cria)
  179 {
  180         const struct auth_hash *thash;
  181         int keylen;
  182 
  183         thash = auth_algorithm_lookup(sav->alg_auth);
  184         if (thash == NULL) {
  185                 DPRINTF(("%s: unsupported authentication algorithm %u\n",
  186                         __func__, sav->alg_auth));
  187                 return EINVAL;
  188         }
  189 
  190         switch (sav->alg_auth) {
  191         case SADB_AALG_MD5HMAC:
  192                 if (ratecheck(&md5warn, &ipsec_warn_interval))
  193                         gone_in(13, "MD5-HMAC authenticator for IPsec");
  194                 break;
  195         case SADB_X_AALG_RIPEMD160HMAC:
  196                 if (ratecheck(&ripewarn, &ipsec_warn_interval))
  197                         gone_in(13, "RIPEMD160-HMAC authenticator for IPsec");
  198                 break;
  199         case SADB_X_AALG_MD5:
  200                 if (ratecheck(&kpdkmd5warn, &ipsec_warn_interval))
  201                         gone_in(13, "Keyed-MD5 authenticator for IPsec");
  202                 break;
  203         case SADB_X_AALG_SHA:
  204                 if (ratecheck(&kpdksha1warn, &ipsec_warn_interval))
  205                         gone_in(13, "Keyed-SHA1 authenticator for IPsec");
  206                 break;
  207         }
  208 
  209         /*
  210          * Verify the replay state block allocation is consistent with
  211          * the protocol type.  We check here so we can make assumptions
  212          * later during protocol processing.
  213          */
  214         /* NB: replay state is setup elsewhere (sigh) */
  215         if (((sav->flags&SADB_X_EXT_OLD) == 0) ^ (sav->replay != NULL)) {
  216                 DPRINTF(("%s: replay state block inconsistency, "
  217                         "%s algorithm %s replay state\n", __func__,
  218                         (sav->flags & SADB_X_EXT_OLD) ? "old" : "new",
  219                         sav->replay == NULL ? "without" : "with"));
  220                 return EINVAL;
  221         }
  222         if (sav->key_auth == NULL) {
  223                 DPRINTF(("%s: no authentication key for %s algorithm\n",
  224                         __func__, thash->name));
  225                 return EINVAL;
  226         }
  227         keylen = _KEYLEN(sav->key_auth);
  228         if (keylen > thash->keysize && thash->keysize != 0) {
  229                 DPRINTF(("%s: invalid keylength %d, algorithm %s requires "
  230                         "keysize less than %d\n", __func__,
  231                          keylen, thash->name, thash->keysize));
  232                 return EINVAL;
  233         }
  234 
  235         sav->tdb_xform = xsp;
  236         sav->tdb_authalgxform = thash;
  237 
  238         /* Initialize crypto session. */
  239         bzero(cria, sizeof (*cria));
  240         cria->cri_alg = sav->tdb_authalgxform->type;
  241         cria->cri_klen = _KEYBITS(sav->key_auth);
  242         cria->cri_key = sav->key_auth->key_data;
  243         cria->cri_mlen = AUTHSIZE(sav);
  244 
  245         return 0;
  246 }
  247 
  248 /*
  249  * ah_init() is called when an SPI is being set up.
  250  */
  251 static int
  252 ah_init(struct secasvar *sav, struct xformsw *xsp)
  253 {
  254         struct cryptoini cria;
  255         int error;
  256 
  257         error = ah_init0(sav, xsp, &cria);
  258         return error ? error :
  259                  crypto_newsession(&sav->tdb_cryptoid, &cria, V_crypto_support);
  260 }
  261 
  262 /*
  263  * Paranoia.
  264  *
  265  * NB: public for use by esp_zeroize (XXX).
  266  */
  267 int
  268 ah_zeroize(struct secasvar *sav)
  269 {
  270 
  271         if (sav->key_auth)
  272                 bzero(sav->key_auth->key_data, _KEYLEN(sav->key_auth));
  273 
  274         crypto_freesession(sav->tdb_cryptoid);
  275         sav->tdb_cryptoid = NULL;
  276         sav->tdb_authalgxform = NULL;
  277         sav->tdb_xform = NULL;
  278         return 0;
  279 }
  280 
  281 /*
  282  * Massage IPv4/IPv6 headers for AH processing.
  283  */
  284 static int
  285 ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out)
  286 {
  287         struct mbuf *m = *m0;
  288         unsigned char *ptr;
  289         int off, count;
  290 
  291 #ifdef INET
  292         struct ip *ip;
  293 #endif /* INET */
  294 
  295 #ifdef INET6
  296         struct ip6_ext *ip6e;
  297         struct ip6_hdr ip6;
  298         int ad, alloc, nxt, noff;
  299 #endif /* INET6 */
  300 
  301         switch (proto) {
  302 #ifdef INET
  303         case AF_INET:
  304                 /*
  305                  * This is the least painful way of dealing with IPv4 header
  306                  * and option processing -- just make sure they're in
  307                  * contiguous memory.
  308                  */
  309                 *m0 = m = m_pullup(m, skip);
  310                 if (m == NULL) {
  311                         DPRINTF(("%s: m_pullup failed\n", __func__));
  312                         return ENOBUFS;
  313                 }
  314 
  315                 /* Fix the IP header */
  316                 ip = mtod(m, struct ip *);
  317                 if (V_ah_cleartos)
  318                         ip->ip_tos = 0;
  319                 ip->ip_ttl = 0;
  320                 ip->ip_sum = 0;
  321 
  322                 if (alg == CRYPTO_MD5_KPDK || alg == CRYPTO_SHA1_KPDK)
  323                         ip->ip_off &= htons(IP_DF);
  324                 else
  325                         ip->ip_off = htons(0);
  326 
  327                 ptr = mtod(m, unsigned char *);
  328 
  329                 /* IPv4 option processing */
  330                 for (off = sizeof(struct ip); off < skip;) {
  331                         if (ptr[off] == IPOPT_EOL || ptr[off] == IPOPT_NOP ||
  332                             off + 1 < skip)
  333                                 ;
  334                         else {
  335                                 DPRINTF(("%s: illegal IPv4 option length for "
  336                                         "option %d\n", __func__, ptr[off]));
  337 
  338                                 m_freem(m);
  339                                 return EINVAL;
  340                         }
  341 
  342                         switch (ptr[off]) {
  343                         case IPOPT_EOL:
  344                                 off = skip;  /* End the loop. */
  345                                 break;
  346 
  347                         case IPOPT_NOP:
  348                                 off++;
  349                                 break;
  350 
  351                         case IPOPT_SECURITY:    /* 0x82 */
  352                         case 0x85:      /* Extended security. */
  353                         case 0x86:      /* Commercial security. */
  354                         case 0x94:      /* Router alert */
  355                         case 0x95:      /* RFC1770 */
  356                                 /* Sanity check for option length. */
  357                                 if (ptr[off + 1] < 2) {
  358                                         DPRINTF(("%s: illegal IPv4 option "
  359                                                 "length for option %d\n",
  360                                                 __func__, ptr[off]));
  361 
  362                                         m_freem(m);
  363                                         return EINVAL;
  364                                 }
  365 
  366                                 off += ptr[off + 1];
  367                                 break;
  368 
  369                         case IPOPT_LSRR:
  370                         case IPOPT_SSRR:
  371                                 /* Sanity check for option length. */
  372                                 if (ptr[off + 1] < 2) {
  373                                         DPRINTF(("%s: illegal IPv4 option "
  374                                                 "length for option %d\n",
  375                                                 __func__, ptr[off]));
  376 
  377                                         m_freem(m);
  378                                         return EINVAL;
  379                                 }
  380 
  381                                 /*
  382                                  * On output, if we have either of the
  383                                  * source routing options, we should
  384                                  * swap the destination address of the
  385                                  * IP header with the last address
  386                                  * specified in the option, as that is
  387                                  * what the destination's IP header
  388                                  * will look like.
  389                                  */
  390                                 if (out)
  391                                         bcopy(ptr + off + ptr[off + 1] -
  392                                             sizeof(struct in_addr),
  393                                             &(ip->ip_dst), sizeof(struct in_addr));
  394 
  395                                 /* Fall through */
  396                         default:
  397                                 /* Sanity check for option length. */
  398                                 if (ptr[off + 1] < 2) {
  399                                         DPRINTF(("%s: illegal IPv4 option "
  400                                                 "length for option %d\n",
  401                                                 __func__, ptr[off]));
  402                                         m_freem(m);
  403                                         return EINVAL;
  404                                 }
  405 
  406                                 /* Zeroize all other options. */
  407                                 count = ptr[off + 1];
  408                                 bcopy(ipseczeroes, ptr + off, count);
  409                                 off += count;
  410                                 break;
  411                         }
  412 
  413                         /* Sanity check. */
  414                         if (off > skip) {
  415                                 DPRINTF(("%s: malformed IPv4 options header\n",
  416                                         __func__));
  417 
  418                                 m_freem(m);
  419                                 return EINVAL;
  420                         }
  421                 }
  422 
  423                 break;
  424 #endif /* INET */
  425 
  426 #ifdef INET6
  427         case AF_INET6:  /* Ugly... */
  428                 /* Copy and "cook" the IPv6 header. */
  429                 m_copydata(m, 0, sizeof(ip6), (caddr_t) &ip6);
  430 
  431                 /* We don't do IPv6 Jumbograms. */
  432                 if (ip6.ip6_plen == 0) {
  433                         DPRINTF(("%s: unsupported IPv6 jumbogram\n", __func__));
  434                         m_freem(m);
  435                         return EMSGSIZE;
  436                 }
  437 
  438                 ip6.ip6_flow = 0;
  439                 ip6.ip6_hlim = 0;
  440                 ip6.ip6_vfc &= ~IPV6_VERSION_MASK;
  441                 ip6.ip6_vfc |= IPV6_VERSION;
  442 
  443                 /* Scoped address handling. */
  444                 if (IN6_IS_SCOPE_LINKLOCAL(&ip6.ip6_src))
  445                         ip6.ip6_src.s6_addr16[1] = 0;
  446                 if (IN6_IS_SCOPE_LINKLOCAL(&ip6.ip6_dst))
  447                         ip6.ip6_dst.s6_addr16[1] = 0;
  448 
  449                 /* Done with IPv6 header. */
  450                 m_copyback(m, 0, sizeof(struct ip6_hdr), (caddr_t) &ip6);
  451 
  452                 /* Let's deal with the remaining headers (if any). */
  453                 if (skip - sizeof(struct ip6_hdr) > 0) {
  454                         if (m->m_len <= skip) {
  455                                 ptr = (unsigned char *) malloc(
  456                                     skip - sizeof(struct ip6_hdr),
  457                                     M_XDATA, M_NOWAIT);
  458                                 if (ptr == NULL) {
  459                                         DPRINTF(("%s: failed to allocate memory"
  460                                                 "for IPv6 headers\n",__func__));
  461                                         m_freem(m);
  462                                         return ENOBUFS;
  463                                 }
  464 
  465                                 /*
  466                                  * Copy all the protocol headers after
  467                                  * the IPv6 header.
  468                                  */
  469                                 m_copydata(m, sizeof(struct ip6_hdr),
  470                                     skip - sizeof(struct ip6_hdr), ptr);
  471                                 alloc = 1;
  472                         } else {
  473                                 /* No need to allocate memory. */
  474                                 ptr = mtod(m, unsigned char *) +
  475                                     sizeof(struct ip6_hdr);
  476                                 alloc = 0;
  477                         }
  478                 } else
  479                         break;
  480 
  481                 nxt = ip6.ip6_nxt & 0xff; /* Next header type. */
  482 
  483                 for (off = 0; off < skip - sizeof(struct ip6_hdr);)
  484                         switch (nxt) {
  485                         case IPPROTO_HOPOPTS:
  486                         case IPPROTO_DSTOPTS:
  487                                 ip6e = (struct ip6_ext *)(ptr + off);
  488                                 noff = off + ((ip6e->ip6e_len + 1) << 3);
  489 
  490                                 /* Sanity check. */
  491                                 if (noff > skip - sizeof(struct ip6_hdr))
  492                                         goto error6;
  493 
  494                                 /*
  495                                  * Zero out mutable options.
  496                                  */
  497                                 for (count = off + sizeof(struct ip6_ext);
  498                                      count < noff;) {
  499                                         if (ptr[count] == IP6OPT_PAD1) {
  500                                                 count++;
  501                                                 continue; /* Skip padding. */
  502                                         }
  503 
  504                                         ad = ptr[count + 1] + 2;
  505                                         if (count + ad > noff)
  506                                                 goto error6;
  507 
  508                                         if (ptr[count] & IP6OPT_MUTABLE)
  509                                                 memset(ptr + count, 0, ad);
  510                                         count += ad;
  511                                 }
  512 
  513                                 if (count != noff)
  514                                         goto error6;
  515 
  516                                 /* Advance. */
  517                                 off += ((ip6e->ip6e_len + 1) << 3);
  518                                 nxt = ip6e->ip6e_nxt;
  519                                 break;
  520 
  521                         case IPPROTO_ROUTING:
  522                                 /*
  523                                  * Always include routing headers in
  524                                  * computation.
  525                                  */
  526                                 ip6e = (struct ip6_ext *) (ptr + off);
  527                                 off += ((ip6e->ip6e_len + 1) << 3);
  528                                 nxt = ip6e->ip6e_nxt;
  529                                 break;
  530 
  531                         default:
  532                                 DPRINTF(("%s: unexpected IPv6 header type %d",
  533                                         __func__, off));
  534 error6:
  535                                 if (alloc)
  536                                         free(ptr, M_XDATA);
  537                                 m_freem(m);
  538                                 return EINVAL;
  539                         }
  540 
  541                 /* Copyback and free, if we allocated. */
  542                 if (alloc) {
  543                         m_copyback(m, sizeof(struct ip6_hdr),
  544                             skip - sizeof(struct ip6_hdr), ptr);
  545                         free(ptr, M_XDATA);
  546                 }
  547 
  548                 break;
  549 #endif /* INET6 */
  550         }
  551 
  552         return 0;
  553 }
  554 
  555 /*
  556  * ah_input() gets called to verify that an input packet
  557  * passes authentication.
  558  */
  559 static int
  560 ah_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
  561 {
  562         IPSEC_DEBUG_DECLARE(char buf[128]);
  563         const struct auth_hash *ahx;
  564         struct cryptodesc *crda;
  565         struct cryptop *crp;
  566         struct xform_data *xd;
  567         struct newah *ah;
  568         crypto_session_t cryptoid;
  569         int hl, rplen, authsize, ahsize, error;
  570 
  571         IPSEC_ASSERT(sav != NULL, ("null SA"));
  572         IPSEC_ASSERT(sav->key_auth != NULL, ("null authentication key"));
  573         IPSEC_ASSERT(sav->tdb_authalgxform != NULL,
  574                 ("null authentication xform"));
  575 
  576         /* Figure out header size. */
  577         rplen = HDRSIZE(sav);
  578 
  579         if (m->m_len < skip + rplen) {
  580                 m = m_pullup(m, skip + rplen);
  581                 if (m == NULL) {
  582                         DPRINTF(("ah_input: cannot pullup header\n"));
  583                         AHSTAT_INC(ahs_hdrops);         /*XXX*/
  584                         error = ENOBUFS;
  585                         goto bad;
  586                 }
  587         }
  588         ah = (struct newah *)(mtod(m, caddr_t) + skip);
  589 
  590         /* Check replay window, if applicable. */
  591         SECASVAR_LOCK(sav);
  592         if (sav->replay != NULL && sav->replay->wsize != 0 &&
  593             ipsec_chkreplay(ntohl(ah->ah_seq), sav) == 0) {
  594                 SECASVAR_UNLOCK(sav);
  595                 AHSTAT_INC(ahs_replay);
  596                 DPRINTF(("%s: packet replay failure: %s\n", __func__,
  597                     ipsec_sa2str(sav, buf, sizeof(buf))));
  598                 error = EACCES;
  599                 goto bad;
  600         }
  601         cryptoid = sav->tdb_cryptoid;
  602         SECASVAR_UNLOCK(sav);
  603 
  604         /* Verify AH header length. */
  605         hl = sizeof(struct ah) + (ah->ah_len * sizeof (u_int32_t));
  606         ahx = sav->tdb_authalgxform;
  607         authsize = AUTHSIZE(sav);
  608         ahsize = ah_hdrsiz(sav);
  609         if (hl != ahsize) {
  610                 DPRINTF(("%s: bad authenticator length %u (expecting %lu)"
  611                     " for packet in SA %s/%08lx\n", __func__, hl,
  612                     (u_long)ahsize,
  613                     ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)),
  614                     (u_long) ntohl(sav->spi)));
  615                 AHSTAT_INC(ahs_badauthl);
  616                 error = EACCES;
  617                 goto bad;
  618         }
  619         if (skip + ahsize > m->m_pkthdr.len) {
  620                 DPRINTF(("%s: bad mbuf length %u (expecting %lu)"
  621                     " for packet in SA %s/%08lx\n", __func__,
  622                     m->m_pkthdr.len, (u_long)(skip + ahsize),
  623                     ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)),
  624                     (u_long) ntohl(sav->spi)));
  625                 AHSTAT_INC(ahs_badauthl);
  626                 error = EACCES;
  627                 goto bad;
  628         }
  629         AHSTAT_ADD(ahs_ibytes, m->m_pkthdr.len - skip - hl);
  630 
  631         /* Get crypto descriptors. */
  632         crp = crypto_getreq(1);
  633         if (crp == NULL) {
  634                 DPRINTF(("%s: failed to acquire crypto descriptor\n",
  635                     __func__));
  636                 AHSTAT_INC(ahs_crypto);
  637                 error = ENOBUFS;
  638                 goto bad;
  639         }
  640 
  641         crda = crp->crp_desc;
  642         IPSEC_ASSERT(crda != NULL, ("null crypto descriptor"));
  643 
  644         crda->crd_skip = 0;
  645         crda->crd_len = m->m_pkthdr.len;
  646         crda->crd_inject = skip + rplen;
  647 
  648         /* Authentication operation. */
  649         crda->crd_alg = ahx->type;
  650         crda->crd_klen = _KEYBITS(sav->key_auth);
  651         crda->crd_key = sav->key_auth->key_data;
  652 
  653         /* Allocate IPsec-specific opaque crypto info. */
  654         xd = malloc(sizeof(*xd) + skip + rplen + authsize, M_XDATA,
  655             M_NOWAIT | M_ZERO);
  656         if (xd == NULL) {
  657                 DPRINTF(("%s: failed to allocate xform_data\n", __func__));
  658                 AHSTAT_INC(ahs_crypto);
  659                 crypto_freereq(crp);
  660                 error = ENOBUFS;
  661                 goto bad;
  662         }
  663 
  664         /*
  665          * Save the authenticator, the skipped portion of the packet,
  666          * and the AH header.
  667          */
  668         m_copydata(m, 0, skip + rplen + authsize, (caddr_t)(xd + 1));
  669 
  670         /* Zeroize the authenticator on the packet. */
  671         m_copyback(m, skip + rplen, authsize, ipseczeroes);
  672 
  673         /* Save ah_nxt, since ah pointer can become invalid after "massage" */
  674         hl = ah->ah_nxt;
  675 
  676         /* "Massage" the packet headers for crypto processing. */
  677         error = ah_massage_headers(&m, sav->sah->saidx.dst.sa.sa_family,
  678             skip, ahx->type, 0);
  679         if (error != 0) {
  680                 /* NB: mbuf is free'd by ah_massage_headers */
  681                 AHSTAT_INC(ahs_hdrops);
  682                 free(xd, M_XDATA);
  683                 crypto_freereq(crp);
  684                 key_freesav(&sav);
  685                 return (error);
  686         }
  687 
  688         /* Crypto operation descriptor. */
  689         crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */
  690         crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_CBIFSYNC;
  691         if (V_async_crypto)
  692                 crp->crp_flags |= CRYPTO_F_ASYNC | CRYPTO_F_ASYNC_KEEPORDER;
  693         crp->crp_buf = (caddr_t) m;
  694         crp->crp_callback = ah_input_cb;
  695         crp->crp_session = cryptoid;
  696         crp->crp_opaque = (caddr_t) xd;
  697 
  698         /* These are passed as-is to the callback. */
  699         xd->sav = sav;
  700         xd->nxt = hl;
  701         xd->protoff = protoff;
  702         xd->skip = skip;
  703         xd->cryptoid = cryptoid;
  704         xd->vnet = curvnet;
  705         return (crypto_dispatch(crp));
  706 bad:
  707         m_freem(m);
  708         key_freesav(&sav);
  709         return (error);
  710 }
  711 
  712 /*
  713  * AH input callback from the crypto driver.
  714  */
  715 static int
  716 ah_input_cb(struct cryptop *crp)
  717 {
  718         IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]);
  719         unsigned char calc[AH_ALEN_MAX];
  720         struct mbuf *m;
  721         struct xform_data *xd;
  722         struct secasvar *sav;
  723         struct secasindex *saidx;
  724         caddr_t ptr;
  725         crypto_session_t cryptoid;
  726         int authsize, rplen, ahsize, error, skip, protoff;
  727         uint8_t nxt;
  728 
  729         m = (struct mbuf *) crp->crp_buf;
  730         xd = (struct xform_data *) crp->crp_opaque;
  731         CURVNET_SET(xd->vnet);
  732         sav = xd->sav;
  733         skip = xd->skip;
  734         nxt = xd->nxt;
  735         protoff = xd->protoff;
  736         cryptoid = xd->cryptoid;
  737         saidx = &sav->sah->saidx;
  738         IPSEC_ASSERT(saidx->dst.sa.sa_family == AF_INET ||
  739                 saidx->dst.sa.sa_family == AF_INET6,
  740                 ("unexpected protocol family %u", saidx->dst.sa.sa_family));
  741 
  742         /* Check for crypto errors. */
  743         if (crp->crp_etype) {
  744                 if (crp->crp_etype == EAGAIN) {
  745                         /* Reset the session ID */
  746                         if (ipsec_updateid(sav, &crp->crp_session, &cryptoid) != 0)
  747                                 crypto_freesession(cryptoid);
  748                         xd->cryptoid = crp->crp_session;
  749                         CURVNET_RESTORE();
  750                         return (crypto_dispatch(crp));
  751                 }
  752                 AHSTAT_INC(ahs_noxform);
  753                 DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
  754                 error = crp->crp_etype;
  755                 goto bad;
  756         } else {
  757                 AHSTAT_INC(ahs_hist[sav->alg_auth]);
  758                 crypto_freereq(crp);            /* No longer needed. */
  759                 crp = NULL;
  760         }
  761 
  762         /* Shouldn't happen... */
  763         if (m == NULL) {
  764                 AHSTAT_INC(ahs_crypto);
  765                 DPRINTF(("%s: bogus returned buffer from crypto\n", __func__));
  766                 error = EINVAL;
  767                 goto bad;
  768         }
  769 
  770         /* Figure out header size. */
  771         rplen = HDRSIZE(sav);
  772         authsize = AUTHSIZE(sav);
  773         ahsize = ah_hdrsiz(sav);
  774 
  775         /* Copy authenticator off the packet. */
  776         m_copydata(m, skip + rplen, authsize, calc);
  777 
  778         /* Verify authenticator. */
  779         ptr = (caddr_t) (xd + 1);
  780         if (timingsafe_bcmp(ptr + skip + rplen, calc, authsize)) {
  781                 DPRINTF(("%s: authentication hash mismatch for packet "
  782                     "in SA %s/%08lx\n", __func__,
  783                     ipsec_address(&saidx->dst, buf, sizeof(buf)),
  784                     (u_long) ntohl(sav->spi)));
  785                 AHSTAT_INC(ahs_badauth);
  786                 error = EACCES;
  787                 goto bad;
  788         }
  789         /* Fix the Next Protocol field. */
  790         ((uint8_t *) ptr)[protoff] = nxt;
  791 
  792         /* Copyback the saved (uncooked) network headers. */
  793         m_copyback(m, 0, skip, ptr);
  794         free(xd, M_XDATA), xd = NULL;                   /* No longer needed */
  795 
  796         /*
  797          * Header is now authenticated.
  798          */
  799         m->m_flags |= M_AUTHIPHDR|M_AUTHIPDGM;
  800 
  801         /*
  802          * Update replay sequence number, if appropriate.
  803          */
  804         if (sav->replay) {
  805                 u_int32_t seq;
  806 
  807                 m_copydata(m, skip + offsetof(struct newah, ah_seq),
  808                            sizeof (seq), (caddr_t) &seq);
  809                 SECASVAR_LOCK(sav);
  810                 if (ipsec_updatereplay(ntohl(seq), sav)) {
  811                         SECASVAR_UNLOCK(sav);
  812                         AHSTAT_INC(ahs_replay);
  813                         error = EACCES;
  814                         goto bad;
  815                 }
  816                 SECASVAR_UNLOCK(sav);
  817         }
  818 
  819         /*
  820          * Remove the AH header and authenticator from the mbuf.
  821          */
  822         error = m_striphdr(m, skip, ahsize);
  823         if (error) {
  824                 DPRINTF(("%s: mangled mbuf chain for SA %s/%08lx\n", __func__,
  825                     ipsec_address(&saidx->dst, buf, sizeof(buf)),
  826                     (u_long) ntohl(sav->spi)));
  827                 AHSTAT_INC(ahs_hdrops);
  828                 goto bad;
  829         }
  830 
  831         switch (saidx->dst.sa.sa_family) {
  832 #ifdef INET6
  833         case AF_INET6:
  834                 error = ipsec6_common_input_cb(m, sav, skip, protoff);
  835                 break;
  836 #endif
  837 #ifdef INET
  838         case AF_INET:
  839                 error = ipsec4_common_input_cb(m, sav, skip, protoff);
  840                 break;
  841 #endif
  842         default:
  843                 panic("%s: Unexpected address family: %d saidx=%p", __func__,
  844                     saidx->dst.sa.sa_family, saidx);
  845         }
  846         CURVNET_RESTORE();
  847         return error;
  848 bad:
  849         CURVNET_RESTORE();
  850         if (sav)
  851                 key_freesav(&sav);
  852         if (m != NULL)
  853                 m_freem(m);
  854         if (xd != NULL)
  855                 free(xd, M_XDATA);
  856         if (crp != NULL)
  857                 crypto_freereq(crp);
  858         return error;
  859 }
  860 
  861 /*
  862  * AH output routine, called by ipsec[46]_perform_request().
  863  */
  864 static int
  865 ah_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
  866     u_int idx, int skip, int protoff)
  867 {
  868         IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]);
  869         const struct auth_hash *ahx;
  870         struct cryptodesc *crda;
  871         struct xform_data *xd;
  872         struct mbuf *mi;
  873         struct cryptop *crp;
  874         struct newah *ah;
  875         crypto_session_t cryptoid;
  876         uint16_t iplen;
  877         int error, rplen, authsize, ahsize, maxpacketsize, roff;
  878         uint8_t prot;
  879 
  880         IPSEC_ASSERT(sav != NULL, ("null SA"));
  881         ahx = sav->tdb_authalgxform;
  882         IPSEC_ASSERT(ahx != NULL, ("null authentication xform"));
  883 
  884         AHSTAT_INC(ahs_output);
  885 
  886         /* Figure out header size. */
  887         rplen = HDRSIZE(sav);
  888         authsize = AUTHSIZE(sav);
  889         ahsize = ah_hdrsiz(sav);
  890 
  891         /* Check for maximum packet size violations. */
  892         switch (sav->sah->saidx.dst.sa.sa_family) {
  893 #ifdef INET
  894         case AF_INET:
  895                 maxpacketsize = IP_MAXPACKET;
  896                 break;
  897 #endif /* INET */
  898 #ifdef INET6
  899         case AF_INET6:
  900                 maxpacketsize = IPV6_MAXPACKET;
  901                 break;
  902 #endif /* INET6 */
  903         default:
  904                 DPRINTF(("%s: unknown/unsupported protocol family %u, "
  905                     "SA %s/%08lx\n", __func__,
  906                     sav->sah->saidx.dst.sa.sa_family,
  907                     ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)),
  908                     (u_long) ntohl(sav->spi)));
  909                 AHSTAT_INC(ahs_nopf);
  910                 error = EPFNOSUPPORT;
  911                 goto bad;
  912         }
  913         if (ahsize + m->m_pkthdr.len > maxpacketsize) {
  914                 DPRINTF(("%s: packet in SA %s/%08lx got too big "
  915                     "(len %u, max len %u)\n", __func__,
  916                     ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)),
  917                     (u_long) ntohl(sav->spi),
  918                     ahsize + m->m_pkthdr.len, maxpacketsize));
  919                 AHSTAT_INC(ahs_toobig);
  920                 error = EMSGSIZE;
  921                 goto bad;
  922         }
  923 
  924         /* Update the counters. */
  925         AHSTAT_ADD(ahs_obytes, m->m_pkthdr.len - skip);
  926 
  927         m = m_unshare(m, M_NOWAIT);
  928         if (m == NULL) {
  929                 DPRINTF(("%s: cannot clone mbuf chain, SA %s/%08lx\n", __func__,
  930                     ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)),
  931                     (u_long) ntohl(sav->spi)));
  932                 AHSTAT_INC(ahs_hdrops);
  933                 error = ENOBUFS;
  934                 goto bad;
  935         }
  936 
  937         /* Inject AH header. */
  938         mi = m_makespace(m, skip, ahsize, &roff);
  939         if (mi == NULL) {
  940                 DPRINTF(("%s: failed to inject %u byte AH header for SA "
  941                     "%s/%08lx\n", __func__, ahsize,
  942                     ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)),
  943                     (u_long) ntohl(sav->spi)));
  944                 AHSTAT_INC(ahs_hdrops);         /*XXX differs from openbsd */
  945                 error = ENOBUFS;
  946                 goto bad;
  947         }
  948 
  949         /*
  950          * The AH header is guaranteed by m_makespace() to be in
  951          * contiguous memory, at roff bytes offset into the returned mbuf.
  952          */
  953         ah = (struct newah *)(mtod(mi, caddr_t) + roff);
  954 
  955         /* Initialize the AH header. */
  956         m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &ah->ah_nxt);
  957         ah->ah_len = (ahsize - sizeof(struct ah)) / sizeof(u_int32_t);
  958         ah->ah_reserve = 0;
  959         ah->ah_spi = sav->spi;
  960 
  961         /* Zeroize authenticator. */
  962         m_copyback(m, skip + rplen, authsize, ipseczeroes);
  963 
  964         /* Zeroize padding */
  965         m_copyback(m, skip + rplen + authsize, ahsize - (rplen + authsize),
  966             ipseczeroes);
  967 
  968         /* Insert packet replay counter, as requested.  */
  969         SECASVAR_LOCK(sav);
  970         if (sav->replay) {
  971                 if (sav->replay->count == ~0 &&
  972                     (sav->flags & SADB_X_EXT_CYCSEQ) == 0) {
  973                         SECASVAR_UNLOCK(sav);
  974                         DPRINTF(("%s: replay counter wrapped for SA %s/%08lx\n",
  975                             __func__, ipsec_address(&sav->sah->saidx.dst, buf,
  976                             sizeof(buf)), (u_long) ntohl(sav->spi)));
  977                         AHSTAT_INC(ahs_wrap);
  978                         error = EACCES;
  979                         goto bad;
  980                 }
  981 #ifdef REGRESSION
  982                 /* Emulate replay attack when ipsec_replay is TRUE. */
  983                 if (!V_ipsec_replay)
  984 #endif
  985                         sav->replay->count++;
  986                 ah->ah_seq = htonl(sav->replay->count);
  987         }
  988         cryptoid = sav->tdb_cryptoid;
  989         SECASVAR_UNLOCK(sav);
  990 
  991         /* Get crypto descriptors. */
  992         crp = crypto_getreq(1);
  993         if (crp == NULL) {
  994                 DPRINTF(("%s: failed to acquire crypto descriptors\n",
  995                         __func__));
  996                 AHSTAT_INC(ahs_crypto);
  997                 error = ENOBUFS;
  998                 goto bad;
  999         }
 1000 
 1001         crda = crp->crp_desc;
 1002         crda->crd_skip = 0;
 1003         crda->crd_inject = skip + rplen;
 1004         crda->crd_len = m->m_pkthdr.len;
 1005 
 1006         /* Authentication operation. */
 1007         crda->crd_alg = ahx->type;
 1008         crda->crd_key = sav->key_auth->key_data;
 1009         crda->crd_klen = _KEYBITS(sav->key_auth);
 1010 
 1011         /* Allocate IPsec-specific opaque crypto info. */
 1012         xd =  malloc(sizeof(struct xform_data) + skip, M_XDATA,
 1013             M_NOWAIT | M_ZERO);
 1014         if (xd == NULL) {
 1015                 crypto_freereq(crp);
 1016                 DPRINTF(("%s: failed to allocate xform_data\n", __func__));
 1017                 AHSTAT_INC(ahs_crypto);
 1018                 error = ENOBUFS;
 1019                 goto bad;
 1020         }
 1021 
 1022         /* Save the skipped portion of the packet. */
 1023         m_copydata(m, 0, skip, (caddr_t) (xd + 1));
 1024 
 1025         /*
 1026          * Fix IP header length on the header used for
 1027          * authentication. We don't need to fix the original
 1028          * header length as it will be fixed by our caller.
 1029          */
 1030         switch (sav->sah->saidx.dst.sa.sa_family) {
 1031 #ifdef INET
 1032         case AF_INET:
 1033                 bcopy(((caddr_t)(xd + 1)) +
 1034                     offsetof(struct ip, ip_len),
 1035                     (caddr_t) &iplen, sizeof(u_int16_t));
 1036                 iplen = htons(ntohs(iplen) + ahsize);
 1037                 m_copyback(m, offsetof(struct ip, ip_len),
 1038                     sizeof(u_int16_t), (caddr_t) &iplen);
 1039                 break;
 1040 #endif /* INET */
 1041 
 1042 #ifdef INET6
 1043         case AF_INET6:
 1044                 bcopy(((caddr_t)(xd + 1)) +
 1045                     offsetof(struct ip6_hdr, ip6_plen),
 1046                     (caddr_t) &iplen, sizeof(uint16_t));
 1047                 iplen = htons(ntohs(iplen) + ahsize);
 1048                 m_copyback(m, offsetof(struct ip6_hdr, ip6_plen),
 1049                     sizeof(uint16_t), (caddr_t) &iplen);
 1050                 break;
 1051 #endif /* INET6 */
 1052         }
 1053 
 1054         /* Fix the Next Header field in saved header. */
 1055         ((uint8_t *) (xd + 1))[protoff] = IPPROTO_AH;
 1056 
 1057         /* Update the Next Protocol field in the IP header. */
 1058         prot = IPPROTO_AH;
 1059         m_copyback(m, protoff, sizeof(uint8_t), (caddr_t) &prot);
 1060 
 1061         /* "Massage" the packet headers for crypto processing. */
 1062         error = ah_massage_headers(&m, sav->sah->saidx.dst.sa.sa_family,
 1063                         skip, ahx->type, 1);
 1064         if (error != 0) {
 1065                 m = NULL;       /* mbuf was free'd by ah_massage_headers. */
 1066                 free(xd, M_XDATA);
 1067                 crypto_freereq(crp);
 1068                 goto bad;
 1069         }
 1070 
 1071         /* Crypto operation descriptor. */
 1072         crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */
 1073         crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_CBIFSYNC;
 1074         if (V_async_crypto)
 1075                 crp->crp_flags |= CRYPTO_F_ASYNC | CRYPTO_F_ASYNC_KEEPORDER;
 1076         crp->crp_buf = (caddr_t) m;
 1077         crp->crp_callback = ah_output_cb;
 1078         crp->crp_session = cryptoid;
 1079         crp->crp_opaque = (caddr_t) xd;
 1080 
 1081         /* These are passed as-is to the callback. */
 1082         xd->sp = sp;
 1083         xd->sav = sav;
 1084         xd->skip = skip;
 1085         xd->idx = idx;
 1086         xd->cryptoid = cryptoid;
 1087         xd->vnet = curvnet;
 1088 
 1089         return crypto_dispatch(crp);
 1090 bad:
 1091         if (m)
 1092                 m_freem(m);
 1093         key_freesav(&sav);
 1094         key_freesp(&sp);
 1095         return (error);
 1096 }
 1097 
 1098 /*
 1099  * AH output callback from the crypto driver.
 1100  */
 1101 static int
 1102 ah_output_cb(struct cryptop *crp)
 1103 {
 1104         struct xform_data *xd;
 1105         struct secpolicy *sp;
 1106         struct secasvar *sav;
 1107         struct mbuf *m;
 1108         crypto_session_t cryptoid;
 1109         caddr_t ptr;
 1110         u_int idx;
 1111         int skip, error;
 1112 
 1113         m = (struct mbuf *) crp->crp_buf;
 1114         xd = (struct xform_data *) crp->crp_opaque;
 1115         CURVNET_SET(xd->vnet);
 1116         sp = xd->sp;
 1117         sav = xd->sav;
 1118         skip = xd->skip;
 1119         idx = xd->idx;
 1120         cryptoid = xd->cryptoid;
 1121         ptr = (caddr_t) (xd + 1);
 1122 
 1123         /* Check for crypto errors. */
 1124         if (crp->crp_etype) {
 1125                 if (crp->crp_etype == EAGAIN) {
 1126                         /* Reset the session ID */
 1127                         if (ipsec_updateid(sav, &crp->crp_session, &cryptoid) != 0)
 1128                                 crypto_freesession(cryptoid);
 1129                         xd->cryptoid = crp->crp_session;
 1130                         CURVNET_RESTORE();
 1131                         return (crypto_dispatch(crp));
 1132                 }
 1133                 AHSTAT_INC(ahs_noxform);
 1134                 DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
 1135                 error = crp->crp_etype;
 1136                 m_freem(m);
 1137                 goto bad;
 1138         }
 1139 
 1140         /* Shouldn't happen... */
 1141         if (m == NULL) {
 1142                 AHSTAT_INC(ahs_crypto);
 1143                 DPRINTF(("%s: bogus returned buffer from crypto\n", __func__));
 1144                 error = EINVAL;
 1145                 goto bad;
 1146         }
 1147         /*
 1148          * Copy original headers (with the new protocol number) back
 1149          * in place.
 1150          */
 1151         m_copyback(m, 0, skip, ptr);
 1152 
 1153         free(xd, M_XDATA);
 1154         crypto_freereq(crp);
 1155         AHSTAT_INC(ahs_hist[sav->alg_auth]);
 1156 #ifdef REGRESSION
 1157         /* Emulate man-in-the-middle attack when ipsec_integrity is TRUE. */
 1158         if (V_ipsec_integrity) {
 1159                 int alen;
 1160 
 1161                 /*
 1162                  * Corrupt HMAC if we want to test integrity verification of
 1163                  * the other side.
 1164                  */
 1165                 alen = AUTHSIZE(sav);
 1166                 m_copyback(m, m->m_pkthdr.len - alen, alen, ipseczeroes);
 1167         }
 1168 #endif
 1169 
 1170         /* NB: m is reclaimed by ipsec_process_done. */
 1171         error = ipsec_process_done(m, sp, sav, idx);
 1172         CURVNET_RESTORE();
 1173         return (error);
 1174 bad:
 1175         CURVNET_RESTORE();
 1176         free(xd, M_XDATA);
 1177         crypto_freereq(crp);
 1178         key_freesav(&sav);
 1179         key_freesp(&sp);
 1180         return (error);
 1181 }
 1182 
 1183 static struct xformsw ah_xformsw = {
 1184         .xf_type =      XF_AH,
 1185         .xf_name =      "IPsec AH",
 1186         .xf_init =      ah_init,
 1187         .xf_zeroize =   ah_zeroize,
 1188         .xf_input =     ah_input,
 1189         .xf_output =    ah_output,
 1190 };
 1191 
 1192 SYSINIT(ah_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE,
 1193     xform_attach, &ah_xformsw);
 1194 SYSUNINIT(ah_xform_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE,
 1195     xform_detach, &ah_xformsw);

Cache object: dbbea24145c9b59ae79db1c27f2da435


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.