1/* 2 * Copyright (c) 2008-2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29/* $FreeBSD: src/sys/netinet6/esp_input.c,v 1.1.2.3 2001/07/03 11:01:50 ume Exp $ */ 30/* $KAME: esp_input.c,v 1.55 2001/03/23 08:08:47 itojun Exp $ */ 31 32/* 33 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 34 * All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. Neither the name of the project nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 */ 60 61/* 62 * RFC1827/2406 Encapsulated Security Payload. 63 */ 64 65#include <sys/param.h> 66#include <sys/systm.h> 67#include <sys/malloc.h> 68#include <sys/mbuf.h> 69#include <sys/mcache.h> 70#include <sys/domain.h> 71#include <sys/protosw.h> 72#include <sys/socket.h> 73#include <sys/errno.h> 74#include <sys/time.h> 75#include <sys/kernel.h> 76#include <sys/syslog.h> 77 78#include <net/if.h> 79#include <net/if_ipsec.h> 80#include <net/route.h> 81#include <kern/cpu_number.h> 82#include <kern/locks.h> 83 84#include <netinet/in.h> 85#include <netinet/in_systm.h> 86#include <netinet/ip.h> 87#include <netinet/ip_var.h> 88#include <netinet/in_var.h> 89#include <netinet/ip_ecn.h> 90#include <netinet/in_pcb.h> 91#include <netinet/udp.h> 92#if INET6 93#include <netinet6/ip6_ecn.h> 94#endif 95 96#if INET6 97#include <netinet/ip6.h> 98#include <netinet6/in6_pcb.h> 99#include <netinet6/ip6_var.h> 100#include <netinet/icmp6.h> 101#include <netinet6/ip6protosw.h> 102#endif 103 104#include <netinet6/ipsec.h> 105#if INET6 106#include <netinet6/ipsec6.h> 107#endif 108#include <netinet6/ah.h> 109#if INET6 110#include <netinet6/ah6.h> 111#endif 112#include <netinet6/esp.h> 113#if INET6 114#include <netinet6/esp6.h> 115#endif 116#include <netkey/key.h> 117#include <netkey/keydb.h> 118#include <netkey/key_debug.h> 119 120#include <net/kpi_protocol.h> 121#include <netinet/kpi_ipfilter_var.h> 122 123#include <net/net_osdep.h> 124#include <mach/sdt.h> 125 126#include <sys/kdebug.h> 127#define DBG_LAYER_BEG NETDBG_CODE(DBG_NETIPSEC, 1) 128#define DBG_LAYER_END NETDBG_CODE(DBG_NETIPSEC, 3) 129#define DBG_FNC_ESPIN NETDBG_CODE(DBG_NETIPSEC, (6 << 8)) 130#define DBG_FNC_DECRYPT NETDBG_CODE(DBG_NETIPSEC, (7 << 8)) 131#define IPLEN_FLIPPED 132 133extern lck_mtx_t *sadb_mutex; 134 135#if INET 136#define ESPMAXLEN \ 137 (sizeof(struct esp) < sizeof(struct newesp) \ 138 ? sizeof(struct newesp) : sizeof(struct esp)) 139 140static struct ip * 141esp4_input_strip_UDP_encap (struct mbuf *m, int iphlen) 142{ 143 // strip the udp header that's encapsulating ESP 144 struct ip *ip; 145 size_t stripsiz = sizeof(struct udphdr); 146 147 ip = mtod(m, __typeof__(ip)); 148 ovbcopy((caddr_t)ip, (caddr_t)(((u_char *)ip) + stripsiz), iphlen); 149 m->m_data += stripsiz; 150 m->m_len -= stripsiz; 151 m->m_pkthdr.len -= stripsiz; 152 ip = mtod(m, __typeof__(ip)); 153 ip->ip_len = ip->ip_len - stripsiz; 154 ip->ip_p = IPPROTO_ESP; 155 return ip; 156} 157 158void 159esp4_input(m, off) 160 struct mbuf *m; 161 int off; 162{ 163 struct ip *ip; 164#if INET6 165 struct ip6_hdr *ip6; 166#endif /* INET6 */ 167 struct esp *esp; 168 struct esptail esptail; 169 u_int32_t spi; 170 u_int32_t seq; 171 struct secasvar *sav = NULL; 172 size_t taillen; 173 u_int16_t nxt; 174 const struct esp_algorithm *algo; 175 int ivlen; 176 size_t hlen; 177 size_t esplen; 178 sa_family_t ifamily; 179 180 KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_START, 0,0,0,0,0); 181 /* sanity check for alignment. */ 182 if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) { 183 ipseclog((LOG_ERR, "IPv4 ESP input: packet alignment problem " 184 "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len)); 185 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 186 goto bad; 187 } 188 189 if (m->m_len < off + ESPMAXLEN) { 190 m = m_pullup(m, off + ESPMAXLEN); 191 if (!m) { 192 ipseclog((LOG_DEBUG, 193 "IPv4 ESP input: can't pullup in esp4_input\n")); 194 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 195 goto bad; 196 } 197 } 198 199 /* Expect 32-bit aligned data pointer on strict-align platforms */ 200 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m); 201 202 ip = mtod(m, struct ip *); 203 // expect udp-encap and esp packets only 204 if (ip->ip_p != IPPROTO_ESP && 205 !(ip->ip_p == IPPROTO_UDP && off >= sizeof(struct udphdr))) { 206 ipseclog((LOG_DEBUG, 207 "IPv4 ESP input: invalid protocol type\n")); 208 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 209 goto bad; 210 } 211 esp = (struct esp *)(void *)(((u_int8_t *)ip) + off); 212#ifdef _IP_VHL 213 hlen = IP_VHL_HL(ip->ip_vhl) << 2; 214#else 215 hlen = ip->ip_hl << 2; 216#endif 217 218 /* find the sassoc. */ 219 spi = esp->esp_spi; 220 221 if ((sav = key_allocsa(AF_INET, 222 (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst, 223 IPPROTO_ESP, spi)) == 0) { 224 ipseclog((LOG_WARNING, 225 "IPv4 ESP input: no key association found for spi %u\n", 226 (u_int32_t)ntohl(spi))); 227 IPSEC_STAT_INCREMENT(ipsecstat.in_nosa); 228 goto bad; 229 } 230 KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 231 printf("DP esp4_input called to allocate SA:0x%llx\n", 232 (uint64_t)VM_KERNEL_ADDRPERM(sav))); 233 if (sav->state != SADB_SASTATE_MATURE 234 && sav->state != SADB_SASTATE_DYING) { 235 ipseclog((LOG_DEBUG, 236 "IPv4 ESP input: non-mature/dying SA found for spi %u\n", 237 (u_int32_t)ntohl(spi))); 238 IPSEC_STAT_INCREMENT(ipsecstat.in_badspi); 239 goto bad; 240 } 241 algo = esp_algorithm_lookup(sav->alg_enc); 242 if (!algo) { 243 ipseclog((LOG_DEBUG, "IPv4 ESP input: " 244 "unsupported encryption algorithm for spi %u\n", 245 (u_int32_t)ntohl(spi))); 246 IPSEC_STAT_INCREMENT(ipsecstat.in_badspi); 247 goto bad; 248 } 249 250 /* check if we have proper ivlen information */ 251 ivlen = sav->ivlen; 252 if (ivlen < 0) { 253 ipseclog((LOG_ERR, "inproper ivlen in IPv4 ESP input: %s %s\n", 254 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); 255 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 256 goto bad; 257 } 258 259 seq = ntohl(((struct newesp *)esp)->esp_seq); 260 if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay 261 && (sav->alg_auth && sav->key_auth))) 262 goto noreplaycheck; 263 264 if (sav->alg_auth == SADB_X_AALG_NULL || 265 sav->alg_auth == SADB_AALG_NONE) 266 goto noreplaycheck; 267 268 /* 269 * check for sequence number. 270 */ 271 if (ipsec_chkreplay(seq, sav)) 272 ; /*okey*/ 273 else { 274 IPSEC_STAT_INCREMENT(ipsecstat.in_espreplay); 275 ipseclog((LOG_WARNING, 276 "replay packet in IPv4 ESP input: %s %s\n", 277 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); 278 goto bad; 279 } 280 281 /* check ICV */ 282 { 283 u_char sum0[AH_MAXSUMSIZE] __attribute__((aligned(4))); 284 u_char sum[AH_MAXSUMSIZE] __attribute__((aligned(4))); 285 const struct ah_algorithm *sumalgo; 286 size_t siz; 287 288 sumalgo = ah_algorithm_lookup(sav->alg_auth); 289 if (!sumalgo) 290 goto noreplaycheck; 291 siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1)); 292 if (m->m_pkthdr.len < off + ESPMAXLEN + siz) { 293 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 294 goto bad; 295 } 296 if (AH_MAXSUMSIZE < siz) { 297 ipseclog((LOG_DEBUG, 298 "internal error: AH_MAXSUMSIZE must be larger than %lu\n", 299 (u_int32_t)siz)); 300 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 301 goto bad; 302 } 303 304 m_copydata(m, m->m_pkthdr.len - siz, siz, (caddr_t) &sum0[0]); 305 306 if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) { 307 ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n", 308 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); 309 IPSEC_STAT_INCREMENT(ipsecstat.in_espauthfail); 310 goto bad; 311 } 312 313 if (bcmp(sum0, sum, siz) != 0) { 314 ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n", 315 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); 316 IPSEC_STAT_INCREMENT(ipsecstat.in_espauthfail); 317 goto bad; 318 } 319 320 /* strip off the authentication data */ 321 m_adj(m, -siz); 322 ip = mtod(m, struct ip *); 323#ifdef IPLEN_FLIPPED 324 ip->ip_len = ip->ip_len - siz; 325#else 326 ip->ip_len = htons(ntohs(ip->ip_len) - siz); 327#endif 328 m->m_flags |= M_AUTHIPDGM; 329 IPSEC_STAT_INCREMENT(ipsecstat.in_espauthsucc); 330 } 331 332 /* 333 * update sequence number. 334 */ 335 if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) { 336 if (ipsec_updatereplay(seq, sav)) { 337 IPSEC_STAT_INCREMENT(ipsecstat.in_espreplay); 338 goto bad; 339 } 340 } 341 342noreplaycheck: 343 344 /* process main esp header. */ 345 if (sav->flags & SADB_X_EXT_OLD) { 346 /* RFC 1827 */ 347 esplen = sizeof(struct esp); 348 } else { 349 /* RFC 2406 */ 350 if (sav->flags & SADB_X_EXT_DERIV) 351 esplen = sizeof(struct esp); 352 else 353 esplen = sizeof(struct newesp); 354 } 355 356 if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) { 357 ipseclog((LOG_WARNING, 358 "IPv4 ESP input: packet too short\n")); 359 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 360 goto bad; 361 } 362 363 if (m->m_len < off + esplen + ivlen) { 364 m = m_pullup(m, off + esplen + ivlen); 365 if (!m) { 366 ipseclog((LOG_DEBUG, 367 "IPv4 ESP input: can't pullup in esp4_input\n")); 368 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 369 goto bad; 370 } 371 } 372 373 /* 374 * pre-compute and cache intermediate key 375 */ 376 if (esp_schedule(algo, sav) != 0) { 377 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 378 goto bad; 379 } 380 381 /* 382 * decrypt the packet. 383 */ 384 if (!algo->decrypt) 385 panic("internal error: no decrypt function"); 386 KERNEL_DEBUG(DBG_FNC_DECRYPT | DBG_FUNC_START, 0,0,0,0,0); 387 if ((*algo->decrypt)(m, off, sav, algo, ivlen)) { 388 /* m is already freed */ 389 m = NULL; 390 ipseclog((LOG_ERR, "decrypt fail in IPv4 ESP input: %s\n", 391 ipsec_logsastr(sav))); 392 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 393 KERNEL_DEBUG(DBG_FNC_DECRYPT | DBG_FUNC_END, 1,0,0,0,0); 394 goto bad; 395 } 396 KERNEL_DEBUG(DBG_FNC_DECRYPT | DBG_FUNC_END, 2,0,0,0,0); 397 IPSEC_STAT_INCREMENT(ipsecstat.in_esphist[sav->alg_enc]); 398 399 m->m_flags |= M_DECRYPTED; 400 401 /* 402 * find the trailer of the ESP. 403 */ 404 m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail), 405 (caddr_t)&esptail); 406 nxt = esptail.esp_nxt; 407 taillen = esptail.esp_padlen + sizeof(esptail); 408 409 if (m->m_pkthdr.len < taillen 410 || m->m_pkthdr.len - taillen < hlen) { /*?*/ 411 ipseclog((LOG_WARNING, 412 "bad pad length in IPv4 ESP input: %s %s\n", 413 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); 414 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 415 goto bad; 416 } 417 418 /* strip off the trailing pad area. */ 419 m_adj(m, -taillen); 420 ip = mtod(m, struct ip *); 421#ifdef IPLEN_FLIPPED 422 ip->ip_len = ip->ip_len - taillen; 423#else 424 ip->ip_len = htons(ntohs(ip->ip_len) - taillen); 425#endif 426 if (ip->ip_p == IPPROTO_UDP) { 427 // offset includes the outer ip and udp header lengths. 428 if (m->m_len < off) { 429 m = m_pullup(m, off); 430 if (!m) { 431 ipseclog((LOG_DEBUG, 432 "IPv4 ESP input: invalid udp encapsulated ESP packet length \n")); 433 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 434 goto bad; 435 } 436 } 437 438 // check the UDP encap header to detect changes in the source port, and then strip the header 439 off -= sizeof(struct udphdr); // off no longer includes the udphdr's size 440 // if peer is behind nat and this is the latest esp packet 441 if ((sav->flags & SADB_X_EXT_NATT_DETECTED_PEER) != 0 && 442 (sav->flags & SADB_X_EXT_OLD) == 0 && 443 seq && sav->replay && 444 seq >= sav->replay->lastseq) { 445 struct udphdr *encap_uh = (__typeof__(encap_uh))(void *)((caddr_t)ip + off); 446 if (encap_uh->uh_sport && 447 ntohs(encap_uh->uh_sport) != sav->remote_ike_port) { 448 sav->remote_ike_port = ntohs(encap_uh->uh_sport); 449 } 450 } 451 ip = esp4_input_strip_UDP_encap(m, off); 452 esp = (struct esp *)(void *)(((u_int8_t *)ip) + off); 453 } 454 455 if (sav->utun_is_keepalive_fn) { 456 if (sav->utun_is_keepalive_fn(sav->utun_pcb, &m, nxt, sav->flags, (off + esplen + ivlen))) { 457 if (m) { 458 // not really bad, we just wanna exit 459 IPSEC_STAT_INCREMENT(ipsecstat.in_success); 460 m = NULL; 461 } 462 goto bad; 463 } 464 } 465 466 /* was it transmitted over the IPsec tunnel SA? */ 467 if (ipsec4_tunnel_validate(m, off + esplen + ivlen, nxt, sav, &ifamily)) { 468 ifaddr_t ifa; 469 struct sockaddr_storage addr; 470 471 /* 472 * strip off all the headers that precedes ESP header. 473 * IP4 xx ESP IP4' payload -> IP4' payload 474 * 475 * XXX more sanity checks 476 * XXX relationship with gif? 477 */ 478 u_int8_t tos; 479 480 tos = ip->ip_tos; 481 m_adj(m, off + esplen + ivlen); 482 if (ifamily == AF_INET) { 483 struct sockaddr_in *ipaddr; 484 485 if (m->m_len < sizeof(*ip)) { 486 m = m_pullup(m, sizeof(*ip)); 487 if (!m) { 488 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 489 goto bad; 490 } 491 } 492 ip = mtod(m, struct ip *); 493 /* ECN consideration. */ 494 ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos); 495 if (!key_checktunnelsanity(sav, AF_INET, 496 (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) { 497 ipseclog((LOG_ERR, "ipsec tunnel address mismatch " 498 "in ESP input: %s %s\n", 499 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); 500 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 501 goto bad; 502 } 503 504 if (ip_doscopedroute) { 505 bzero(&addr, sizeof(addr)); 506 ipaddr = (__typeof__(ipaddr))&addr; 507 ipaddr->sin_family = AF_INET; 508 ipaddr->sin_len = sizeof(*ipaddr); 509 ipaddr->sin_addr = ip->ip_dst; 510 } 511#if INET6 512 } else if (ifamily == AF_INET6) { 513 struct sockaddr_in6 *ip6addr; 514 515 /* 516 * m_pullup is prohibited in KAME IPv6 input processing 517 * but there's no other way! 518 */ 519 if (m->m_len < sizeof(*ip6)) { 520 m = m_pullup(m, sizeof(*ip6)); 521 if (!m) { 522 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 523 goto bad; 524 } 525 } 526 527 /* 528 * Expect 32-bit aligned data pointer on strict-align 529 * platforms. 530 */ 531 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m); 532 533 ip6 = mtod(m, struct ip6_hdr *); 534 535 /* ECN consideration. */ 536 /* XXX To be fixed later if needed */ 537 // ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos); 538 539 if (!key_checktunnelsanity(sav, AF_INET6, 540 (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) { 541 ipseclog((LOG_ERR, "ipsec tunnel address mismatch " 542 "in ESP input: %s %s\n", 543 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); 544 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 545 goto bad; 546 } 547 548 if (ip6_doscopedroute) { 549 bzero(&addr, sizeof(addr)); 550 ip6addr = (__typeof__(ip6addr))&addr; 551 ip6addr->sin6_family = AF_INET6; 552 ip6addr->sin6_len = sizeof(*ip6addr); 553 ip6addr->sin6_addr = ip6->ip6_dst; 554 } 555#endif /* INET6 */ 556 } else { 557 ipseclog((LOG_ERR, "ipsec tunnel unsupported address family " 558 "in ESP input\n")); 559 goto bad; 560 } 561 562 key_sa_recordxfer(sav, m); 563 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 || 564 ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) { 565 IPSEC_STAT_INCREMENT(ipsecstat.in_nomem); 566 goto bad; 567 } 568 569 if (ip_doscopedroute || ip6_doscopedroute) { 570 // update the receiving interface address based on the inner address 571 ifa = ifa_ifwithaddr((struct sockaddr *)&addr); 572 if (ifa) { 573 m->m_pkthdr.rcvif = ifa->ifa_ifp; 574 IFA_REMREF(ifa); 575 } 576 } 577 578 /* Clear the csum flags, they can't be valid for the inner headers */ 579 m->m_pkthdr.csum_flags = 0; 580 581 // Input via IPSec interface 582 if (sav->sah->ipsec_if != NULL) { 583 if (ipsec_inject_inbound_packet(sav->sah->ipsec_if, m) == 0) { 584 m = NULL; 585 goto done; 586 } else { 587 goto bad; 588 } 589 } 590 591 if (sav->utun_in_fn) { 592 if (!(sav->utun_in_fn(sav->utun_pcb, &m, ifamily == AF_INET ? PF_INET : PF_INET6))) { 593 m = NULL; 594 // we just wanna exit since packet has been completely processed 595 goto bad; 596 } 597 } 598 599 if (proto_input(ifamily == AF_INET ? PF_INET : PF_INET6, m) != 0) 600 goto bad; 601 602 nxt = IPPROTO_DONE; 603 KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_END, 2,0,0,0,0); 604 } else { 605 /* 606 * strip off ESP header and IV. 607 * even in m_pulldown case, we need to strip off ESP so that 608 * we can always compute checksum for AH correctly. 609 */ 610 size_t stripsiz; 611 612 stripsiz = esplen + ivlen; 613 614 ip = mtod(m, struct ip *); 615 ovbcopy((caddr_t)ip, (caddr_t)(((u_char *)ip) + stripsiz), off); 616 m->m_data += stripsiz; 617 m->m_len -= stripsiz; 618 m->m_pkthdr.len -= stripsiz; 619 620 ip = mtod(m, struct ip *); 621#ifdef IPLEN_FLIPPED 622 ip->ip_len = ip->ip_len - stripsiz; 623#else 624 ip->ip_len = htons(ntohs(ip->ip_len) - stripsiz); 625#endif 626 ip->ip_p = nxt; 627 628 key_sa_recordxfer(sav, m); 629 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) { 630 IPSEC_STAT_INCREMENT(ipsecstat.in_nomem); 631 goto bad; 632 } 633 634 /* 635 * Set the csum valid flag, if we authenticated the 636 * packet, the payload shouldn't be corrupt unless 637 * it was corrupted before being signed on the other 638 * side. 639 */ 640 if (nxt == IPPROTO_TCP || nxt == IPPROTO_UDP) { 641 m->m_pkthdr.csum_flags = CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 642 m->m_pkthdr.csum_data = 0xFFFF; 643 } 644 645 if (nxt != IPPROTO_DONE) { 646 if ((ip_protox[nxt]->pr_flags & PR_LASTHDR) != 0 && 647 ipsec4_in_reject(m, NULL)) { 648 IPSEC_STAT_INCREMENT(ipsecstat.in_polvio); 649 goto bad; 650 } 651 KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_END, 3,0,0,0,0); 652 653 /* translate encapsulated UDP port ? */ 654 if ((sav->flags & SADB_X_EXT_NATT_MULTIPLEUSERS) != 0) { 655 struct udphdr *udp; 656 657 if (nxt != IPPROTO_UDP) { /* not UPD packet - drop it */ 658 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 659 goto bad; 660 } 661 662 if (m->m_len < off + sizeof(struct udphdr)) { 663 m = m_pullup(m, off + sizeof(struct udphdr)); 664 if (!m) { 665 ipseclog((LOG_DEBUG, 666 "IPv4 ESP input: can't pullup UDP header in esp4_input\n")); 667 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 668 goto bad; 669 } 670 ip = mtod(m, struct ip *); 671 } 672 udp = (struct udphdr *)(void *)(((u_int8_t *)ip) + off); 673 674 lck_mtx_lock(sadb_mutex); 675 if (sav->natt_encapsulated_src_port == 0) { 676 sav->natt_encapsulated_src_port = udp->uh_sport; 677 } else if (sav->natt_encapsulated_src_port != udp->uh_sport) { /* something wrong */ 678 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 679 lck_mtx_unlock(sadb_mutex); 680 goto bad; 681 } 682 lck_mtx_unlock(sadb_mutex); 683 udp->uh_sport = htons(sav->remote_ike_port); 684 udp->uh_sum = 0; 685 } 686 687 DTRACE_IP6(receive, struct mbuf *, m, struct inpcb *, NULL, 688 struct ip *, ip, struct ifnet *, m->m_pkthdr.rcvif, 689 struct ip *, ip, struct ip6_hdr *, NULL); 690 691 // Input via IPSec interface 692 if (sav->sah->ipsec_if != NULL) { 693 ip->ip_len = htons(ip->ip_len + hlen); 694 ip->ip_off = htons(ip->ip_off); 695 ip->ip_sum = 0; 696 ip->ip_sum = ip_cksum_hdr_in(m, hlen); 697 if (ipsec_inject_inbound_packet(sav->sah->ipsec_if, m) == 0) { 698 m = NULL; 699 goto done; 700 } else { 701 goto bad; 702 } 703 } 704 705 if (sav->utun_in_fn) { 706 if (!(sav->utun_in_fn(sav->utun_pcb, &m, PF_INET))) { 707 m = NULL; 708 // we just wanna exit since packet has been completely processed 709 goto bad; 710 } 711 } 712 713 ip_proto_dispatch_in(m, off, nxt, 0); 714 } else 715 m_freem(m); 716 m = NULL; 717 } 718 719done: 720 if (sav) { 721 KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 722 printf("DP esp4_input call free SA:0x%llx\n", 723 (uint64_t)VM_KERNEL_ADDRPERM(sav))); 724 key_freesav(sav, KEY_SADB_UNLOCKED); 725 } 726 IPSEC_STAT_INCREMENT(ipsecstat.in_success); 727 return; 728 729bad: 730 if (sav) { 731 KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 732 printf("DP esp4_input call free SA:0x%llx\n", 733 (uint64_t)VM_KERNEL_ADDRPERM(sav))); 734 key_freesav(sav, KEY_SADB_UNLOCKED); 735 } 736 if (m) 737 m_freem(m); 738 KERNEL_DEBUG(DBG_FNC_ESPIN | DBG_FUNC_END, 4,0,0,0,0); 739 return; 740} 741#endif /* INET */ 742 743#if INET6 744int 745esp6_input(struct mbuf **mp, int *offp, int proto) 746{ 747#pragma unused(proto) 748 struct mbuf *m = *mp; 749 int off = *offp; 750 struct ip6_hdr *ip6; 751 struct esp *esp; 752 struct esptail esptail; 753 u_int32_t spi; 754 u_int32_t seq; 755 struct secasvar *sav = NULL; 756 size_t taillen; 757 u_int16_t nxt; 758 const struct esp_algorithm *algo; 759 int ivlen; 760 size_t esplen; 761 762 /* sanity check for alignment. */ 763 if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) { 764 ipseclog((LOG_ERR, "IPv6 ESP input: packet alignment problem " 765 "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len)); 766 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval); 767 goto bad; 768 } 769 770#ifndef PULLDOWN_TEST 771 IP6_EXTHDR_CHECK(m, off, ESPMAXLEN, {return IPPROTO_DONE;}); 772 esp = (struct esp *)(void *)(mtod(m, caddr_t) + off); 773#else 774 IP6_EXTHDR_GET(esp, struct esp *, m, off, ESPMAXLEN); 775 if (esp == NULL) { 776 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval); 777 return IPPROTO_DONE; 778 } 779#endif 780 /* Expect 32-bit data aligned pointer on strict-align platforms */ 781 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m); 782 783 ip6 = mtod(m, struct ip6_hdr *); 784 785 if (ntohs(ip6->ip6_plen) == 0) { 786 ipseclog((LOG_ERR, "IPv6 ESP input: " 787 "ESP with IPv6 jumbogram is not supported.\n")); 788 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval); 789 goto bad; 790 } 791 792 /* find the sassoc. */ 793 spi = esp->esp_spi; 794 795 if ((sav = key_allocsa(AF_INET6, 796 (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst, 797 IPPROTO_ESP, spi)) == 0) { 798 ipseclog((LOG_WARNING, 799 "IPv6 ESP input: no key association found for spi %u\n", 800 (u_int32_t)ntohl(spi))); 801 IPSEC_STAT_INCREMENT(ipsec6stat.in_nosa); 802 goto bad; 803 } 804 KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 805 printf("DP esp6_input called to allocate SA:0x%llx\n", 806 (uint64_t)VM_KERNEL_ADDRPERM(sav))); 807 if (sav->state != SADB_SASTATE_MATURE 808 && sav->state != SADB_SASTATE_DYING) { 809 ipseclog((LOG_DEBUG, 810 "IPv6 ESP input: non-mature/dying SA found for spi %u\n", 811 (u_int32_t)ntohl(spi))); 812 IPSEC_STAT_INCREMENT(ipsec6stat.in_badspi); 813 goto bad; 814 } 815 algo = esp_algorithm_lookup(sav->alg_enc); 816 if (!algo) { 817 ipseclog((LOG_DEBUG, "IPv6 ESP input: " 818 "unsupported encryption algorithm for spi %u\n", 819 (u_int32_t)ntohl(spi))); 820 IPSEC_STAT_INCREMENT(ipsec6stat.in_badspi); 821 goto bad; 822 } 823 824 /* check if we have proper ivlen information */ 825 ivlen = sav->ivlen; 826 if (ivlen < 0) { 827 ipseclog((LOG_ERR, "inproper ivlen in IPv6 ESP input: %s %s\n", 828 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); 829 IPSEC_STAT_INCREMENT(ipsec6stat.in_badspi); 830 goto bad; 831 } 832 833 seq = ntohl(((struct newesp *)esp)->esp_seq); 834 835 if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay 836 && (sav->alg_auth && sav->key_auth))) 837 goto noreplaycheck; 838 839 if (sav->alg_auth == SADB_X_AALG_NULL || 840 sav->alg_auth == SADB_AALG_NONE) 841 goto noreplaycheck; 842 843 /* 844 * check for sequence number. 845 */ 846 if (ipsec_chkreplay(seq, sav)) 847 ; /*okey*/ 848 else { 849 IPSEC_STAT_INCREMENT(ipsec6stat.in_espreplay); 850 ipseclog((LOG_WARNING, 851 "replay packet in IPv6 ESP input: %s %s\n", 852 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); 853 goto bad; 854 } 855 856 /* check ICV */ 857 { 858 u_char sum0[AH_MAXSUMSIZE] __attribute__((aligned(4))); 859 u_char sum[AH_MAXSUMSIZE] __attribute__((aligned(4))); 860 const struct ah_algorithm *sumalgo; 861 size_t siz; 862 863 sumalgo = ah_algorithm_lookup(sav->alg_auth); 864 if (!sumalgo) 865 goto noreplaycheck; 866 siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1)); 867 if (m->m_pkthdr.len < off + ESPMAXLEN + siz) { 868 IPSEC_STAT_INCREMENT(ipsecstat.in_inval); 869 goto bad; 870 } 871 if (AH_MAXSUMSIZE < siz) { 872 ipseclog((LOG_DEBUG, 873 "internal error: AH_MAXSUMSIZE must be larger than %lu\n", 874 (u_int32_t)siz)); 875 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval); 876 goto bad; 877 } 878 879 m_copydata(m, m->m_pkthdr.len - siz, siz, (caddr_t) &sum0[0]); 880 881 if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) { 882 ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n", 883 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); 884 IPSEC_STAT_INCREMENT(ipsec6stat.in_espauthfail); 885 goto bad; 886 } 887 888 if (bcmp(sum0, sum, siz) != 0) { 889 ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n", 890 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); 891 IPSEC_STAT_INCREMENT(ipsec6stat.in_espauthfail); 892 goto bad; 893 } 894 895 /* strip off the authentication data */ 896 m_adj(m, -siz); 897 ip6 = mtod(m, struct ip6_hdr *); 898 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - siz); 899 900 m->m_flags |= M_AUTHIPDGM; 901 IPSEC_STAT_INCREMENT(ipsec6stat.in_espauthsucc); 902 } 903 904 /* 905 * update sequence number. 906 */ 907 if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) { 908 if (ipsec_updatereplay(seq, sav)) { 909 IPSEC_STAT_INCREMENT(ipsec6stat.in_espreplay); 910 goto bad; 911 } 912 } 913 914noreplaycheck: 915 916 /* process main esp header. */ 917 if (sav->flags & SADB_X_EXT_OLD) { 918 /* RFC 1827 */ 919 esplen = sizeof(struct esp); 920 } else { 921 /* RFC 2406 */ 922 if (sav->flags & SADB_X_EXT_DERIV) 923 esplen = sizeof(struct esp); 924 else 925 esplen = sizeof(struct newesp); 926 } 927 928 if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) { 929 ipseclog((LOG_WARNING, 930 "IPv6 ESP input: packet too short\n")); 931 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval); 932 goto bad; 933 } 934 935#ifndef PULLDOWN_TEST 936 IP6_EXTHDR_CHECK(m, off, esplen + ivlen, return IPPROTO_DONE); /*XXX*/ 937#else 938 IP6_EXTHDR_GET(esp, struct esp *, m, off, esplen + ivlen); 939 if (esp == NULL) { 940 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval); 941 m = NULL; 942 goto bad; 943 } 944#endif 945 ip6 = mtod(m, struct ip6_hdr *); /*set it again just in case*/ 946 947 /* 948 * pre-compute and cache intermediate key 949 */ 950 if (esp_schedule(algo, sav) != 0) { 951 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval); 952 goto bad; 953 } 954 955 /* 956 * decrypt the packet. 957 */ 958 if (!algo->decrypt) 959 panic("internal error: no decrypt function"); 960 if ((*algo->decrypt)(m, off, sav, algo, ivlen)) { 961 /* m is already freed */ 962 m = NULL; 963 ipseclog((LOG_ERR, "decrypt fail in IPv6 ESP input: %s\n", 964 ipsec_logsastr(sav))); 965 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval); 966 goto bad; 967 } 968 IPSEC_STAT_INCREMENT(ipsec6stat.in_esphist[sav->alg_enc]); 969 970 m->m_flags |= M_DECRYPTED; 971 972 /* 973 * find the trailer of the ESP. 974 */ 975 m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail), 976 (caddr_t)&esptail); 977 nxt = esptail.esp_nxt; 978 taillen = esptail.esp_padlen + sizeof(esptail); 979 980 if (m->m_pkthdr.len < taillen 981 || m->m_pkthdr.len - taillen < sizeof(struct ip6_hdr)) { /*?*/ 982 ipseclog((LOG_WARNING, 983 "bad pad length in IPv6 ESP input: %s %s\n", 984 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); 985 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval); 986 goto bad; 987 } 988 989 /* strip off the trailing pad area. */ 990 m_adj(m, -taillen); 991 ip6 = mtod(m, struct ip6_hdr *); 992 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - taillen); 993 994 if (sav->utun_is_keepalive_fn) { 995 if (sav->utun_is_keepalive_fn(sav->utun_pcb, &m, nxt, sav->flags, (off + esplen + ivlen))) { 996 if (m) { 997 // not really bad, we just wanna exit 998 IPSEC_STAT_INCREMENT(ipsec6stat.in_success); 999 m = NULL; 1000 } 1001 goto bad; 1002 } 1003 } 1004 1005 /* was it transmitted over the IPsec tunnel SA? */ 1006 if (ipsec6_tunnel_validate(m, off + esplen + ivlen, nxt, sav)) { 1007 ifaddr_t ifa; 1008 struct sockaddr_storage addr; 1009 1010 /* 1011 * strip off all the headers that precedes ESP header. 1012 * IP6 xx ESP IP6' payload -> IP6' payload 1013 * 1014 * XXX more sanity checks 1015 * XXX relationship with gif? 1016 */ 1017 u_int32_t flowinfo; /*net endian*/ 1018 flowinfo = ip6->ip6_flow; 1019 m_adj(m, off + esplen + ivlen); 1020 if (m->m_len < sizeof(*ip6)) { 1021#ifndef PULLDOWN_TEST 1022 /* 1023 * m_pullup is prohibited in KAME IPv6 input processing 1024 * but there's no other way! 1025 */ 1026#else 1027 /* okay to pullup in m_pulldown style */ 1028#endif 1029 m = m_pullup(m, sizeof(*ip6)); 1030 if (!m) { 1031 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval); 1032 goto bad; 1033 } 1034 } 1035 ip6 = mtod(m, struct ip6_hdr *); 1036 /* ECN consideration. */ 1037 ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow); 1038 if (!key_checktunnelsanity(sav, AF_INET6, 1039 (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) { 1040 ipseclog((LOG_ERR, "ipsec tunnel address mismatch " 1041 "in IPv6 ESP input: %s %s\n", 1042 ipsec6_logpacketstr(ip6, spi), 1043 ipsec_logsastr(sav))); 1044 IPSEC_STAT_INCREMENT(ipsec6stat.in_inval); 1045 goto bad; 1046 } 1047 1048 key_sa_recordxfer(sav, m); 1049 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 || 1050 ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) { 1051 IPSEC_STAT_INCREMENT(ipsec6stat.in_nomem); 1052 goto bad; 1053 } 1054 1055 if (ip6_doscopedroute) { 1056 struct sockaddr_in6 *ip6addr; 1057 1058 bzero(&addr, sizeof(addr)); 1059 ip6addr = (__typeof__(ip6addr))&addr; 1060 ip6addr->sin6_family = AF_INET6; 1061 ip6addr->sin6_len = sizeof(*ip6addr); 1062 ip6addr->sin6_addr = ip6->ip6_dst; 1063 1064 // update the receiving interface address based on the inner address 1065 ifa = ifa_ifwithaddr((struct sockaddr *)&addr); 1066 if (ifa) { 1067 m->m_pkthdr.rcvif = ifa->ifa_ifp; 1068 IFA_REMREF(ifa); 1069 } 1070 } 1071 1072 // Input via IPSec interface 1073 if (sav->sah->ipsec_if != NULL) { 1074 if (ipsec_inject_inbound_packet(sav->sah->ipsec_if, m) == 0) { 1075 m = NULL; 1076 nxt = IPPROTO_DONE; 1077 goto done; 1078 } else { 1079 goto bad; 1080 } 1081 } 1082 1083 if (sav->utun_in_fn) { 1084 if (!(sav->utun_in_fn(sav->utun_pcb, &m, PF_INET6))) { 1085 m = NULL; 1086 // we just wanna exit since packet has been completely processed 1087 goto bad; 1088 } 1089 } 1090 1091 if (proto_input(PF_INET6, m) != 0) 1092 goto bad; 1093 nxt = IPPROTO_DONE; 1094 } else { 1095 /* 1096 * strip off ESP header and IV. 1097 * even in m_pulldown case, we need to strip off ESP so that 1098 * we can always compute checksum for AH correctly. 1099 */ 1100 size_t stripsiz; 1101 char *prvnxtp; 1102 1103 /* 1104 * Set the next header field of the previous header correctly. 1105 */ 1106 prvnxtp = ip6_get_prevhdr(m, off); /* XXX */ 1107 *prvnxtp = nxt; 1108 1109 stripsiz = esplen + ivlen; 1110 1111 ip6 = mtod(m, struct ip6_hdr *); 1112 if (m->m_len >= stripsiz + off) { 1113 ovbcopy((caddr_t)ip6, ((caddr_t)ip6) + stripsiz, off); 1114 m->m_data += stripsiz; 1115 m->m_len -= stripsiz; 1116 m->m_pkthdr.len -= stripsiz; 1117 } else { 1118 /* 1119 * this comes with no copy if the boundary is on 1120 * cluster 1121 */ 1122 struct mbuf *n; 1123 1124 n = m_split(m, off, M_DONTWAIT); 1125 if (n == NULL) { 1126 /* m is retained by m_split */ 1127 goto bad; 1128 } 1129 m_adj(n, stripsiz); 1130 /* m_cat does not update m_pkthdr.len */ 1131 m->m_pkthdr.len += n->m_pkthdr.len; 1132 m_cat(m, n); 1133 } 1134 1135#ifndef PULLDOWN_TEST 1136 /* 1137 * KAME requires that the packet to be contiguous on the 1138 * mbuf. We need to make that sure. 1139 * this kind of code should be avoided. 1140 * XXX other conditions to avoid running this part? 1141 */ 1142 if (m->m_len != m->m_pkthdr.len) { 1143 struct mbuf *n = NULL; 1144 int maxlen; 1145 1146 MGETHDR(n, M_DONTWAIT, MT_HEADER); /* MAC-OK */ 1147 maxlen = MHLEN; 1148 if (n) 1149 M_COPY_PKTHDR(n, m); 1150 if (n && m->m_pkthdr.len > maxlen) { 1151 MCLGET(n, M_DONTWAIT); 1152 maxlen = MCLBYTES; 1153 if ((n->m_flags & M_EXT) == 0) { 1154 m_free(n); 1155 n = NULL; 1156 } 1157 } 1158 if (!n) { 1159 printf("esp6_input: mbuf allocation failed\n"); 1160 goto bad; 1161 } 1162 1163 if (m->m_pkthdr.len <= maxlen) { 1164 m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t)); 1165 n->m_len = m->m_pkthdr.len; 1166 n->m_pkthdr.len = m->m_pkthdr.len; 1167 n->m_next = NULL; 1168 m_freem(m); 1169 } else { 1170 m_copydata(m, 0, maxlen, mtod(n, caddr_t)); 1171 n->m_len = maxlen; 1172 n->m_pkthdr.len = m->m_pkthdr.len; 1173 n->m_next = m; 1174 m_adj(m, maxlen); 1175 m->m_flags &= ~M_PKTHDR; 1176 } 1177 m = n; 1178 } 1179#endif 1180 1181 ip6 = mtod(m, struct ip6_hdr *); 1182 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - stripsiz); 1183 1184 key_sa_recordxfer(sav, m); 1185 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) { 1186 IPSEC_STAT_INCREMENT(ipsec6stat.in_nomem); 1187 goto bad; 1188 } 1189 1190 // Input via IPSec interface 1191 if (sav->sah->ipsec_if != NULL) { 1192 if (ipsec_inject_inbound_packet(sav->sah->ipsec_if, m) == 0) { 1193 m = NULL; 1194 nxt = IPPROTO_DONE; 1195 goto done; 1196 } else { 1197 goto bad; 1198 } 1199 } 1200 1201 if (sav->utun_in_fn) { 1202 if (!(sav->utun_in_fn(sav->utun_pcb, &m, PF_INET6))) { 1203 m = NULL; 1204 // we just wanna exit since packet has been completely processed 1205 goto bad; 1206 } 1207 } 1208 } 1209 1210done: 1211 *offp = off; 1212 *mp = m; 1213 if (sav) { 1214 KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 1215 printf("DP esp6_input call free SA:0x%llx\n", 1216 (uint64_t)VM_KERNEL_ADDRPERM(sav))); 1217 key_freesav(sav, KEY_SADB_UNLOCKED); 1218 } 1219 IPSEC_STAT_INCREMENT(ipsec6stat.in_success); 1220 return nxt; 1221 1222bad: 1223 if (sav) { 1224 KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 1225 printf("DP esp6_input call free SA:0x%llx\n", 1226 (uint64_t)VM_KERNEL_ADDRPERM(sav))); 1227 key_freesav(sav, KEY_SADB_UNLOCKED); 1228 } 1229 if (m) 1230 m_freem(m); 1231 return IPPROTO_DONE; 1232} 1233 1234void 1235esp6_ctlinput(cmd, sa, d) 1236 int cmd; 1237 struct sockaddr *sa; 1238 void *d; 1239{ 1240 const struct newesp *espp; 1241 struct newesp esp; 1242 struct ip6ctlparam *ip6cp = NULL, ip6cp1; 1243 struct secasvar *sav; 1244 struct ip6_hdr *ip6; 1245 struct mbuf *m; 1246 int off; 1247 struct sockaddr_in6 *sa6_src, *sa6_dst; 1248 1249 if (sa->sa_family != AF_INET6 || 1250 sa->sa_len != sizeof(struct sockaddr_in6)) 1251 return; 1252 if ((unsigned)cmd >= PRC_NCMDS) 1253 return; 1254 1255 /* if the parameter is from icmp6, decode it. */ 1256 if (d != NULL) { 1257 ip6cp = (struct ip6ctlparam *)d; 1258 m = ip6cp->ip6c_m; 1259 ip6 = ip6cp->ip6c_ip6; 1260 off = ip6cp->ip6c_off; 1261 } else { 1262 m = NULL; 1263 ip6 = NULL; 1264 } 1265 1266 if (ip6) { 1267 /* 1268 * Notify the error to all possible sockets via pfctlinput2. 1269 * Since the upper layer information (such as protocol type, 1270 * source and destination ports) is embedded in the encrypted 1271 * data and might have been cut, we can't directly call 1272 * an upper layer ctlinput function. However, the pcbnotify 1273 * function will consider source and destination addresses 1274 * as well as the flow info value, and may be able to find 1275 * some PCB that should be notified. 1276 * Although pfctlinput2 will call esp6_ctlinput(), there is 1277 * no possibility of an infinite loop of function calls, 1278 * because we don't pass the inner IPv6 header. 1279 */ 1280 bzero(&ip6cp1, sizeof(ip6cp1)); 1281 ip6cp1.ip6c_src = ip6cp->ip6c_src; 1282 pfctlinput2(cmd, sa, (void *)&ip6cp1); 1283 1284 /* 1285 * Then go to special cases that need ESP header information. 1286 * XXX: We assume that when ip6 is non NULL, 1287 * M and OFF are valid. 1288 */ 1289 1290 /* check if we can safely examine src and dst ports */ 1291 if (m->m_pkthdr.len < off + sizeof(esp)) 1292 return; 1293 1294 if (m->m_len < off + sizeof(esp)) { 1295 /* 1296 * this should be rare case, 1297 * so we compromise on this copy... 1298 */ 1299 m_copydata(m, off, sizeof(esp), (caddr_t)&esp); 1300 espp = &esp; 1301 } else 1302 espp = (struct newesp*)(void *)(mtod(m, caddr_t) + off); 1303 1304 if (cmd == PRC_MSGSIZE) { 1305 int valid = 0; 1306 1307 /* 1308 * Check to see if we have a valid SA corresponding to 1309 * the address in the ICMP message payload. 1310 */ 1311 sa6_src = ip6cp->ip6c_src; 1312 sa6_dst = (struct sockaddr_in6 *)(void *)sa; 1313 sav = key_allocsa(AF_INET6, 1314 (caddr_t)&sa6_src->sin6_addr, 1315 (caddr_t)&sa6_dst->sin6_addr, 1316 IPPROTO_ESP, espp->esp_spi); 1317 if (sav) { 1318 if (sav->state == SADB_SASTATE_MATURE || 1319 sav->state == SADB_SASTATE_DYING) 1320 valid++; 1321 key_freesav(sav, KEY_SADB_LOCKED); 1322 } 1323 1324 /* XXX Further validation? */ 1325 1326 /* 1327 * Depending on the value of "valid" and routing table 1328 * size (mtudisc_{hi,lo}wat), we will: 1329 * - recalcurate the new MTU and create the 1330 * corresponding routing entry, or 1331 * - ignore the MTU change notification. 1332 */ 1333 icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); 1334 } 1335 } else { 1336 /* we normally notify any pcb here */ 1337 } 1338} 1339#endif /* INET6 */ 1340