xref: /openbsd-src/sys/netinet/ipsec_output.c (revision 5a38ef86d0b61900239c7913d24a05e7b88a58f0)
1 /*	$OpenBSD: ipsec_output.c,v 1.94 2021/12/11 16:33:47 bluhm 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 "pf.h"
24 
25 #include <sys/param.h>
26 #include <sys/systm.h>
27 #include <sys/mbuf.h>
28 #include <sys/socket.h>
29 #include <sys/kernel.h>
30 #include <sys/timeout.h>
31 
32 #include <net/if.h>
33 #include <net/route.h>
34 
35 #include <netinet/in.h>
36 #include <netinet/ip.h>
37 #include <netinet/in_pcb.h>
38 #include <netinet/ip_var.h>
39 
40 #if NPF > 0
41 #include <net/pfvar.h>
42 #endif
43 
44 #include <netinet/udp.h>
45 #include <netinet/ip_ipip.h>
46 #include <netinet/ip_ah.h>
47 #include <netinet/ip_esp.h>
48 #include <netinet/ip_ipcomp.h>
49 
50 #include <crypto/cryptodev.h>
51 #include <crypto/xform.h>
52 
53 #ifdef ENCDEBUG
54 #define DPRINTF(fmt, args...)						\
55 	do {								\
56 		if (encdebug)						\
57 			printf("%s: " fmt "\n", __func__, ## args);	\
58 	} while (0)
59 #else
60 #define DPRINTF(fmt, args...)						\
61 	do { } while (0)
62 #endif
63 
64 int	udpencap_enable = 1;	/* enabled by default */
65 int	udpencap_port = 4500;	/* triggers decapsulation */
66 
67 /*
68  * Loop over a tdb chain, taking into consideration protocol tunneling. The
69  * fourth argument is set if the first encapsulation header is already in
70  * place.
71  */
72 int
73 ipsp_process_packet(struct mbuf *m, struct tdb *tdb, int af, int tunalready)
74 {
75 	int hlen, off, error;
76 #ifdef INET6
77 	struct ip6_ext ip6e;
78 	int nxt;
79 	int dstopt = 0;
80 #endif
81 
82 	int setdf = 0;
83 	struct ip *ip;
84 #ifdef INET6
85 	struct ip6_hdr *ip6;
86 #endif /* INET6 */
87 
88 #ifdef ENCDEBUG
89 	char buf[INET6_ADDRSTRLEN];
90 #endif
91 
92 	/* Check that the transform is allowed by the administrator. */
93 	if ((tdb->tdb_sproto == IPPROTO_ESP && !esp_enable) ||
94 	    (tdb->tdb_sproto == IPPROTO_AH && !ah_enable) ||
95 	    (tdb->tdb_sproto == IPPROTO_IPCOMP && !ipcomp_enable)) {
96 		DPRINTF("IPsec outbound packet dropped due to policy "
97 		    "(check your sysctls)");
98 		error = EHOSTUNREACH;
99 		goto drop;
100 	}
101 
102 	/* Sanity check. */
103 	if (!tdb->tdb_xform) {
104 		DPRINTF("uninitialized TDB");
105 		error = EHOSTUNREACH;
106 		goto drop;
107 	}
108 
109 	/* Check if the SPI is invalid. */
110 	if (tdb->tdb_flags & TDBF_INVALID) {
111 		DPRINTF("attempt to use invalid SA %s/%08x/%u",
112 		    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
113 		    ntohl(tdb->tdb_spi), tdb->tdb_sproto);
114 		error = ENXIO;
115 		goto drop;
116 	}
117 
118 	/* Check that the network protocol is supported */
119 	switch (tdb->tdb_dst.sa.sa_family) {
120 	case AF_INET:
121 		break;
122 
123 #ifdef INET6
124 	case AF_INET6:
125 		break;
126 #endif /* INET6 */
127 
128 	default:
129 		DPRINTF("attempt to use SA %s/%08x/%u for protocol family %d",
130 		    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
131 		    ntohl(tdb->tdb_spi), tdb->tdb_sproto,
132 		    tdb->tdb_dst.sa.sa_family);
133 		error = EPFNOSUPPORT;
134 		goto drop;
135 	}
136 
137 	/*
138 	 * Register first use if applicable, setup relevant expiration timer.
139 	 */
140 	if (tdb->tdb_first_use == 0) {
141 		tdb->tdb_first_use = gettime();
142 		if (tdb->tdb_flags & TDBF_FIRSTUSE) {
143 			if (timeout_add_sec(&tdb->tdb_first_tmo,
144 			    tdb->tdb_exp_first_use))
145 				tdb_ref(tdb);
146 		}
147 		if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) {
148 			if (timeout_add_sec(&tdb->tdb_sfirst_tmo,
149 			    tdb->tdb_soft_first_use))
150 				tdb_ref(tdb);
151 		}
152 	}
153 
154 	/*
155 	 * Check for tunneling if we don't have the first header in place.
156 	 * When doing Ethernet-over-IP, we are handed an already-encapsulated
157 	 * frame, so we don't need to re-encapsulate.
158 	 */
159 	if (tunalready == 0) {
160 		/*
161 		 * If the target protocol family is different, we know we'll be
162 		 * doing tunneling.
163 		 */
164 		if (af == tdb->tdb_dst.sa.sa_family) {
165 			switch (af) {
166 			case AF_INET:
167 				hlen = sizeof(struct ip);
168 				break;
169 #ifdef INET6
170 			case AF_INET6:
171 				hlen = sizeof(struct ip6_hdr);
172 				break;
173 #endif /* INET6 */
174 			}
175 
176 			/* Bring the network header in the first mbuf. */
177 			if (m->m_len < hlen) {
178 				if ((m = m_pullup(m, hlen)) == NULL) {
179 					error = ENOBUFS;
180 					goto drop;
181 				}
182 			}
183 
184 			if (af == AF_INET) {
185 				ip = mtod(m, struct ip *);
186 
187 				/*
188 				 * This is not a bridge packet, remember if we
189 				 * had IP_DF.
190 				 */
191 				setdf = ip->ip_off & htons(IP_DF);
192 			}
193 
194 #ifdef INET6
195 			if (af == AF_INET6)
196 				ip6 = mtod(m, struct ip6_hdr *);
197 #endif /* INET6 */
198 		}
199 
200 		/* Do the appropriate encapsulation, if necessary. */
201 		if ((tdb->tdb_dst.sa.sa_family != af) || /* PF mismatch */
202 		    (tdb->tdb_flags & TDBF_TUNNELING) || /* Tunneling needed */
203 		    (tdb->tdb_xform->xf_type == XF_IP4) || /* ditto */
204 		    ((tdb->tdb_dst.sa.sa_family == AF_INET) &&
205 		     (tdb->tdb_dst.sin.sin_addr.s_addr != INADDR_ANY) &&
206 		     (tdb->tdb_dst.sin.sin_addr.s_addr != ip->ip_dst.s_addr)) ||
207 #ifdef INET6
208 		    ((tdb->tdb_dst.sa.sa_family == AF_INET6) &&
209 		     (!IN6_IS_ADDR_UNSPECIFIED(&tdb->tdb_dst.sin6.sin6_addr)) &&
210 		     (!IN6_ARE_ADDR_EQUAL(&tdb->tdb_dst.sin6.sin6_addr,
211 		      &ip6->ip6_dst))) ||
212 #endif /* INET6 */
213 		    0) {
214 			/* Fix IPv4 header checksum and length. */
215 			if (af == AF_INET) {
216 				if (m->m_len < sizeof(struct ip))
217 					if ((m = m_pullup(m,
218 					    sizeof(struct ip))) == NULL) {
219 						error = ENOBUFS;
220 						goto drop;
221 					}
222 
223 				ip = mtod(m, struct ip *);
224 				ip->ip_len = htons(m->m_pkthdr.len);
225 				ip->ip_sum = 0;
226 				ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
227 			}
228 
229 #ifdef INET6
230 			/* Fix IPv6 header payload length. */
231 			if (af == AF_INET6) {
232 				if (m->m_len < sizeof(struct ip6_hdr))
233 					if ((m = m_pullup(m,
234 					    sizeof(struct ip6_hdr))) == NULL) {
235 						error = ENOBUFS;
236 						goto drop;
237 					}
238 
239 				if (m->m_pkthdr.len - sizeof(*ip6) >
240 				    IPV6_MAXPACKET) {
241 					/* No jumbogram support. */
242 					error = ENXIO;	/*?*/
243 					goto drop;
244 				}
245 				ip6 = mtod(m, struct ip6_hdr *);
246 				ip6->ip6_plen = htons(m->m_pkthdr.len
247 				    - sizeof(*ip6));
248 			}
249 #endif /* INET6 */
250 
251 			/* Encapsulate -- m may be changed or set to NULL. */
252 			error = ipip_output(&m, tdb);
253 			if ((m == NULL) && (!error))
254 				error = EFAULT;
255 			if (error)
256 				goto drop;
257 
258 			if (tdb->tdb_dst.sa.sa_family == AF_INET && setdf) {
259 				if (m->m_len < sizeof(struct ip))
260 					if ((m = m_pullup(m,
261 					    sizeof(struct ip))) == NULL) {
262 						error = ENOBUFS;
263 						goto drop;
264 					}
265 
266 				ip = mtod(m, struct ip *);
267 				ip->ip_off |= htons(IP_DF);
268 			}
269 
270 			/* Remember that we appended a tunnel header. */
271 			mtx_enter(&tdb->tdb_mtx);
272 			tdb->tdb_flags |= TDBF_USEDTUNNEL;
273 			mtx_leave(&tdb->tdb_mtx);
274 		}
275 	}
276 
277 	/*
278 	 * If this is just an IP-IP TDB and we're told there's already an
279 	 * encapsulation header or ipip_output() has encapsulted it, move on.
280 	 */
281 	if (tdb->tdb_xform->xf_type == XF_IP4)
282 		return ipsp_process_done(m, tdb);
283 
284 	/* Extract some information off the headers. */
285 	switch (tdb->tdb_dst.sa.sa_family) {
286 	case AF_INET:
287 		ip = mtod(m, struct ip *);
288 		hlen = ip->ip_hl << 2;
289 		off = offsetof(struct ip, ip_p);
290 		break;
291 
292 #ifdef INET6
293 	case AF_INET6:
294 		ip6 = mtod(m, struct ip6_hdr *);
295 		hlen = sizeof(struct ip6_hdr);
296 		off = offsetof(struct ip6_hdr, ip6_nxt);
297 		nxt = ip6->ip6_nxt;
298 		/*
299 		 * chase mbuf chain to find the appropriate place to
300 		 * put AH/ESP/IPcomp header.
301 		 *	IPv6 hbh dest1 rthdr ah* [esp* dest2 payload]
302 		 */
303 		do {
304 			switch (nxt) {
305 			case IPPROTO_AH:
306 			case IPPROTO_ESP:
307 			case IPPROTO_IPCOMP:
308 				/*
309 				 * we should not skip security header added
310 				 * beforehand.
311 				 */
312 				goto exitip6loop;
313 
314 			case IPPROTO_HOPOPTS:
315 			case IPPROTO_DSTOPTS:
316 			case IPPROTO_ROUTING:
317 				/*
318 				 * if we see 2nd destination option header,
319 				 * we should stop there.
320 				 */
321 				if (nxt == IPPROTO_DSTOPTS && dstopt)
322 					goto exitip6loop;
323 
324 				if (nxt == IPPROTO_DSTOPTS) {
325 					/*
326 					 * seen 1st or 2nd destination option.
327 					 * next time we see one, it must be 2nd.
328 					 */
329 					dstopt = 1;
330 				} else if (nxt == IPPROTO_ROUTING) {
331 					/*
332 					 * if we see destination option next
333 					 * time, it must be dest2.
334 					 */
335 					dstopt = 2;
336 				}
337 				if (m->m_pkthdr.len < hlen + sizeof(ip6e)) {
338 					error = EINVAL;
339 					goto drop;
340 				}
341 				/* skip this header */
342 				m_copydata(m, hlen, sizeof(ip6e),
343 				    (caddr_t)&ip6e);
344 				nxt = ip6e.ip6e_nxt;
345 				off = hlen + offsetof(struct ip6_ext, ip6e_nxt);
346 				/*
347 				 * we will never see nxt == IPPROTO_AH
348 				 * so it is safe to omit AH case.
349 				 */
350 				hlen += (ip6e.ip6e_len + 1) << 3;
351 				break;
352 			default:
353 				goto exitip6loop;
354 			}
355 		} while (hlen < m->m_pkthdr.len);
356 	exitip6loop:
357 		break;
358 #endif /* INET6 */
359 	default:
360 		error = EPFNOSUPPORT;
361 		goto drop;
362 	}
363 
364 	if (m->m_pkthdr.len < hlen) {
365 		error = EINVAL;
366 		goto drop;
367 	}
368 
369 	ipsecstat_add(ipsec_ouncompbytes, m->m_pkthdr.len);
370 	tdb->tdb_ouncompbytes += m->m_pkthdr.len;
371 
372 	/* Non expansion policy for IPCOMP */
373 	if (tdb->tdb_sproto == IPPROTO_IPCOMP) {
374 		if ((m->m_pkthdr.len - hlen) < tdb->tdb_compalgxform->minlen) {
375 			/* No need to compress, leave the packet untouched */
376 			ipcompstat_inc(ipcomps_minlen);
377 			return ipsp_process_done(m, tdb);
378 		}
379 	}
380 
381 	/* Invoke the IPsec transform. */
382 	return (*(tdb->tdb_xform->xf_output))(m, tdb, hlen, off);
383 
384  drop:
385 	m_freem(m);
386 	return error;
387 }
388 
389 /*
390  * Called by the IPsec output transform callbacks, to transmit the packet
391  * or do further processing, as necessary.
392  */
393 int
394 ipsp_process_done(struct mbuf *m, struct tdb *tdb)
395 {
396 	struct ip *ip;
397 #ifdef INET6
398 	struct ip6_hdr *ip6;
399 #endif /* INET6 */
400 	struct tdb *tdbo;
401 	struct tdb_ident *tdbi;
402 	struct m_tag *mtag;
403 	int roff, error;
404 
405 	NET_ASSERT_LOCKED();
406 
407 	tdb->tdb_last_used = gettime();
408 
409 	if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0) {
410 		struct mbuf *mi;
411 		struct udphdr *uh;
412 		int iphlen;
413 
414 		if (!udpencap_enable || !udpencap_port) {
415 			error = ENXIO;
416 			goto drop;
417 		}
418 
419 		switch (tdb->tdb_dst.sa.sa_family) {
420 		case AF_INET:
421 			iphlen = sizeof(struct ip);
422 			break;
423 #ifdef INET6
424 		case AF_INET6:
425 			iphlen = sizeof(struct ip6_hdr);
426 			break;
427 #endif /* INET6 */
428 		default:
429 			DPRINTF("unknown protocol family (%d)",
430 			    tdb->tdb_dst.sa.sa_family);
431 			error = EPFNOSUPPORT;
432 			goto drop;
433 		}
434 
435 		mi = m_makespace(m, iphlen, sizeof(struct udphdr), &roff);
436 		if (mi == NULL) {
437 			error = ENOMEM;
438 			goto drop;
439 		}
440 		uh = (struct udphdr *)(mtod(mi, caddr_t) + roff);
441 		uh->uh_sport = uh->uh_dport = htons(udpencap_port);
442 		if (tdb->tdb_udpencap_port)
443 			uh->uh_dport = tdb->tdb_udpencap_port;
444 
445 		uh->uh_ulen = htons(m->m_pkthdr.len - iphlen);
446 		uh->uh_sum = 0;
447 #ifdef INET6
448 		if (tdb->tdb_dst.sa.sa_family == AF_INET6)
449 			m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
450 #endif /* INET6 */
451 		espstat_inc(esps_udpencout);
452 	}
453 
454 	switch (tdb->tdb_dst.sa.sa_family) {
455 	case AF_INET:
456 		/* Fix the header length, for AH processing. */
457 		ip = mtod(m, struct ip *);
458 		ip->ip_len = htons(m->m_pkthdr.len);
459 		if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0)
460 			ip->ip_p = IPPROTO_UDP;
461 		break;
462 
463 #ifdef INET6
464 	case AF_INET6:
465 		/* Fix the header length, for AH processing. */
466 		if (m->m_pkthdr.len < sizeof(*ip6)) {
467 			error = ENXIO;
468 			goto drop;
469 		}
470 		if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) {
471 			/* No jumbogram support. */
472 			error = ENXIO;
473 			goto drop;
474 		}
475 		ip6 = mtod(m, struct ip6_hdr *);
476 		ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6));
477 		if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0)
478 			ip6->ip6_nxt = IPPROTO_UDP;
479 		break;
480 #endif /* INET6 */
481 
482 	default:
483 		DPRINTF("unknown protocol family (%d)",
484 		    tdb->tdb_dst.sa.sa_family);
485 		error = EPFNOSUPPORT;
486 		goto drop;
487 	}
488 
489 	/*
490 	 * Add a record of what we've done or what needs to be done to the
491 	 * packet.
492 	 */
493 	mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE, sizeof(struct tdb_ident),
494 	    M_NOWAIT);
495 	if (mtag == NULL) {
496 		DPRINTF("could not allocate packet tag");
497 		error = ENOMEM;
498 		goto drop;
499 	}
500 
501 	tdbi = (struct tdb_ident *)(mtag + 1);
502 	tdbi->dst = tdb->tdb_dst;
503 	tdbi->proto = tdb->tdb_sproto;
504 	tdbi->spi = tdb->tdb_spi;
505 	tdbi->rdomain = tdb->tdb_rdomain;
506 
507 	m_tag_prepend(m, mtag);
508 
509 	ipsecstat_pkt(ipsec_opackets, ipsec_obytes, m->m_pkthdr.len);
510 	tdb->tdb_opackets++;
511 	tdb->tdb_obytes += m->m_pkthdr.len;
512 
513 	/* If there's another (bundled) TDB to apply, do so. */
514 	tdbo = tdb_ref(tdb->tdb_onext);
515 	if (tdbo != NULL) {
516 		error = ipsp_process_packet(m, tdbo,
517 		    tdb->tdb_dst.sa.sa_family, 0);
518 		tdb_unref(tdbo);
519 		return error;
520 	}
521 
522 #if NPF > 0
523 	/* Add pf tag if requested. */
524 	pf_tag_packet(m, tdb->tdb_tag, -1);
525 	pf_pkt_addr_changed(m);
526 #endif
527 	if (tdb->tdb_rdomain != tdb->tdb_rdomain_post)
528 		m->m_pkthdr.ph_rtableid = tdb->tdb_rdomain_post;
529 
530 	/*
531 	 * We're done with IPsec processing, transmit the packet using the
532 	 * appropriate network protocol (IP or IPv6). SPD lookup will be
533 	 * performed again there.
534 	 */
535 	switch (tdb->tdb_dst.sa.sa_family) {
536 	case AF_INET:
537 		error = ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL, 0);
538 		break;
539 #ifdef INET6
540 	case AF_INET6:
541 		/*
542 		 * We don't need massage, IPv6 header fields are always in
543 		 * net endian.
544 		 */
545 		error = ip6_output(m, NULL, NULL, 0, NULL, NULL);
546 		break;
547 #endif /* INET6 */
548 	default:
549 		error = EPFNOSUPPORT;
550 		break;
551 	}
552 	return error;
553 
554  drop:
555 	m_freem(m);
556 	return error;
557 }
558 
559 ssize_t
560 ipsec_hdrsz(struct tdb *tdbp)
561 {
562 	ssize_t adjust;
563 
564 	switch (tdbp->tdb_sproto) {
565 	case IPPROTO_IPIP:
566 		adjust = 0;
567 		break;
568 
569 	case IPPROTO_ESP:
570 		if (tdbp->tdb_encalgxform == NULL)
571 			return (-1);
572 
573 		/* Header length */
574 		adjust = 2 * sizeof(u_int32_t) + tdbp->tdb_ivlen;
575 		if (tdbp->tdb_flags & TDBF_UDPENCAP)
576 			adjust += sizeof(struct udphdr);
577 		/* Authenticator */
578 		if (tdbp->tdb_authalgxform != NULL)
579 			adjust += tdbp->tdb_authalgxform->authsize;
580 		/* Padding */
581 		adjust += MAX(4, tdbp->tdb_encalgxform->blocksize);
582 		break;
583 
584 	case IPPROTO_AH:
585 		if (tdbp->tdb_authalgxform == NULL)
586 			return (-1);
587 
588 		adjust = AH_FLENGTH + sizeof(u_int32_t);
589 		adjust += tdbp->tdb_authalgxform->authsize;
590 		break;
591 
592 	default:
593 		return (-1);
594 	}
595 
596 	if (!(tdbp->tdb_flags & TDBF_TUNNELING) &&
597 	    !(tdbp->tdb_flags & TDBF_USEDTUNNEL))
598 		return (adjust);
599 
600 	switch (tdbp->tdb_dst.sa.sa_family) {
601 	case AF_INET:
602 		adjust += sizeof(struct ip);
603 		break;
604 #ifdef INET6
605 	case AF_INET6:
606 		adjust += sizeof(struct ip6_hdr);
607 		break;
608 #endif /* INET6 */
609 	}
610 
611 	return (adjust);
612 }
613 
614 void
615 ipsec_adjust_mtu(struct mbuf *m, u_int32_t mtu)
616 {
617 	struct tdb_ident *tdbi;
618 	struct tdb *tdbp;
619 	struct m_tag *mtag;
620 	ssize_t adjust;
621 
622 	NET_ASSERT_LOCKED();
623 
624 	for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, NULL); mtag;
625 	     mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, mtag)) {
626 		tdbi = (struct tdb_ident *)(mtag + 1);
627 		tdbp = gettdb(tdbi->rdomain, tdbi->spi, &tdbi->dst,
628 		    tdbi->proto);
629 		if (tdbp == NULL)
630 			break;
631 
632 		if ((adjust = ipsec_hdrsz(tdbp)) == -1) {
633 			tdb_unref(tdbp);
634 			break;
635 		}
636 
637 		mtu -= adjust;
638 		tdbp->tdb_mtu = mtu;
639 		tdbp->tdb_mtutimeout = gettime() + ip_mtudisc_timeout;
640 		DPRINTF("spi %08x mtu %d adjust %ld mbuf %p",
641 		    ntohl(tdbp->tdb_spi), tdbp->tdb_mtu, adjust, m);
642 		tdb_unref(tdbp);
643 	}
644 }
645