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 <net/route.h> 60105197Ssam#include <netipsec/ipsec.h> 61105197Ssam#include <netipsec/ah.h> 62105197Ssam#include <netipsec/ah_var.h> 63105197Ssam#include <netipsec/esp.h> 64105197Ssam#include <netipsec/esp_var.h> 65105197Ssam#include <netipsec/xform.h> 66105197Ssam 67105197Ssam#ifdef INET6 68105197Ssam#include <netinet6/ip6_var.h> 69105197Ssam#include <netipsec/ipsec6.h> 70105197Ssam#include <netinet6/ip6_ecn.h> 71105197Ssam#endif 72105197Ssam 73105197Ssam#include <netipsec/key.h> 74105197Ssam#include <netipsec/key_debug.h> 75105197Ssam 76105197Ssam#include <opencrypto/cryptodev.h> 77105197Ssam#include <opencrypto/xform.h> 78105197Ssam 79195699SrwatsonVNET_DEFINE(int, esp_enable) = 1; 80253088SaeVNET_PCPUSTAT_DEFINE(struct espstat, espstat); 81253088SaeVNET_PCPUSTAT_SYSINIT(espstat); 82105197Ssam 83253088Sae#ifdef VIMAGE 84253088SaeVNET_PCPUSTAT_SYSUNINIT(espstat); 85253088Sae#endif /* VIMAGE */ 86253088Sae 87105197SsamSYSCTL_DECL(_net_inet_esp); 88195699SrwatsonSYSCTL_VNET_INT(_net_inet_esp, OID_AUTO, 89195699Srwatson esp_enable, CTLFLAG_RW, &VNET_NAME(esp_enable), 0, ""); 90253088SaeSYSCTL_VNET_PCPUSTAT(_net_inet_esp, IPSECCTL_STATS, stats, 91253088Sae struct espstat, espstat, 92253088Sae "ESP statistics (struct espstat, netipsec/esp_var.h"); 93105197Ssam 94105197Ssamstatic int esp_input_cb(struct cryptop *op); 95105197Ssamstatic int esp_output_cb(struct cryptop *crp); 96105197Ssam 97105197Ssam/* 98105197Ssam * NB: this is public for use by the PF_KEY support. 99105197Ssam * NB: if you add support here; be sure to add code to esp_attach below! 100105197Ssam */ 101105197Ssamstruct enc_xform * 102105197Ssamesp_algorithm_lookup(int alg) 103105197Ssam{ 104105197Ssam if (alg >= ESP_ALG_MAX) 105105197Ssam return NULL; 106105197Ssam switch (alg) { 107105197Ssam case SADB_EALG_DESCBC: 108105197Ssam return &enc_xform_des; 109105197Ssam case SADB_EALG_3DESCBC: 110105197Ssam return &enc_xform_3des; 111105197Ssam case SADB_X_EALG_AES: 112105197Ssam return &enc_xform_rijndael128; 113105197Ssam case SADB_X_EALG_BLOWFISHCBC: 114105197Ssam return &enc_xform_blf; 115105197Ssam case SADB_X_EALG_CAST128CBC: 116105197Ssam return &enc_xform_cast5; 117105197Ssam case SADB_X_EALG_SKIPJACK: 118105197Ssam return &enc_xform_skipjack; 119105197Ssam case SADB_EALG_NULL: 120105197Ssam return &enc_xform_null; 121169425Sgnn case SADB_X_EALG_CAMELLIACBC: 122169425Sgnn return &enc_xform_camellia; 123105197Ssam } 124105197Ssam return NULL; 125105197Ssam} 126105197Ssam 127105197Ssamsize_t 128105197Ssamesp_hdrsiz(struct secasvar *sav) 129105197Ssam{ 130105197Ssam size_t size; 131105197Ssam 132105197Ssam if (sav != NULL) { 133105197Ssam /*XXX not right for null algorithm--does it matter??*/ 134120585Ssam IPSEC_ASSERT(sav->tdb_encalgxform != NULL, 135120585Ssam ("SA with null xform")); 136105197Ssam if (sav->flags & SADB_X_EXT_OLD) 137105197Ssam size = sizeof (struct esp); 138105197Ssam else 139105197Ssam size = sizeof (struct newesp); 140105197Ssam size += sav->tdb_encalgxform->blocksize + 9; 141105197Ssam /*XXX need alg check???*/ 142105197Ssam if (sav->tdb_authalgxform != NULL && sav->replay) 143105197Ssam size += ah_hdrsiz(sav); 144105197Ssam } else { 145105197Ssam /* 146105197Ssam * base header size 147105197Ssam * + max iv length for CBC mode 148105197Ssam * + max pad length 149105197Ssam * + sizeof (pad length field) 150105197Ssam * + sizeof (next header field) 151105197Ssam * + max icv supported. 152105197Ssam */ 153228012Spjd size = sizeof (struct newesp) + EALG_MAX_BLOCK_LEN + 9 + 16; 154105197Ssam } 155105197Ssam return size; 156105197Ssam} 157105197Ssam 158105197Ssam/* 159105197Ssam * esp_init() is called when an SPI is being set up. 160105197Ssam */ 161105197Ssamstatic int 162105197Ssamesp_init(struct secasvar *sav, struct xformsw *xsp) 163105197Ssam{ 164105197Ssam struct enc_xform *txform; 165105197Ssam struct cryptoini cria, crie; 166105197Ssam int keylen; 167105197Ssam int error; 168105197Ssam 169105197Ssam txform = esp_algorithm_lookup(sav->alg_enc); 170105197Ssam if (txform == NULL) { 171120585Ssam DPRINTF(("%s: unsupported encryption algorithm %d\n", 172120585Ssam __func__, sav->alg_enc)); 173105197Ssam return EINVAL; 174105197Ssam } 175105197Ssam if (sav->key_enc == NULL) { 176120585Ssam DPRINTF(("%s: no encoding key for %s algorithm\n", 177120585Ssam __func__, txform->name)); 178105197Ssam return EINVAL; 179105197Ssam } 180105197Ssam if ((sav->flags&(SADB_X_EXT_OLD|SADB_X_EXT_IV4B)) == SADB_X_EXT_IV4B) { 181120585Ssam DPRINTF(("%s: 4-byte IV not supported with protocol\n", 182120585Ssam __func__)); 183105197Ssam return EINVAL; 184105197Ssam } 185105197Ssam keylen = _KEYLEN(sav->key_enc); 186105197Ssam if (txform->minkey > keylen || keylen > txform->maxkey) { 187120585Ssam DPRINTF(("%s: invalid key length %u, must be in the range " 188120585Ssam "[%u..%u] for algorithm %s\n", __func__, 189105197Ssam keylen, txform->minkey, txform->maxkey, 190105197Ssam txform->name)); 191105197Ssam return EINVAL; 192105197Ssam } 193105197Ssam 194105197Ssam /* 195105197Ssam * NB: The null xform needs a non-zero blocksize to keep the 196105197Ssam * crypto code happy but if we use it to set ivlen then 197105197Ssam * the ESP header will be processed incorrectly. The 198105197Ssam * compromise is to force it to zero here. 199105197Ssam */ 200105197Ssam sav->ivlen = (txform == &enc_xform_null ? 0 : txform->blocksize); 201111119Simp sav->iv = (caddr_t) malloc(sav->ivlen, M_XDATA, M_WAITOK); 202105197Ssam key_randomfill(sav->iv, sav->ivlen); /*XXX*/ 203105197Ssam 204105197Ssam /* 205105197Ssam * Setup AH-related state. 206105197Ssam */ 207105197Ssam if (sav->alg_auth != 0) { 208105197Ssam error = ah_init0(sav, xsp, &cria); 209105197Ssam if (error) 210105197Ssam return error; 211105197Ssam } 212105197Ssam 213105197Ssam /* NB: override anything set in ah_init0 */ 214105197Ssam sav->tdb_xform = xsp; 215105197Ssam sav->tdb_encalgxform = txform; 216105197Ssam 217105197Ssam /* Initialize crypto session. */ 218105197Ssam bzero(&crie, sizeof (crie)); 219105197Ssam crie.cri_alg = sav->tdb_encalgxform->type; 220105197Ssam crie.cri_klen = _KEYBITS(sav->key_enc); 221157123Sgnn crie.cri_key = sav->key_enc->key_data; 222105197Ssam /* XXX Rounds ? */ 223105197Ssam 224105197Ssam if (sav->tdb_authalgxform && sav->tdb_encalgxform) { 225105197Ssam /* init both auth & enc */ 226105197Ssam crie.cri_next = &cria; 227105197Ssam error = crypto_newsession(&sav->tdb_cryptoid, 228181803Sbz &crie, V_crypto_support); 229105197Ssam } else if (sav->tdb_encalgxform) { 230105197Ssam error = crypto_newsession(&sav->tdb_cryptoid, 231181803Sbz &crie, V_crypto_support); 232105197Ssam } else if (sav->tdb_authalgxform) { 233105197Ssam error = crypto_newsession(&sav->tdb_cryptoid, 234181803Sbz &cria, V_crypto_support); 235105197Ssam } else { 236105197Ssam /* XXX cannot happen? */ 237120585Ssam DPRINTF(("%s: no encoding OR authentication xform!\n", 238120585Ssam __func__)); 239105197Ssam error = EINVAL; 240105197Ssam } 241105197Ssam return error; 242105197Ssam} 243105197Ssam 244105197Ssam/* 245105197Ssam * Paranoia. 246105197Ssam */ 247105197Ssamstatic int 248105197Ssamesp_zeroize(struct secasvar *sav) 249105197Ssam{ 250105197Ssam /* NB: ah_zerorize free's the crypto session state */ 251105197Ssam int error = ah_zeroize(sav); 252105197Ssam 253105197Ssam if (sav->key_enc) 254157123Sgnn bzero(sav->key_enc->key_data, _KEYLEN(sav->key_enc)); 255120585Ssam if (sav->iv) { 256120585Ssam free(sav->iv, M_XDATA); 257120585Ssam sav->iv = NULL; 258120585Ssam } 259105197Ssam sav->tdb_encalgxform = NULL; 260105197Ssam sav->tdb_xform = NULL; 261105197Ssam return error; 262105197Ssam} 263105197Ssam 264105197Ssam/* 265105197Ssam * ESP input processing, called (eventually) through the protocol switch. 266105197Ssam */ 267105197Ssamstatic int 268105197Ssamesp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff) 269105197Ssam{ 270105197Ssam struct auth_hash *esph; 271105197Ssam struct enc_xform *espx; 272105197Ssam struct tdb_ident *tdbi; 273105197Ssam struct tdb_crypto *tc; 274105197Ssam int plen, alen, hlen; 275105197Ssam struct m_tag *mtag; 276105197Ssam struct newesp *esp; 277105197Ssam 278105197Ssam struct cryptodesc *crde; 279105197Ssam struct cryptop *crp; 280105197Ssam 281120585Ssam IPSEC_ASSERT(sav != NULL, ("null SA")); 282120585Ssam IPSEC_ASSERT(sav->tdb_encalgxform != NULL, ("null encoding xform")); 283105197Ssam 284197674Svanhu /* Valid IP Packet length ? */ 285197674Svanhu if ( (skip&3) || (m->m_pkthdr.len&3) ){ 286197674Svanhu DPRINTF(("%s: misaligned packet, skip %u pkt len %u", 287197674Svanhu __func__, skip, m->m_pkthdr.len)); 288252028Sae ESPSTAT_INC(esps_badilen); 289197674Svanhu m_freem(m); 290197674Svanhu return EINVAL; 291197674Svanhu } 292197674Svanhu 293105197Ssam /* XXX don't pullup, just copy header */ 294105197Ssam IP6_EXTHDR_GET(esp, struct newesp *, m, skip, sizeof (struct newesp)); 295105197Ssam 296105197Ssam esph = sav->tdb_authalgxform; 297105197Ssam espx = sav->tdb_encalgxform; 298105197Ssam 299105197Ssam /* Determine the ESP header length */ 300105197Ssam if (sav->flags & SADB_X_EXT_OLD) 301105197Ssam hlen = sizeof (struct esp) + sav->ivlen; 302105197Ssam else 303105197Ssam hlen = sizeof (struct newesp) + sav->ivlen; 304105197Ssam /* Authenticator hash size */ 305218794Svanhu if (esph != NULL) { 306218794Svanhu switch (esph->type) { 307218794Svanhu case CRYPTO_SHA2_256_HMAC: 308218794Svanhu case CRYPTO_SHA2_384_HMAC: 309218794Svanhu case CRYPTO_SHA2_512_HMAC: 310218794Svanhu alen = esph->hashsize/2; 311218794Svanhu break; 312218794Svanhu default: 313218794Svanhu alen = AH_HMAC_HASHLEN; 314218794Svanhu break; 315218794Svanhu } 316218794Svanhu }else 317218794Svanhu alen = 0; 318105197Ssam 319105197Ssam /* 320105197Ssam * Verify payload length is multiple of encryption algorithm 321105197Ssam * block size. 322105197Ssam * 323105197Ssam * NB: This works for the null algorithm because the blocksize 324105197Ssam * is 4 and all packets must be 4-byte aligned regardless 325105197Ssam * of the algorithm. 326105197Ssam */ 327105197Ssam plen = m->m_pkthdr.len - (skip + hlen + alen); 328105197Ssam if ((plen & (espx->blocksize - 1)) || (plen <= 0)) { 329120585Ssam DPRINTF(("%s: payload of %d octets not a multiple of %d octets," 330120585Ssam " SA %s/%08lx\n", __func__, 331105197Ssam plen, espx->blocksize, 332105197Ssam ipsec_address(&sav->sah->saidx.dst), 333105197Ssam (u_long) ntohl(sav->spi))); 334252028Sae ESPSTAT_INC(esps_badilen); 335105197Ssam m_freem(m); 336105197Ssam return EINVAL; 337105197Ssam } 338105197Ssam 339105197Ssam /* 340105197Ssam * Check sequence number. 341105197Ssam */ 342105197Ssam if (esph && sav->replay && !ipsec_chkreplay(ntohl(esp->esp_seq), sav)) { 343120585Ssam DPRINTF(("%s: packet replay check for %s\n", __func__, 344105197Ssam ipsec_logsastr(sav))); /*XXX*/ 345252028Sae ESPSTAT_INC(esps_replay); 346105197Ssam m_freem(m); 347105197Ssam return ENOBUFS; /*XXX*/ 348105197Ssam } 349105197Ssam 350105197Ssam /* Update the counters */ 351252028Sae ESPSTAT_ADD(esps_ibytes, m->m_pkthdr.len - (skip + hlen + alen)); 352105197Ssam 353105197Ssam /* Find out if we've already done crypto */ 354105197Ssam for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL); 355105197Ssam mtag != NULL; 356105197Ssam mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, mtag)) { 357105197Ssam tdbi = (struct tdb_ident *) (mtag + 1); 358105197Ssam if (tdbi->proto == sav->sah->saidx.proto && 359105197Ssam tdbi->spi == sav->spi && 360105197Ssam !bcmp(&tdbi->dst, &sav->sah->saidx.dst, 361105197Ssam sizeof(union sockaddr_union))) 362105197Ssam break; 363105197Ssam } 364105197Ssam 365105197Ssam /* Get crypto descriptors */ 366105197Ssam crp = crypto_getreq(esph && espx ? 2 : 1); 367105197Ssam if (crp == NULL) { 368120585Ssam DPRINTF(("%s: failed to acquire crypto descriptors\n", 369120585Ssam __func__)); 370252028Sae ESPSTAT_INC(esps_crypto); 371105197Ssam m_freem(m); 372105197Ssam return ENOBUFS; 373105197Ssam } 374105197Ssam 375105197Ssam /* Get IPsec-specific opaque pointer */ 376105197Ssam if (esph == NULL || mtag != NULL) 377105197Ssam tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto), 378105197Ssam M_XDATA, M_NOWAIT|M_ZERO); 379105197Ssam else 380105197Ssam tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto) + alen, 381105197Ssam M_XDATA, M_NOWAIT|M_ZERO); 382105197Ssam if (tc == NULL) { 383105197Ssam crypto_freereq(crp); 384120585Ssam DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__)); 385252028Sae ESPSTAT_INC(esps_crypto); 386105197Ssam m_freem(m); 387105197Ssam return ENOBUFS; 388105197Ssam } 389105197Ssam 390105197Ssam tc->tc_ptr = (caddr_t) mtag; 391105197Ssam 392105197Ssam if (esph) { 393105197Ssam struct cryptodesc *crda = crp->crp_desc; 394105197Ssam 395120585Ssam IPSEC_ASSERT(crda != NULL, ("null ah crypto descriptor")); 396105197Ssam 397105197Ssam /* Authentication descriptor */ 398105197Ssam crda->crd_skip = skip; 399105197Ssam crda->crd_len = m->m_pkthdr.len - (skip + alen); 400105197Ssam crda->crd_inject = m->m_pkthdr.len - alen; 401105197Ssam 402105197Ssam crda->crd_alg = esph->type; 403157123Sgnn crda->crd_key = sav->key_auth->key_data; 404105197Ssam crda->crd_klen = _KEYBITS(sav->key_auth); 405105197Ssam 406105197Ssam /* Copy the authenticator */ 407105197Ssam if (mtag == NULL) 408105197Ssam m_copydata(m, m->m_pkthdr.len - alen, alen, 409105197Ssam (caddr_t) (tc + 1)); 410105197Ssam 411105197Ssam /* Chain authentication request */ 412105197Ssam crde = crda->crd_next; 413105197Ssam } else { 414105197Ssam crde = crp->crp_desc; 415105197Ssam } 416105197Ssam 417105197Ssam /* Crypto operation descriptor */ 418105197Ssam crp->crp_ilen = m->m_pkthdr.len; /* Total input length */ 419117058Ssam crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_CBIFSYNC; 420105197Ssam crp->crp_buf = (caddr_t) m; 421105197Ssam crp->crp_callback = esp_input_cb; 422105197Ssam crp->crp_sid = sav->tdb_cryptoid; 423105197Ssam crp->crp_opaque = (caddr_t) tc; 424105197Ssam 425105197Ssam /* These are passed as-is to the callback */ 426105197Ssam tc->tc_spi = sav->spi; 427105197Ssam tc->tc_dst = sav->sah->saidx.dst; 428105197Ssam tc->tc_proto = sav->sah->saidx.proto; 429105197Ssam tc->tc_protoff = protoff; 430105197Ssam tc->tc_skip = skip; 431220206Sfabient KEY_ADDREFSA(sav); 432220206Sfabient tc->tc_sav = sav; 433105197Ssam 434105197Ssam /* Decryption descriptor */ 435105197Ssam if (espx) { 436120585Ssam IPSEC_ASSERT(crde != NULL, ("null esp crypto descriptor")); 437105197Ssam crde->crd_skip = skip + hlen; 438105197Ssam crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen); 439105197Ssam crde->crd_inject = skip + hlen - sav->ivlen; 440105197Ssam 441105197Ssam crde->crd_alg = espx->type; 442157123Sgnn crde->crd_key = sav->key_enc->key_data; 443105197Ssam crde->crd_klen = _KEYBITS(sav->key_enc); 444105197Ssam /* XXX Rounds ? */ 445105197Ssam } 446105197Ssam 447105197Ssam if (mtag == NULL) 448105197Ssam return crypto_dispatch(crp); 449105197Ssam else 450105197Ssam return esp_input_cb(crp); 451105197Ssam} 452105197Ssam 453105197Ssam/* 454105197Ssam * ESP input callback from the crypto driver. 455105197Ssam */ 456105197Ssamstatic int 457105197Ssamesp_input_cb(struct cryptop *crp) 458105197Ssam{ 459218794Svanhu u_int8_t lastthree[3], aalg[AH_HMAC_MAXHASHLEN]; 460218794Svanhu int hlen, skip, protoff, error, alen; 461105197Ssam struct mbuf *m; 462105197Ssam struct cryptodesc *crd; 463105197Ssam struct auth_hash *esph; 464105197Ssam struct enc_xform *espx; 465105197Ssam struct tdb_crypto *tc; 466105197Ssam struct m_tag *mtag; 467105197Ssam struct secasvar *sav; 468105197Ssam struct secasindex *saidx; 469105197Ssam caddr_t ptr; 470105197Ssam 471105197Ssam crd = crp->crp_desc; 472120585Ssam IPSEC_ASSERT(crd != NULL, ("null crypto descriptor!")); 473105197Ssam 474105197Ssam tc = (struct tdb_crypto *) crp->crp_opaque; 475120585Ssam IPSEC_ASSERT(tc != NULL, ("null opaque crypto data area!")); 476105197Ssam skip = tc->tc_skip; 477105197Ssam protoff = tc->tc_protoff; 478105197Ssam mtag = (struct m_tag *) tc->tc_ptr; 479105197Ssam m = (struct mbuf *) crp->crp_buf; 480105197Ssam 481220206Sfabient sav = tc->tc_sav; 482220206Sfabient IPSEC_ASSERT(sav != NULL, ("null SA!")); 483105197Ssam 484105197Ssam saidx = &sav->sah->saidx; 485120585Ssam IPSEC_ASSERT(saidx->dst.sa.sa_family == AF_INET || 486105197Ssam saidx->dst.sa.sa_family == AF_INET6, 487120585Ssam ("unexpected protocol family %u", saidx->dst.sa.sa_family)); 488105197Ssam 489105197Ssam esph = sav->tdb_authalgxform; 490105197Ssam espx = sav->tdb_encalgxform; 491105197Ssam 492105197Ssam /* Check for crypto errors */ 493105197Ssam if (crp->crp_etype) { 494105197Ssam /* Reset the session ID */ 495105197Ssam if (sav->tdb_cryptoid != 0) 496105197Ssam sav->tdb_cryptoid = crp->crp_sid; 497105197Ssam 498228009Spjd if (crp->crp_etype == EAGAIN) 499228009Spjd return (crypto_dispatch(crp)); 500105197Ssam 501252028Sae ESPSTAT_INC(esps_noxform); 502120585Ssam DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype)); 503105197Ssam error = crp->crp_etype; 504105197Ssam goto bad; 505105197Ssam } 506105197Ssam 507105197Ssam /* Shouldn't happen... */ 508105197Ssam if (m == NULL) { 509252028Sae ESPSTAT_INC(esps_crypto); 510120585Ssam DPRINTF(("%s: bogus returned buffer from crypto\n", __func__)); 511105197Ssam error = EINVAL; 512105197Ssam goto bad; 513105197Ssam } 514252028Sae ESPSTAT_INC(esps_hist[sav->alg_enc]); 515105197Ssam 516105197Ssam /* If authentication was performed, check now. */ 517105197Ssam if (esph != NULL) { 518218794Svanhu switch (esph->type) { 519218794Svanhu case CRYPTO_SHA2_256_HMAC: 520218794Svanhu case CRYPTO_SHA2_384_HMAC: 521218794Svanhu case CRYPTO_SHA2_512_HMAC: 522218794Svanhu alen = esph->hashsize/2; 523218794Svanhu break; 524218794Svanhu default: 525218794Svanhu alen = AH_HMAC_HASHLEN; 526218794Svanhu break; 527218794Svanhu } 528105197Ssam /* 529105197Ssam * If we have a tag, it means an IPsec-aware NIC did 530105197Ssam * the verification for us. Otherwise we need to 531105197Ssam * check the authentication calculation. 532105197Ssam */ 533252028Sae AHSTAT_INC(ahs_hist[sav->alg_auth]); 534105197Ssam if (mtag == NULL) { 535105197Ssam /* Copy the authenticator from the packet */ 536218794Svanhu m_copydata(m, m->m_pkthdr.len - alen, 537218794Svanhu alen, aalg); 538105197Ssam 539105197Ssam ptr = (caddr_t) (tc + 1); 540105197Ssam 541105197Ssam /* Verify authenticator */ 542218794Svanhu if (bcmp(ptr, aalg, alen) != 0) { 543120585Ssam DPRINTF(("%s: " 544105197Ssam "authentication hash mismatch for packet in SA %s/%08lx\n", 545120585Ssam __func__, 546105197Ssam ipsec_address(&saidx->dst), 547105197Ssam (u_long) ntohl(sav->spi))); 548252028Sae ESPSTAT_INC(esps_badauth); 549105197Ssam error = EACCES; 550105197Ssam goto bad; 551105197Ssam } 552105197Ssam } 553105197Ssam 554105197Ssam /* Remove trailing authenticator */ 555218794Svanhu m_adj(m, -alen); 556105197Ssam } 557105197Ssam 558105197Ssam /* Release the crypto descriptors */ 559105197Ssam free(tc, M_XDATA), tc = NULL; 560105197Ssam crypto_freereq(crp), crp = NULL; 561105197Ssam 562105197Ssam /* 563105197Ssam * Packet is now decrypted. 564105197Ssam */ 565105197Ssam m->m_flags |= M_DECRYPTED; 566105197Ssam 567156997Scperciva /* 568156997Scperciva * Update replay sequence number, if appropriate. 569156997Scperciva */ 570156997Scperciva if (sav->replay) { 571156997Scperciva u_int32_t seq; 572156997Scperciva 573156997Scperciva m_copydata(m, skip + offsetof(struct newesp, esp_seq), 574156997Scperciva sizeof (seq), (caddr_t) &seq); 575156997Scperciva if (ipsec_updatereplay(ntohl(seq), sav)) { 576156997Scperciva DPRINTF(("%s: packet replay check for %s\n", __func__, 577156997Scperciva ipsec_logsastr(sav))); 578252028Sae ESPSTAT_INC(esps_replay); 579156997Scperciva error = ENOBUFS; 580156997Scperciva goto bad; 581156997Scperciva } 582156997Scperciva } 583156997Scperciva 584105197Ssam /* Determine the ESP header length */ 585105197Ssam if (sav->flags & SADB_X_EXT_OLD) 586105197Ssam hlen = sizeof (struct esp) + sav->ivlen; 587105197Ssam else 588105197Ssam hlen = sizeof (struct newesp) + sav->ivlen; 589105197Ssam 590105197Ssam /* Remove the ESP header and IV from the mbuf. */ 591105197Ssam error = m_striphdr(m, skip, hlen); 592105197Ssam if (error) { 593252028Sae ESPSTAT_INC(esps_hdrops); 594120585Ssam DPRINTF(("%s: bad mbuf chain, SA %s/%08lx\n", __func__, 595105197Ssam ipsec_address(&sav->sah->saidx.dst), 596105197Ssam (u_long) ntohl(sav->spi))); 597105197Ssam goto bad; 598105197Ssam } 599105197Ssam 600105197Ssam /* Save the last three bytes of decrypted data */ 601105197Ssam m_copydata(m, m->m_pkthdr.len - 3, 3, lastthree); 602105197Ssam 603105197Ssam /* Verify pad length */ 604105197Ssam if (lastthree[1] + 2 > m->m_pkthdr.len - skip) { 605252028Sae ESPSTAT_INC(esps_badilen); 606120585Ssam DPRINTF(("%s: invalid padding length %d for %u byte packet " 607120585Ssam "in SA %s/%08lx\n", __func__, 608105197Ssam lastthree[1], m->m_pkthdr.len - skip, 609105197Ssam ipsec_address(&sav->sah->saidx.dst), 610105197Ssam (u_long) ntohl(sav->spi))); 611105197Ssam error = EINVAL; 612105197Ssam goto bad; 613105197Ssam } 614105197Ssam 615105197Ssam /* Verify correct decryption by checking the last padding bytes */ 616105197Ssam if ((sav->flags & SADB_X_EXT_PMASK) != SADB_X_EXT_PRAND) { 617105197Ssam if (lastthree[1] != lastthree[0] && lastthree[1] != 0) { 618252028Sae ESPSTAT_INC(esps_badenc); 619120585Ssam DPRINTF(("%s: decryption failed for packet in " 620120585Ssam "SA %s/%08lx\n", __func__, 621105197Ssam ipsec_address(&sav->sah->saidx.dst), 622105197Ssam (u_long) ntohl(sav->spi))); 623105197Ssam error = EINVAL; 624105197Ssam goto bad; 625105197Ssam } 626105197Ssam } 627105197Ssam 628105197Ssam /* Trim the mbuf chain to remove trailing authenticator and padding */ 629105197Ssam m_adj(m, -(lastthree[1] + 2)); 630105197Ssam 631105197Ssam /* Restore the Next Protocol field */ 632105197Ssam m_copyback(m, protoff, sizeof (u_int8_t), lastthree + 2); 633105197Ssam 634221129Sbz switch (saidx->dst.sa.sa_family) { 635221129Sbz#ifdef INET6 636221129Sbz case AF_INET6: 637221129Sbz error = ipsec6_common_input_cb(m, sav, skip, protoff, mtag); 638221129Sbz break; 639221129Sbz#endif 640221129Sbz#ifdef INET 641221129Sbz case AF_INET: 642221129Sbz error = ipsec4_common_input_cb(m, sav, skip, protoff, mtag); 643221129Sbz break; 644221129Sbz#endif 645221129Sbz default: 646221129Sbz panic("%s: Unexpected address family: %d saidx=%p", __func__, 647221129Sbz saidx->dst.sa.sa_family, saidx); 648221129Sbz } 649105197Ssam 650105197Ssam KEY_FREESAV(&sav); 651105197Ssam return error; 652105197Ssambad: 653105197Ssam if (sav) 654105197Ssam KEY_FREESAV(&sav); 655105197Ssam if (m != NULL) 656105197Ssam m_freem(m); 657105197Ssam if (tc != NULL) 658105197Ssam free(tc, M_XDATA); 659105197Ssam if (crp != NULL) 660105197Ssam crypto_freereq(crp); 661105197Ssam return error; 662105197Ssam} 663105197Ssam 664105197Ssam/* 665105197Ssam * ESP output routine, called by ipsec[46]_process_packet(). 666105197Ssam */ 667105197Ssamstatic int 668105197Ssamesp_output( 669105197Ssam struct mbuf *m, 670105197Ssam struct ipsecrequest *isr, 671105197Ssam struct mbuf **mp, 672105197Ssam int skip, 673105197Ssam int protoff 674105197Ssam) 675105197Ssam{ 676105197Ssam struct enc_xform *espx; 677105197Ssam struct auth_hash *esph; 678228014Spjd int hlen, rlen, padding, blks, alen, i, roff; 679105197Ssam struct mbuf *mo = (struct mbuf *) NULL; 680105197Ssam struct tdb_crypto *tc; 681105197Ssam struct secasvar *sav; 682105197Ssam struct secasindex *saidx; 683105197Ssam unsigned char *pad; 684105197Ssam u_int8_t prot; 685105197Ssam int error, maxpacketsize; 686105197Ssam 687105197Ssam struct cryptodesc *crde = NULL, *crda = NULL; 688105197Ssam struct cryptop *crp; 689105197Ssam 690105197Ssam sav = isr->sav; 691120585Ssam IPSEC_ASSERT(sav != NULL, ("null SA")); 692105197Ssam esph = sav->tdb_authalgxform; 693105197Ssam espx = sav->tdb_encalgxform; 694120585Ssam IPSEC_ASSERT(espx != NULL, ("null encoding xform")); 695105197Ssam 696105197Ssam if (sav->flags & SADB_X_EXT_OLD) 697105197Ssam hlen = sizeof (struct esp) + sav->ivlen; 698105197Ssam else 699105197Ssam hlen = sizeof (struct newesp) + sav->ivlen; 700105197Ssam 701105197Ssam rlen = m->m_pkthdr.len - skip; /* Raw payload length. */ 702105197Ssam /* 703105197Ssam * NB: The null encoding transform has a blocksize of 4 704105197Ssam * so that headers are properly aligned. 705105197Ssam */ 706105197Ssam blks = espx->blocksize; /* IV blocksize */ 707105197Ssam 708105197Ssam /* XXX clamp padding length a la KAME??? */ 709105197Ssam padding = ((blks - ((rlen + 2) % blks)) % blks) + 2; 710105197Ssam 711105197Ssam if (esph) 712218794Svanhu switch (esph->type) { 713218794Svanhu case CRYPTO_SHA2_256_HMAC: 714218794Svanhu case CRYPTO_SHA2_384_HMAC: 715218794Svanhu case CRYPTO_SHA2_512_HMAC: 716218794Svanhu alen = esph->hashsize/2; 717218794Svanhu break; 718218794Svanhu default: 719105197Ssam alen = AH_HMAC_HASHLEN; 720218794Svanhu break; 721218794Svanhu } 722105197Ssam else 723105197Ssam alen = 0; 724105197Ssam 725252028Sae ESPSTAT_INC(esps_output); 726105197Ssam 727105197Ssam saidx = &sav->sah->saidx; 728105197Ssam /* Check for maximum packet size violations. */ 729105197Ssam switch (saidx->dst.sa.sa_family) { 730105197Ssam#ifdef INET 731105197Ssam case AF_INET: 732105197Ssam maxpacketsize = IP_MAXPACKET; 733105197Ssam break; 734105197Ssam#endif /* INET */ 735105197Ssam#ifdef INET6 736105197Ssam case AF_INET6: 737105197Ssam maxpacketsize = IPV6_MAXPACKET; 738105197Ssam break; 739105197Ssam#endif /* INET6 */ 740105197Ssam default: 741120585Ssam DPRINTF(("%s: unknown/unsupported protocol " 742120585Ssam "family %d, SA %s/%08lx\n", __func__, 743105197Ssam saidx->dst.sa.sa_family, ipsec_address(&saidx->dst), 744105197Ssam (u_long) ntohl(sav->spi))); 745252028Sae ESPSTAT_INC(esps_nopf); 746105197Ssam error = EPFNOSUPPORT; 747105197Ssam goto bad; 748105197Ssam } 749105197Ssam if (skip + hlen + rlen + padding + alen > maxpacketsize) { 750120585Ssam DPRINTF(("%s: packet in SA %s/%08lx got too big " 751120585Ssam "(len %u, max len %u)\n", __func__, 752105197Ssam ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi), 753105197Ssam skip + hlen + rlen + padding + alen, maxpacketsize)); 754252028Sae ESPSTAT_INC(esps_toobig); 755105197Ssam error = EMSGSIZE; 756105197Ssam goto bad; 757105197Ssam } 758105197Ssam 759105197Ssam /* Update the counters. */ 760252028Sae ESPSTAT_ADD(esps_obytes, m->m_pkthdr.len - skip); 761105197Ssam 762156756Ssam m = m_unshare(m, M_NOWAIT); 763105197Ssam if (m == NULL) { 764120585Ssam DPRINTF(("%s: cannot clone mbuf chain, SA %s/%08lx\n", __func__, 765105197Ssam ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); 766252028Sae ESPSTAT_INC(esps_hdrops); 767105197Ssam error = ENOBUFS; 768105197Ssam goto bad; 769105197Ssam } 770105197Ssam 771105197Ssam /* Inject ESP header. */ 772105197Ssam mo = m_makespace(m, skip, hlen, &roff); 773105197Ssam if (mo == NULL) { 774120585Ssam DPRINTF(("%s: %u byte ESP hdr inject failed for SA %s/%08lx\n", 775120585Ssam __func__, hlen, ipsec_address(&saidx->dst), 776105197Ssam (u_long) ntohl(sav->spi))); 777252028Sae ESPSTAT_INC(esps_hdrops); /* XXX diffs from openbsd */ 778105197Ssam error = ENOBUFS; 779105197Ssam goto bad; 780105197Ssam } 781105197Ssam 782105197Ssam /* Initialize ESP header. */ 783105197Ssam bcopy((caddr_t) &sav->spi, mtod(mo, caddr_t) + roff, sizeof(u_int32_t)); 784105197Ssam if (sav->replay) { 785157613Spjd u_int32_t replay; 786157613Spjd 787157634Spjd#ifdef REGRESSION 788157613Spjd /* Emulate replay attack when ipsec_replay is TRUE. */ 789181803Sbz if (!V_ipsec_replay) 790157634Spjd#endif 791157613Spjd sav->replay->count++; 792157613Spjd replay = htonl(sav->replay->count); 793105197Ssam bcopy((caddr_t) &replay, 794105197Ssam mtod(mo, caddr_t) + roff + sizeof(u_int32_t), 795105197Ssam sizeof(u_int32_t)); 796105197Ssam } 797105197Ssam 798105197Ssam /* 799105197Ssam * Add padding -- better to do it ourselves than use the crypto engine, 800105197Ssam * although if/when we support compression, we'd have to do that. 801105197Ssam */ 802105197Ssam pad = (u_char *) m_pad(m, padding + alen); 803105197Ssam if (pad == NULL) { 804120585Ssam DPRINTF(("%s: m_pad failed for SA %s/%08lx\n", __func__, 805105197Ssam ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); 806105197Ssam m = NULL; /* NB: free'd by m_pad */ 807105197Ssam error = ENOBUFS; 808105197Ssam goto bad; 809105197Ssam } 810105197Ssam 811105197Ssam /* 812105197Ssam * Add padding: random, zero, or self-describing. 813105197Ssam * XXX catch unexpected setting 814105197Ssam */ 815105197Ssam switch (sav->flags & SADB_X_EXT_PMASK) { 816105197Ssam case SADB_X_EXT_PRAND: 817105197Ssam (void) read_random(pad, padding - 2); 818105197Ssam break; 819105197Ssam case SADB_X_EXT_PZERO: 820105197Ssam bzero(pad, padding - 2); 821105197Ssam break; 822105197Ssam case SADB_X_EXT_PSEQ: 823105197Ssam for (i = 0; i < padding - 2; i++) 824105197Ssam pad[i] = i+1; 825105197Ssam break; 826105197Ssam } 827105197Ssam 828105197Ssam /* Fix padding length and Next Protocol in padding itself. */ 829105197Ssam pad[padding - 2] = padding - 2; 830105197Ssam m_copydata(m, protoff, sizeof(u_int8_t), pad + padding - 1); 831105197Ssam 832105197Ssam /* Fix Next Protocol in IPv4/IPv6 header. */ 833105197Ssam prot = IPPROTO_ESP; 834105197Ssam m_copyback(m, protoff, sizeof(u_int8_t), (u_char *) &prot); 835105197Ssam 836105197Ssam /* Get crypto descriptors. */ 837105197Ssam crp = crypto_getreq(esph && espx ? 2 : 1); 838105197Ssam if (crp == NULL) { 839120585Ssam DPRINTF(("%s: failed to acquire crypto descriptors\n", 840120585Ssam __func__)); 841252028Sae ESPSTAT_INC(esps_crypto); 842105197Ssam error = ENOBUFS; 843105197Ssam goto bad; 844105197Ssam } 845105197Ssam 846105197Ssam if (espx) { 847105197Ssam crde = crp->crp_desc; 848105197Ssam crda = crde->crd_next; 849105197Ssam 850105197Ssam /* Encryption descriptor. */ 851105197Ssam crde->crd_skip = skip + hlen; 852105197Ssam crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen); 853105197Ssam crde->crd_flags = CRD_F_ENCRYPT; 854105197Ssam crde->crd_inject = skip + hlen - sav->ivlen; 855105197Ssam 856105197Ssam /* Encryption operation. */ 857105197Ssam crde->crd_alg = espx->type; 858157123Sgnn crde->crd_key = sav->key_enc->key_data; 859105197Ssam crde->crd_klen = _KEYBITS(sav->key_enc); 860105197Ssam /* XXX Rounds ? */ 861105197Ssam } else 862105197Ssam crda = crp->crp_desc; 863105197Ssam 864105197Ssam /* IPsec-specific opaque crypto info. */ 865105197Ssam tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto), 866105197Ssam M_XDATA, M_NOWAIT|M_ZERO); 867105197Ssam if (tc == NULL) { 868105197Ssam crypto_freereq(crp); 869120585Ssam DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__)); 870252028Sae ESPSTAT_INC(esps_crypto); 871105197Ssam error = ENOBUFS; 872105197Ssam goto bad; 873105197Ssam } 874105197Ssam 875105197Ssam /* Callback parameters */ 876105197Ssam tc->tc_isr = isr; 877220206Sfabient KEY_ADDREFSA(sav); 878220206Sfabient tc->tc_sav = sav; 879105197Ssam tc->tc_spi = sav->spi; 880105197Ssam tc->tc_dst = saidx->dst; 881105197Ssam tc->tc_proto = saidx->proto; 882105197Ssam 883105197Ssam /* Crypto operation descriptor. */ 884105197Ssam crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */ 885117058Ssam crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_CBIFSYNC; 886105197Ssam crp->crp_buf = (caddr_t) m; 887105197Ssam crp->crp_callback = esp_output_cb; 888105197Ssam crp->crp_opaque = (caddr_t) tc; 889105197Ssam crp->crp_sid = sav->tdb_cryptoid; 890105197Ssam 891105197Ssam if (esph) { 892105197Ssam /* Authentication descriptor. */ 893105197Ssam crda->crd_skip = skip; 894105197Ssam crda->crd_len = m->m_pkthdr.len - (skip + alen); 895105197Ssam crda->crd_inject = m->m_pkthdr.len - alen; 896105197Ssam 897105197Ssam /* Authentication operation. */ 898105197Ssam crda->crd_alg = esph->type; 899157123Sgnn crda->crd_key = sav->key_auth->key_data; 900105197Ssam crda->crd_klen = _KEYBITS(sav->key_auth); 901105197Ssam } 902105197Ssam 903105197Ssam return crypto_dispatch(crp); 904105197Ssambad: 905105197Ssam if (m) 906105197Ssam m_freem(m); 907105197Ssam return (error); 908105197Ssam} 909105197Ssam 910105197Ssam/* 911105197Ssam * ESP output callback from the crypto driver. 912105197Ssam */ 913105197Ssamstatic int 914105197Ssamesp_output_cb(struct cryptop *crp) 915105197Ssam{ 916105197Ssam struct tdb_crypto *tc; 917105197Ssam struct ipsecrequest *isr; 918105197Ssam struct secasvar *sav; 919105197Ssam struct mbuf *m; 920228010Spjd int error; 921105197Ssam 922105197Ssam tc = (struct tdb_crypto *) crp->crp_opaque; 923120585Ssam IPSEC_ASSERT(tc != NULL, ("null opaque data area!")); 924105197Ssam m = (struct mbuf *) crp->crp_buf; 925105197Ssam 926105197Ssam isr = tc->tc_isr; 927120585Ssam IPSECREQUEST_LOCK(isr); 928220206Sfabient sav = tc->tc_sav; 929220206Sfabient /* With the isr lock released SA pointer can be updated. */ 930220206Sfabient if (sav != isr->sav) { 931252028Sae ESPSTAT_INC(esps_notdb); 932120585Ssam DPRINTF(("%s: SA gone during crypto (SA %s/%08lx proto %u)\n", 933120585Ssam __func__, ipsec_address(&tc->tc_dst), 934105197Ssam (u_long) ntohl(tc->tc_spi), tc->tc_proto)); 935105197Ssam error = ENOBUFS; /*XXX*/ 936105197Ssam goto bad; 937105197Ssam } 938105197Ssam 939105197Ssam /* Check for crypto errors. */ 940105197Ssam if (crp->crp_etype) { 941105197Ssam /* Reset session ID. */ 942105197Ssam if (sav->tdb_cryptoid != 0) 943105197Ssam sav->tdb_cryptoid = crp->crp_sid; 944105197Ssam 945105197Ssam if (crp->crp_etype == EAGAIN) { 946120585Ssam IPSECREQUEST_UNLOCK(isr); 947228009Spjd return (crypto_dispatch(crp)); 948105197Ssam } 949105197Ssam 950252028Sae ESPSTAT_INC(esps_noxform); 951120585Ssam DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype)); 952105197Ssam error = crp->crp_etype; 953105197Ssam goto bad; 954105197Ssam } 955105197Ssam 956105197Ssam /* Shouldn't happen... */ 957105197Ssam if (m == NULL) { 958252028Sae ESPSTAT_INC(esps_crypto); 959120585Ssam DPRINTF(("%s: bogus returned buffer from crypto\n", __func__)); 960105197Ssam error = EINVAL; 961105197Ssam goto bad; 962105197Ssam } 963252028Sae ESPSTAT_INC(esps_hist[sav->alg_enc]); 964105197Ssam if (sav->tdb_authalgxform != NULL) 965252028Sae AHSTAT_INC(ahs_hist[sav->alg_auth]); 966105197Ssam 967105197Ssam /* Release crypto descriptors. */ 968105197Ssam free(tc, M_XDATA); 969105197Ssam crypto_freereq(crp); 970105197Ssam 971157634Spjd#ifdef REGRESSION 972157613Spjd /* Emulate man-in-the-middle attack when ipsec_integrity is TRUE. */ 973181803Sbz if (V_ipsec_integrity) { 974218794Svanhu static unsigned char ipseczeroes[AH_HMAC_MAXHASHLEN]; 975157613Spjd struct auth_hash *esph; 976157613Spjd 977157613Spjd /* 978157613Spjd * Corrupt HMAC if we want to test integrity verification of 979157613Spjd * the other side. 980157613Spjd */ 981157613Spjd esph = sav->tdb_authalgxform; 982157613Spjd if (esph != NULL) { 983218794Svanhu int alen; 984218794Svanhu 985218794Svanhu switch (esph->type) { 986218794Svanhu case CRYPTO_SHA2_256_HMAC: 987218794Svanhu case CRYPTO_SHA2_384_HMAC: 988218794Svanhu case CRYPTO_SHA2_512_HMAC: 989218794Svanhu alen = esph->hashsize/2; 990218794Svanhu break; 991218794Svanhu default: 992218794Svanhu alen = AH_HMAC_HASHLEN; 993218794Svanhu break; 994218794Svanhu } 995218794Svanhu m_copyback(m, m->m_pkthdr.len - alen, 996218794Svanhu alen, ipseczeroes); 997157613Spjd } 998157613Spjd } 999157634Spjd#endif 1000157613Spjd 1001105197Ssam /* NB: m is reclaimed by ipsec_process_done. */ 1002228010Spjd error = ipsec_process_done(m, isr); 1003105197Ssam KEY_FREESAV(&sav); 1004120585Ssam IPSECREQUEST_UNLOCK(isr); 1005228010Spjd return error; 1006105197Ssambad: 1007105197Ssam if (sav) 1008105197Ssam KEY_FREESAV(&sav); 1009120585Ssam IPSECREQUEST_UNLOCK(isr); 1010105197Ssam if (m) 1011105197Ssam m_freem(m); 1012105197Ssam free(tc, M_XDATA); 1013105197Ssam crypto_freereq(crp); 1014105197Ssam return error; 1015105197Ssam} 1016105197Ssam 1017105197Ssamstatic struct xformsw esp_xformsw = { 1018105197Ssam XF_ESP, XFT_CONF|XFT_AUTH, "IPsec ESP", 1019105197Ssam esp_init, esp_zeroize, esp_input, 1020105197Ssam esp_output 1021105197Ssam}; 1022105197Ssam 1023105197Ssamstatic void 1024105197Ssamesp_attach(void) 1025105197Ssam{ 1026105197Ssam 1027195699Srwatson xform_register(&esp_xformsw); 1028105197Ssam} 1029125099SsamSYSINIT(esp_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, esp_attach, NULL); 1030