This source file includes following definitions.
- ah_attach
- ah_init
- ah_zeroize
- ah_massage_headers
- ah_input
- ah_input_cb
- ah_output
- ah_output_cb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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
55
56 #ifdef INET6
57 #ifndef INET
58 #include <netinet/in.h>
59 #endif
60 #include <netinet/ip6.h>
61 #endif
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
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
88
89 int
90 ah_attach()
91 {
92 return 0;
93 }
94
95
96
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
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
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
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
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
205
206 #ifdef INET6
207 struct ip6_ext *ip6e;
208 struct ip6_hdr ip6;
209 int ad, alloc, nxt;
210 #endif
211
212 switch (proto) {
213 #ifdef INET
214 case AF_INET:
215
216
217
218
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
228 ip = mtod(m, struct ip *);
229 ip->ip_tos = 0;
230 ip->ip_ttl = 0;
231 ip->ip_sum = 0;
232
233
234
235
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
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;
262 break;
263
264 case IPOPT_NOP:
265 off++;
266 break;
267
268 case IPOPT_SECURITY:
269 case 0x85:
270 case 0x86:
271 case 0x94:
272 case 0x95:
273
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
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
302
303
304
305
306
307
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
315 default:
316
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
327 count = ptr[off + 1];
328 bcopy(ipseczeroes, ptr, count);
329 off += count;
330 break;
331 }
332
333
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
346
347 #ifdef INET6
348 case AF_INET6:
349
350 m_copydata(m, 0, sizeof(ip6), (caddr_t) &ip6);
351
352
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
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
373 m_copyback(m, 0, sizeof(struct ip6_hdr), &ip6);
374
375
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
390
391
392 m_copydata(m, sizeof(struct ip6_hdr),
393 skip - sizeof(struct ip6_hdr), ptr);
394 alloc = 1;
395 } else {
396
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;
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
414
415
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;
422 }
423
424
425 if (count > off +
426 ((ip6e->ip6e_len + 1) << 3)) {
427 ahstat.ahs_hdrops++;
428 m_freem(m);
429
430
431 if (alloc)
432 FREE(ptr, M_XDATA);
433 return EINVAL;
434 }
435
436 ad = ptr[count + 1];
437
438
439 if (ptr[count] & IP6OPT_MUTABLE)
440 bcopy(ipseczeroes, ptr + count,
441 ptr[count + 1]);
442
443 count += ad;
444
445
446 if (count >
447 skip - sizeof(struct ip6_hdr)) {
448 ahstat.ahs_hdrops++;
449 m_freem(m);
450
451
452 if (alloc)
453 FREE(ptr, M_XDATA);
454 return EINVAL;
455 }
456 }
457
458
459 off += ((ip6e->ip6e_len + 1) << 3);
460 nxt = ip6e->ip6e_nxt;
461 break;
462
463 case IPPROTO_ROUTING:
464
465
466
467
468 {
469 struct ip6_rthdr *rh;
470
471 ip6e = (struct ip6_ext *) (ptr + off);
472 rh = (struct ip6_rthdr *)(ptr + off);
473
474
475
476
477
478
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
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
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
532 }
533
534 return 0;
535 }
536
537
538
539
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
560 m_copydata(m, skip + offsetof(struct ah, ah_hl), sizeof(u_int8_t),
561 (caddr_t) &hl);
562
563
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:
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
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
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
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
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;
633 }
634
635
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
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
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
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
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
693 if (mtag == NULL) {
694
695
696
697
698 m_copydata(m, 0, skip + rplen + ahx->authsize,
699 (caddr_t) (tc + 1));
700
701
702 m_copyback(m, skip + rplen, ahx->authsize, ipseczeroes);
703
704
705 if ((btsx = ah_massage_headers(&m, tdb->tdb_dst.sa.sa_family,
706 skip, ahx->type, 0)) != 0) {
707
708 FREE(tc, M_XDATA);
709 crypto_freereq(crp);
710 return btsx;
711 }
712 }
713
714
715 crp->crp_ilen = m->m_pkthdr.len;
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
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;
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
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
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
788 if (crp->crp_etype) {
789 if (crp->crp_etype == EAGAIN) {
790
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);
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
812 m_copydata(m, skip + rplen, ahx->authsize, calc);
813
814
815
816
817
818 if (mtag == NULL) {
819 ptr = (caddr_t) (tc + 1);
820
821
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
835 ((u_int8_t *) ptr)[protoff] = ((u_int8_t *) ptr)[skip];
836
837
838 m_copyback(m, 0, skip, ptr);
839 } else {
840
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
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:
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
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
905 if (roff == 0) {
906
907
908
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
917
918
919
920
921
922 if (roff + rplen + ahx->authsize > m1->m_len) {
923
924 m_adj(m1->m_next, roff + rplen +
925 ahx->authsize - m1->m_len);
926
927
928
929
930
931 m->m_pkthdr.len -=
932 (roff + rplen + ahx->authsize - m1->m_len);
933 }
934
935
936 m0 = m1->m_next;
937 m1->m_next = NULL;
938
939
940
941
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
948 m1->m_next = m0;
949 } else {
950
951
952
953
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
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
1018
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
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
1048
1049 #ifdef INET6
1050 case AF_INET6:
1051
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
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
1073 tdb->tdb_cur_bytes += m->m_pkthdr.len - skip;
1074 ahstat.ahs_obytes += m->m_pkthdr.len - skip;
1075
1076
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
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;
1090 }
1091
1092
1093
1094
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
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
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
1135
1136
1137 ah = mtod(mi, struct ah *);
1138
1139
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
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
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
1172 crda->crd_alg = ahx->type;
1173 crda->crd_key = tdb->tdb_amxkey;
1174 crda->crd_klen = tdb->tdb_amxkeylen * 8;
1175
1176
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
1194 if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0) {
1195 m_copydata(m, 0, skip, (caddr_t) (tc + 1));
1196
1197
1198
1199
1200
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
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
1224 }
1225
1226
1227 ((u_int8_t *) (tc + 1))[protoff] = IPPROTO_AH;
1228
1229
1230 prot = IPPROTO_AH;
1231 m_copyback(m, protoff, sizeof(u_int8_t), &prot);
1232
1233
1234 if ((len = ah_massage_headers(&m, tdb->tdb_dst.sa.sa_family,
1235 skip, ahx->type, 1)) != 0) {
1236
1237 FREE(tc, M_XDATA);
1238 crypto_freereq(crp);
1239 return len;
1240 }
1241 } else {
1242
1243 prot = IPPROTO_AH;
1244 m_copyback(m, protoff, sizeof(u_int8_t), &prot);
1245 }
1246
1247
1248 crp->crp_ilen = m->m_pkthdr.len;
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
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
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
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
1311 if (crp->crp_etype) {
1312 if (crp->crp_etype == EAGAIN) {
1313
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
1328
1329
1330 if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0)
1331 m_copyback(m, 0, skip, ptr);
1332
1333 FREE(tc, M_XDATA);
1334
1335
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 }