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