xref: /openbsd/sys/netinet/ip_ah.c (revision 5a38ef86)
1 /*	$OpenBSD: ip_ah.c,v 1.169 2021/12/11 16:33:46 bluhm Exp $ */
2 /*
3  * The authors of this code are John Ioannidis (ji@tla.org),
4  * Angelos D. Keromytis (kermit@csd.uch.gr) and
5  * Niels Provos (provos@physnet.uni-hamburg.de).
6  *
7  * The original version of this code was written by John Ioannidis
8  * for BSD/OS in Athens, Greece, in November 1995.
9  *
10  * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
11  * by Angelos D. Keromytis.
12  *
13  * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
14  * and Niels Provos.
15  *
16  * Additional features in 1999 by Angelos D. Keromytis and Niklas Hallqvist.
17  *
18  * Copyright (c) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
19  * Angelos D. Keromytis and Niels Provos.
20  * Copyright (c) 1999 Niklas Hallqvist.
21  * Copyright (c) 2001 Angelos D. Keromytis.
22  *
23  * Permission to use, copy, and modify this software with or without fee
24  * is hereby granted, provided that this entire notice is included in
25  * all copies of any software which is or includes a copy or
26  * modification of this software.
27  * You may use this code under the GNU public license if you so wish. Please
28  * contribute changes back to the authors under this freer than GPL license
29  * so that we may further the use of strong encryption without limitations to
30  * all.
31  *
32  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
33  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
34  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
35  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
36  * PURPOSE.
37  */
38 
39 #include "pfsync.h"
40 
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/mbuf.h>
44 #include <sys/socket.h>
45 
46 #include <net/if.h>
47 #include <net/if_var.h>
48 #include <net/bpf.h>
49 
50 #include <netinet/in.h>
51 #include <netinet/ip.h>
52 #include <netinet/ip_var.h>
53 
54 #ifdef INET6
55 #include <netinet/ip6.h>
56 #endif /* INET6 */
57 
58 #include <netinet/ip_ipsp.h>
59 #include <netinet/ip_ah.h>
60 #include <net/pfkeyv2.h>
61 #include <net/if_enc.h>
62 
63 #if NPFSYNC > 0
64 #include <net/pfvar.h>
65 #include <net/if_pfsync.h>
66 #endif /* NPFSYNC > 0 */
67 
68 #include <crypto/cryptodev.h>
69 #include <crypto/xform.h>
70 
71 #include "bpfilter.h"
72 
73 #ifdef ENCDEBUG
74 #define DPRINTF(fmt, args...)						\
75 	do {								\
76 		if (encdebug)						\
77 			printf("%s: " fmt "\n", __func__, ## args);	\
78 	} while (0)
79 #else
80 #define DPRINTF(fmt, args...)						\
81 	do { } while (0)
82 #endif
83 
84 int	ah_massage_headers(struct mbuf **, int, int, int, int);
85 
86 const unsigned char ipseczeroes[IPSEC_ZEROES_SIZE]; /* zeroes! */
87 
88 
89 /*
90  * ah_attach() is called from the transformation initialization code.
91  */
92 int
93 ah_attach(void)
94 {
95 	return 0;
96 }
97 
98 /*
99  * ah_init() is called when an SPI is being set up.
100  */
101 int
102 ah_init(struct tdb *tdbp, const struct xformsw *xsp, struct ipsecinit *ii)
103 {
104 	const struct auth_hash *thash = NULL;
105 	struct cryptoini cria, crin;
106 	int error;
107 
108 	/* Authentication operation. */
109 	switch (ii->ii_authalg) {
110 	case SADB_AALG_MD5HMAC:
111 		thash = &auth_hash_hmac_md5_96;
112 		break;
113 
114 	case SADB_AALG_SHA1HMAC:
115 		thash = &auth_hash_hmac_sha1_96;
116 		break;
117 
118 	case SADB_X_AALG_RIPEMD160HMAC:
119 		thash = &auth_hash_hmac_ripemd_160_96;
120 		break;
121 
122 	case SADB_X_AALG_SHA2_256:
123 		thash = &auth_hash_hmac_sha2_256_128;
124 		break;
125 
126 	case SADB_X_AALG_SHA2_384:
127 		thash = &auth_hash_hmac_sha2_384_192;
128 		break;
129 
130 	case SADB_X_AALG_SHA2_512:
131 		thash = &auth_hash_hmac_sha2_512_256;
132 		break;
133 
134 	default:
135 		DPRINTF("unsupported authentication algorithm %d specified",
136 		    ii->ii_authalg);
137 		return EINVAL;
138 	}
139 
140 	if (ii->ii_authkeylen != thash->keysize && thash->keysize != 0) {
141 		DPRINTF("keylength %d doesn't match algorithm %s keysize (%d)",
142 		    ii->ii_authkeylen, thash->name, thash->keysize);
143 		return EINVAL;
144 	}
145 
146 	tdbp->tdb_xform = xsp;
147 	tdbp->tdb_authalgxform = thash;
148 	tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL;
149 
150 	DPRINTF("initialized TDB with hash algorithm %s", thash->name);
151 
152 	tdbp->tdb_amxkeylen = ii->ii_authkeylen;
153 	tdbp->tdb_amxkey = malloc(tdbp->tdb_amxkeylen, M_XDATA, M_WAITOK);
154 
155 	memcpy(tdbp->tdb_amxkey, ii->ii_authkey, tdbp->tdb_amxkeylen);
156 
157 	/* Initialize crypto session. */
158 	memset(&cria, 0, sizeof(cria));
159 	cria.cri_alg = tdbp->tdb_authalgxform->type;
160 	cria.cri_klen = ii->ii_authkeylen * 8;
161 	cria.cri_key = ii->ii_authkey;
162 
163 	if ((tdbp->tdb_wnd > 0) && (tdbp->tdb_flags & TDBF_ESN)) {
164 		memset(&crin, 0, sizeof(crin));
165 		crin.cri_alg = CRYPTO_ESN;
166 		cria.cri_next = &crin;
167 	}
168 
169 	KERNEL_LOCK();
170 	error = crypto_newsession(&tdbp->tdb_cryptoid, &cria, 0);
171 	KERNEL_UNLOCK();
172 	return error;
173 }
174 
175 /*
176  * Paranoia.
177  */
178 int
179 ah_zeroize(struct tdb *tdbp)
180 {
181 	int error;
182 
183 	if (tdbp->tdb_amxkey) {
184 		explicit_bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
185 		free(tdbp->tdb_amxkey, M_XDATA, tdbp->tdb_amxkeylen);
186 		tdbp->tdb_amxkey = NULL;
187 	}
188 
189 	KERNEL_LOCK();
190 	error = crypto_freesession(tdbp->tdb_cryptoid);
191 	KERNEL_UNLOCK();
192 	tdbp->tdb_cryptoid = 0;
193 	return error;
194 }
195 
196 /*
197  * Massage IPv4/IPv6 headers for AH processing.
198  */
199 int
200 ah_massage_headers(struct mbuf **mp, int af, int skip, int alg, int out)
201 {
202 	struct mbuf *m = *mp;
203 	unsigned char *ptr;
204 	int off, count, error;
205 	struct ip *ip;
206 #ifdef INET6
207 	struct ip6_ext *ip6e;
208 	struct ip6_hdr ip6;
209 	int ad, alloc, nxt, noff;
210 #endif /* INET6 */
211 
212 	switch (af) {
213 	case AF_INET:
214 		/*
215 		 * This is the least painful way of dealing with IPv4 header
216 		 * and option processing -- just make sure they're in
217 		 * contiguous memory.
218 		 */
219 		m = *mp = m_pullup(m, skip);
220 		if (m == NULL) {
221 			DPRINTF("m_pullup() failed");
222 			ahstat_inc(ahs_hdrops);
223 			error = ENOBUFS;
224 			goto drop;
225 		}
226 
227 		/* Fix the IP header */
228 		ip = mtod(m, struct ip *);
229 		ip->ip_tos = 0;
230 		ip->ip_ttl = 0;
231 		ip->ip_sum = 0;
232 		ip->ip_off = 0;
233 
234 		ptr = mtod(m, unsigned char *);
235 
236 		/* IPv4 option processing */
237 		for (off = sizeof(struct ip); off < skip;) {
238 			if (ptr[off] != IPOPT_EOL && ptr[off] != IPOPT_NOP &&
239 			    off + 1 >= skip) {
240 				DPRINTF("illegal IPv4 option length "
241 				    "for option %d",
242 				    ptr[off]);
243 				ahstat_inc(ahs_hdrops);
244 				error = EINVAL;
245 				goto drop;
246 			}
247 
248 			switch (ptr[off]) {
249 			case IPOPT_EOL:
250 				off = skip;  /* End the loop. */
251 				break;
252 
253 			case IPOPT_NOP:
254 				off++;
255 				break;
256 
257 			case IPOPT_SECURITY:	/* 0x82 */
258 			case 0x85:	/* Extended security. */
259 			case 0x86:	/* Commercial security. */
260 			case 0x94:	/* Router alert */
261 			case 0x95:	/* RFC1770 */
262 				/* Sanity check for option length. */
263 				if (ptr[off + 1] < 2) {
264 					DPRINTF("illegal IPv4 option length "
265 					    "for option %d",
266 					    ptr[off]);
267 					ahstat_inc(ahs_hdrops);
268 					error = EINVAL;
269 					goto drop;
270 				}
271 
272 				off += ptr[off + 1];
273 				break;
274 
275 			case IPOPT_LSRR:
276 			case IPOPT_SSRR:
277 				/* Sanity check for option length. */
278 				if (ptr[off + 1] < 2) {
279 					DPRINTF("illegal IPv4 option length "
280 					    "for option %d",
281 					    ptr[off]);
282 					ahstat_inc(ahs_hdrops);
283 					error = EINVAL;
284 					goto drop;
285 				}
286 
287 				/*
288 				 * On output, if we have either of the
289 				 * source routing options, we should
290 				 * swap the destination address of the
291 				 * IP header with the last address
292 				 * specified in the option, as that is
293 				 * what the destination's IP header
294 				 * will look like.
295 				 */
296 				if (out &&
297 				    ptr[off + 1] >= 2 + sizeof(struct in_addr))
298 					memcpy(&ip->ip_dst,
299 					    ptr + off + ptr[off + 1] -
300 					    sizeof(struct in_addr),
301 					    sizeof(struct in_addr));
302 
303 				/* FALLTHROUGH */
304 			default:
305 				/* Sanity check for option length. */
306 				if (ptr[off + 1] < 2) {
307 					DPRINTF("illegal IPv4 option length "
308 					    "for option %d",
309 					    ptr[off]);
310 					ahstat_inc(ahs_hdrops);
311 					error = EINVAL;
312 					goto drop;
313 				}
314 
315 				/* Zeroize all other options. */
316 				count = ptr[off + 1];
317 				memset(ptr + off, 0, count);
318 				off += count;
319 				break;
320 			}
321 
322 			/* Sanity check. */
323 			if (off > skip)	{
324 				DPRINTF("malformed IPv4 options header");
325 				ahstat_inc(ahs_hdrops);
326 				error = EINVAL;
327 				goto drop;
328 			}
329 		}
330 
331 		break;
332 
333 #ifdef INET6
334 	case AF_INET6:  /* Ugly... */
335 		/* Copy and "cook" the IPv6 header. */
336 		m_copydata(m, 0, sizeof(ip6), &ip6);
337 
338 		/* We don't do IPv6 Jumbograms. */
339 		if (ip6.ip6_plen == 0) {
340 			DPRINTF("unsupported IPv6 jumbogram");
341 			ahstat_inc(ahs_hdrops);
342 			error = EMSGSIZE;
343 			goto drop;
344 		}
345 
346 		ip6.ip6_flow = 0;
347 		ip6.ip6_hlim = 0;
348 		ip6.ip6_vfc &= ~IPV6_VERSION_MASK;
349 		ip6.ip6_vfc |= IPV6_VERSION;
350 
351 		/* Scoped address handling. */
352 		if (IN6_IS_SCOPE_EMBED(&ip6.ip6_src))
353 			ip6.ip6_src.s6_addr16[1] = 0;
354 		if (IN6_IS_SCOPE_EMBED(&ip6.ip6_dst))
355 			ip6.ip6_dst.s6_addr16[1] = 0;
356 
357 		/* Done with IPv6 header. */
358 		error = m_copyback(m, 0, sizeof(struct ip6_hdr), &ip6,
359 		    M_NOWAIT);
360 		if (error) {
361 			DPRINTF("m_copyback no memory");
362 			ahstat_inc(ahs_hdrops);
363 			goto drop;
364 		}
365 
366 		/* Let's deal with the remaining headers (if any). */
367 		if (skip - sizeof(struct ip6_hdr) > 0) {
368 			if (m->m_len <= skip) {
369 				ptr = malloc(skip - sizeof(struct ip6_hdr),
370 				    M_XDATA, M_NOWAIT);
371 				if (ptr == NULL) {
372 					DPRINTF("failed to allocate "
373 					    "memory for IPv6 headers");
374 					ahstat_inc(ahs_hdrops);
375 					error = ENOBUFS;
376 					goto drop;
377 				}
378 
379 				/*
380 				 * Copy all the protocol headers after
381 				 * the IPv6 header.
382 				 */
383 				m_copydata(m, sizeof(struct ip6_hdr),
384 				    skip - sizeof(struct ip6_hdr), ptr);
385 				alloc = 1;
386 			} else {
387 				/* No need to allocate memory. */
388 				ptr = mtod(m, unsigned char *) +
389 				    sizeof(struct ip6_hdr);
390 				alloc = 0;
391 			}
392 		} else
393 			break;
394 
395 		nxt = ip6.ip6_nxt;  /* Next header type. */
396 
397 		for (off = 0; off < skip - sizeof(struct ip6_hdr);) {
398 			if (off + sizeof(struct ip6_ext) >
399 			    skip - sizeof(struct ip6_hdr))
400 				goto error6;
401 			ip6e = (struct ip6_ext *)(ptr + off);
402 
403 			switch (nxt) {
404 			case IPPROTO_HOPOPTS:
405 			case IPPROTO_DSTOPTS:
406 				noff = off + ((ip6e->ip6e_len + 1) << 3);
407 
408 				/* Sanity check. */
409 				if (noff > skip - sizeof(struct ip6_hdr))
410 					goto error6;
411 
412 				/*
413 				 * Zero out mutable options.
414 				 */
415 				for (count = off + sizeof(struct ip6_ext);
416 				     count < noff;) {
417 					if (ptr[count] == IP6OPT_PAD1) {
418 						count++;
419 						continue; /* Skip padding. */
420 					}
421 
422 					if (count + 2 > noff)
423 						goto error6;
424 					ad = ptr[count + 1] + 2;
425 					if (count + ad > noff)
426 						goto error6;
427 
428 					/* If mutable option, zeroize. */
429 					if (ptr[count] & IP6OPT_MUTABLE)
430 						memset(ptr + count, 0, ad);
431 
432 					count += ad;
433 				}
434 
435 				if (count != noff)
436 					goto error6;
437 				break;
438 
439 			case IPPROTO_ROUTING:
440 				/*
441 				 * Always include routing headers in
442 				 * computation.
443 				 */
444 			    {
445 				struct ip6_rthdr *rh;
446 
447 				rh = (struct ip6_rthdr *)(ptr + off);
448 				/*
449 				 * must adjust content to make it look like
450 				 * its final form (as seen at the final
451 				 * destination).
452 				 * we only know how to massage type 0 routing
453 				 * header.
454 				 */
455 				if (out && rh->ip6r_type == IPV6_RTHDR_TYPE_0) {
456 					struct ip6_rthdr0 *rh0;
457 					struct in6_addr *addr, finaldst;
458 					int i;
459 
460 					rh0 = (struct ip6_rthdr0 *)rh;
461 					addr = (struct in6_addr *)(rh0 + 1);
462 
463 					for (i = 0; i < rh0->ip6r0_segleft; i++)
464 						if (IN6_IS_SCOPE_EMBED(&addr[i]))
465 							addr[i].s6_addr16[1] = 0;
466 
467 					finaldst = addr[rh0->ip6r0_segleft - 1];
468 					memmove(&addr[1], &addr[0],
469 					    sizeof(struct in6_addr) *
470 					    (rh0->ip6r0_segleft - 1));
471 
472 					m_copydata(m, 0, sizeof(ip6), &ip6);
473 					addr[0] = ip6.ip6_dst;
474 					ip6.ip6_dst = finaldst;
475 					error = m_copyback(m, 0, sizeof(ip6),
476 					    &ip6, M_NOWAIT);
477 					if (error) {
478 						if (alloc)
479 							free(ptr, M_XDATA, 0);
480 						ahstat_inc(ahs_hdrops);
481 						goto drop;
482 					}
483 					rh0->ip6r0_segleft = 0;
484 				}
485 				break;
486 			    }
487 
488 			default:
489 				DPRINTF("unexpected IPv6 header type %d", off);
490 error6:
491 				if (alloc)
492 					free(ptr, M_XDATA, 0);
493 				ahstat_inc(ahs_hdrops);
494 				error = EINVAL;
495 				goto drop;
496 			}
497 
498 			/* Advance. */
499 			off += ((ip6e->ip6e_len + 1) << 3);
500 			nxt = ip6e->ip6e_nxt;
501 		}
502 
503 		/* Copyback and free, if we allocated. */
504 		if (alloc) {
505 			error = m_copyback(m, sizeof(struct ip6_hdr),
506 			    skip - sizeof(struct ip6_hdr), ptr, M_NOWAIT);
507 			free(ptr, M_XDATA, 0);
508 			if (error) {
509 				ahstat_inc(ahs_hdrops);
510 				goto drop;
511 			}
512 		}
513 
514 		break;
515 #endif /* INET6 */
516 	}
517 
518 	return 0;
519 
520  drop:
521 	m_freemp(mp);
522 	return error;
523 }
524 
525 /*
526  * ah_input() gets called to verify that an input packet
527  * passes authentication.
528  */
529 int
530 ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff)
531 {
532 	const struct auth_hash *ahx = tdb->tdb_authalgxform;
533 	struct mbuf *m = *mp, *m1, *m0;
534 	struct cryptodesc *crda = NULL;
535 	struct cryptop *crp = NULL;
536 	int roff;
537 	uint32_t btsx, esn;
538 	uint8_t *ptr = NULL;
539 	uint8_t hl;
540 	int error, rplen, clen;
541 	uint64_t ibytes;
542 #ifdef ENCDEBUG
543 	char buf[INET6_ADDRSTRLEN];
544 #endif
545 	uint8_t calc[AH_ALEN_MAX];
546 
547 	rplen = AH_FLENGTH + sizeof(u_int32_t);
548 
549 	/* Save the AH header, we use it throughout. */
550 	m_copydata(m, skip + offsetof(struct ah, ah_hl), sizeof(u_int8_t), &hl);
551 
552 	/* Replay window checking, if applicable. */
553 	if (tdb->tdb_wnd > 0) {
554 		m_copydata(m, skip + offsetof(struct ah, ah_rpl),
555 		    sizeof(u_int32_t), &btsx);
556 		btsx = ntohl(btsx);
557 
558 		switch (checkreplaywindow(tdb, tdb->tdb_rpl, btsx, &esn, 0)) {
559 		case 0: /* All's well. */
560 			break;
561 		case 1:
562 			DPRINTF("replay counter wrapped for SA %s/%08x",
563 			    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
564 			    ntohl(tdb->tdb_spi));
565 			ahstat_inc(ahs_wrap);
566 			goto drop;
567 		case 2:
568 			DPRINTF("old packet received in SA %s/%08x",
569 			    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
570 			    ntohl(tdb->tdb_spi));
571 			ahstat_inc(ahs_replay);
572 			goto drop;
573 		case 3:
574 			DPRINTF("duplicate packet received in SA %s/%08x",
575 			    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
576 			    ntohl(tdb->tdb_spi));
577 			ahstat_inc(ahs_replay);
578 			goto drop;
579 		default:
580 			DPRINTF("bogus value from checkreplaywindow() "
581 			    "in SA %s/%08x",
582 			    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
583 			    ntohl(tdb->tdb_spi));
584 			ahstat_inc(ahs_replay);
585 			goto drop;
586 		}
587 	}
588 
589 	/* Verify AH header length. */
590 	if (hl * sizeof(u_int32_t) != ahx->authsize + rplen - AH_FLENGTH) {
591 		DPRINTF("bad authenticator length %ld for packet in SA %s/%08x",
592 		    hl * sizeof(u_int32_t),
593 		    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
594 		    ntohl(tdb->tdb_spi));
595 		ahstat_inc(ahs_badauthl);
596 		goto drop;
597 	}
598 	if (skip + ahx->authsize + rplen > m->m_pkthdr.len) {
599 		DPRINTF("bad mbuf length %d (expecting %d) for packet "
600 		    "in SA %s/%08x",
601 		    m->m_pkthdr.len, skip + ahx->authsize + rplen,
602 		    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
603 		    ntohl(tdb->tdb_spi));
604 		ahstat_inc(ahs_badauthl);
605 		goto drop;
606 	}
607 
608 	/* Update the counters. */
609 	ibytes = (m->m_pkthdr.len - skip - hl * sizeof(u_int32_t));
610 	tdb->tdb_cur_bytes += ibytes;
611 	tdb->tdb_ibytes += ibytes;
612 	ahstat_add(ahs_ibytes, ibytes);
613 
614 	/* Hard expiration. */
615 	if ((tdb->tdb_flags & TDBF_BYTES) &&
616 	    (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) {
617 		ipsecstat_inc(ipsec_exctdb);
618 		pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
619 		tdb_delete(tdb);
620 		goto drop;
621 	}
622 
623 	/* Notify on expiration. */
624 	mtx_enter(&tdb->tdb_mtx);
625 	if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
626 	    (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) {
627 		tdb->tdb_flags &= ~TDBF_SOFT_BYTES;  /* Turn off checking */
628 		mtx_leave(&tdb->tdb_mtx);
629 		/* may sleep in solock() for the pfkey socket */
630 		pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
631 	} else
632 		mtx_leave(&tdb->tdb_mtx);
633 
634 	/* Get crypto descriptors. */
635 	crp = crypto_getreq(1);
636 	if (crp == NULL) {
637 		DPRINTF("failed to acquire crypto descriptors");
638 		ahstat_inc(ahs_crypto);
639 		goto drop;
640 	}
641 
642 	crda = &crp->crp_desc[0];
643 
644 	crda->crd_skip = 0;
645 	crda->crd_len = m->m_pkthdr.len;
646 	crda->crd_inject = skip + rplen;
647 
648 	/* Authentication operation. */
649 	crda->crd_alg = ahx->type;
650 	crda->crd_key = tdb->tdb_amxkey;
651 	crda->crd_klen = tdb->tdb_amxkeylen * 8;
652 
653 	if ((tdb->tdb_wnd > 0) && (tdb->tdb_flags & TDBF_ESN)) {
654 		esn = htonl(esn);
655 		memcpy(crda->crd_esn, &esn, 4);
656 		crda->crd_flags |= CRD_F_ESN;
657 	}
658 
659 	/* Allocate IPsec-specific opaque crypto info. */
660 	ptr = malloc(skip + rplen + ahx->authsize, M_XDATA, M_NOWAIT | M_ZERO);
661 	if (ptr == NULL) {
662 		DPRINTF("failed to allocate buffer");
663 		ahstat_inc(ahs_crypto);
664 		goto drop;
665 	}
666 
667 	/*
668 	 * Save the authenticator, the skipped portion of the packet,
669 	 * and the AH header.
670 	 */
671 	m_copydata(m, 0, skip + rplen + ahx->authsize, ptr);
672 
673 	/* Zeroize the authenticator on the packet. */
674 	m_copyback(m, skip + rplen, ahx->authsize, ipseczeroes, M_NOWAIT);
675 
676 	/* "Massage" the packet headers for crypto processing. */
677 	error = ah_massage_headers(mp, tdb->tdb_dst.sa.sa_family, skip,
678 	    ahx->type, 0);
679 	/* callee may change or free mbuf */
680 	m = *mp;
681 	if (error)
682 		goto drop;
683 
684 	/* Crypto operation descriptor. */
685 	crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */
686 	crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_MPSAFE;
687 	crp->crp_buf = (caddr_t)m;
688 	crp->crp_sid = tdb->tdb_cryptoid;
689 
690 	KERNEL_LOCK();
691 	while ((error = crypto_invoke(crp)) == EAGAIN) {
692 		/* Reset the session ID */
693 		if (tdb->tdb_cryptoid != 0)
694 			tdb->tdb_cryptoid = crp->crp_sid;
695 	}
696 	KERNEL_UNLOCK();
697 	if (error) {
698 		DPRINTF("crypto error %d", error);
699 		ipsecstat_inc(ipsec_noxform);
700 		goto drop;
701 	}
702 
703 	/* Length of data after processing */
704 	clen = crp->crp_olen;
705 
706 	/* Release the crypto descriptors */
707 	crypto_freereq(crp);
708 	crp = NULL;
709 
710 	/* Copy authenticator off the packet. */
711 	m_copydata(m, skip + rplen, ahx->authsize, calc);
712 
713 	/* Verify authenticator. */
714 	if (timingsafe_bcmp(ptr + skip + rplen, calc, ahx->authsize)) {
715 		DPRINTF("authentication failed for packet in SA %s/%08x",
716 		    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
717 		    ntohl(tdb->tdb_spi));
718 		ahstat_inc(ahs_badauth);
719 		goto drop;
720 	}
721 
722 	/* Fix the Next Protocol field. */
723 	ptr[protoff] = ptr[skip];
724 
725 	/* Copyback the saved (uncooked) network headers. */
726 	m_copyback(m, 0, skip, ptr, M_NOWAIT);
727 
728 	free(ptr, M_XDATA, 0);
729 	ptr = NULL;
730 
731 	/* Replay window checking, if applicable. */
732 	if (tdb->tdb_wnd > 0) {
733 		m_copydata(m, skip + offsetof(struct ah, ah_rpl),
734 		    sizeof(u_int32_t), &btsx);
735 		btsx = ntohl(btsx);
736 
737 		switch (checkreplaywindow(tdb, tdb->tdb_rpl, btsx, &esn, 1)) {
738 		case 0: /* All's well. */
739 #if NPFSYNC > 0
740 			pfsync_update_tdb(tdb,0);
741 #endif
742 			break;
743 		case 1:
744 			DPRINTF("replay counter wrapped for SA %s/%08x",
745 			    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
746 			    ntohl(tdb->tdb_spi));
747 			ahstat_inc(ahs_wrap);
748 			goto drop;
749 		case 2:
750 			DPRINTF("old packet received in SA %s/%08x",
751 			    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
752 			    ntohl(tdb->tdb_spi));
753 			ahstat_inc(ahs_replay);
754 			goto drop;
755 		case 3:
756 			DPRINTF("duplicate packet received in SA %s/%08x",
757 			    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
758 			    ntohl(tdb->tdb_spi));
759 			ahstat_inc(ahs_replay);
760 			goto drop;
761 		default:
762 			DPRINTF("bogus value from checkreplaywindow() "
763 			    "in SA %s/%08x",
764 			    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
765 			    ntohl(tdb->tdb_spi));
766 			ahstat_inc(ahs_replay);
767 			goto drop;
768 		}
769 	}
770 
771 	/* Record the beginning of the AH header. */
772 	m1 = m_getptr(m, skip, &roff);
773 	if (m1 == NULL) {
774 		DPRINTF("bad mbuf chain for packet in SA %s/%08x",
775 		    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
776 		    ntohl(tdb->tdb_spi));
777 		ahstat_inc(ahs_hdrops);
778 		goto drop;
779 	}
780 
781 	/* Remove the AH header from the mbuf. */
782 	if (roff == 0) {
783 		/*
784 		 * The AH header was conveniently at the beginning of
785 		 * the mbuf.
786 		 */
787 		m_adj(m1, rplen + ahx->authsize);
788 		/*
789 		 * If m1 is the first mbuf, it has set M_PKTHDR and m_adj()
790 		 * has already adjusted the packet header length for us.
791 		 */
792 		if (m1 != m)
793 			m->m_pkthdr.len -= rplen + ahx->authsize;
794 	} else
795 		if (roff + rplen + ahx->authsize >= m1->m_len) {
796 			int adjlen;
797 
798 			/*
799 			 * Part or all of the AH header is at the end
800 			 * of this mbuf, so first let's remove the
801 			 * remainder of the AH header from the
802 			 * beginning of the remainder of the mbuf
803 			 * chain, if any.
804 			 */
805 			if (roff + rplen + ahx->authsize > m1->m_len) {
806 				adjlen = roff + rplen + ahx->authsize -
807 				    m1->m_len;
808 				/* Adjust the next mbuf by the remainder. */
809 				m_adj(m1->m_next, adjlen);
810 
811 				/*
812 				 * The second mbuf is guaranteed not
813 				 * to have a pkthdr...
814 				 */
815 				m->m_pkthdr.len -= adjlen;
816 			}
817 
818 			/* Now, let's unlink the mbuf chain for a second... */
819 			m0 = m1->m_next;
820 			m1->m_next = NULL;
821 
822 			/*
823 			 * ...and trim the end of the first part of
824 			 * the chain...sick
825 			 */
826 			adjlen = m1->m_len - roff;
827 			m_adj(m1, -adjlen);
828 			/*
829 			 * If m1 is the first mbuf, it has set M_PKTHDR and
830 			 * m_adj() has already adjusted the packet header len.
831 			 */
832 			if (m1 != m)
833 				m->m_pkthdr.len -= adjlen;
834 
835 			/* Finally, let's relink. */
836 			m1->m_next = m0;
837 		} else {
838 			/*
839 			 * The AH header lies in the "middle" of the
840 			 * mbuf...do an overlapping copy of the
841 			 * remainder of the mbuf over the ESP header.
842 			 */
843 			bcopy(mtod(m1, u_char *) + roff + rplen +
844 			    ahx->authsize, mtod(m1, u_char *) + roff,
845 			    m1->m_len - (roff + rplen + ahx->authsize));
846 			m1->m_len -= rplen + ahx->authsize;
847 			m->m_pkthdr.len -= rplen + ahx->authsize;
848 		}
849 
850 	return ipsec_common_input_cb(mp, tdb, skip, protoff);
851 
852  drop:
853 	free(ptr, M_XDATA, 0);
854 	m_freemp(mp);
855 	crypto_freereq(crp);
856 	return IPPROTO_DONE;
857 }
858 
859 /*
860  * AH output routine, called by ipsp_process_packet().
861  */
862 int
863 ah_output(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
864 {
865 	const struct auth_hash *ahx = tdb->tdb_authalgxform;
866 	struct cryptodesc *crda;
867 	struct mbuf *mi;
868 	struct cryptop *crp = NULL;
869 	uint64_t replay64;
870 	uint16_t iplen;
871 	int error, rplen, roff, ilen, olen;
872 	uint8_t *ptr = NULL;
873 	uint8_t prot;
874 	struct ah *ah;
875 #if NBPFILTER > 0
876 	struct ifnet *encif;
877 #ifdef ENCDEBUG
878 	char buf[INET6_ADDRSTRLEN];
879 #endif
880 
881 	if ((encif = enc_getif(tdb->tdb_rdomain, tdb->tdb_tap)) != NULL) {
882 		encif->if_opackets++;
883 		encif->if_obytes += m->m_pkthdr.len;
884 
885 		if (encif->if_bpf) {
886 			struct enchdr hdr;
887 
888 			memset(&hdr, 0, sizeof(hdr));
889 
890 			hdr.af = tdb->tdb_dst.sa.sa_family;
891 			hdr.spi = tdb->tdb_spi;
892 			hdr.flags |= M_AUTH;
893 
894 			bpf_mtap_hdr(encif->if_bpf, (char *)&hdr,
895 			    ENC_HDRLEN, m, BPF_DIRECTION_OUT);
896 		}
897 	}
898 #endif
899 
900 	ahstat_inc(ahs_output);
901 
902 	/*
903 	 * Check for replay counter wrap-around in automatic (not
904 	 * manual) keying.
905 	 */
906 	if ((tdb->tdb_rpl == 0) && (tdb->tdb_wnd > 0)) {
907 		DPRINTF("SA %s/%08x should have expired",
908 		    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
909 		    ntohl(tdb->tdb_spi));
910 		ahstat_inc(ahs_wrap);
911 		error = EINVAL;
912 		goto drop;
913 	}
914 
915 	rplen = AH_FLENGTH + sizeof(u_int32_t);
916 
917 	switch (tdb->tdb_dst.sa.sa_family) {
918 	case AF_INET:
919 		/* Check for IP maximum packet size violations. */
920 		if (rplen + ahx->authsize + m->m_pkthdr.len > IP_MAXPACKET) {
921 			DPRINTF("packet in SA %s/%08x got too big",
922 			    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
923 			    ntohl(tdb->tdb_spi));
924 			ahstat_inc(ahs_toobig);
925 			error = EMSGSIZE;
926 			goto drop;
927 		}
928 		break;
929 
930 #ifdef INET6
931 	case AF_INET6:
932 		/* Check for IPv6 maximum packet size violations. */
933 		if (rplen + ahx->authsize + m->m_pkthdr.len > IPV6_MAXPACKET) {
934 			DPRINTF("packet in SA %s/%08x got too big",
935 			    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
936 			    ntohl(tdb->tdb_spi));
937 			ahstat_inc(ahs_toobig);
938 			error = EMSGSIZE;
939 			goto drop;
940 		}
941 		break;
942 #endif /* INET6 */
943 
944 	default:
945 		DPRINTF("unknown/unsupported protocol family %d, SA %s/%08x",
946 		    tdb->tdb_dst.sa.sa_family,
947 		    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
948 		    ntohl(tdb->tdb_spi));
949 		ahstat_inc(ahs_nopf);
950 		error = EPFNOSUPPORT;
951 		goto drop;
952 	}
953 
954 	/* Update the counters. */
955 	tdb->tdb_cur_bytes += m->m_pkthdr.len - skip;
956 	ahstat_add(ahs_obytes, m->m_pkthdr.len - skip);
957 
958 	/* Hard expiration. */
959 	if ((tdb->tdb_flags & TDBF_BYTES) &&
960 	    (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) {
961 		ipsecstat_inc(ipsec_exctdb);
962 		pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
963 		tdb_delete(tdb);
964 		error = EINVAL;
965 		goto drop;
966 	}
967 
968 	/* Notify on expiration. */
969 	mtx_enter(&tdb->tdb_mtx);
970 	if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
971 	    (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) {
972 		tdb->tdb_flags &= ~TDBF_SOFT_BYTES;  /* Turn off checking */
973 		mtx_leave(&tdb->tdb_mtx);
974 		/* may sleep in solock() for the pfkey socket */
975 		pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
976 	} else
977 		mtx_leave(&tdb->tdb_mtx);
978 
979 	/*
980 	 * Loop through mbuf chain; if we find a readonly mbuf,
981 	 * copy the packet.
982 	 */
983 	mi = m;
984 	while (mi != NULL && !M_READONLY(mi))
985 		mi = mi->m_next;
986 
987 	if (mi != NULL) {
988 		struct mbuf *n = m_dup_pkt(m, 0, M_DONTWAIT);
989 
990 		if (n == NULL) {
991 			ahstat_inc(ahs_hdrops);
992 			error = ENOBUFS;
993 			goto drop;
994 		}
995 
996 		m_freem(m);
997 		m = n;
998 	}
999 
1000 	/* Inject AH header. */
1001 	mi = m_makespace(m, skip, rplen + ahx->authsize, &roff);
1002 	if (mi == NULL) {
1003 		DPRINTF("failed to inject AH header for SA %s/%08x",
1004 		    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
1005 		    ntohl(tdb->tdb_spi));
1006 		ahstat_inc(ahs_hdrops);
1007 		error = ENOBUFS;
1008 		goto drop;
1009 	}
1010 
1011 	/*
1012 	 * The AH header is guaranteed by m_makespace() to be in
1013 	 * contiguous memory, at 'roff' of the returned mbuf.
1014 	 */
1015 	ah = (struct ah *)(mtod(mi, caddr_t) + roff);
1016 
1017 	/* Initialize the AH header. */
1018 	m_copydata(m, protoff, sizeof(u_int8_t), &ah->ah_nh);
1019 	ah->ah_hl = (rplen + ahx->authsize - AH_FLENGTH) / sizeof(u_int32_t);
1020 	ah->ah_rv = 0;
1021 	ah->ah_spi = tdb->tdb_spi;
1022 
1023 	/* Zeroize authenticator. */
1024 	m_copyback(m, skip + rplen, ahx->authsize, ipseczeroes, M_NOWAIT);
1025 
1026 	replay64 = tdb->tdb_rpl++;
1027 	ah->ah_rpl = htonl((u_int32_t)replay64);
1028 #if NPFSYNC > 0
1029 	pfsync_update_tdb(tdb,1);
1030 #endif
1031 
1032 	/* Get crypto descriptors. */
1033 	crp = crypto_getreq(1);
1034 	if (crp == NULL) {
1035 		DPRINTF("failed to acquire crypto descriptors");
1036 		ahstat_inc(ahs_crypto);
1037 		error = ENOBUFS;
1038 		goto drop;
1039 	}
1040 
1041 	crda = &crp->crp_desc[0];
1042 
1043 	crda->crd_skip = 0;
1044 	crda->crd_inject = skip + rplen;
1045 	crda->crd_len = m->m_pkthdr.len;
1046 
1047 	/* Authentication operation. */
1048 	crda->crd_alg = ahx->type;
1049 	crda->crd_key = tdb->tdb_amxkey;
1050 	crda->crd_klen = tdb->tdb_amxkeylen * 8;
1051 
1052 	if ((tdb->tdb_wnd > 0) && (tdb->tdb_flags & TDBF_ESN)) {
1053 		u_int32_t esn;
1054 
1055 		esn = htonl((u_int32_t)(replay64 >> 32));
1056 		memcpy(crda->crd_esn, &esn, 4);
1057 		crda->crd_flags |= CRD_F_ESN;
1058 	}
1059 
1060 	ptr = malloc(skip, M_XDATA, M_NOWAIT | M_ZERO);
1061 	if (ptr == NULL) {
1062 		DPRINTF("failed to allocate buffer");
1063 		ahstat_inc(ahs_crypto);
1064 		error = ENOBUFS;
1065 		goto drop;
1066 	}
1067 
1068 	/* Save the skipped portion of the packet. */
1069 	m_copydata(m, 0, skip, ptr);
1070 
1071 	/*
1072 	 * Fix IP header length on the header used for
1073 	 * authentication. We don't need to fix the original
1074 	 * header length as it will be fixed by our caller.
1075 	 */
1076 	switch (tdb->tdb_dst.sa.sa_family) {
1077 	case AF_INET:
1078 		memcpy((caddr_t) &iplen, ((caddr_t)ptr) +
1079 		    offsetof(struct ip, ip_len), sizeof(u_int16_t));
1080 		iplen = htons(ntohs(iplen) + rplen + ahx->authsize);
1081 		m_copyback(m, offsetof(struct ip, ip_len),
1082 		    sizeof(u_int16_t), &iplen, M_NOWAIT);
1083 		break;
1084 
1085 #ifdef INET6
1086 	case AF_INET6:
1087 		memcpy((caddr_t) &iplen, ((caddr_t)ptr) +
1088 		    offsetof(struct ip6_hdr, ip6_plen), sizeof(u_int16_t));
1089 		iplen = htons(ntohs(iplen) + rplen + ahx->authsize);
1090 		m_copyback(m, offsetof(struct ip6_hdr, ip6_plen),
1091 		    sizeof(u_int16_t), &iplen, M_NOWAIT);
1092 		break;
1093 #endif /* INET6 */
1094 	}
1095 
1096 	/* Fix the Next Header field in saved header. */
1097 	ptr[protoff] = IPPROTO_AH;
1098 
1099 	/* Update the Next Protocol field in the IP header. */
1100 	prot = IPPROTO_AH;
1101 	m_copyback(m, protoff, sizeof(u_int8_t), &prot, M_NOWAIT);
1102 
1103 	/* "Massage" the packet headers for crypto processing. */
1104 	error = ah_massage_headers(&m, tdb->tdb_dst.sa.sa_family, skip,
1105 	    ahx->type, 1);
1106 	if (error) {
1107 		/* mbuf was freed by callee. */
1108 		m = NULL;
1109 		goto drop;
1110 	}
1111 
1112 	/* Crypto operation descriptor. */
1113 	crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */
1114 	crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_MPSAFE;
1115 	crp->crp_buf = (caddr_t)m;
1116 	crp->crp_sid = tdb->tdb_cryptoid;
1117 
1118 	KERNEL_LOCK();
1119 	while ((error = crypto_invoke(crp)) == EAGAIN) {
1120 		/* Reset the session ID */
1121 		if (tdb->tdb_cryptoid != 0)
1122 			tdb->tdb_cryptoid = crp->crp_sid;
1123 	}
1124 	KERNEL_UNLOCK();
1125 	if (error) {
1126 		DPRINTF("crypto error %d", error);
1127 		ipsecstat_inc(ipsec_noxform);
1128 		goto drop;
1129 	}
1130 
1131 	ilen = crp->crp_ilen;
1132 	olen = crp->crp_olen;
1133 
1134 	/* Release the crypto descriptors */
1135 	crypto_freereq(crp);
1136 	crp = NULL;
1137 
1138 	/*
1139 	 * Copy original headers (with the new protocol number) back
1140 	 * in place.
1141 	 */
1142 	m_copyback(m, 0, skip, ptr, M_NOWAIT);
1143 	free(ptr, M_XDATA, 0);
1144 	ptr = NULL;
1145 
1146 	/* Call the IPsec input callback. */
1147 	error = ipsp_process_done(m, tdb);
1148 	if (error)
1149 		ahstat_inc(ahs_outfail);
1150 	return error;
1151 
1152  drop:
1153 	free(ptr, M_XDATA, 0);
1154 	m_freem(m);
1155 	crypto_freereq(crp);
1156 	return error;
1157 }
1158