1 /*
2 * Copyright (c) 2008-2021, 2023 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 /* $FreeBSD: src/sys/netinet6/ah_core.c,v 1.2.2.4 2001/07/03 11:01:49 ume Exp $ */
30 /* $KAME: ah_core.c,v 1.44 2001/03/12 11:24:39 itojun Exp $ */
31
32 /*
33 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the project nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 */
60
61 /*
62 * RFC1826/2402 authentication header.
63 */
64
65 /* TODO: have shared routines for hmac-* algorithms */
66
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/malloc.h>
70 #include <sys/mbuf.h>
71 #include <sys/domain.h>
72 #include <sys/protosw.h>
73 #include <sys/socket.h>
74 #include <sys/socketvar.h>
75 #include <sys/errno.h>
76 #include <sys/time.h>
77 #include <sys/syslog.h>
78
79 #include <net/if.h>
80 #include <net/route.h>
81
82 #include <netinet/in.h>
83 #include <netinet/in_systm.h>
84 #include <netinet/ip.h>
85 #include <netinet/in_var.h>
86
87 #include <netinet/ip6.h>
88 #include <netinet6/ip6_var.h>
89 #include <netinet/icmp6.h>
90
91 #include <netinet6/ipsec.h>
92 #include <netinet6/ipsec6.h>
93 #include <netinet6/ah.h>
94 #include <netinet6/ah6.h>
95 #if IPSEC_ESP
96 #include <netinet6/esp.h>
97 #include <netinet6/esp6.h>
98 #endif
99 #include <net/pfkeyv2.h>
100 #include <netkey/key.h>
101 #include <netkey/keydb.h>
102 #include <libkern/crypto/crypto_internal.h>
103 #include <libkern/crypto/md5.h>
104 #include <libkern/crypto/sha1.h>
105 #include <libkern/crypto/sha2.h>
106
107 #include <net/net_osdep.h>
108
109 static int ah_hmac_mature(struct secasvar *);
110 static int ah_hmac_state_init(struct ah_algorithm_state *, struct secasvar *);
111 static size_t ah_hmac_schedlen(const struct ah_algorithm *);
112 static int ah_hmac_schedule(const struct ah_algorithm *, struct secasvar *);
113 static void ah_hmac_loop(struct ah_algorithm_state *,
114 caddr_t __sized_by(len), size_t len);
115 static void ah_hmac_result(struct ah_algorithm_state *,
116 caddr_t __sized_by(len), size_t len);
117
118 static int ah_sumsiz_1216(struct secasvar *);
119 static const struct ccdigest_info *ah_digest_md5(void);
120 static const struct ccdigest_info *ah_digest_sha1(void);
121 #if AH_ALL_CRYPTO
122 static int ah_sumsiz_sha2_256(struct secasvar *);
123 static const struct ccdigest_info *ah_digest_sha2_256(void);
124 static int ah_sumsiz_sha2_384(struct secasvar *);
125 static const struct ccdigest_info *ah_digest_sha2_384(void);
126 static int ah_sumsiz_sha2_512(struct secasvar *);
127 static const struct ccdigest_info *ah_digest_sha2_512(void);
128 #endif /* AH_ALL_CRYPTO */
129
130 static int ah_sumsiz_zero(struct secasvar *);
131 static int ah_none_mature(struct secasvar *);
132 static int ah_none_init(struct ah_algorithm_state *, struct secasvar *);
133 static void ah_none_loop(struct ah_algorithm_state *,
134 caddr_t __sized_by(len), size_t len);
135 static void ah_none_result(struct ah_algorithm_state *,
136 caddr_t __sized_by(len), size_t len);
137
138 static void ah_update_mbuf(struct mbuf *, int, int,
139 const struct ah_algorithm *, struct ah_algorithm_state *);
140
141 /*
142 * If any algorithm requires more than 2048 bits (256 bytes) of key material,
143 * update IPSEC_KEY_AUTH_MAX_BYTES in ipsec.h
144 */
145 const struct ah_algorithm *
ah_algorithm_lookup(int idx)146 ah_algorithm_lookup(int idx)
147 {
148 /* checksum algorithms */
149 static const struct ah_algorithm hmac_md5 =
150 { ah_sumsiz_1216, ah_hmac_mature,
151 128, 128, "hmac-md5", ah_hmac_state_init,
152 ah_hmac_loop, ah_hmac_result, ah_digest_md5,
153 ah_hmac_schedlen, ah_hmac_schedule, };
154 static const struct ah_algorithm hmac_sha1 =
155 { ah_sumsiz_1216, ah_hmac_mature,
156 160, 160, "hmac-sha1", ah_hmac_state_init,
157 ah_hmac_loop, ah_hmac_result, ah_digest_sha1,
158 ah_hmac_schedlen, ah_hmac_schedule, };
159 static const struct ah_algorithm ah_none =
160 { ah_sumsiz_zero, ah_none_mature,
161 0, 2048, "none", ah_none_init,
162 ah_none_loop, ah_none_result,
163 NULL, NULL, NULL, };
164 #if AH_ALL_CRYPTO
165 static const struct ah_algorithm hmac_sha2_256 =
166 { ah_sumsiz_sha2_256, ah_hmac_mature,
167 256, 256, "hmac-sha2-256", ah_hmac_state_init,
168 ah_hmac_loop, ah_hmac_result, ah_digest_sha2_256,
169 ah_hmac_schedlen, ah_hmac_schedule, };
170 static const struct ah_algorithm hmac_sha2_384 =
171 { ah_sumsiz_sha2_384, ah_hmac_mature,
172 384, 384, "hmac-sha2-384", ah_hmac_state_init,
173 ah_hmac_loop, ah_hmac_result, ah_digest_sha2_384,
174 ah_hmac_schedlen, ah_hmac_schedule, };
175 static const struct ah_algorithm hmac_sha2_512 =
176 { ah_sumsiz_sha2_512, ah_hmac_mature,
177 512, 512, "hmac-sha2-512", ah_hmac_state_init,
178 ah_hmac_loop, ah_hmac_result, ah_digest_sha2_512,
179 ah_hmac_schedlen, ah_hmac_schedule, };
180 #endif /* AH_ALL_CRYPTO */
181
182 switch (idx) {
183 case SADB_AALG_MD5HMAC:
184 return &hmac_md5;
185 case SADB_AALG_SHA1HMAC:
186 return &hmac_sha1;
187 case SADB_X_AALG_NULL:
188 return &ah_none;
189 #if AH_ALL_CRYPTO
190 case SADB_X_AALG_SHA2_256:
191 return &hmac_sha2_256;
192 case SADB_X_AALG_SHA2_384:
193 return &hmac_sha2_384;
194 case SADB_X_AALG_SHA2_512:
195 return &hmac_sha2_512;
196 #endif /* AH_ALL_CRYPTO */
197 default:
198 return NULL;
199 }
200 }
201
202 int
ah_schedule(const struct ah_algorithm * algo,struct secasvar * sav)203 ah_schedule(
204 const struct ah_algorithm *algo,
205 struct secasvar *sav)
206 {
207 void *sched = NULL;
208 size_t schedlen = 0;
209 int error;
210
211 lck_mtx_lock(sadb_mutex);
212 /* already allocated */
213 if (sav->sched_auth != NULL && sav->schedlen_auth != 0) {
214 lck_mtx_unlock(sadb_mutex);
215 return 0;
216 }
217
218 /* no schedule necessary */
219 if (algo->schedule == NULL || algo->schedlen == NULL) {
220 lck_mtx_unlock(sadb_mutex);
221 return 0;
222 }
223
224 schedlen = (*algo->schedlen)(algo);
225 if (__improbable((signed)schedlen < 0)) {
226 lck_mtx_unlock(sadb_mutex);
227 return EINVAL;
228 }
229
230 sched = kalloc_data(schedlen, Z_NOWAIT);
231 if (__improbable(sched == NULL)) {
232 lck_mtx_unlock(sadb_mutex);
233 return ENOBUFS;
234 }
235
236 sav->sched_auth = sched;
237 sav->schedlen_auth = schedlen;
238
239 error = (*algo->schedule)(algo, sav);
240 if (__improbable(error != 0)) {
241 ipseclog((LOG_ERR, "ah_schedule %s: error %d\n",
242 algo->name, error));
243 memset(sav->sched_auth, 0, sav->schedlen_auth);
244 kfree_data_sized_by(sav->sched_auth, sav->schedlen_auth);
245 }
246 lck_mtx_unlock(sadb_mutex);
247 return error;
248 }
249
250 static int
ah_hmac_mature(struct secasvar * sav)251 ah_hmac_mature(struct secasvar *sav)
252 {
253 const struct ah_algorithm *algo;
254
255 if (__improbable(sav->key_auth == NULL)) {
256 ipseclog((LOG_ERR, "ah_hmac_mature: no key is given.\n"));
257 return 1;
258 }
259
260 algo = ah_algorithm_lookup(sav->alg_auth);
261 if (__improbable(algo == NULL)) {
262 ipseclog((LOG_ERR, "ah_hmac_mature: unsupported algorithm.\n"));
263 return 1;
264 }
265
266 if (sav->key_auth->sadb_key_bits < algo->keymin
267 || algo->keymax < sav->key_auth->sadb_key_bits) {
268 ipseclog((LOG_ERR,
269 "ah_hmac_mature: invalid key length %d.\n",
270 sav->key_auth->sadb_key_bits));
271 return 1;
272 }
273
274 return 0;
275 }
276
277 static int
ah_hmac_state_init(struct ah_algorithm_state * state,struct secasvar * sav)278 ah_hmac_state_init(struct ah_algorithm_state *state, struct secasvar *sav)
279 {
280 if (__improbable(state == NULL || sav == NULL)) {
281 panic("ah_hmac_state_init: what?");
282 }
283
284 const struct ah_algorithm *algo = ah_algorithm_lookup(sav->alg_auth);
285 if (__improbable(algo == NULL)) {
286 ipseclog((LOG_ERR, "ah_hmac_state_init: unsupported algorithm.\n"));
287 return EINVAL;
288 }
289
290 const size_t schedlen = sav->schedlen_auth;
291 memcpy(state->hmac_ctx, sav->sched_auth, schedlen);
292 state->digest = algo->digest();
293
294 return 0;
295 }
296
297 static size_t
ah_hmac_schedlen(const struct ah_algorithm * algo)298 ah_hmac_schedlen(const struct ah_algorithm *algo)
299 {
300 return cchmac_di_size(algo->digest());
301 }
302
303 static int
ah_hmac_schedule(const struct ah_algorithm * algo,struct secasvar * sav)304 ah_hmac_schedule(
305 const struct ah_algorithm *algo,
306 struct secasvar *sav)
307 {
308 const struct ccdigest_info *di = algo->digest();
309 cchmac_ctx_t ctx = (cchmac_ctx_t)sav->sched_auth;
310
311 g_crypto_funcs->cchmac_init_fn(di, ctx,
312 _KEYLEN(sav->key_auth), _KEYBUF(sav->key_auth));
313
314 return 0;
315 }
316
317 static void
ah_hmac_loop(struct ah_algorithm_state * state,caddr_t __sized_by (len)addr,size_t len)318 ah_hmac_loop(
319 struct ah_algorithm_state *state,
320 caddr_t __sized_by(len)addr, size_t len)
321 {
322 if (__improbable(state == NULL || state->digest == NULL)) {
323 panic("ah_hmac_loop: what?");
324 }
325
326 VERIFY(len <= UINT_MAX);
327 if (len > 0) {
328 g_crypto_funcs->cchmac_update_fn(state->digest, state->hmac_ctx, len, (void *)addr);
329 }
330 }
331
332 static void
ah_hmac_result(struct ah_algorithm_state * state,caddr_t __sized_by (len)addr,size_t len)333 ah_hmac_result(
334 struct ah_algorithm_state *state,
335 caddr_t __sized_by(len)addr, size_t len)
336 {
337 if (__improbable(state == NULL || state->digest == NULL)) {
338 panic("ah_hmac_result: what?");
339 }
340
341 const size_t output_size = state->digest->output_size;
342 u_char digest[output_size] __attribute__((aligned(4)));
343
344 g_crypto_funcs->cchmac_final_fn(state->digest, state->hmac_ctx, &digest[0]);
345 cchmac_di_clear(state->digest, state->hmac_ctx);
346 memcpy((void *)addr, &digest[0], sizeof(digest) > len ? len : sizeof(digest));
347 }
348
349 static int
ah_sumsiz_1216(struct secasvar * sav)350 ah_sumsiz_1216(struct secasvar *sav)
351 {
352 if (!sav) {
353 return -1;
354 }
355 if (sav->flags & SADB_X_EXT_OLD) {
356 return 16;
357 } else {
358 return 12;
359 }
360 }
361
362 static const struct ccdigest_info *
ah_digest_md5(void)363 ah_digest_md5(void)
364 {
365 return g_crypto_funcs->ccmd5_di;
366 }
367
368 static const struct ccdigest_info *
ah_digest_sha1(void)369 ah_digest_sha1(void)
370 {
371 return g_crypto_funcs->ccsha1_di;
372 }
373
374 #if AH_ALL_CRYPTO
375 static int
ah_sumsiz_sha2_256(struct secasvar * sav)376 ah_sumsiz_sha2_256(struct secasvar *sav)
377 {
378 if (!sav) {
379 return -1;
380 }
381 // return half the output size (in bytes), as per rfc 4868
382 return SHA256_DIGEST_LENGTH / 2;
383 }
384
385 static const struct ccdigest_info *
ah_digest_sha2_256(void)386 ah_digest_sha2_256(void)
387 {
388 return g_crypto_funcs->ccsha256_di;
389 }
390
391 static int
ah_sumsiz_sha2_384(struct secasvar * sav)392 ah_sumsiz_sha2_384(struct secasvar *sav)
393 {
394 if (!sav) {
395 return -1;
396 }
397 // return half the output size (in bytes), as per rfc 4868
398 return SHA384_DIGEST_LENGTH / 2;
399 }
400
401 static const struct ccdigest_info *
ah_digest_sha2_384(void)402 ah_digest_sha2_384(void)
403 {
404 return g_crypto_funcs->ccsha384_di;
405 }
406
407 static int
ah_sumsiz_sha2_512(struct secasvar * sav)408 ah_sumsiz_sha2_512(struct secasvar *sav)
409 {
410 if (!sav) {
411 return -1;
412 }
413 // return half the output size (in bytes), as per rfc 4868
414 return SHA512_DIGEST_LENGTH / 2;
415 }
416
417 static const struct ccdigest_info *
ah_digest_sha2_512(void)418 ah_digest_sha2_512(void)
419 {
420 return g_crypto_funcs->ccsha512_di;
421 }
422 #endif /* AH_ALL_CRYPTO */
423
424 static int
ah_sumsiz_zero(struct secasvar * sav)425 ah_sumsiz_zero(struct secasvar *sav)
426 {
427 if (!sav) {
428 return -1;
429 }
430 return 0;
431 }
432
433 static int
ah_none_mature(struct secasvar * sav)434 ah_none_mature(struct secasvar *sav)
435 {
436 if (sav->sah->saidx.proto == IPPROTO_AH) {
437 ipseclog((LOG_ERR,
438 "ah_none_mature: protocol and algorithm mismatch.\n"));
439 return 1;
440 }
441 return 0;
442 }
443
444 static int
ah_none_init(struct ah_algorithm_state * state,__unused struct secasvar * sav)445 ah_none_init(
446 struct ah_algorithm_state *state,
447 __unused struct secasvar *sav)
448 {
449 state->digest = NULL;
450 return 0;
451 }
452
453 static void
ah_none_loop(__unused struct ah_algorithm_state * state,__unused caddr_t __sized_by (len)addr,__unused size_t len)454 ah_none_loop(
455 __unused struct ah_algorithm_state *state,
456 __unused caddr_t __sized_by(len)addr,
457 __unused size_t len)
458 {
459 }
460
461 static void
ah_none_result(__unused struct ah_algorithm_state * state,__unused caddr_t __sized_by (len)addr,__unused size_t len)462 ah_none_result(
463 __unused struct ah_algorithm_state *state,
464 __unused caddr_t __sized_by(len)addr,
465 __unused size_t len)
466 {
467 }
468
469 /*------------------------------------------------------------*/
470
471 /*
472 * go generate the checksum.
473 */
474 static void
ah_update_mbuf(struct mbuf * m,int off,int len,const struct ah_algorithm * algo,struct ah_algorithm_state * algos)475 ah_update_mbuf(struct mbuf *m, int off, int len,
476 const struct ah_algorithm *algo,
477 struct ah_algorithm_state *algos)
478 {
479 struct mbuf *n;
480 int tlen;
481
482 /* easy case first */
483 if (off + len <= m->m_len) {
484 (algo->update)(algos, mtod(m, caddr_t) + off, len);
485 return;
486 }
487
488 for (n = m; n; n = n->m_next) {
489 if (off < n->m_len) {
490 break;
491 }
492
493 off -= n->m_len;
494 }
495
496 if (!n) {
497 panic("ah_update_mbuf: wrong offset specified");
498 }
499
500 for (/*nothing*/; n && len > 0; n = n->m_next) {
501 if (n->m_len == 0) {
502 continue;
503 }
504 if (n->m_len - off < len) {
505 tlen = n->m_len - off;
506 } else {
507 tlen = len;
508 }
509
510 (algo->update)(algos, mtod(n, caddr_t) + off, tlen);
511
512 len -= tlen;
513 off = 0;
514 }
515 }
516
517 #if INET
518 /*
519 * Go generate the checksum. This function won't modify the mbuf chain
520 * except AH itself.
521 *
522 * NOTE: the function does not free mbuf on failure.
523 * Don't use m_copy(), it will try to share cluster mbuf by using refcnt.
524 */
525 int
ah4_calccksum(struct mbuf * m,caddr_t __sized_by (len)ahdat,size_t len,const struct ah_algorithm * algo,struct secasvar * sav)526 ah4_calccksum(struct mbuf *m, caddr_t __sized_by(len)ahdat, size_t len,
527 const struct ah_algorithm *algo, struct secasvar *sav)
528 {
529 int off;
530 int hdrtype;
531 size_t advancewidth;
532 struct ah_algorithm_state algos;
533 u_char sumbuf[AH_MAXSUMSIZE] __attribute__((aligned(4)));
534 int error = 0;
535 int ahseen;
536 struct mbuf *n = NULL;
537
538 if ((m->m_flags & M_PKTHDR) == 0) {
539 return EINVAL;
540 }
541
542 ahseen = 0;
543 hdrtype = -1; /*dummy, it is called IPPROTO_IP*/
544
545 off = 0;
546
547 /*
548 * pre-compute and cache intermediate key
549 */
550 if (__improbable((error = ah_schedule(algo, sav)) != 0)) {
551 return error;
552 }
553
554 error = (algo->init)(&algos, sav);
555 if (error) {
556 return error;
557 }
558
559 advancewidth = 0; /*safety*/
560
561 again:
562 /* gory. */
563 switch (hdrtype) {
564 case -1: /*first one only*/
565 {
566 /*
567 * copy ip hdr, modify to fit the AH checksum rule,
568 * then take a checksum.
569 */
570 struct ip iphdr;
571 size_t hlen;
572
573 m_copydata(m, off, sizeof(iphdr), (caddr_t)&iphdr);
574 #if _IP_VHL
575 hlen = IP_VHL_HL(iphdr.ip_vhl) << 2;
576 #else
577 hlen = iphdr.ip_hl << 2;
578 #endif
579 iphdr.ip_ttl = 0;
580 iphdr.ip_sum = htons(0);
581 if (ip4_ah_cleartos) {
582 iphdr.ip_tos = 0;
583 }
584 iphdr.ip_off = htons(ntohs(iphdr.ip_off) & ip4_ah_offsetmask);
585 (algo->update)(&algos, (caddr_t)&iphdr, sizeof(struct ip));
586
587 if (hlen != sizeof(struct ip)) {
588 u_char *p;
589 int i, l, skip;
590
591 if (hlen > MCLBYTES) {
592 error = EMSGSIZE;
593 goto fail;
594 }
595 MGET(n, M_DONTWAIT, MT_DATA);
596 if (n && hlen > MLEN) {
597 MCLGET(n, M_DONTWAIT);
598 if ((n->m_flags & M_EXT) == 0) {
599 m_free(n);
600 n = NULL;
601 }
602 }
603 if (n == NULL) {
604 error = ENOBUFS;
605 goto fail;
606 }
607 VERIFY(hlen <= INT_MAX);
608 m_copydata(m, off, (int)hlen, mtod(n, caddr_t));
609
610 /*
611 * IP options processing.
612 * See RFC2402 appendix A.
613 */
614 p = mtod(n, u_char *);
615 i = sizeof(struct ip);
616 while (i < hlen) {
617 if (i + IPOPT_OPTVAL >= hlen) {
618 ipseclog((LOG_ERR, "ah4_calccksum: "
619 "invalid IP option\n"));
620 error = EINVAL;
621 goto fail;
622 }
623 if (p[i + IPOPT_OPTVAL] == IPOPT_EOL ||
624 p[i + IPOPT_OPTVAL] == IPOPT_NOP ||
625 i + IPOPT_OLEN < hlen) {
626 ;
627 } else {
628 ipseclog((LOG_ERR,
629 "ah4_calccksum: invalid IP option "
630 "(type=%02x)\n",
631 p[i + IPOPT_OPTVAL]));
632 error = EINVAL;
633 goto fail;
634 }
635
636 skip = 1;
637 switch (p[i + IPOPT_OPTVAL]) {
638 case IPOPT_EOL:
639 case IPOPT_NOP:
640 l = 1;
641 skip = 0;
642 break;
643 case IPOPT_SECURITY: /* 0x82 */
644 case 0x85: /* Extended security */
645 case 0x86: /* Commercial security */
646 case 0x94: /* Router alert */
647 case 0x95: /* RFC1770 */
648 l = p[i + IPOPT_OLEN];
649 if (l < 2) {
650 goto invalopt;
651 }
652 skip = 0;
653 break;
654 default:
655 l = p[i + IPOPT_OLEN];
656 if (l < 2) {
657 goto invalopt;
658 }
659 skip = 1;
660 break;
661 }
662 if (l < 1 || hlen - i < l) {
663 invalopt:
664 ipseclog((LOG_ERR,
665 "ah4_calccksum: invalid IP option "
666 "(type=%02x len=%02x)\n",
667 p[i + IPOPT_OPTVAL],
668 p[i + IPOPT_OLEN]));
669 error = EINVAL;
670 goto fail;
671 }
672 if (skip) {
673 bzero(p + i, l);
674 }
675 if (p[i + IPOPT_OPTVAL] == IPOPT_EOL) {
676 break;
677 }
678 i += l;
679 }
680
681 p = mtod(n, u_char *) + sizeof(struct ip);
682 (algo->update)(&algos, (caddr_t)p, hlen - sizeof(struct ip));
683
684 m_free(n);
685 n = NULL;
686 }
687
688 hdrtype = (iphdr.ip_p) & 0xff;
689 advancewidth = hlen;
690 break;
691 }
692
693 case IPPROTO_AH:
694 {
695 struct ah ah;
696 int siz;
697 int hdrsiz;
698 int totlen;
699
700 if (m->m_pkthdr.len - off < sizeof(ah)) {
701 error = EMSGSIZE;
702 goto fail;
703 }
704
705 m_copydata(m, off, sizeof(ah), (caddr_t)&ah);
706 hdrsiz = (sav->flags & SADB_X_EXT_OLD)
707 ? sizeof(struct ah)
708 : sizeof(struct newah);
709 siz = (*algo->sumsiz)(sav);
710 totlen = (ah.ah_len + 2) << 2;
711
712 if (totlen > m->m_pkthdr.len - off) {
713 error = EMSGSIZE;
714 goto fail;
715 }
716
717 /*
718 * special treatment is necessary for the first one, not others
719 */
720 if (!ahseen) {
721 if (totlen > MCLBYTES) {
722 error = EMSGSIZE;
723 goto fail;
724 }
725 MGET(n, M_DONTWAIT, MT_DATA);
726 if (n && totlen > MLEN) {
727 MCLGET(n, M_DONTWAIT);
728 if ((n->m_flags & M_EXT) == 0) {
729 m_free(n);
730 n = NULL;
731 }
732 }
733 if (n == NULL) {
734 error = ENOBUFS;
735 goto fail;
736 }
737 m_copydata(m, off, totlen, mtod(n, caddr_t));
738 n->m_len = totlen;
739 bzero(mtod(n, caddr_t) + hdrsiz, siz);
740 (algo->update)(&algos, mtod(n, caddr_t), n->m_len);
741 m_free(n);
742 n = NULL;
743 } else {
744 ah_update_mbuf(m, off, totlen, algo, &algos);
745 }
746 ahseen++;
747
748 hdrtype = ah.ah_nxt;
749 advancewidth = totlen;
750 break;
751 }
752
753 default:
754 ah_update_mbuf(m, off, m->m_pkthdr.len - off, algo, &algos);
755 advancewidth = m->m_pkthdr.len - off;
756 break;
757 }
758
759 off += advancewidth;
760 if (off < m->m_pkthdr.len) {
761 goto again;
762 }
763
764 if (len < (*algo->sumsiz)(sav)) {
765 error = EINVAL;
766 goto fail;
767 }
768
769 (algo->result)(&algos, (caddr_t) &sumbuf[0], sizeof(sumbuf));
770 bcopy(&sumbuf[0], ahdat, (*algo->sumsiz)(sav));
771
772 if (n) {
773 m_free(n);
774 }
775 return error;
776
777 fail:
778 if (n) {
779 m_free(n);
780 }
781 return error;
782 }
783 #endif
784
785 /*
786 * Go generate the checksum. This function won't modify the mbuf chain
787 * except AH itself.
788 *
789 * NOTE: the function does not free mbuf on failure.
790 * Don't use m_copy(), it will try to share cluster mbuf by using refcnt.
791 */
792 int
ah6_calccksum(struct mbuf * m,caddr_t __sized_by (len)ahdat,size_t len,const struct ah_algorithm * algo,struct secasvar * sav)793 ah6_calccksum(struct mbuf *m, caddr_t __sized_by(len)ahdat, size_t len,
794 const struct ah_algorithm *algo, struct secasvar *sav)
795 {
796 int newoff, off;
797 int proto, nxt;
798 struct mbuf *n = NULL;
799 int error;
800 int ahseen;
801 struct ah_algorithm_state algos;
802 u_char sumbuf[AH_MAXSUMSIZE] __attribute__((aligned(4)));
803
804 if ((m->m_flags & M_PKTHDR) == 0) {
805 return EINVAL;
806 }
807
808 /*
809 * pre-compute and cache intermediate key
810 */
811 if (__improbable((error = ah_schedule(algo, sav)) != 0)) {
812 return error;
813 }
814
815 error = (algo->init)(&algos, sav);
816 if (error) {
817 return error;
818 }
819
820 off = 0;
821 proto = IPPROTO_IPV6;
822 nxt = -1;
823 ahseen = 0;
824
825 again:
826 newoff = ip6_nexthdr(m, off, proto, &nxt);
827 if (newoff < 0) {
828 newoff = m->m_pkthdr.len;
829 } else if (newoff <= off) {
830 error = EINVAL;
831 goto fail;
832 } else if (m->m_pkthdr.len < newoff) {
833 error = EINVAL;
834 goto fail;
835 }
836
837 switch (proto) {
838 case IPPROTO_IPV6:
839 /*
840 * special treatment is necessary for the first one, not others
841 */
842 if (off == 0) {
843 struct ip6_hdr ip6copy;
844
845 if (newoff - off != sizeof(struct ip6_hdr)) {
846 error = EINVAL;
847 goto fail;
848 }
849
850 m_copydata(m, off, newoff - off, (caddr_t)&ip6copy);
851 /* RFC2402 */
852 ip6copy.ip6_flow = 0;
853 ip6copy.ip6_vfc &= ~IPV6_VERSION_MASK;
854 ip6copy.ip6_vfc |= IPV6_VERSION;
855 ip6copy.ip6_hlim = 0;
856 if (IN6_IS_ADDR_LINKLOCAL(&ip6copy.ip6_src)) {
857 ip6copy.ip6_src.s6_addr16[1] = 0x0000;
858 }
859 if (IN6_IS_ADDR_LINKLOCAL(&ip6copy.ip6_dst)) {
860 ip6copy.ip6_dst.s6_addr16[1] = 0x0000;
861 }
862 (algo->update)(&algos, (caddr_t)&ip6copy,
863 sizeof(struct ip6_hdr));
864 } else {
865 newoff = m->m_pkthdr.len;
866 ah_update_mbuf(m, off, m->m_pkthdr.len - off, algo,
867 &algos);
868 }
869 break;
870
871 case IPPROTO_AH:
872 {
873 int siz;
874 int hdrsiz;
875
876 hdrsiz = (sav->flags & SADB_X_EXT_OLD)
877 ? sizeof(struct ah)
878 : sizeof(struct newah);
879 siz = (*algo->sumsiz)(sav);
880
881 /*
882 * special treatment is necessary for the first one, not others
883 */
884 if (!ahseen) {
885 if (newoff - off > MCLBYTES) {
886 error = EMSGSIZE;
887 goto fail;
888 }
889 MGET(n, M_DONTWAIT, MT_DATA);
890 if (n && newoff - off > MLEN) {
891 MCLGET(n, M_DONTWAIT);
892 if ((n->m_flags & M_EXT) == 0) {
893 m_free(n);
894 n = NULL;
895 }
896 }
897 if (n == NULL) {
898 error = ENOBUFS;
899 goto fail;
900 }
901 m_copydata(m, off, newoff - off, mtod(n, caddr_t));
902 n->m_len = newoff - off;
903 bzero(mtod(n, caddr_t) + hdrsiz, siz);
904 (algo->update)(&algos, mtod(n, caddr_t), n->m_len);
905 m_free(n);
906 n = NULL;
907 } else {
908 ah_update_mbuf(m, off, newoff - off, algo, &algos);
909 }
910 ahseen++;
911 break;
912 }
913
914 case IPPROTO_HOPOPTS:
915 case IPPROTO_DSTOPTS:
916 {
917 struct ip6_ext *ip6e;
918 int hdrlen, optlen;
919 u_int8_t *p, *optend, *optp;
920
921 if (newoff - off > MCLBYTES) {
922 error = EMSGSIZE;
923 goto fail;
924 }
925 MGET(n, M_DONTWAIT, MT_DATA);
926 if (n && newoff - off > MLEN) {
927 MCLGET(n, M_DONTWAIT);
928 if ((n->m_flags & M_EXT) == 0) {
929 m_free(n);
930 n = NULL;
931 }
932 }
933 if (n == NULL) {
934 error = ENOBUFS;
935 goto fail;
936 }
937 m_copydata(m, off, newoff - off, mtod(n, caddr_t));
938 n->m_len = newoff - off;
939
940 ip6e = mtod(n, struct ip6_ext *);
941 hdrlen = (ip6e->ip6e_len + 1) << 3;
942 if (newoff - off < hdrlen) {
943 error = EINVAL;
944 m_free(n);
945 n = NULL;
946 goto fail;
947 }
948 p = mtod(n, u_int8_t *);
949 optend = p + hdrlen;
950
951 /*
952 * ICV calculation for the options header including all
953 * options. This part is a little tricky since there are
954 * two type of options; mutable and immutable. We try to
955 * null-out mutable ones here.
956 */
957 optp = p + 2;
958 while (optp < optend) {
959 if (optp[0] == IP6OPT_PAD1) {
960 optlen = 1;
961 } else {
962 if (optp + 2 > optend) {
963 error = EINVAL;
964 m_free(n);
965 n = NULL;
966 goto fail;
967 }
968 optlen = optp[1] + 2;
969 if (optp + optlen > optend) {
970 error = EINVAL;
971 m_free(n);
972 n = NULL;
973 goto fail;
974 }
975
976 if (optp[0] & IP6OPT_MUTABLE) {
977 bzero(optp + 2, optlen - 2);
978 }
979 }
980
981 optp += optlen;
982 }
983
984 (algo->update)(&algos, mtod(n, caddr_t), n->m_len);
985 m_free(n);
986 n = NULL;
987 break;
988 }
989
990 case IPPROTO_ROUTING:
991 /*
992 * For an input packet, we can just calculate `as is'.
993 * For an output packet, we assume ip6_output have already
994 * made packet how it will be received at the final
995 * destination.
996 */
997 /* FALLTHROUGH */
998
999 default:
1000 ah_update_mbuf(m, off, newoff - off, algo, &algos);
1001 break;
1002 }
1003
1004 if (newoff < m->m_pkthdr.len) {
1005 proto = nxt;
1006 off = newoff;
1007 goto again;
1008 }
1009
1010 if (len < (*algo->sumsiz)(sav)) {
1011 error = EINVAL;
1012 goto fail;
1013 }
1014
1015 (algo->result)(&algos, (caddr_t) &sumbuf[0], sizeof(sumbuf));
1016 bcopy(&sumbuf[0], ahdat, (*algo->sumsiz)(sav));
1017
1018 /* just in case */
1019 if (n) {
1020 m_free(n);
1021 }
1022 return 0;
1023 fail:
1024 /* just in case */
1025 if (n) {
1026 m_free(n);
1027 }
1028 return error;
1029 }
1030