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