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