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

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

Generated by: LCOV version 1.13