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