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