xref: /openbsd-src/sys/netinet/ipsec_output.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /*	$OpenBSD: ipsec_output.c,v 1.50 2013/10/24 11:31:43 mpi 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 #if NPF > 0
36 #include <net/pfvar.h>
37 #endif
38 
39 #ifdef INET
40 #include <netinet/in.h>
41 #include <netinet/in_systm.h>
42 #include <netinet/ip.h>
43 #include <netinet/in_pcb.h>
44 #include <netinet/ip_var.h>
45 #endif /* INET */
46 
47 #ifdef INET6
48 #ifndef INET
49 #include <netinet/in.h>
50 #endif
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 			/* No need to compress, leave the packet untouched */
378 			ipcompstat.ipcomps_minlen++;
379 			return ipsp_process_done(m, tdb);
380 		}
381 	}
382 
383 	/* Invoke the IPsec transform. */
384 	return (*(tdb->tdb_xform->xf_output))(m, tdb, NULL, i, off);
385 }
386 
387 /*
388  * Called by the IPsec output transform callbacks, to transmit the packet
389  * or do further processing, as necessary.
390  */
391 int
392 ipsp_process_done(struct mbuf *m, struct tdb *tdb)
393 {
394 #ifdef INET
395 	struct ip *ip;
396 #endif /* INET */
397 
398 #ifdef INET6
399 	struct ip6_hdr *ip6;
400 #endif /* INET6 */
401 
402 	struct tdb_ident *tdbi;
403 	struct m_tag *mtag;
404 
405 	tdb->tdb_last_used = time_second;
406 
407 	if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0) {
408 		struct mbuf *mi;
409 		struct udphdr *uh;
410 
411 		if (!udpencap_enable || !udpencap_port) {
412 			m_freem(m);
413 			return ENXIO;
414 		}
415 		mi = m_inject(m, sizeof(struct ip), sizeof(struct udphdr),
416 		    M_DONTWAIT);
417 		if (mi == NULL) {
418 			m_freem(m);
419 			return ENOMEM;
420 		}
421 		uh = mtod(mi, struct udphdr *);
422 		uh->uh_sport = uh->uh_dport = htons(udpencap_port);
423 		if (tdb->tdb_udpencap_port)
424 			uh->uh_dport = tdb->tdb_udpencap_port;
425 
426 		uh->uh_ulen = htons(m->m_pkthdr.len - sizeof(struct ip));
427 		uh->uh_sum = 0;
428 		espstat.esps_udpencout++;
429 	}
430 
431 	switch (tdb->tdb_dst.sa.sa_family) {
432 #ifdef INET
433 	case AF_INET:
434 		/* Fix the header length, for AH processing. */
435 		ip = mtod(m, struct ip *);
436 		ip->ip_len = htons(m->m_pkthdr.len);
437 		if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0)
438 			ip->ip_p = IPPROTO_UDP;
439 		break;
440 #endif /* INET */
441 
442 #ifdef INET6
443 	case AF_INET6:
444 		/* Fix the header length, for AH processing. */
445 		if (m->m_pkthdr.len < sizeof(*ip6)) {
446 			m_freem(m);
447 			return ENXIO;
448 		}
449 		if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) {
450 			/* No jumbogram support. */
451 			m_freem(m);
452 			return ENXIO;
453 		}
454 		ip6 = mtod(m, struct ip6_hdr *);
455 		ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6));
456 		if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0)
457 			ip6->ip6_nxt = IPPROTO_UDP;
458 		break;
459 #endif /* INET6 */
460 
461 	default:
462 		m_freem(m);
463 		DPRINTF(("ipsp_process_done(): unknown protocol family (%d)\n",
464 		    tdb->tdb_dst.sa.sa_family));
465 		return ENXIO;
466 	}
467 
468 	/*
469 	 * Add a record of what we've done or what needs to be done to the
470 	 * packet.
471 	 */
472 	if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0)
473 		mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE,
474 		    sizeof(struct tdb_ident),
475 		    M_NOWAIT);
476 	else
477 		mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED,
478 		    sizeof(struct tdb_ident), M_NOWAIT);
479 
480 	if (mtag == NULL) {
481 		m_freem(m);
482 		DPRINTF(("ipsp_process_done(): could not allocate packet "
483 		    "tag\n"));
484 		return ENOMEM;
485 	}
486 
487 	tdbi = (struct tdb_ident *)(mtag + 1);
488 	bcopy(&tdb->tdb_dst, &tdbi->dst, sizeof(union sockaddr_union));
489 	tdbi->proto = tdb->tdb_sproto;
490 	tdbi->spi = tdb->tdb_spi;
491 	tdbi->rdomain = tdb->tdb_rdomain;
492 
493 	m_tag_prepend(m, mtag);
494 
495 	/* If there's another (bundled) TDB to apply, do so. */
496 	if (tdb->tdb_onext)
497 		return ipsp_process_packet(m, tdb->tdb_onext,
498 		    tdb->tdb_dst.sa.sa_family, 0);
499 
500 #if NPF > 0
501 	/* Add pf tag if requested. */
502 	pf_tag_packet(m, tdb->tdb_tag, -1);
503 	pf_pkt_addr_changed(m);
504 #endif
505 
506 	/*
507 	 * We're done with IPsec processing, transmit the packet using the
508 	 * appropriate network protocol (IP or IPv6). SPD lookup will be
509 	 * performed again there.
510 	 */
511 	switch (tdb->tdb_dst.sa.sa_family) {
512 #ifdef INET
513 	case AF_INET:
514 		return ip_output(m, (void *)NULL, (void *)NULL, IP_RAWOUTPUT, (void *)NULL, (void *)NULL);
515 #endif /* INET */
516 
517 #ifdef INET6
518 	case AF_INET6:
519 		/*
520 		 * We don't need massage, IPv6 header fields are always in
521 		 * net endian.
522 		 */
523 		return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
524 #endif /* INET6 */
525 	}
526 	return EINVAL; /* Not reached. */
527 }
528 
529 ssize_t
530 ipsec_hdrsz(struct tdb *tdbp)
531 {
532 	ssize_t adjust;
533 
534 	switch (tdbp->tdb_sproto) {
535 	case IPPROTO_IPIP:
536 		adjust = 0;
537 		break;
538 
539 	case IPPROTO_ESP:
540 		if (tdbp->tdb_encalgxform == NULL)
541 			return (-1);
542 
543 		/* Header length */
544 		adjust = 2 * sizeof(u_int32_t) + tdbp->tdb_ivlen;
545 		if (tdbp->tdb_flags & TDBF_UDPENCAP)
546 			adjust += sizeof(struct udphdr);
547 		/* Authenticator */
548 		if (tdbp->tdb_authalgxform != NULL)
549 			adjust += tdbp->tdb_authalgxform->authsize;
550 		/* Padding */
551 		adjust += MAX(4, tdbp->tdb_encalgxform->blocksize);
552 		break;
553 
554 	case IPPROTO_AH:
555 		if (tdbp->tdb_authalgxform == NULL)
556 			return (-1);
557 
558 		adjust = AH_FLENGTH + sizeof(u_int32_t);
559 		adjust += tdbp->tdb_authalgxform->authsize;
560 		break;
561 
562 	default:
563 		return (-1);
564 	}
565 
566 	if (!(tdbp->tdb_flags & TDBF_TUNNELING) &&
567 	    !(tdbp->tdb_flags & TDBF_USEDTUNNEL))
568 		return (adjust);
569 
570 	switch (tdbp->tdb_dst.sa.sa_family) {
571 #ifdef INET
572 	case AF_INET:
573 		adjust += sizeof(struct ip);
574 		break;
575 #endif /* INET */
576 #ifdef INET6
577 	case AF_INET6:
578 		adjust += sizeof(struct ip6_hdr);
579 		break;
580 #endif /* INET6 */
581 	}
582 
583 	return (adjust);
584 }
585 
586 void
587 ipsec_adjust_mtu(struct mbuf *m, u_int32_t mtu)
588 {
589 	struct tdb_ident *tdbi;
590 	struct tdb *tdbp;
591 	struct m_tag *mtag;
592 	ssize_t adjust;
593 	int s;
594 
595 	s = splsoftnet();
596 
597 	for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, NULL); mtag;
598 	     mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, mtag)) {
599 		tdbi = (struct tdb_ident *)(mtag + 1);
600 		tdbp = gettdb(tdbi->rdomain, tdbi->spi, &tdbi->dst,
601 		    tdbi->proto);
602 		if (tdbp == NULL)
603 			break;
604 
605 		if ((adjust = ipsec_hdrsz(tdbp)) == -1)
606 			break;
607 
608 		mtu -= adjust;
609 		tdbp->tdb_mtu = mtu;
610 		tdbp->tdb_mtutimeout = time_second + ip_mtudisc_timeout;
611 		DPRINTF(("ipsec_adjust_mtu: "
612 		    "spi %08x mtu %d adjust %d mbuf %p\n",
613 		    ntohl(tdbp->tdb_spi), tdbp->tdb_mtu,
614 		    adjust, m));
615 	}
616 
617 	splx(s);
618 }
619