1 /* $OpenBSD: ipsec_output.c,v 1.28 2003/12/02 23:16:29 markus Exp $ */ 2 /* 3 * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) 4 * 5 * Copyright (c) 2000-2001 Angelos D. Keromytis. 6 * 7 * Permission to use, copy, and modify this software with or without fee 8 * is hereby granted, provided that this entire notice is included in 9 * all copies of any software which is or includes a copy or 10 * modification of this software. 11 * You may use this code under the GNU public license if you so wish. Please 12 * contribute changes back to the authors under this freer than GPL license 13 * so that we may further the use of strong encryption without limitations to 14 * all. 15 * 16 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 18 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 19 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 20 * PURPOSE. 21 */ 22 23 #include <sys/param.h> 24 #include <sys/systm.h> 25 #include <sys/mbuf.h> 26 #include <sys/socket.h> 27 #include <sys/kernel.h> 28 29 #include <net/if.h> 30 #include <net/route.h> 31 32 #ifdef INET 33 #include <netinet/in.h> 34 #include <netinet/in_systm.h> 35 #include <netinet/ip.h> 36 #include <netinet/in_pcb.h> 37 #include <netinet/ip_var.h> 38 #endif /* INET */ 39 40 #ifdef INET6 41 #ifndef INET 42 #include <netinet/in.h> 43 #endif 44 #include <netinet6/in6_var.h> 45 #endif /* INET6 */ 46 47 #include <netinet/udp.h> 48 #include <netinet/ip_ipsp.h> 49 #include <netinet/ip_ah.h> 50 #include <netinet/ip_esp.h> 51 #include <netinet/ip_ipcomp.h> 52 #include <crypto/xform.h> 53 54 #ifdef ENCDEBUG 55 #define DPRINTF(x) if (encdebug) printf x 56 #else 57 #define DPRINTF(x) 58 #endif 59 60 int udpencap_enable = 0; /* disabled by default */ 61 int udpencap_port = 4500; /* triggers decapsulation */ 62 63 /* 64 * Loop over a tdb chain, taking into consideration protocol tunneling. The 65 * fourth argument is set if the first encapsulation header is already in 66 * place. 67 */ 68 int 69 ipsp_process_packet(struct mbuf *m, struct tdb *tdb, int af, int tunalready) 70 { 71 struct timeval tv; 72 int i, off, error; 73 struct mbuf *mp; 74 75 #ifdef INET 76 int setdf = 0; 77 struct ip *ip; 78 #endif /* INET */ 79 #ifdef INET6 80 struct ip6_hdr *ip6; 81 #endif /* INET6 */ 82 83 /* Check that the transform is allowed by the administrator. */ 84 if ((tdb->tdb_sproto == IPPROTO_ESP && !esp_enable) || 85 (tdb->tdb_sproto == IPPROTO_AH && !ah_enable) || 86 (tdb->tdb_sproto == IPPROTO_IPCOMP && !ipcomp_enable)) { 87 DPRINTF(("ipsp_process_packet(): IPsec outbound packet " 88 "dropped due to policy (check your sysctls)\n")); 89 m_freem(m); 90 return EHOSTUNREACH; 91 } 92 93 /* Sanity check. */ 94 if (!tdb->tdb_xform) { 95 DPRINTF(("ipsp_process_packet(): uninitialized TDB\n")); 96 m_freem(m); 97 return EHOSTUNREACH; 98 } 99 100 /* Check if the SPI is invalid. */ 101 if (tdb->tdb_flags & TDBF_INVALID) { 102 DPRINTF(("ipsp_process_packet(): attempt to use invalid " 103 "SA %s/%08x/%u\n", ipsp_address(tdb->tdb_dst), 104 ntohl(tdb->tdb_spi), tdb->tdb_sproto)); 105 m_freem(m); 106 return ENXIO; 107 } 108 109 /* Check that the network protocol is supported */ 110 switch (tdb->tdb_dst.sa.sa_family) { 111 #ifdef INET 112 case AF_INET: 113 break; 114 #endif /* INET */ 115 116 #ifdef INET6 117 case AF_INET6: 118 break; 119 #endif /* INET6 */ 120 121 default: 122 DPRINTF(("ipsp_process_packet(): attempt to use " 123 "SA %s/%08x/%u for protocol family %d\n", 124 ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi), 125 tdb->tdb_sproto, tdb->tdb_dst.sa.sa_family)); 126 m_freem(m); 127 return ENXIO; 128 } 129 130 /* 131 * Register first use if applicable, setup relevant expiration timer. 132 */ 133 if (tdb->tdb_first_use == 0) { 134 int pri; 135 136 pri = splhigh(); 137 tdb->tdb_first_use = time.tv_sec; 138 splx(pri); 139 140 tv.tv_usec = 0; 141 142 tv.tv_sec = tdb->tdb_first_use + tdb->tdb_exp_first_use; 143 if (tdb->tdb_flags & TDBF_FIRSTUSE) 144 timeout_add(&tdb->tdb_first_tmo, 145 hzto(&tv)); 146 147 tv.tv_sec = tdb->tdb_first_use + tdb->tdb_soft_first_use; 148 if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) 149 timeout_add(&tdb->tdb_sfirst_tmo, 150 hzto(&tv)); 151 } 152 153 /* 154 * Check for tunneling if we don't have the first header in place. 155 * When doing Ethernet-over-IP, we are handed an already-encapsulated 156 * frame, so we don't need to re-encapsulate. 157 */ 158 if (tunalready == 0) { 159 /* 160 * If the target protocol family is different, we know we'll be 161 * doing tunneling. 162 */ 163 if (af == tdb->tdb_dst.sa.sa_family) { 164 #ifdef INET 165 if (af == AF_INET) 166 i = sizeof(struct ip); 167 #endif /* INET */ 168 169 #ifdef INET6 170 if (af == AF_INET6) 171 i = sizeof(struct ip6_hdr); 172 #endif /* INET6 */ 173 174 /* Bring the network header in the first mbuf. */ 175 if (m->m_len < i) { 176 if ((m = m_pullup(m, i)) == NULL) 177 return ENOBUFS; 178 } 179 180 #ifdef INET 181 ip = mtod(m, struct ip *); 182 183 /* 184 * This is not a bridge packet, remember if we 185 * had IP_DF. 186 */ 187 setdf = ip->ip_off & htons(IP_DF); 188 #endif /* INET */ 189 190 #ifdef INET6 191 ip6 = mtod(m, struct ip6_hdr *); 192 #endif /* INET6 */ 193 } 194 195 /* Do the appropriate encapsulation, if necessary. */ 196 if ((tdb->tdb_dst.sa.sa_family != af) || /* PF mismatch */ 197 (tdb->tdb_flags & TDBF_TUNNELING) || /* Tunneling needed */ 198 (tdb->tdb_xform->xf_type == XF_IP4) || /* ditto */ 199 #ifdef INET 200 ((tdb->tdb_dst.sa.sa_family == AF_INET) && 201 (tdb->tdb_dst.sin.sin_addr.s_addr != INADDR_ANY) && 202 (tdb->tdb_dst.sin.sin_addr.s_addr != ip->ip_dst.s_addr)) || 203 #endif /* INET */ 204 #ifdef INET6 205 ((tdb->tdb_dst.sa.sa_family == AF_INET6) && 206 (!IN6_IS_ADDR_UNSPECIFIED(&tdb->tdb_dst.sin6.sin6_addr)) && 207 (!IN6_ARE_ADDR_EQUAL(&tdb->tdb_dst.sin6.sin6_addr, 208 &ip6->ip6_dst))) || 209 #endif /* INET6 */ 210 0) { 211 #ifdef INET 212 /* Fix IPv4 header checksum and length. */ 213 if (af == AF_INET) { 214 if (m->m_len < sizeof(struct ip)) 215 if ((m = m_pullup(m, 216 sizeof(struct ip))) == NULL) 217 return ENOBUFS; 218 219 ip = mtod(m, struct ip *); 220 ip->ip_len = htons(m->m_pkthdr.len); 221 ip->ip_sum = 0; 222 ip->ip_sum = in_cksum(m, ip->ip_hl << 2); 223 } 224 #endif /* INET */ 225 226 #ifdef INET6 227 /* Fix IPv6 header payload length. */ 228 if (af == AF_INET6) { 229 if (m->m_len < sizeof(struct ip6_hdr)) 230 if ((m = m_pullup(m, 231 sizeof(struct ip6_hdr))) == NULL) 232 return ENOBUFS; 233 234 if (m->m_pkthdr.len - sizeof(*ip6) > 235 IPV6_MAXPACKET) { 236 /* No jumbogram support. */ 237 m_freem(m); 238 return ENXIO; /*?*/ 239 } 240 ip6 = mtod(m, struct ip6_hdr *); 241 ip6->ip6_plen = htons(m->m_pkthdr.len 242 - sizeof(*ip6)); 243 } 244 #endif /* INET6 */ 245 246 /* Encapsulate -- the last two arguments are unused. */ 247 error = ipip_output(m, tdb, &mp, 0, 0); 248 if ((mp == NULL) && (!error)) 249 error = EFAULT; 250 if (error) { 251 if (mp) { 252 m_freem(mp); 253 mp = NULL; 254 } 255 return error; 256 } 257 258 m = mp; 259 mp = NULL; 260 261 #ifdef INET 262 if (tdb->tdb_dst.sa.sa_family == AF_INET && setdf) { 263 if (m->m_len < sizeof(struct ip)) 264 if ((m = m_pullup(m, 265 sizeof(struct ip))) == NULL) 266 return ENOBUFS; 267 268 ip = mtod(m, struct ip *); 269 ip->ip_off |= htons(IP_DF); 270 } 271 272 /* Remember that we appended a tunnel header. */ 273 tdb->tdb_flags |= TDBF_USEDTUNNEL; 274 #endif 275 } 276 277 /* We may be done with this TDB */ 278 if (tdb->tdb_xform->xf_type == XF_IP4) 279 return ipsp_process_done(m, tdb); 280 } else { 281 /* 282 * If this is just an IP-IP TDB and we're told there's 283 * already an encapsulation header, move on. 284 */ 285 if (tdb->tdb_xform->xf_type == XF_IP4) 286 return ipsp_process_done(m, tdb); 287 } 288 289 /* Extract some information off the headers. */ 290 switch (tdb->tdb_dst.sa.sa_family) { 291 #ifdef INET 292 case AF_INET: 293 ip = mtod(m, struct ip *); 294 i = ip->ip_hl << 2; 295 off = offsetof(struct ip, ip_p); 296 break; 297 #endif /* INET */ 298 299 #ifdef INET6 300 case AF_INET6: 301 ip6 = mtod(m, struct ip6_hdr *); 302 i = sizeof(struct ip6_hdr); 303 off = offsetof(struct ip6_hdr, ip6_nxt); 304 break; 305 #endif /* INET6 */ 306 } 307 308 /* Non expansion policy for IPCOMP */ 309 if (tdb->tdb_sproto == IPPROTO_IPCOMP) { 310 if ((m->m_pkthdr.len - i) < tdb->tdb_compalgxform->minlen) { 311 extern struct ipcompstat ipcompstat; 312 313 /* No need to compress, leave the packet untouched */ 314 ipcompstat.ipcomps_minlen++; 315 return ipsp_process_done(m, tdb); 316 } 317 } 318 319 /* Invoke the IPsec transform. */ 320 return (*(tdb->tdb_xform->xf_output))(m, tdb, NULL, i, off); 321 } 322 323 /* 324 * Called by the IPsec output transform callbacks, to transmit the packet 325 * or do further processing, as necessary. 326 */ 327 int 328 ipsp_process_done(struct mbuf *m, struct tdb *tdb) 329 { 330 #ifdef INET 331 struct ip *ip; 332 #endif /* INET */ 333 334 #ifdef INET6 335 struct ip6_hdr *ip6; 336 #endif /* INET6 */ 337 338 struct tdb_ident *tdbi; 339 struct m_tag *mtag; 340 341 tdb->tdb_last_used = time.tv_sec; 342 343 if (udpencap_enable && udpencap_port && 344 (tdb->tdb_flags & TDBF_UDPENCAP) != 0) { 345 struct mbuf *mi; 346 struct udphdr *uh; 347 348 mi = m_inject(m, sizeof(struct ip), sizeof(struct udphdr), 349 M_DONTWAIT); 350 if (mi == NULL) { 351 m_freem(m); 352 return ENOMEM; 353 } 354 uh = mtod(mi, struct udphdr *); 355 uh->uh_sport = uh->uh_dport = htons(udpencap_port); 356 if (tdb->tdb_udpencap_port) 357 uh->uh_dport = tdb->tdb_udpencap_port; 358 359 uh->uh_ulen = htons(m->m_pkthdr.len - sizeof(struct ip)); 360 uh->uh_sum = 0; 361 espstat.esps_udpencout++; 362 } 363 364 switch (tdb->tdb_dst.sa.sa_family) { 365 #ifdef INET 366 case AF_INET: 367 /* Fix the header length, for AH processing. */ 368 ip = mtod(m, struct ip *); 369 ip->ip_len = htons(m->m_pkthdr.len); 370 if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0) 371 ip->ip_p = IPPROTO_UDP; 372 break; 373 #endif /* INET */ 374 375 #ifdef INET6 376 case AF_INET6: 377 /* Fix the header length, for AH processing. */ 378 if (m->m_pkthdr.len < sizeof(*ip6)) { 379 m_freem(m); 380 return ENXIO; 381 } 382 if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) { 383 /* No jumbogram support. */ 384 m_freem(m); 385 return ENXIO; 386 } 387 ip6 = mtod(m, struct ip6_hdr *); 388 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6)); 389 if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0) 390 ip6->ip6_nxt = IPPROTO_UDP; 391 break; 392 #endif /* INET6 */ 393 394 default: 395 m_freem(m); 396 DPRINTF(("ipsp_process_done(): unknown protocol family (%d)\n", 397 tdb->tdb_dst.sa.sa_family)); 398 return ENXIO; 399 } 400 401 /* 402 * Add a record of what we've done or what needs to be done to the 403 * packet. 404 */ 405 if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0) 406 mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE, 407 sizeof(struct tdb_ident), 408 M_NOWAIT); 409 else 410 mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED, 411 sizeof(struct tdb_ident), M_NOWAIT); 412 413 if (mtag == NULL) { 414 m_freem(m); 415 DPRINTF(("ipsp_process_done(): could not allocate packet " 416 "tag\n")); 417 return ENOMEM; 418 } 419 420 tdbi = (struct tdb_ident *)(mtag + 1); 421 bcopy(&tdb->tdb_dst, &tdbi->dst, sizeof(union sockaddr_union)); 422 tdbi->proto = tdb->tdb_sproto; 423 tdbi->spi = tdb->tdb_spi; 424 425 m_tag_prepend(m, mtag); 426 427 /* If there's another (bundled) TDB to apply, do so. */ 428 if (tdb->tdb_onext) 429 return ipsp_process_packet(m, tdb->tdb_onext, 430 tdb->tdb_dst.sa.sa_family, 0); 431 432 /* 433 * We're done with IPsec processing, transmit the packet using the 434 * appropriate network protocol (IP or IPv6). SPD lookup will be 435 * performed again there. 436 */ 437 switch (tdb->tdb_dst.sa.sa_family) { 438 #ifdef INET 439 case AF_INET: 440 return ip_output(m, (void *)NULL, (void *)NULL, IP_RAWOUTPUT, (void *)NULL, (void *)NULL); 441 #endif /* INET */ 442 443 #ifdef INET6 444 case AF_INET6: 445 /* 446 * We don't need massage, IPv6 header fields are always in 447 * net endian. 448 */ 449 return ip6_output(m, NULL, NULL, 0, NULL, NULL); 450 #endif /* INET6 */ 451 } 452 return EINVAL; /* Not reached. */ 453 } 454 455 ssize_t 456 ipsec_hdrsz(struct tdb *tdbp) 457 { 458 ssize_t adjust; 459 460 switch (tdbp->tdb_sproto) { 461 case IPPROTO_ESP: 462 if (tdbp->tdb_encalgxform == NULL) 463 return (-1); 464 465 /* Header length */ 466 if (tdbp->tdb_flags & TDBF_NOREPLAY) 467 adjust = sizeof(u_int32_t) + tdbp->tdb_ivlen; 468 else 469 adjust = 2 * sizeof(u_int32_t) + tdbp->tdb_ivlen; 470 /* Authenticator */ 471 if (tdbp->tdb_authalgxform != NULL) 472 adjust += AH_HMAC_HASHLEN; 473 /* Padding */ 474 adjust += tdbp->tdb_encalgxform->blocksize; 475 break; 476 477 case IPPROTO_AH: 478 if (tdbp->tdb_authalgxform == NULL) 479 return (-1); 480 481 if (!(tdbp->tdb_flags & TDBF_NOREPLAY)) 482 adjust = AH_FLENGTH + sizeof(u_int32_t); 483 else 484 adjust = AH_FLENGTH; 485 adjust += tdbp->tdb_authalgxform->authsize; 486 break; 487 488 default: 489 return (-1); 490 } 491 492 if (!(tdbp->tdb_flags & TDBF_TUNNELING) && 493 !(tdbp->tdb_flags & TDBF_USEDTUNNEL)) 494 return (adjust); 495 496 switch (tdbp->tdb_dst.sa.sa_family) { 497 #ifdef INET 498 case AF_INET: 499 adjust += sizeof(struct ip); 500 break; 501 #endif /* INET */ 502 #ifdef INET6 503 case AF_INET6: 504 adjust += sizeof(struct ip6_hdr); 505 break; 506 #endif /* INET6 */ 507 } 508 509 return (adjust); 510 } 511 512 void 513 ipsec_adjust_mtu(struct mbuf *m, u_int32_t mtu) 514 { 515 struct tdb_ident *tdbi; 516 struct tdb *tdbp; 517 struct m_tag *mtag; 518 ssize_t adjust; 519 int s; 520 521 s = spltdb(); 522 523 for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, NULL); mtag; 524 mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, mtag)) { 525 tdbi = (struct tdb_ident *)(mtag + 1); 526 tdbp = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto); 527 if (tdbp == NULL) 528 break; 529 530 if ((adjust = ipsec_hdrsz(tdbp)) == -1) 531 break; 532 533 mtu -= adjust; 534 tdbp->tdb_mtu = mtu; 535 tdbp->tdb_mtutimeout = time.tv_sec + ip_mtudisc_timeout; 536 } 537 538 splx(s); 539 } 540