1105197Ssam/* $FreeBSD$ */ 2105197Ssam/* $OpenBSD: ip_esp.c,v 1.69 2001/06/26 06:18:59 angelos Exp $ */ 3139823Simp/*- 4105197Ssam * The authors of this code are John Ioannidis (ji@tla.org), 5105197Ssam * Angelos D. Keromytis (kermit@csd.uch.gr) and 6105197Ssam * Niels Provos (provos@physnet.uni-hamburg.de). 7105197Ssam * 8105197Ssam * The original version of this code was written by John Ioannidis 9105197Ssam * for BSD/OS in Athens, Greece, in November 1995. 10105197Ssam * 11105197Ssam * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, 12105197Ssam * by Angelos D. Keromytis. 13105197Ssam * 14105197Ssam * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis 15105197Ssam * and Niels Provos. 16105197Ssam * 17105197Ssam * Additional features in 1999 by Angelos D. Keromytis. 18105197Ssam * 19105197Ssam * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, 20105197Ssam * Angelos D. Keromytis and Niels Provos. 21105197Ssam * Copyright (c) 2001 Angelos D. Keromytis. 22105197Ssam * 23105197Ssam * Permission to use, copy, and modify this software with or without fee 24105197Ssam * is hereby granted, provided that this entire notice is included in 25105197Ssam * all copies of any software which is or includes a copy or 26105197Ssam * modification of this software. 27105197Ssam * You may use this code under the GNU public license if you so wish. Please 28105197Ssam * contribute changes back to the authors under this freer than GPL license 29105197Ssam * so that we may further the use of strong encryption without limitations to 30105197Ssam * all. 31105197Ssam * 32105197Ssam * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 33105197Ssam * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 34105197Ssam * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 35105197Ssam * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 36105197Ssam * PURPOSE. 37105197Ssam */ 38105197Ssam#include "opt_inet.h" 39105197Ssam#include "opt_inet6.h" 40105197Ssam 41105197Ssam#include <sys/param.h> 42105197Ssam#include <sys/systm.h> 43105197Ssam#include <sys/mbuf.h> 44105197Ssam#include <sys/socket.h> 45105197Ssam#include <sys/syslog.h> 46105197Ssam#include <sys/kernel.h> 47105197Ssam#include <sys/random.h> 48105197Ssam#include <sys/sysctl.h> 49105197Ssam 50105197Ssam#include <net/if.h> 51195699Srwatson#include <net/vnet.h> 52105197Ssam 53105197Ssam#include <netinet/in.h> 54105197Ssam#include <netinet/in_systm.h> 55105197Ssam#include <netinet/ip.h> 56105197Ssam#include <netinet/ip_ecn.h> 57105197Ssam#include <netinet/ip6.h> 58105197Ssam 59105197Ssam#include <netipsec/ipsec.h> 60105197Ssam#include <netipsec/ah.h> 61105197Ssam#include <netipsec/ah_var.h> 62105197Ssam#include <netipsec/esp.h> 63105197Ssam#include <netipsec/esp_var.h> 64105197Ssam#include <netipsec/xform.h> 65105197Ssam 66105197Ssam#ifdef INET6 67105197Ssam#include <netinet6/ip6_var.h> 68105197Ssam#include <netipsec/ipsec6.h> 69105197Ssam#include <netinet6/ip6_ecn.h> 70105197Ssam#endif 71105197Ssam 72105197Ssam#include <netipsec/key.h> 73105197Ssam#include <netipsec/key_debug.h> 74105197Ssam 75105197Ssam#include <opencrypto/cryptodev.h> 76105197Ssam#include <opencrypto/xform.h> 77105197Ssam 78195699SrwatsonVNET_DEFINE(int, esp_enable) = 1; 79253088SaeVNET_PCPUSTAT_DEFINE(struct espstat, espstat); 80253088SaeVNET_PCPUSTAT_SYSINIT(espstat); 81105197Ssam 82253088Sae#ifdef VIMAGE 83253088SaeVNET_PCPUSTAT_SYSUNINIT(espstat); 84253088Sae#endif /* VIMAGE */ 85253088Sae 86105197SsamSYSCTL_DECL(_net_inet_esp); 87195699SrwatsonSYSCTL_VNET_INT(_net_inet_esp, OID_AUTO, 88195699Srwatson esp_enable, CTLFLAG_RW, &VNET_NAME(esp_enable), 0, ""); 89253088SaeSYSCTL_VNET_PCPUSTAT(_net_inet_esp, IPSECCTL_STATS, stats, 90253088Sae struct espstat, espstat, 91253088Sae "ESP statistics (struct espstat, netipsec/esp_var.h"); 92105197Ssam 93105197Ssamstatic int esp_input_cb(struct cryptop *op); 94105197Ssamstatic int esp_output_cb(struct cryptop *crp); 95105197Ssam 96105197Ssam/* 97105197Ssam * NB: this is public for use by the PF_KEY support. 98105197Ssam * NB: if you add support here; be sure to add code to esp_attach below! 99105197Ssam */ 100105197Ssamstruct enc_xform * 101105197Ssamesp_algorithm_lookup(int alg) 102105197Ssam{ 103105197Ssam if (alg >= ESP_ALG_MAX) 104105197Ssam return NULL; 105105197Ssam switch (alg) { 106105197Ssam case SADB_EALG_DESCBC: 107105197Ssam return &enc_xform_des; 108105197Ssam case SADB_EALG_3DESCBC: 109105197Ssam return &enc_xform_3des; 110105197Ssam case SADB_X_EALG_AES: 111105197Ssam return &enc_xform_rijndael128; 112105197Ssam case SADB_X_EALG_BLOWFISHCBC: 113105197Ssam return &enc_xform_blf; 114105197Ssam case SADB_X_EALG_CAST128CBC: 115105197Ssam return &enc_xform_cast5; 116105197Ssam case SADB_X_EALG_SKIPJACK: 117105197Ssam return &enc_xform_skipjack; 118105197Ssam case SADB_EALG_NULL: 119105197Ssam return &enc_xform_null; 120169425Sgnn case SADB_X_EALG_CAMELLIACBC: 121169425Sgnn return &enc_xform_camellia; 122105197Ssam } 123105197Ssam return NULL; 124105197Ssam} 125105197Ssam 126105197Ssamsize_t 127105197Ssamesp_hdrsiz(struct secasvar *sav) 128105197Ssam{ 129105197Ssam size_t size; 130105197Ssam 131105197Ssam if (sav != NULL) { 132105197Ssam /*XXX not right for null algorithm--does it matter??*/ 133120585Ssam IPSEC_ASSERT(sav->tdb_encalgxform != NULL, 134120585Ssam ("SA with null xform")); 135105197Ssam if (sav->flags & SADB_X_EXT_OLD) 136105197Ssam size = sizeof (struct esp); 137105197Ssam else 138105197Ssam size = sizeof (struct newesp); 139105197Ssam size += sav->tdb_encalgxform->blocksize + 9; 140105197Ssam /*XXX need alg check???*/ 141105197Ssam if (sav->tdb_authalgxform != NULL && sav->replay) 142105197Ssam size += ah_hdrsiz(sav); 143105197Ssam } else { 144105197Ssam /* 145105197Ssam * base header size 146105197Ssam * + max iv length for CBC mode 147105197Ssam * + max pad length 148105197Ssam * + sizeof (pad length field) 149105197Ssam * + sizeof (next header field) 150105197Ssam * + max icv supported. 151105197Ssam */ 152228012Spjd size = sizeof (struct newesp) + EALG_MAX_BLOCK_LEN + 9 + 16; 153105197Ssam } 154105197Ssam return size; 155105197Ssam} 156105197Ssam 157105197Ssam/* 158105197Ssam * esp_init() is called when an SPI is being set up. 159105197Ssam */ 160105197Ssamstatic int 161105197Ssamesp_init(struct secasvar *sav, struct xformsw *xsp) 162105197Ssam{ 163105197Ssam struct enc_xform *txform; 164105197Ssam struct cryptoini cria, crie; 165105197Ssam int keylen; 166105197Ssam int error; 167105197Ssam 168105197Ssam txform = esp_algorithm_lookup(sav->alg_enc); 169105197Ssam if (txform == NULL) { 170120585Ssam DPRINTF(("%s: unsupported encryption algorithm %d\n", 171120585Ssam __func__, sav->alg_enc)); 172105197Ssam return EINVAL; 173105197Ssam } 174105197Ssam if (sav->key_enc == NULL) { 175120585Ssam DPRINTF(("%s: no encoding key for %s algorithm\n", 176120585Ssam __func__, txform->name)); 177105197Ssam return EINVAL; 178105197Ssam } 179105197Ssam if ((sav->flags&(SADB_X_EXT_OLD|SADB_X_EXT_IV4B)) == SADB_X_EXT_IV4B) { 180120585Ssam DPRINTF(("%s: 4-byte IV not supported with protocol\n", 181120585Ssam __func__)); 182105197Ssam return EINVAL; 183105197Ssam } 184105197Ssam keylen = _KEYLEN(sav->key_enc); 185105197Ssam if (txform->minkey > keylen || keylen > txform->maxkey) { 186120585Ssam DPRINTF(("%s: invalid key length %u, must be in the range " 187120585Ssam "[%u..%u] for algorithm %s\n", __func__, 188105197Ssam keylen, txform->minkey, txform->maxkey, 189105197Ssam txform->name)); 190105197Ssam return EINVAL; 191105197Ssam } 192105197Ssam 193105197Ssam /* 194105197Ssam * NB: The null xform needs a non-zero blocksize to keep the 195105197Ssam * crypto code happy but if we use it to set ivlen then 196105197Ssam * the ESP header will be processed incorrectly. The 197105197Ssam * compromise is to force it to zero here. 198105197Ssam */ 199105197Ssam sav->ivlen = (txform == &enc_xform_null ? 0 : txform->blocksize); 200111119Simp sav->iv = (caddr_t) malloc(sav->ivlen, M_XDATA, M_WAITOK); 201105197Ssam key_randomfill(sav->iv, sav->ivlen); /*XXX*/ 202105197Ssam 203105197Ssam /* 204105197Ssam * Setup AH-related state. 205105197Ssam */ 206105197Ssam if (sav->alg_auth != 0) { 207105197Ssam error = ah_init0(sav, xsp, &cria); 208105197Ssam if (error) 209105197Ssam return error; 210105197Ssam } 211105197Ssam 212105197Ssam /* NB: override anything set in ah_init0 */ 213105197Ssam sav->tdb_xform = xsp; 214105197Ssam sav->tdb_encalgxform = txform; 215105197Ssam 216105197Ssam /* Initialize crypto session. */ 217105197Ssam bzero(&crie, sizeof (crie)); 218105197Ssam crie.cri_alg = sav->tdb_encalgxform->type; 219105197Ssam crie.cri_klen = _KEYBITS(sav->key_enc); 220157123Sgnn crie.cri_key = sav->key_enc->key_data; 221105197Ssam /* XXX Rounds ? */ 222105197Ssam 223105197Ssam if (sav->tdb_authalgxform && sav->tdb_encalgxform) { 224105197Ssam /* init both auth & enc */ 225105197Ssam crie.cri_next = &cria; 226105197Ssam error = crypto_newsession(&sav->tdb_cryptoid, 227181803Sbz &crie, V_crypto_support); 228105197Ssam } else if (sav->tdb_encalgxform) { 229105197Ssam error = crypto_newsession(&sav->tdb_cryptoid, 230181803Sbz &crie, V_crypto_support); 231105197Ssam } else if (sav->tdb_authalgxform) { 232105197Ssam error = crypto_newsession(&sav->tdb_cryptoid, 233181803Sbz &cria, V_crypto_support); 234105197Ssam } else { 235105197Ssam /* XXX cannot happen? */ 236120585Ssam DPRINTF(("%s: no encoding OR authentication xform!\n", 237120585Ssam __func__)); 238105197Ssam error = EINVAL; 239105197Ssam } 240105197Ssam return error; 241105197Ssam} 242105197Ssam 243105197Ssam/* 244105197Ssam * Paranoia. 245105197Ssam */ 246105197Ssamstatic int 247105197Ssamesp_zeroize(struct secasvar *sav) 248105197Ssam{ 249105197Ssam /* NB: ah_zerorize free's the crypto session state */ 250105197Ssam int error = ah_zeroize(sav); 251105197Ssam 252105197Ssam if (sav->key_enc) 253157123Sgnn bzero(sav->key_enc->key_data, _KEYLEN(sav->key_enc)); 254120585Ssam if (sav->iv) { 255120585Ssam free(sav->iv, M_XDATA); 256120585Ssam sav->iv = NULL; 257120585Ssam } 258105197Ssam sav->tdb_encalgxform = NULL; 259105197Ssam sav->tdb_xform = NULL; 260105197Ssam return error; 261105197Ssam} 262105197Ssam 263105197Ssam/* 264105197Ssam * ESP input processing, called (eventually) through the protocol switch. 265105197Ssam */ 266105197Ssamstatic int 267105197Ssamesp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff) 268105197Ssam{ 269105197Ssam struct auth_hash *esph; 270105197Ssam struct enc_xform *espx; 271105197Ssam struct tdb_ident *tdbi; 272105197Ssam struct tdb_crypto *tc; 273105197Ssam int plen, alen, hlen; 274105197Ssam struct m_tag *mtag; 275105197Ssam struct newesp *esp; 276105197Ssam 277105197Ssam struct cryptodesc *crde; 278105197Ssam struct cryptop *crp; 279105197Ssam 280120585Ssam IPSEC_ASSERT(sav != NULL, ("null SA")); 281120585Ssam IPSEC_ASSERT(sav->tdb_encalgxform != NULL, ("null encoding xform")); 282105197Ssam 283197674Svanhu /* Valid IP Packet length ? */ 284197674Svanhu if ( (skip&3) || (m->m_pkthdr.len&3) ){ 285197674Svanhu DPRINTF(("%s: misaligned packet, skip %u pkt len %u", 286197674Svanhu __func__, skip, m->m_pkthdr.len)); 287252028Sae ESPSTAT_INC(esps_badilen); 288197674Svanhu m_freem(m); 289197674Svanhu return EINVAL; 290197674Svanhu } 291197674Svanhu 292105197Ssam /* XXX don't pullup, just copy header */ 293105197Ssam IP6_EXTHDR_GET(esp, struct newesp *, m, skip, sizeof (struct newesp)); 294105197Ssam 295105197Ssam esph = sav->tdb_authalgxform; 296105197Ssam espx = sav->tdb_encalgxform; 297105197Ssam 298105197Ssam /* Determine the ESP header length */ 299105197Ssam if (sav->flags & SADB_X_EXT_OLD) 300105197Ssam hlen = sizeof (struct esp) + sav->ivlen; 301105197Ssam else 302105197Ssam hlen = sizeof (struct newesp) + sav->ivlen; 303105197Ssam /* Authenticator hash size */ 304218794Svanhu if (esph != NULL) { 305218794Svanhu switch (esph->type) { 306218794Svanhu case CRYPTO_SHA2_256_HMAC: 307218794Svanhu case CRYPTO_SHA2_384_HMAC: 308218794Svanhu case CRYPTO_SHA2_512_HMAC: 309218794Svanhu alen = esph->hashsize/2; 310218794Svanhu break; 311218794Svanhu default: 312218794Svanhu alen = AH_HMAC_HASHLEN; 313218794Svanhu break; 314218794Svanhu } 315218794Svanhu }else 316218794Svanhu alen = 0; 317105197Ssam 318105197Ssam /* 319105197Ssam * Verify payload length is multiple of encryption algorithm 320105197Ssam * block size. 321105197Ssam * 322105197Ssam * NB: This works for the null algorithm because the blocksize 323105197Ssam * is 4 and all packets must be 4-byte aligned regardless 324105197Ssam * of the algorithm. 325105197Ssam */ 326105197Ssam plen = m->m_pkthdr.len - (skip + hlen + alen); 327105197Ssam if ((plen & (espx->blocksize - 1)) || (plen <= 0)) { 328120585Ssam DPRINTF(("%s: payload of %d octets not a multiple of %d octets," 329120585Ssam " SA %s/%08lx\n", __func__, 330105197Ssam plen, espx->blocksize, 331105197Ssam ipsec_address(&sav->sah->saidx.dst), 332105197Ssam (u_long) ntohl(sav->spi))); 333252028Sae ESPSTAT_INC(esps_badilen); 334105197Ssam m_freem(m); 335105197Ssam return EINVAL; 336105197Ssam } 337105197Ssam 338105197Ssam /* 339105197Ssam * Check sequence number. 340105197Ssam */ 341105197Ssam if (esph && sav->replay && !ipsec_chkreplay(ntohl(esp->esp_seq), sav)) { 342120585Ssam DPRINTF(("%s: packet replay check for %s\n", __func__, 343105197Ssam ipsec_logsastr(sav))); /*XXX*/ 344252028Sae ESPSTAT_INC(esps_replay); 345105197Ssam m_freem(m); 346105197Ssam return ENOBUFS; /*XXX*/ 347105197Ssam } 348105197Ssam 349105197Ssam /* Update the counters */ 350252028Sae ESPSTAT_ADD(esps_ibytes, m->m_pkthdr.len - (skip + hlen + alen)); 351105197Ssam 352105197Ssam /* Find out if we've already done crypto */ 353105197Ssam for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL); 354105197Ssam mtag != NULL; 355105197Ssam mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, mtag)) { 356105197Ssam tdbi = (struct tdb_ident *) (mtag + 1); 357105197Ssam if (tdbi->proto == sav->sah->saidx.proto && 358105197Ssam tdbi->spi == sav->spi && 359105197Ssam !bcmp(&tdbi->dst, &sav->sah->saidx.dst, 360105197Ssam sizeof(union sockaddr_union))) 361105197Ssam break; 362105197Ssam } 363105197Ssam 364105197Ssam /* Get crypto descriptors */ 365105197Ssam crp = crypto_getreq(esph && espx ? 2 : 1); 366105197Ssam if (crp == NULL) { 367120585Ssam DPRINTF(("%s: failed to acquire crypto descriptors\n", 368120585Ssam __func__)); 369252028Sae ESPSTAT_INC(esps_crypto); 370105197Ssam m_freem(m); 371105197Ssam return ENOBUFS; 372105197Ssam } 373105197Ssam 374105197Ssam /* Get IPsec-specific opaque pointer */ 375105197Ssam if (esph == NULL || mtag != NULL) 376105197Ssam tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto), 377105197Ssam M_XDATA, M_NOWAIT|M_ZERO); 378105197Ssam else 379105197Ssam tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto) + alen, 380105197Ssam M_XDATA, M_NOWAIT|M_ZERO); 381105197Ssam if (tc == NULL) { 382105197Ssam crypto_freereq(crp); 383120585Ssam DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__)); 384252028Sae ESPSTAT_INC(esps_crypto); 385105197Ssam m_freem(m); 386105197Ssam return ENOBUFS; 387105197Ssam } 388105197Ssam 389105197Ssam tc->tc_ptr = (caddr_t) mtag; 390105197Ssam 391105197Ssam if (esph) { 392105197Ssam struct cryptodesc *crda = crp->crp_desc; 393105197Ssam 394120585Ssam IPSEC_ASSERT(crda != NULL, ("null ah crypto descriptor")); 395105197Ssam 396105197Ssam /* Authentication descriptor */ 397105197Ssam crda->crd_skip = skip; 398105197Ssam crda->crd_len = m->m_pkthdr.len - (skip + alen); 399105197Ssam crda->crd_inject = m->m_pkthdr.len - alen; 400105197Ssam 401105197Ssam crda->crd_alg = esph->type; 402157123Sgnn crda->crd_key = sav->key_auth->key_data; 403105197Ssam crda->crd_klen = _KEYBITS(sav->key_auth); 404105197Ssam 405105197Ssam /* Copy the authenticator */ 406105197Ssam if (mtag == NULL) 407105197Ssam m_copydata(m, m->m_pkthdr.len - alen, alen, 408105197Ssam (caddr_t) (tc + 1)); 409105197Ssam 410105197Ssam /* Chain authentication request */ 411105197Ssam crde = crda->crd_next; 412105197Ssam } else { 413105197Ssam crde = crp->crp_desc; 414105197Ssam } 415105197Ssam 416105197Ssam /* Crypto operation descriptor */ 417105197Ssam crp->crp_ilen = m->m_pkthdr.len; /* Total input length */ 418117058Ssam crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_CBIFSYNC; 419105197Ssam crp->crp_buf = (caddr_t) m; 420105197Ssam crp->crp_callback = esp_input_cb; 421105197Ssam crp->crp_sid = sav->tdb_cryptoid; 422105197Ssam crp->crp_opaque = (caddr_t) tc; 423105197Ssam 424105197Ssam /* These are passed as-is to the callback */ 425105197Ssam tc->tc_spi = sav->spi; 426105197Ssam tc->tc_dst = sav->sah->saidx.dst; 427105197Ssam tc->tc_proto = sav->sah->saidx.proto; 428105197Ssam tc->tc_protoff = protoff; 429105197Ssam tc->tc_skip = skip; 430220206Sfabient KEY_ADDREFSA(sav); 431220206Sfabient tc->tc_sav = sav; 432105197Ssam 433105197Ssam /* Decryption descriptor */ 434105197Ssam if (espx) { 435120585Ssam IPSEC_ASSERT(crde != NULL, ("null esp crypto descriptor")); 436105197Ssam crde->crd_skip = skip + hlen; 437105197Ssam crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen); 438105197Ssam crde->crd_inject = skip + hlen - sav->ivlen; 439105197Ssam 440105197Ssam crde->crd_alg = espx->type; 441157123Sgnn crde->crd_key = sav->key_enc->key_data; 442105197Ssam crde->crd_klen = _KEYBITS(sav->key_enc); 443105197Ssam /* XXX Rounds ? */ 444105197Ssam } 445105197Ssam 446105197Ssam if (mtag == NULL) 447105197Ssam return crypto_dispatch(crp); 448105197Ssam else 449105197Ssam return esp_input_cb(crp); 450105197Ssam} 451105197Ssam 452105197Ssam/* 453105197Ssam * ESP input callback from the crypto driver. 454105197Ssam */ 455105197Ssamstatic int 456105197Ssamesp_input_cb(struct cryptop *crp) 457105197Ssam{ 458218794Svanhu u_int8_t lastthree[3], aalg[AH_HMAC_MAXHASHLEN]; 459218794Svanhu int hlen, skip, protoff, error, alen; 460105197Ssam struct mbuf *m; 461105197Ssam struct cryptodesc *crd; 462105197Ssam struct auth_hash *esph; 463105197Ssam struct enc_xform *espx; 464105197Ssam struct tdb_crypto *tc; 465105197Ssam struct m_tag *mtag; 466105197Ssam struct secasvar *sav; 467105197Ssam struct secasindex *saidx; 468105197Ssam caddr_t ptr; 469105197Ssam 470105197Ssam crd = crp->crp_desc; 471120585Ssam IPSEC_ASSERT(crd != NULL, ("null crypto descriptor!")); 472105197Ssam 473105197Ssam tc = (struct tdb_crypto *) crp->crp_opaque; 474120585Ssam IPSEC_ASSERT(tc != NULL, ("null opaque crypto data area!")); 475105197Ssam skip = tc->tc_skip; 476105197Ssam protoff = tc->tc_protoff; 477105197Ssam mtag = (struct m_tag *) tc->tc_ptr; 478105197Ssam m = (struct mbuf *) crp->crp_buf; 479105197Ssam 480220206Sfabient sav = tc->tc_sav; 481220206Sfabient IPSEC_ASSERT(sav != NULL, ("null SA!")); 482105197Ssam 483105197Ssam saidx = &sav->sah->saidx; 484120585Ssam IPSEC_ASSERT(saidx->dst.sa.sa_family == AF_INET || 485105197Ssam saidx->dst.sa.sa_family == AF_INET6, 486120585Ssam ("unexpected protocol family %u", saidx->dst.sa.sa_family)); 487105197Ssam 488105197Ssam esph = sav->tdb_authalgxform; 489105197Ssam espx = sav->tdb_encalgxform; 490105197Ssam 491105197Ssam /* Check for crypto errors */ 492105197Ssam if (crp->crp_etype) { 493105197Ssam /* Reset the session ID */ 494105197Ssam if (sav->tdb_cryptoid != 0) 495105197Ssam sav->tdb_cryptoid = crp->crp_sid; 496105197Ssam 497228009Spjd if (crp->crp_etype == EAGAIN) 498228009Spjd return (crypto_dispatch(crp)); 499105197Ssam 500252028Sae ESPSTAT_INC(esps_noxform); 501120585Ssam DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype)); 502105197Ssam error = crp->crp_etype; 503105197Ssam goto bad; 504105197Ssam } 505105197Ssam 506105197Ssam /* Shouldn't happen... */ 507105197Ssam if (m == NULL) { 508252028Sae ESPSTAT_INC(esps_crypto); 509120585Ssam DPRINTF(("%s: bogus returned buffer from crypto\n", __func__)); 510105197Ssam error = EINVAL; 511105197Ssam goto bad; 512105197Ssam } 513252028Sae ESPSTAT_INC(esps_hist[sav->alg_enc]); 514105197Ssam 515105197Ssam /* If authentication was performed, check now. */ 516105197Ssam if (esph != NULL) { 517218794Svanhu switch (esph->type) { 518218794Svanhu case CRYPTO_SHA2_256_HMAC: 519218794Svanhu case CRYPTO_SHA2_384_HMAC: 520218794Svanhu case CRYPTO_SHA2_512_HMAC: 521218794Svanhu alen = esph->hashsize/2; 522218794Svanhu break; 523218794Svanhu default: 524218794Svanhu alen = AH_HMAC_HASHLEN; 525218794Svanhu break; 526218794Svanhu } 527105197Ssam /* 528105197Ssam * If we have a tag, it means an IPsec-aware NIC did 529105197Ssam * the verification for us. Otherwise we need to 530105197Ssam * check the authentication calculation. 531105197Ssam */ 532252028Sae AHSTAT_INC(ahs_hist[sav->alg_auth]); 533105197Ssam if (mtag == NULL) { 534105197Ssam /* Copy the authenticator from the packet */ 535218794Svanhu m_copydata(m, m->m_pkthdr.len - alen, 536218794Svanhu alen, aalg); 537105197Ssam 538105197Ssam ptr = (caddr_t) (tc + 1); 539105197Ssam 540105197Ssam /* Verify authenticator */ 541218794Svanhu if (bcmp(ptr, aalg, alen) != 0) { 542120585Ssam DPRINTF(("%s: " 543105197Ssam "authentication hash mismatch for packet in SA %s/%08lx\n", 544120585Ssam __func__, 545105197Ssam ipsec_address(&saidx->dst), 546105197Ssam (u_long) ntohl(sav->spi))); 547252028Sae ESPSTAT_INC(esps_badauth); 548105197Ssam error = EACCES; 549105197Ssam goto bad; 550105197Ssam } 551105197Ssam } 552105197Ssam 553105197Ssam /* Remove trailing authenticator */ 554218794Svanhu m_adj(m, -alen); 555105197Ssam } 556105197Ssam 557105197Ssam /* Release the crypto descriptors */ 558105197Ssam free(tc, M_XDATA), tc = NULL; 559105197Ssam crypto_freereq(crp), crp = NULL; 560105197Ssam 561105197Ssam /* 562105197Ssam * Packet is now decrypted. 563105197Ssam */ 564105197Ssam m->m_flags |= M_DECRYPTED; 565105197Ssam 566156997Scperciva /* 567156997Scperciva * Update replay sequence number, if appropriate. 568156997Scperciva */ 569156997Scperciva if (sav->replay) { 570156997Scperciva u_int32_t seq; 571156997Scperciva 572156997Scperciva m_copydata(m, skip + offsetof(struct newesp, esp_seq), 573156997Scperciva sizeof (seq), (caddr_t) &seq); 574156997Scperciva if (ipsec_updatereplay(ntohl(seq), sav)) { 575156997Scperciva DPRINTF(("%s: packet replay check for %s\n", __func__, 576156997Scperciva ipsec_logsastr(sav))); 577252028Sae ESPSTAT_INC(esps_replay); 578156997Scperciva error = ENOBUFS; 579156997Scperciva goto bad; 580156997Scperciva } 581156997Scperciva } 582156997Scperciva 583105197Ssam /* Determine the ESP header length */ 584105197Ssam if (sav->flags & SADB_X_EXT_OLD) 585105197Ssam hlen = sizeof (struct esp) + sav->ivlen; 586105197Ssam else 587105197Ssam hlen = sizeof (struct newesp) + sav->ivlen; 588105197Ssam 589105197Ssam /* Remove the ESP header and IV from the mbuf. */ 590105197Ssam error = m_striphdr(m, skip, hlen); 591105197Ssam if (error) { 592252028Sae ESPSTAT_INC(esps_hdrops); 593120585Ssam DPRINTF(("%s: bad mbuf chain, SA %s/%08lx\n", __func__, 594105197Ssam ipsec_address(&sav->sah->saidx.dst), 595105197Ssam (u_long) ntohl(sav->spi))); 596105197Ssam goto bad; 597105197Ssam } 598105197Ssam 599105197Ssam /* Save the last three bytes of decrypted data */ 600105197Ssam m_copydata(m, m->m_pkthdr.len - 3, 3, lastthree); 601105197Ssam 602105197Ssam /* Verify pad length */ 603105197Ssam if (lastthree[1] + 2 > m->m_pkthdr.len - skip) { 604252028Sae ESPSTAT_INC(esps_badilen); 605120585Ssam DPRINTF(("%s: invalid padding length %d for %u byte packet " 606120585Ssam "in SA %s/%08lx\n", __func__, 607105197Ssam lastthree[1], m->m_pkthdr.len - skip, 608105197Ssam ipsec_address(&sav->sah->saidx.dst), 609105197Ssam (u_long) ntohl(sav->spi))); 610105197Ssam error = EINVAL; 611105197Ssam goto bad; 612105197Ssam } 613105197Ssam 614105197Ssam /* Verify correct decryption by checking the last padding bytes */ 615105197Ssam if ((sav->flags & SADB_X_EXT_PMASK) != SADB_X_EXT_PRAND) { 616105197Ssam if (lastthree[1] != lastthree[0] && lastthree[1] != 0) { 617252028Sae ESPSTAT_INC(esps_badenc); 618120585Ssam DPRINTF(("%s: decryption failed for packet in " 619120585Ssam "SA %s/%08lx\n", __func__, 620105197Ssam ipsec_address(&sav->sah->saidx.dst), 621105197Ssam (u_long) ntohl(sav->spi))); 622105197Ssam error = EINVAL; 623105197Ssam goto bad; 624105197Ssam } 625105197Ssam } 626105197Ssam 627105197Ssam /* Trim the mbuf chain to remove trailing authenticator and padding */ 628105197Ssam m_adj(m, -(lastthree[1] + 2)); 629105197Ssam 630105197Ssam /* Restore the Next Protocol field */ 631105197Ssam m_copyback(m, protoff, sizeof (u_int8_t), lastthree + 2); 632105197Ssam 633221129Sbz switch (saidx->dst.sa.sa_family) { 634221129Sbz#ifdef INET6 635221129Sbz case AF_INET6: 636221129Sbz error = ipsec6_common_input_cb(m, sav, skip, protoff, mtag); 637221129Sbz break; 638221129Sbz#endif 639221129Sbz#ifdef INET 640221129Sbz case AF_INET: 641221129Sbz error = ipsec4_common_input_cb(m, sav, skip, protoff, mtag); 642221129Sbz break; 643221129Sbz#endif 644221129Sbz default: 645221129Sbz panic("%s: Unexpected address family: %d saidx=%p", __func__, 646221129Sbz saidx->dst.sa.sa_family, saidx); 647221129Sbz } 648105197Ssam 649105197Ssam KEY_FREESAV(&sav); 650105197Ssam return error; 651105197Ssambad: 652105197Ssam if (sav) 653105197Ssam KEY_FREESAV(&sav); 654105197Ssam if (m != NULL) 655105197Ssam m_freem(m); 656105197Ssam if (tc != NULL) 657105197Ssam free(tc, M_XDATA); 658105197Ssam if (crp != NULL) 659105197Ssam crypto_freereq(crp); 660105197Ssam return error; 661105197Ssam} 662105197Ssam 663105197Ssam/* 664105197Ssam * ESP output routine, called by ipsec[46]_process_packet(). 665105197Ssam */ 666105197Ssamstatic int 667105197Ssamesp_output( 668105197Ssam struct mbuf *m, 669105197Ssam struct ipsecrequest *isr, 670105197Ssam struct mbuf **mp, 671105197Ssam int skip, 672105197Ssam int protoff 673105197Ssam) 674105197Ssam{ 675105197Ssam struct enc_xform *espx; 676105197Ssam struct auth_hash *esph; 677228014Spjd int hlen, rlen, padding, blks, alen, i, roff; 678105197Ssam struct mbuf *mo = (struct mbuf *) NULL; 679105197Ssam struct tdb_crypto *tc; 680105197Ssam struct secasvar *sav; 681105197Ssam struct secasindex *saidx; 682105197Ssam unsigned char *pad; 683105197Ssam u_int8_t prot; 684105197Ssam int error, maxpacketsize; 685105197Ssam 686105197Ssam struct cryptodesc *crde = NULL, *crda = NULL; 687105197Ssam struct cryptop *crp; 688105197Ssam 689105197Ssam sav = isr->sav; 690120585Ssam IPSEC_ASSERT(sav != NULL, ("null SA")); 691105197Ssam esph = sav->tdb_authalgxform; 692105197Ssam espx = sav->tdb_encalgxform; 693120585Ssam IPSEC_ASSERT(espx != NULL, ("null encoding xform")); 694105197Ssam 695105197Ssam if (sav->flags & SADB_X_EXT_OLD) 696105197Ssam hlen = sizeof (struct esp) + sav->ivlen; 697105197Ssam else 698105197Ssam hlen = sizeof (struct newesp) + sav->ivlen; 699105197Ssam 700105197Ssam rlen = m->m_pkthdr.len - skip; /* Raw payload length. */ 701105197Ssam /* 702105197Ssam * NB: The null encoding transform has a blocksize of 4 703105197Ssam * so that headers are properly aligned. 704105197Ssam */ 705105197Ssam blks = espx->blocksize; /* IV blocksize */ 706105197Ssam 707105197Ssam /* XXX clamp padding length a la KAME??? */ 708105197Ssam padding = ((blks - ((rlen + 2) % blks)) % blks) + 2; 709105197Ssam 710105197Ssam if (esph) 711218794Svanhu switch (esph->type) { 712218794Svanhu case CRYPTO_SHA2_256_HMAC: 713218794Svanhu case CRYPTO_SHA2_384_HMAC: 714218794Svanhu case CRYPTO_SHA2_512_HMAC: 715218794Svanhu alen = esph->hashsize/2; 716218794Svanhu break; 717218794Svanhu default: 718105197Ssam alen = AH_HMAC_HASHLEN; 719218794Svanhu break; 720218794Svanhu } 721105197Ssam else 722105197Ssam alen = 0; 723105197Ssam 724252028Sae ESPSTAT_INC(esps_output); 725105197Ssam 726105197Ssam saidx = &sav->sah->saidx; 727105197Ssam /* Check for maximum packet size violations. */ 728105197Ssam switch (saidx->dst.sa.sa_family) { 729105197Ssam#ifdef INET 730105197Ssam case AF_INET: 731105197Ssam maxpacketsize = IP_MAXPACKET; 732105197Ssam break; 733105197Ssam#endif /* INET */ 734105197Ssam#ifdef INET6 735105197Ssam case AF_INET6: 736105197Ssam maxpacketsize = IPV6_MAXPACKET; 737105197Ssam break; 738105197Ssam#endif /* INET6 */ 739105197Ssam default: 740120585Ssam DPRINTF(("%s: unknown/unsupported protocol " 741120585Ssam "family %d, SA %s/%08lx\n", __func__, 742105197Ssam saidx->dst.sa.sa_family, ipsec_address(&saidx->dst), 743105197Ssam (u_long) ntohl(sav->spi))); 744252028Sae ESPSTAT_INC(esps_nopf); 745105197Ssam error = EPFNOSUPPORT; 746105197Ssam goto bad; 747105197Ssam } 748105197Ssam if (skip + hlen + rlen + padding + alen > maxpacketsize) { 749120585Ssam DPRINTF(("%s: packet in SA %s/%08lx got too big " 750120585Ssam "(len %u, max len %u)\n", __func__, 751105197Ssam ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi), 752105197Ssam skip + hlen + rlen + padding + alen, maxpacketsize)); 753252028Sae ESPSTAT_INC(esps_toobig); 754105197Ssam error = EMSGSIZE; 755105197Ssam goto bad; 756105197Ssam } 757105197Ssam 758105197Ssam /* Update the counters. */ 759252028Sae ESPSTAT_ADD(esps_obytes, m->m_pkthdr.len - skip); 760105197Ssam 761156756Ssam m = m_unshare(m, M_NOWAIT); 762105197Ssam if (m == NULL) { 763120585Ssam DPRINTF(("%s: cannot clone mbuf chain, SA %s/%08lx\n", __func__, 764105197Ssam ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); 765252028Sae ESPSTAT_INC(esps_hdrops); 766105197Ssam error = ENOBUFS; 767105197Ssam goto bad; 768105197Ssam } 769105197Ssam 770105197Ssam /* Inject ESP header. */ 771105197Ssam mo = m_makespace(m, skip, hlen, &roff); 772105197Ssam if (mo == NULL) { 773120585Ssam DPRINTF(("%s: %u byte ESP hdr inject failed for SA %s/%08lx\n", 774120585Ssam __func__, hlen, ipsec_address(&saidx->dst), 775105197Ssam (u_long) ntohl(sav->spi))); 776252028Sae ESPSTAT_INC(esps_hdrops); /* XXX diffs from openbsd */ 777105197Ssam error = ENOBUFS; 778105197Ssam goto bad; 779105197Ssam } 780105197Ssam 781105197Ssam /* Initialize ESP header. */ 782105197Ssam bcopy((caddr_t) &sav->spi, mtod(mo, caddr_t) + roff, sizeof(u_int32_t)); 783105197Ssam if (sav->replay) { 784157613Spjd u_int32_t replay; 785157613Spjd 786157634Spjd#ifdef REGRESSION 787157613Spjd /* Emulate replay attack when ipsec_replay is TRUE. */ 788181803Sbz if (!V_ipsec_replay) 789157634Spjd#endif 790157613Spjd sav->replay->count++; 791157613Spjd replay = htonl(sav->replay->count); 792105197Ssam bcopy((caddr_t) &replay, 793105197Ssam mtod(mo, caddr_t) + roff + sizeof(u_int32_t), 794105197Ssam sizeof(u_int32_t)); 795105197Ssam } 796105197Ssam 797105197Ssam /* 798105197Ssam * Add padding -- better to do it ourselves than use the crypto engine, 799105197Ssam * although if/when we support compression, we'd have to do that. 800105197Ssam */ 801105197Ssam pad = (u_char *) m_pad(m, padding + alen); 802105197Ssam if (pad == NULL) { 803120585Ssam DPRINTF(("%s: m_pad failed for SA %s/%08lx\n", __func__, 804105197Ssam ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); 805105197Ssam m = NULL; /* NB: free'd by m_pad */ 806105197Ssam error = ENOBUFS; 807105197Ssam goto bad; 808105197Ssam } 809105197Ssam 810105197Ssam /* 811105197Ssam * Add padding: random, zero, or self-describing. 812105197Ssam * XXX catch unexpected setting 813105197Ssam */ 814105197Ssam switch (sav->flags & SADB_X_EXT_PMASK) { 815105197Ssam case SADB_X_EXT_PRAND: 816105197Ssam (void) read_random(pad, padding - 2); 817105197Ssam break; 818105197Ssam case SADB_X_EXT_PZERO: 819105197Ssam bzero(pad, padding - 2); 820105197Ssam break; 821105197Ssam case SADB_X_EXT_PSEQ: 822105197Ssam for (i = 0; i < padding - 2; i++) 823105197Ssam pad[i] = i+1; 824105197Ssam break; 825105197Ssam } 826105197Ssam 827105197Ssam /* Fix padding length and Next Protocol in padding itself. */ 828105197Ssam pad[padding - 2] = padding - 2; 829105197Ssam m_copydata(m, protoff, sizeof(u_int8_t), pad + padding - 1); 830105197Ssam 831105197Ssam /* Fix Next Protocol in IPv4/IPv6 header. */ 832105197Ssam prot = IPPROTO_ESP; 833105197Ssam m_copyback(m, protoff, sizeof(u_int8_t), (u_char *) &prot); 834105197Ssam 835105197Ssam /* Get crypto descriptors. */ 836105197Ssam crp = crypto_getreq(esph && espx ? 2 : 1); 837105197Ssam if (crp == NULL) { 838120585Ssam DPRINTF(("%s: failed to acquire crypto descriptors\n", 839120585Ssam __func__)); 840252028Sae ESPSTAT_INC(esps_crypto); 841105197Ssam error = ENOBUFS; 842105197Ssam goto bad; 843105197Ssam } 844105197Ssam 845105197Ssam if (espx) { 846105197Ssam crde = crp->crp_desc; 847105197Ssam crda = crde->crd_next; 848105197Ssam 849105197Ssam /* Encryption descriptor. */ 850105197Ssam crde->crd_skip = skip + hlen; 851105197Ssam crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen); 852105197Ssam crde->crd_flags = CRD_F_ENCRYPT; 853105197Ssam crde->crd_inject = skip + hlen - sav->ivlen; 854105197Ssam 855105197Ssam /* Encryption operation. */ 856105197Ssam crde->crd_alg = espx->type; 857157123Sgnn crde->crd_key = sav->key_enc->key_data; 858105197Ssam crde->crd_klen = _KEYBITS(sav->key_enc); 859105197Ssam /* XXX Rounds ? */ 860105197Ssam } else 861105197Ssam crda = crp->crp_desc; 862105197Ssam 863105197Ssam /* IPsec-specific opaque crypto info. */ 864105197Ssam tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto), 865105197Ssam M_XDATA, M_NOWAIT|M_ZERO); 866105197Ssam if (tc == NULL) { 867105197Ssam crypto_freereq(crp); 868120585Ssam DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__)); 869252028Sae ESPSTAT_INC(esps_crypto); 870105197Ssam error = ENOBUFS; 871105197Ssam goto bad; 872105197Ssam } 873105197Ssam 874105197Ssam /* Callback parameters */ 875105197Ssam tc->tc_isr = isr; 876220206Sfabient KEY_ADDREFSA(sav); 877220206Sfabient tc->tc_sav = sav; 878105197Ssam tc->tc_spi = sav->spi; 879105197Ssam tc->tc_dst = saidx->dst; 880105197Ssam tc->tc_proto = saidx->proto; 881105197Ssam 882105197Ssam /* Crypto operation descriptor. */ 883105197Ssam crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */ 884117058Ssam crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_CBIFSYNC; 885105197Ssam crp->crp_buf = (caddr_t) m; 886105197Ssam crp->crp_callback = esp_output_cb; 887105197Ssam crp->crp_opaque = (caddr_t) tc; 888105197Ssam crp->crp_sid = sav->tdb_cryptoid; 889105197Ssam 890105197Ssam if (esph) { 891105197Ssam /* Authentication descriptor. */ 892105197Ssam crda->crd_skip = skip; 893105197Ssam crda->crd_len = m->m_pkthdr.len - (skip + alen); 894105197Ssam crda->crd_inject = m->m_pkthdr.len - alen; 895105197Ssam 896105197Ssam /* Authentication operation. */ 897105197Ssam crda->crd_alg = esph->type; 898157123Sgnn crda->crd_key = sav->key_auth->key_data; 899105197Ssam crda->crd_klen = _KEYBITS(sav->key_auth); 900105197Ssam } 901105197Ssam 902105197Ssam return crypto_dispatch(crp); 903105197Ssambad: 904105197Ssam if (m) 905105197Ssam m_freem(m); 906105197Ssam return (error); 907105197Ssam} 908105197Ssam 909105197Ssam/* 910105197Ssam * ESP output callback from the crypto driver. 911105197Ssam */ 912105197Ssamstatic int 913105197Ssamesp_output_cb(struct cryptop *crp) 914105197Ssam{ 915105197Ssam struct tdb_crypto *tc; 916105197Ssam struct ipsecrequest *isr; 917105197Ssam struct secasvar *sav; 918105197Ssam struct mbuf *m; 919228010Spjd int error; 920105197Ssam 921105197Ssam tc = (struct tdb_crypto *) crp->crp_opaque; 922120585Ssam IPSEC_ASSERT(tc != NULL, ("null opaque data area!")); 923105197Ssam m = (struct mbuf *) crp->crp_buf; 924105197Ssam 925105197Ssam isr = tc->tc_isr; 926120585Ssam IPSECREQUEST_LOCK(isr); 927220206Sfabient sav = tc->tc_sav; 928220206Sfabient /* With the isr lock released SA pointer can be updated. */ 929220206Sfabient if (sav != isr->sav) { 930252028Sae ESPSTAT_INC(esps_notdb); 931120585Ssam DPRINTF(("%s: SA gone during crypto (SA %s/%08lx proto %u)\n", 932120585Ssam __func__, ipsec_address(&tc->tc_dst), 933105197Ssam (u_long) ntohl(tc->tc_spi), tc->tc_proto)); 934105197Ssam error = ENOBUFS; /*XXX*/ 935105197Ssam goto bad; 936105197Ssam } 937105197Ssam 938105197Ssam /* Check for crypto errors. */ 939105197Ssam if (crp->crp_etype) { 940105197Ssam /* Reset session ID. */ 941105197Ssam if (sav->tdb_cryptoid != 0) 942105197Ssam sav->tdb_cryptoid = crp->crp_sid; 943105197Ssam 944105197Ssam if (crp->crp_etype == EAGAIN) { 945120585Ssam IPSECREQUEST_UNLOCK(isr); 946228009Spjd return (crypto_dispatch(crp)); 947105197Ssam } 948105197Ssam 949252028Sae ESPSTAT_INC(esps_noxform); 950120585Ssam DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype)); 951105197Ssam error = crp->crp_etype; 952105197Ssam goto bad; 953105197Ssam } 954105197Ssam 955105197Ssam /* Shouldn't happen... */ 956105197Ssam if (m == NULL) { 957252028Sae ESPSTAT_INC(esps_crypto); 958120585Ssam DPRINTF(("%s: bogus returned buffer from crypto\n", __func__)); 959105197Ssam error = EINVAL; 960105197Ssam goto bad; 961105197Ssam } 962252028Sae ESPSTAT_INC(esps_hist[sav->alg_enc]); 963105197Ssam if (sav->tdb_authalgxform != NULL) 964252028Sae AHSTAT_INC(ahs_hist[sav->alg_auth]); 965105197Ssam 966105197Ssam /* Release crypto descriptors. */ 967105197Ssam free(tc, M_XDATA); 968105197Ssam crypto_freereq(crp); 969105197Ssam 970157634Spjd#ifdef REGRESSION 971157613Spjd /* Emulate man-in-the-middle attack when ipsec_integrity is TRUE. */ 972181803Sbz if (V_ipsec_integrity) { 973218794Svanhu static unsigned char ipseczeroes[AH_HMAC_MAXHASHLEN]; 974157613Spjd struct auth_hash *esph; 975157613Spjd 976157613Spjd /* 977157613Spjd * Corrupt HMAC if we want to test integrity verification of 978157613Spjd * the other side. 979157613Spjd */ 980157613Spjd esph = sav->tdb_authalgxform; 981157613Spjd if (esph != NULL) { 982218794Svanhu int alen; 983218794Svanhu 984218794Svanhu switch (esph->type) { 985218794Svanhu case CRYPTO_SHA2_256_HMAC: 986218794Svanhu case CRYPTO_SHA2_384_HMAC: 987218794Svanhu case CRYPTO_SHA2_512_HMAC: 988218794Svanhu alen = esph->hashsize/2; 989218794Svanhu break; 990218794Svanhu default: 991218794Svanhu alen = AH_HMAC_HASHLEN; 992218794Svanhu break; 993218794Svanhu } 994218794Svanhu m_copyback(m, m->m_pkthdr.len - alen, 995218794Svanhu alen, ipseczeroes); 996157613Spjd } 997157613Spjd } 998157634Spjd#endif 999157613Spjd 1000105197Ssam /* NB: m is reclaimed by ipsec_process_done. */ 1001228010Spjd error = ipsec_process_done(m, isr); 1002105197Ssam KEY_FREESAV(&sav); 1003120585Ssam IPSECREQUEST_UNLOCK(isr); 1004228010Spjd return error; 1005105197Ssambad: 1006105197Ssam if (sav) 1007105197Ssam KEY_FREESAV(&sav); 1008120585Ssam IPSECREQUEST_UNLOCK(isr); 1009105197Ssam if (m) 1010105197Ssam m_freem(m); 1011105197Ssam free(tc, M_XDATA); 1012105197Ssam crypto_freereq(crp); 1013105197Ssam return error; 1014105197Ssam} 1015105197Ssam 1016105197Ssamstatic struct xformsw esp_xformsw = { 1017105197Ssam XF_ESP, XFT_CONF|XFT_AUTH, "IPsec ESP", 1018105197Ssam esp_init, esp_zeroize, esp_input, 1019105197Ssam esp_output 1020105197Ssam}; 1021105197Ssam 1022105197Ssamstatic void 1023105197Ssamesp_attach(void) 1024105197Ssam{ 1025105197Ssam 1026195699Srwatson xform_register(&esp_xformsw); 1027105197Ssam} 1028125099SsamSYSINIT(esp_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, esp_attach, NULL); 1029