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

Cache object: 62eb1485467e49eb67a45216333980a5


[ 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.