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