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