jcs's openbsd hax
openbsd
at jcs 1145 lines 28 kB view raw
1/* $OpenBSD: ip_ah.c,v 1.179 2025/12/11 05:06:02 dlg 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 and Niklas Hallqvist. 17 * 18 * Copyright (c) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, 19 * Angelos D. Keromytis and Niels Provos. 20 * Copyright (c) 1999 Niklas Hallqvist. 21 * Copyright (c) 2001 Angelos D. Keromytis. 22 * 23 * Permission to use, copy, and modify this software with or without fee 24 * is hereby granted, provided that this entire notice is included in 25 * all copies of any software which is or includes a copy or 26 * modification of this software. 27 * You may use this code under the GNU public license if you so wish. Please 28 * contribute changes back to the authors under this freer than GPL license 29 * so that we may further the use of strong encryption without limitations to 30 * all. 31 * 32 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 33 * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 34 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 35 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 36 * PURPOSE. 37 */ 38 39#include "pfsync.h" 40 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/mbuf.h> 44#include <sys/socket.h> 45 46#include <net/if.h> 47#include <net/if_var.h> 48#include <net/bpf.h> 49 50#include <netinet/in.h> 51#include <netinet/ip.h> 52 53#ifdef INET6 54#include <netinet/ip6.h> 55#endif /* INET6 */ 56 57#include <netinet/ip_ipsp.h> 58#include <netinet/ip_ah.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 (atomic_load_int(&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 83int ah_massage_headers(struct mbuf **, int, int, int, int); 84 85const unsigned char ipseczeroes[IPSEC_ZEROES_SIZE]; /* zeroes! */ 86 87 88/* 89 * ah_attach() is called from the transformation initialization code. 90 */ 91int 92ah_attach(void) 93{ 94 return 0; 95} 96 97/* 98 * ah_init() is called when an SPI is being set up. 99 */ 100int 101ah_init(struct tdb *tdbp, const struct xformsw *xsp, struct ipsecinit *ii) 102{ 103 const struct auth_hash *thash = NULL; 104 struct cryptoini cria, crin; 105 int error; 106 107 /* Authentication operation. */ 108 switch (ii->ii_authalg) { 109 case SADB_AALG_MD5HMAC: 110 thash = &auth_hash_hmac_md5_96; 111 break; 112 113 case SADB_AALG_SHA1HMAC: 114 thash = &auth_hash_hmac_sha1_96; 115 break; 116 117 case SADB_X_AALG_RIPEMD160HMAC: 118 thash = &auth_hash_hmac_ripemd_160_96; 119 break; 120 121 case SADB_X_AALG_SHA2_256: 122 thash = &auth_hash_hmac_sha2_256_128; 123 break; 124 125 case SADB_X_AALG_SHA2_384: 126 thash = &auth_hash_hmac_sha2_384_192; 127 break; 128 129 case SADB_X_AALG_SHA2_512: 130 thash = &auth_hash_hmac_sha2_512_256; 131 break; 132 133 default: 134 DPRINTF("unsupported authentication algorithm %d specified", 135 ii->ii_authalg); 136 return EINVAL; 137 } 138 139 if (ii->ii_authkeylen != thash->keysize && thash->keysize != 0) { 140 DPRINTF("keylength %d doesn't match algorithm %s keysize (%d)", 141 ii->ii_authkeylen, thash->name, thash->keysize); 142 return EINVAL; 143 } 144 145 tdbp->tdb_xform = xsp; 146 tdbp->tdb_authalgxform = thash; 147 tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL; 148 149 DPRINTF("initialized TDB with hash algorithm %s", thash->name); 150 151 tdbp->tdb_amxkeylen = ii->ii_authkeylen; 152 tdbp->tdb_amxkey = malloc(tdbp->tdb_amxkeylen, M_XDATA, M_WAITOK); 153 154 memcpy(tdbp->tdb_amxkey, ii->ii_authkey, tdbp->tdb_amxkeylen); 155 156 /* Initialize crypto session. */ 157 memset(&cria, 0, sizeof(cria)); 158 cria.cri_alg = tdbp->tdb_authalgxform->type; 159 cria.cri_klen = ii->ii_authkeylen * 8; 160 cria.cri_key = ii->ii_authkey; 161 162 if ((tdbp->tdb_wnd > 0) && (tdbp->tdb_flags & TDBF_ESN)) { 163 memset(&crin, 0, sizeof(crin)); 164 crin.cri_alg = CRYPTO_ESN; 165 cria.cri_next = &crin; 166 } 167 168 KERNEL_LOCK(); 169 error = crypto_newsession(&tdbp->tdb_cryptoid, &cria, 0); 170 KERNEL_UNLOCK(); 171 return error; 172} 173 174/* 175 * Paranoia. 176 */ 177int 178ah_zeroize(struct tdb *tdbp) 179{ 180 int error; 181 182 if (tdbp->tdb_amxkey) { 183 explicit_bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen); 184 free(tdbp->tdb_amxkey, M_XDATA, tdbp->tdb_amxkeylen); 185 tdbp->tdb_amxkey = NULL; 186 } 187 188 KERNEL_LOCK(); 189 error = crypto_freesession(tdbp->tdb_cryptoid); 190 KERNEL_UNLOCK(); 191 tdbp->tdb_cryptoid = 0; 192 return error; 193} 194 195/* 196 * Massage IPv4/IPv6 headers for AH processing. 197 */ 198int 199ah_massage_headers(struct mbuf **mp, int af, int skip, int alg, int out) 200{ 201 struct mbuf *m = *mp; 202 unsigned char *ptr; 203 int off, count, error; 204 struct ip *ip; 205#ifdef INET6 206 struct ip6_ext *ip6e; 207 struct ip6_hdr ip6; 208 int ad, alloc, nxt, noff; 209#endif /* INET6 */ 210 211 switch (af) { 212 case AF_INET: 213 /* 214 * This is the least painful way of dealing with IPv4 header 215 * and option processing -- just make sure they're in 216 * contiguous memory. 217 */ 218 m = *mp = m_pullup(m, skip); 219 if (m == NULL) { 220 DPRINTF("m_pullup() failed"); 221 ahstat_inc(ahs_hdrops); 222 error = ENOBUFS; 223 goto drop; 224 } 225 226 /* Fix the IP header */ 227 ip = mtod(m, struct ip *); 228 ip->ip_tos = 0; 229 ip->ip_ttl = 0; 230 ip->ip_sum = 0; 231 ip->ip_off = 0; 232 233 ptr = mtod(m, unsigned char *); 234 235 /* IPv4 option processing */ 236 for (off = sizeof(struct ip); off < skip;) { 237 if (ptr[off] != IPOPT_EOL && ptr[off] != IPOPT_NOP && 238 off + 1 >= skip) { 239 DPRINTF("illegal IPv4 option length " 240 "for option %d", 241 ptr[off]); 242 ahstat_inc(ahs_hdrops); 243 error = EINVAL; 244 goto drop; 245 } 246 247 switch (ptr[off]) { 248 case IPOPT_EOL: 249 off = skip; /* End the loop. */ 250 break; 251 252 case IPOPT_NOP: 253 off++; 254 break; 255 256 case IPOPT_SECURITY: /* 0x82 */ 257 case 0x85: /* Extended security. */ 258 case 0x86: /* Commercial security. */ 259 case 0x94: /* Router alert */ 260 case 0x95: /* RFC1770 */ 261 /* Sanity check for option length. */ 262 if (ptr[off + 1] < 2) { 263 DPRINTF("illegal IPv4 option length " 264 "for option %d", 265 ptr[off]); 266 ahstat_inc(ahs_hdrops); 267 error = EINVAL; 268 goto drop; 269 } 270 271 off += ptr[off + 1]; 272 break; 273 274 case IPOPT_LSRR: 275 case IPOPT_SSRR: 276 /* Sanity check for option length. */ 277 if (ptr[off + 1] < 2) { 278 DPRINTF("illegal IPv4 option length " 279 "for option %d", 280 ptr[off]); 281 ahstat_inc(ahs_hdrops); 282 error = EINVAL; 283 goto drop; 284 } 285 286 /* 287 * On output, if we have either of the 288 * source routing options, we should 289 * swap the destination address of the 290 * IP header with the last address 291 * specified in the option, as that is 292 * what the destination's IP header 293 * will look like. 294 */ 295 if (out && 296 ptr[off + 1] >= 2 + sizeof(struct in_addr)) 297 memcpy(&ip->ip_dst, 298 ptr + off + ptr[off + 1] - 299 sizeof(struct in_addr), 300 sizeof(struct in_addr)); 301 302 /* FALLTHROUGH */ 303 default: 304 /* Sanity check for option length. */ 305 if (ptr[off + 1] < 2) { 306 DPRINTF("illegal IPv4 option length " 307 "for option %d", 308 ptr[off]); 309 ahstat_inc(ahs_hdrops); 310 error = EINVAL; 311 goto drop; 312 } 313 314 /* Zeroize all other options. */ 315 count = ptr[off + 1]; 316 memset(ptr + off, 0, count); 317 off += count; 318 break; 319 } 320 321 /* Sanity check. */ 322 if (off > skip) { 323 DPRINTF("malformed IPv4 options header"); 324 ahstat_inc(ahs_hdrops); 325 error = EINVAL; 326 goto drop; 327 } 328 } 329 330 break; 331 332#ifdef INET6 333 case AF_INET6: /* Ugly... */ 334 /* Copy and "cook" the IPv6 header. */ 335 m_copydata(m, 0, sizeof(ip6), &ip6); 336 337 /* We don't do IPv6 Jumbograms. */ 338 if (ip6.ip6_plen == 0) { 339 DPRINTF("unsupported IPv6 jumbogram"); 340 ahstat_inc(ahs_hdrops); 341 error = EMSGSIZE; 342 goto drop; 343 } 344 345 ip6.ip6_flow = 0; 346 ip6.ip6_hlim = 0; 347 ip6.ip6_vfc &= ~IPV6_VERSION_MASK; 348 ip6.ip6_vfc |= IPV6_VERSION; 349 350 /* Scoped address handling. */ 351 if (IN6_IS_SCOPE_EMBED(&ip6.ip6_src)) 352 ip6.ip6_src.s6_addr16[1] = 0; 353 if (IN6_IS_SCOPE_EMBED(&ip6.ip6_dst)) 354 ip6.ip6_dst.s6_addr16[1] = 0; 355 356 /* Done with IPv6 header. */ 357 error = m_copyback(m, 0, sizeof(struct ip6_hdr), &ip6, 358 M_NOWAIT); 359 if (error) { 360 DPRINTF("m_copyback no memory"); 361 ahstat_inc(ahs_hdrops); 362 goto drop; 363 } 364 365 /* Let's deal with the remaining headers (if any). */ 366 if (skip > sizeof(struct ip6_hdr)) { 367 if (m->m_len <= skip) { 368 ptr = malloc(skip - sizeof(struct ip6_hdr), 369 M_XDATA, M_NOWAIT); 370 if (ptr == NULL) { 371 DPRINTF("failed to allocate " 372 "memory for IPv6 headers"); 373 ahstat_inc(ahs_hdrops); 374 error = ENOBUFS; 375 goto drop; 376 } 377 378 /* 379 * Copy all the protocol headers after 380 * the IPv6 header. 381 */ 382 m_copydata(m, sizeof(struct ip6_hdr), 383 skip - sizeof(struct ip6_hdr), ptr); 384 alloc = 1; 385 } else { 386 /* No need to allocate memory. */ 387 ptr = mtod(m, unsigned char *) + 388 sizeof(struct ip6_hdr); 389 alloc = 0; 390 } 391 } else 392 break; 393 394 nxt = ip6.ip6_nxt; /* Next header type. */ 395 396 for (off = 0; off + sizeof(struct ip6_hdr) < skip;) { 397 if (off + sizeof(struct ip6_hdr) + 398 sizeof(struct ip6_ext) > skip) 399 goto error6; 400 ip6e = (struct ip6_ext *)(ptr + off); 401 402 switch (nxt) { 403 case IPPROTO_HOPOPTS: 404 case IPPROTO_DSTOPTS: 405 noff = off + ((ip6e->ip6e_len + 1) << 3); 406 407 /* Sanity check. */ 408 if (noff + sizeof(struct ip6_hdr) > skip) 409 goto error6; 410 411 /* 412 * Zero out mutable options. 413 */ 414 for (count = off + sizeof(struct ip6_ext); 415 count < noff;) { 416 if (ptr[count] == IP6OPT_PAD1) { 417 count++; 418 continue; /* Skip padding. */ 419 } 420 421 if (count + 2 > noff) 422 goto error6; 423 ad = ptr[count + 1] + 2; 424 if (count + ad > noff) 425 goto error6; 426 427 /* If mutable option, zeroize. */ 428 if (ptr[count] & IP6OPT_MUTABLE) 429 memset(ptr + count, 0, ad); 430 431 count += ad; 432 } 433 434 if (count != noff) 435 goto error6; 436 break; 437 438 case IPPROTO_ROUTING: 439 /* 440 * Always include routing headers in 441 * computation. 442 */ 443 { 444 struct ip6_rthdr *rh; 445 446 rh = (struct ip6_rthdr *)(ptr + off); 447 /* 448 * must adjust content to make it look like 449 * its final form (as seen at the final 450 * destination). 451 * we only know how to massage type 0 routing 452 * header. 453 */ 454 if (out && rh->ip6r_type == IPV6_RTHDR_TYPE_0) { 455 struct ip6_rthdr0 *rh0; 456 struct in6_addr *addr, finaldst; 457 int i; 458 459 rh0 = (struct ip6_rthdr0 *)rh; 460 addr = (struct in6_addr *)(rh0 + 1); 461 462 for (i = 0; i < rh0->ip6r0_segleft; i++) 463 if (IN6_IS_SCOPE_EMBED(&addr[i])) 464 addr[i].s6_addr16[1] = 0; 465 466 finaldst = addr[rh0->ip6r0_segleft - 1]; 467 memmove(&addr[1], &addr[0], 468 sizeof(struct in6_addr) * 469 (rh0->ip6r0_segleft - 1)); 470 471 m_copydata(m, 0, sizeof(ip6), &ip6); 472 addr[0] = ip6.ip6_dst; 473 ip6.ip6_dst = finaldst; 474 error = m_copyback(m, 0, sizeof(ip6), 475 &ip6, M_NOWAIT); 476 if (error) { 477 if (alloc) 478 free(ptr, M_XDATA, 0); 479 ahstat_inc(ahs_hdrops); 480 goto drop; 481 } 482 rh0->ip6r0_segleft = 0; 483 } 484 break; 485 } 486 487 default: 488 DPRINTF("unexpected IPv6 header type %d", off); 489error6: 490 if (alloc) 491 free(ptr, M_XDATA, 0); 492 ahstat_inc(ahs_hdrops); 493 error = EINVAL; 494 goto drop; 495 } 496 497 /* Advance. */ 498 off += ((ip6e->ip6e_len + 1) << 3); 499 nxt = ip6e->ip6e_nxt; 500 } 501 502 /* Copyback and free, if we allocated. */ 503 if (alloc) { 504 error = m_copyback(m, sizeof(struct ip6_hdr), 505 skip - sizeof(struct ip6_hdr), ptr, M_NOWAIT); 506 free(ptr, M_XDATA, 0); 507 if (error) { 508 ahstat_inc(ahs_hdrops); 509 goto drop; 510 } 511 } 512 513 break; 514#endif /* INET6 */ 515 } 516 517 return 0; 518 519 drop: 520 m_freemp(mp); 521 return error; 522} 523 524/* 525 * ah_input() gets called to verify that an input packet 526 * passes authentication. 527 */ 528int 529ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff, 530 struct netstack *ns) 531{ 532 const struct auth_hash *ahx = tdb->tdb_authalgxform; 533 struct mbuf *m = *mp, *m1, *m0; 534 struct cryptodesc *crda = NULL; 535 struct cryptop *crp = NULL; 536 int roff; 537 uint32_t btsx, esn; 538 uint8_t *ptr = NULL; 539 uint8_t hl; 540 int error, rplen; 541 uint64_t ibytes; 542#ifdef ENCDEBUG 543 char buf[INET6_ADDRSTRLEN]; 544#endif 545 uint8_t calc[AH_ALEN_MAX]; 546 547 rplen = AH_FLENGTH + sizeof(u_int32_t); 548 549 /* Save the AH header, we use it throughout. */ 550 m_copydata(m, skip + offsetof(struct ah, ah_hl), sizeof(u_int8_t), &hl); 551 552 /* Replay window checking, if applicable. */ 553 if (tdb->tdb_wnd > 0) { 554 m_copydata(m, skip + offsetof(struct ah, ah_rpl), 555 sizeof(u_int32_t), &btsx); 556 btsx = ntohl(btsx); 557 558 switch (checkreplaywindow(tdb, tdb->tdb_rpl, btsx, &esn, 0)) { 559 case 0: /* All's well. */ 560 break; 561 case 1: 562 DPRINTF("replay counter wrapped for SA %s/%08x", 563 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 564 ntohl(tdb->tdb_spi)); 565 ahstat_inc(ahs_wrap); 566 goto drop; 567 case 2: 568 DPRINTF("old packet received in SA %s/%08x", 569 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 570 ntohl(tdb->tdb_spi)); 571 ahstat_inc(ahs_replay); 572 goto drop; 573 case 3: 574 DPRINTF("duplicate packet received in SA %s/%08x", 575 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 576 ntohl(tdb->tdb_spi)); 577 ahstat_inc(ahs_replay); 578 goto drop; 579 default: 580 DPRINTF("bogus value from checkreplaywindow() " 581 "in SA %s/%08x", 582 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 583 ntohl(tdb->tdb_spi)); 584 ahstat_inc(ahs_replay); 585 goto drop; 586 } 587 } 588 589 /* Verify AH header length. */ 590 if (hl * sizeof(u_int32_t) != ahx->authsize + rplen - AH_FLENGTH) { 591 DPRINTF("bad authenticator length %ld for packet in SA %s/%08x", 592 hl * sizeof(u_int32_t), 593 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 594 ntohl(tdb->tdb_spi)); 595 ahstat_inc(ahs_badauthl); 596 goto drop; 597 } 598 if (skip + ahx->authsize + rplen > m->m_pkthdr.len) { 599 DPRINTF("bad mbuf length %d (expecting %d) for packet " 600 "in SA %s/%08x", 601 m->m_pkthdr.len, skip + ahx->authsize + rplen, 602 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 603 ntohl(tdb->tdb_spi)); 604 ahstat_inc(ahs_badauthl); 605 goto drop; 606 } 607 608 /* Update the counters. */ 609 ibytes = (m->m_pkthdr.len - skip - hl * sizeof(u_int32_t)); 610 tdb->tdb_cur_bytes += ibytes; 611 tdbstat_add(tdb, tdb_ibytes, ibytes); 612 ahstat_add(ahs_ibytes, ibytes); 613 614 /* Hard expiration. */ 615 if ((tdb->tdb_flags & TDBF_BYTES) && 616 (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { 617 ipsecstat_inc(ipsec_exctdb); 618 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); 619 tdb_delete(tdb); 620 goto drop; 621 } 622 623 /* Notify on expiration. */ 624 mtx_enter(&tdb->tdb_mtx); 625 if ((tdb->tdb_flags & TDBF_SOFT_BYTES) && 626 (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) { 627 tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */ 628 mtx_leave(&tdb->tdb_mtx); 629 /* may sleep in solock() for the pfkey socket */ 630 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT); 631 } else 632 mtx_leave(&tdb->tdb_mtx); 633 634 /* Get crypto descriptors. */ 635 crp = crypto_getreq(1); 636 if (crp == NULL) { 637 DPRINTF("failed to acquire crypto descriptors"); 638 ahstat_inc(ahs_crypto); 639 goto drop; 640 } 641 642 crda = &crp->crp_desc[0]; 643 644 crda->crd_skip = 0; 645 crda->crd_len = m->m_pkthdr.len; 646 crda->crd_inject = skip + rplen; 647 648 /* Authentication operation. */ 649 crda->crd_alg = ahx->type; 650 crda->crd_key = tdb->tdb_amxkey; 651 crda->crd_klen = tdb->tdb_amxkeylen * 8; 652 653 if ((tdb->tdb_wnd > 0) && (tdb->tdb_flags & TDBF_ESN)) { 654 esn = htonl(esn); 655 memcpy(crda->crd_esn, &esn, 4); 656 crda->crd_flags |= CRD_F_ESN; 657 } 658 659 /* Allocate IPsec-specific opaque crypto info. */ 660 ptr = malloc(skip + rplen + ahx->authsize, M_XDATA, M_NOWAIT | M_ZERO); 661 if (ptr == NULL) { 662 DPRINTF("failed to allocate buffer"); 663 ahstat_inc(ahs_crypto); 664 goto drop; 665 } 666 667 /* 668 * Save the authenticator, the skipped portion of the packet, 669 * and the AH header. 670 */ 671 m_copydata(m, 0, skip + rplen + ahx->authsize, ptr); 672 673 /* Zeroize the authenticator on the packet. */ 674 m_copyback(m, skip + rplen, ahx->authsize, ipseczeroes, M_NOWAIT); 675 676 /* "Massage" the packet headers for crypto processing. */ 677 error = ah_massage_headers(mp, tdb->tdb_dst.sa.sa_family, skip, 678 ahx->type, 0); 679 /* callee may change or free mbuf */ 680 m = *mp; 681 if (error) 682 goto drop; 683 684 /* Crypto operation descriptor. */ 685 crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */ 686 crp->crp_flags = CRYPTO_F_IMBUF; 687 crp->crp_buf = (caddr_t)m; 688 crp->crp_sid = tdb->tdb_cryptoid; 689 690 while ((error = crypto_invoke(crp)) == EAGAIN) { 691 /* Reset the session ID */ 692 if (tdb->tdb_cryptoid != 0) 693 tdb->tdb_cryptoid = crp->crp_sid; 694 } 695 if (error) { 696 DPRINTF("crypto error %d", error); 697 ipsecstat_inc(ipsec_noxform); 698 goto drop; 699 } 700 701 /* Release the crypto descriptors */ 702 crypto_freereq(crp); 703 crp = NULL; 704 705 /* Copy authenticator off the packet. */ 706 m_copydata(m, skip + rplen, ahx->authsize, calc); 707 708 /* Verify authenticator. */ 709 if (timingsafe_bcmp(ptr + skip + rplen, calc, ahx->authsize)) { 710 DPRINTF("authentication failed for packet in SA %s/%08x", 711 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 712 ntohl(tdb->tdb_spi)); 713 ahstat_inc(ahs_badauth); 714 goto drop; 715 } 716 717 /* Fix the Next Protocol field. */ 718 ptr[protoff] = ptr[skip]; 719 720 /* Copyback the saved (uncooked) network headers. */ 721 m_copyback(m, 0, skip, ptr, M_NOWAIT); 722 723 free(ptr, M_XDATA, 0); 724 ptr = NULL; 725 726 /* Replay window checking, if applicable. */ 727 if (tdb->tdb_wnd > 0) { 728 m_copydata(m, skip + offsetof(struct ah, ah_rpl), 729 sizeof(u_int32_t), &btsx); 730 btsx = ntohl(btsx); 731 732 switch (checkreplaywindow(tdb, tdb->tdb_rpl, btsx, &esn, 1)) { 733 case 0: /* All's well. */ 734#if NPFSYNC > 0 735 pfsync_update_tdb(tdb,0); 736#endif 737 break; 738 case 1: 739 DPRINTF("replay counter wrapped for SA %s/%08x", 740 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 741 ntohl(tdb->tdb_spi)); 742 ahstat_inc(ahs_wrap); 743 goto drop; 744 case 2: 745 DPRINTF("old packet received in SA %s/%08x", 746 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 747 ntohl(tdb->tdb_spi)); 748 ahstat_inc(ahs_replay); 749 goto drop; 750 case 3: 751 DPRINTF("duplicate packet received in SA %s/%08x", 752 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 753 ntohl(tdb->tdb_spi)); 754 ahstat_inc(ahs_replay); 755 goto drop; 756 default: 757 DPRINTF("bogus value from checkreplaywindow() " 758 "in SA %s/%08x", 759 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 760 ntohl(tdb->tdb_spi)); 761 ahstat_inc(ahs_replay); 762 goto drop; 763 } 764 } 765 766 /* Record the beginning of the AH header. */ 767 m1 = m_getptr(m, skip, &roff); 768 if (m1 == NULL) { 769 DPRINTF("bad mbuf chain for packet in SA %s/%08x", 770 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 771 ntohl(tdb->tdb_spi)); 772 ahstat_inc(ahs_hdrops); 773 goto drop; 774 } 775 776 /* Remove the AH header from the mbuf. */ 777 if (roff == 0) { 778 /* 779 * The AH header was conveniently at the beginning of 780 * the mbuf. 781 */ 782 m_adj(m1, rplen + ahx->authsize); 783 /* 784 * If m1 is the first mbuf, it has set M_PKTHDR and m_adj() 785 * has already adjusted the packet header length for us. 786 */ 787 if (m1 != m) 788 m->m_pkthdr.len -= rplen + ahx->authsize; 789 } else 790 if (roff + rplen + ahx->authsize >= m1->m_len) { 791 int adjlen; 792 793 /* 794 * Part or all of the AH header is at the end 795 * of this mbuf, so first let's remove the 796 * remainder of the AH header from the 797 * beginning of the remainder of the mbuf 798 * chain, if any. 799 */ 800 if (roff + rplen + ahx->authsize > m1->m_len) { 801 adjlen = roff + rplen + ahx->authsize - 802 m1->m_len; 803 /* Adjust the next mbuf by the remainder. */ 804 m_adj(m1->m_next, adjlen); 805 806 /* 807 * The second mbuf is guaranteed not 808 * to have a pkthdr... 809 */ 810 m->m_pkthdr.len -= adjlen; 811 } 812 813 /* Now, let's unlink the mbuf chain for a second... */ 814 m0 = m1->m_next; 815 m1->m_next = NULL; 816 817 /* 818 * ...and trim the end of the first part of 819 * the chain...sick 820 */ 821 adjlen = m1->m_len - roff; 822 m_adj(m1, -adjlen); 823 /* 824 * If m1 is the first mbuf, it has set M_PKTHDR and 825 * m_adj() has already adjusted the packet header len. 826 */ 827 if (m1 != m) 828 m->m_pkthdr.len -= adjlen; 829 830 /* Finally, let's relink. */ 831 m1->m_next = m0; 832 } else { 833 /* 834 * The AH header lies in the "middle" of the 835 * mbuf...do an overlapping copy of the 836 * remainder of the mbuf over the ESP header. 837 */ 838 bcopy(mtod(m1, u_char *) + roff + rplen + 839 ahx->authsize, mtod(m1, u_char *) + roff, 840 m1->m_len - (roff + rplen + ahx->authsize)); 841 m1->m_len -= rplen + ahx->authsize; 842 m->m_pkthdr.len -= rplen + ahx->authsize; 843 } 844 845 return ipsec_common_input_cb(mp, tdb, skip, protoff, ns); 846 847 drop: 848 free(ptr, M_XDATA, 0); 849 m_freemp(mp); 850 crypto_freereq(crp); 851 return IPPROTO_DONE; 852} 853 854/* 855 * AH output routine, called by ipsp_process_packet(). 856 */ 857int 858ah_output(struct mbuf *m, struct tdb *tdb, int skip, int protoff) 859{ 860 const struct auth_hash *ahx = tdb->tdb_authalgxform; 861 struct cryptodesc *crda; 862 struct mbuf *mi; 863 struct cryptop *crp = NULL; 864 uint64_t replay64; 865 uint16_t iplen; 866 int error, rplen, roff; 867 uint8_t *ptr = NULL; 868 uint8_t prot; 869 struct ah *ah; 870#if NBPFILTER > 0 871 struct ifnet *encif; 872#ifdef ENCDEBUG 873 char buf[INET6_ADDRSTRLEN]; 874#endif 875 876 if ((encif = enc_getif(tdb->tdb_rdomain, tdb->tdb_tap)) != NULL) { 877 encif->if_opackets++; 878 encif->if_obytes += m->m_pkthdr.len; 879 880 if (encif->if_bpf) { 881 struct enchdr hdr = { 882 .af = htonl(tdb->tdb_dst.sa.sa_family), 883 .spi = tdb->tdb_spi, 884 .flags = htonl(M_AUTH), 885 }; 886 887 bpf_mtap_hdr(encif->if_bpf, (char *)&hdr, 888 ENC_HDRLEN, m, BPF_DIRECTION_OUT); 889 } 890 } 891#endif 892 893 ahstat_inc(ahs_output); 894 895 /* 896 * Check for replay counter wrap-around in automatic (not 897 * manual) keying. 898 */ 899 if ((tdb->tdb_rpl == 0) && (tdb->tdb_wnd > 0)) { 900 DPRINTF("SA %s/%08x should have expired", 901 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 902 ntohl(tdb->tdb_spi)); 903 ahstat_inc(ahs_wrap); 904 error = EINVAL; 905 goto drop; 906 } 907 908 rplen = AH_FLENGTH + sizeof(u_int32_t); 909 910 switch (tdb->tdb_dst.sa.sa_family) { 911 case AF_INET: 912 /* Check for IP maximum packet size violations. */ 913 if (rplen + ahx->authsize + m->m_pkthdr.len > IP_MAXPACKET) { 914 DPRINTF("packet in SA %s/%08x got too big", 915 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 916 ntohl(tdb->tdb_spi)); 917 ahstat_inc(ahs_toobig); 918 error = EMSGSIZE; 919 goto drop; 920 } 921 break; 922 923#ifdef INET6 924 case AF_INET6: 925 /* Check for IPv6 maximum packet size violations. */ 926 if (rplen + ahx->authsize + m->m_pkthdr.len > IPV6_MAXPACKET) { 927 DPRINTF("packet in SA %s/%08x got too big", 928 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 929 ntohl(tdb->tdb_spi)); 930 ahstat_inc(ahs_toobig); 931 error = EMSGSIZE; 932 goto drop; 933 } 934 break; 935#endif /* INET6 */ 936 937 default: 938 DPRINTF("unknown/unsupported protocol family %d, SA %s/%08x", 939 tdb->tdb_dst.sa.sa_family, 940 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 941 ntohl(tdb->tdb_spi)); 942 ahstat_inc(ahs_nopf); 943 error = EPFNOSUPPORT; 944 goto drop; 945 } 946 947 /* Update the counters. */ 948 tdb->tdb_cur_bytes += m->m_pkthdr.len - skip; 949 ahstat_add(ahs_obytes, m->m_pkthdr.len - skip); 950 951 /* Hard expiration. */ 952 if ((tdb->tdb_flags & TDBF_BYTES) && 953 (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { 954 ipsecstat_inc(ipsec_exctdb); 955 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); 956 tdb_delete(tdb); 957 error = EINVAL; 958 goto drop; 959 } 960 961 /* Notify on expiration. */ 962 mtx_enter(&tdb->tdb_mtx); 963 if ((tdb->tdb_flags & TDBF_SOFT_BYTES) && 964 (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) { 965 tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */ 966 mtx_leave(&tdb->tdb_mtx); 967 /* may sleep in solock() for the pfkey socket */ 968 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT); 969 } else 970 mtx_leave(&tdb->tdb_mtx); 971 972 /* 973 * Loop through mbuf chain; if we find a readonly mbuf, 974 * copy the packet. 975 */ 976 mi = m; 977 while (mi != NULL && !M_READONLY(mi)) 978 mi = mi->m_next; 979 980 if (mi != NULL) { 981 struct mbuf *n = m_dup_pkt(m, 0, M_DONTWAIT); 982 983 if (n == NULL) { 984 ahstat_inc(ahs_hdrops); 985 error = ENOBUFS; 986 goto drop; 987 } 988 989 m_freem(m); 990 m = n; 991 } 992 993 /* Inject AH header. */ 994 mi = m_makespace(m, skip, rplen + ahx->authsize, &roff); 995 if (mi == NULL) { 996 DPRINTF("failed to inject AH header for SA %s/%08x", 997 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 998 ntohl(tdb->tdb_spi)); 999 ahstat_inc(ahs_hdrops); 1000 error = ENOBUFS; 1001 goto drop; 1002 } 1003 1004 /* 1005 * The AH header is guaranteed by m_makespace() to be in 1006 * contiguous memory, at 'roff' of the returned mbuf. 1007 */ 1008 ah = (struct ah *)(mtod(mi, caddr_t) + roff); 1009 1010 /* Initialize the AH header. */ 1011 m_copydata(m, protoff, sizeof(u_int8_t), &ah->ah_nh); 1012 ah->ah_hl = (rplen + ahx->authsize - AH_FLENGTH) / sizeof(u_int32_t); 1013 ah->ah_rv = 0; 1014 ah->ah_spi = tdb->tdb_spi; 1015 1016 /* Zeroize authenticator. */ 1017 m_copyback(m, skip + rplen, ahx->authsize, ipseczeroes, M_NOWAIT); 1018 1019 replay64 = tdb->tdb_rpl++; 1020 ah->ah_rpl = htonl((u_int32_t)replay64); 1021#if NPFSYNC > 0 1022 pfsync_update_tdb(tdb,1); 1023#endif 1024 1025 /* Get crypto descriptors. */ 1026 crp = crypto_getreq(1); 1027 if (crp == NULL) { 1028 DPRINTF("failed to acquire crypto descriptors"); 1029 ahstat_inc(ahs_crypto); 1030 error = ENOBUFS; 1031 goto drop; 1032 } 1033 1034 crda = &crp->crp_desc[0]; 1035 1036 crda->crd_skip = 0; 1037 crda->crd_inject = skip + rplen; 1038 crda->crd_len = m->m_pkthdr.len; 1039 1040 /* Authentication operation. */ 1041 crda->crd_alg = ahx->type; 1042 crda->crd_key = tdb->tdb_amxkey; 1043 crda->crd_klen = tdb->tdb_amxkeylen * 8; 1044 1045 if ((tdb->tdb_wnd > 0) && (tdb->tdb_flags & TDBF_ESN)) { 1046 u_int32_t esn; 1047 1048 esn = htonl((u_int32_t)(replay64 >> 32)); 1049 memcpy(crda->crd_esn, &esn, 4); 1050 crda->crd_flags |= CRD_F_ESN; 1051 } 1052 1053 ptr = malloc(skip, M_XDATA, M_NOWAIT | M_ZERO); 1054 if (ptr == NULL) { 1055 DPRINTF("failed to allocate buffer"); 1056 ahstat_inc(ahs_crypto); 1057 error = ENOBUFS; 1058 goto drop; 1059 } 1060 1061 /* Save the skipped portion of the packet. */ 1062 m_copydata(m, 0, skip, ptr); 1063 1064 /* 1065 * Fix IP header length on the header used for 1066 * authentication. We don't need to fix the original 1067 * header length as it will be fixed by our caller. 1068 */ 1069 switch (tdb->tdb_dst.sa.sa_family) { 1070 case AF_INET: 1071 memcpy((caddr_t) &iplen, ((caddr_t)ptr) + 1072 offsetof(struct ip, ip_len), sizeof(u_int16_t)); 1073 iplen = htons(ntohs(iplen) + rplen + ahx->authsize); 1074 m_copyback(m, offsetof(struct ip, ip_len), 1075 sizeof(u_int16_t), &iplen, M_NOWAIT); 1076 break; 1077 1078#ifdef INET6 1079 case AF_INET6: 1080 memcpy((caddr_t) &iplen, ((caddr_t)ptr) + 1081 offsetof(struct ip6_hdr, ip6_plen), sizeof(u_int16_t)); 1082 iplen = htons(ntohs(iplen) + rplen + ahx->authsize); 1083 m_copyback(m, offsetof(struct ip6_hdr, ip6_plen), 1084 sizeof(u_int16_t), &iplen, M_NOWAIT); 1085 break; 1086#endif /* INET6 */ 1087 } 1088 1089 /* Fix the Next Header field in saved header. */ 1090 ptr[protoff] = IPPROTO_AH; 1091 1092 /* Update the Next Protocol field in the IP header. */ 1093 prot = IPPROTO_AH; 1094 m_copyback(m, protoff, sizeof(u_int8_t), &prot, M_NOWAIT); 1095 1096 /* "Massage" the packet headers for crypto processing. */ 1097 error = ah_massage_headers(&m, tdb->tdb_dst.sa.sa_family, skip, 1098 ahx->type, 1); 1099 if (error) { 1100 /* mbuf was freed by callee. */ 1101 m = NULL; 1102 goto drop; 1103 } 1104 1105 /* Crypto operation descriptor. */ 1106 crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */ 1107 crp->crp_flags = CRYPTO_F_IMBUF; 1108 crp->crp_buf = (caddr_t)m; 1109 crp->crp_sid = tdb->tdb_cryptoid; 1110 1111 while ((error = crypto_invoke(crp)) == EAGAIN) { 1112 /* Reset the session ID */ 1113 if (tdb->tdb_cryptoid != 0) 1114 tdb->tdb_cryptoid = crp->crp_sid; 1115 } 1116 if (error) { 1117 DPRINTF("crypto error %d", error); 1118 ipsecstat_inc(ipsec_noxform); 1119 goto drop; 1120 } 1121 1122 /* Release the crypto descriptors */ 1123 crypto_freereq(crp); 1124 crp = NULL; 1125 1126 /* 1127 * Copy original headers (with the new protocol number) back 1128 * in place. 1129 */ 1130 m_copyback(m, 0, skip, ptr, M_NOWAIT); 1131 free(ptr, M_XDATA, 0); 1132 ptr = NULL; 1133 1134 /* Call the IPsec input callback. */ 1135 error = ipsp_process_done(m, tdb); 1136 if (error) 1137 ahstat_inc(ahs_outfail); 1138 return error; 1139 1140 drop: 1141 free(ptr, M_XDATA, 0); 1142 m_freem(m); 1143 crypto_freereq(crp); 1144 return error; 1145}