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