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
109static int ah_keyed_md5_mature(struct secasvar *);
110static int ah_keyed_md5_init(struct ah_algorithm_state *, struct secasvar *);
111static void ah_keyed_md5_loop(struct ah_algorithm_state *, caddr_t, size_t);
112static void ah_keyed_md5_result(struct ah_algorithm_state *, caddr_t, size_t);
113
114static int ah_keyed_sha1_mature(struct secasvar *);
115static int ah_keyed_sha1_init(struct ah_algorithm_state *, struct secasvar *);
116static void ah_keyed_sha1_loop(struct ah_algorithm_state *, caddr_t, size_t);
117static void ah_keyed_sha1_result(struct ah_algorithm_state *, caddr_t, size_t);
118
119static int ah_hmac_mature(struct secasvar *);
120static int ah_hmac_state_init(struct ah_algorithm_state *, struct secasvar *);
121static size_t ah_hmac_schedlen(const struct ah_algorithm *);
122static int ah_hmac_schedule(const struct ah_algorithm *, struct secasvar *);
123static void ah_hmac_loop(struct ah_algorithm_state *, caddr_t, size_t);
124static void ah_hmac_result(struct ah_algorithm_state *, caddr_t, size_t);
125
126static int ah_sumsiz_1216(struct secasvar *);
127static const struct ccdigest_info *ah_digest_md5(void);
128static const struct ccdigest_info *ah_digest_sha1(void);
129#if AH_ALL_CRYPTO
130static int ah_sumsiz_sha2_256(struct secasvar *);
131static const struct ccdigest_info *ah_digest_sha2_256(void);
132static int ah_sumsiz_sha2_384(struct secasvar *);
133static const struct ccdigest_info *ah_digest_sha2_384(void);
134static int ah_sumsiz_sha2_512(struct secasvar *);
135static const struct ccdigest_info *ah_digest_sha2_512(void);
136#endif /* AH_ALL_CRYPTO */
137
138static int ah_sumsiz_zero(struct secasvar *);
139static int ah_none_mature(struct secasvar *);
140static int ah_none_init(struct ah_algorithm_state *, struct secasvar *);
141static void ah_none_loop(struct ah_algorithm_state *, caddr_t, size_t);
142static void ah_none_result(struct ah_algorithm_state *, caddr_t, size_t);
143
144static void ah_update_mbuf(struct mbuf *, int, int,
145 const struct ah_algorithm *, struct ah_algorithm_state *);
146
147/*
148 * If any algorithm requires more than 2048 bits (256 bytes) of key material,
149 * update IPSEC_KEY_AUTH_MAX_BYTES in ipsec.h
150 */
151const struct ah_algorithm *
152ah_algorithm_lookup(int idx)
153{
154 /* checksum algorithms */
155 static const struct ah_algorithm hmac_md5 =
156 { ah_sumsiz_1216, ah_hmac_mature,
157 128, 128, "hmac-md5", ah_hmac_state_init,
158 ah_hmac_loop, ah_hmac_result, ah_digest_md5,
159 ah_hmac_schedlen, ah_hmac_schedule, };
160 static const struct ah_algorithm keyed_md5 =
161 { ah_sumsiz_1216, ah_keyed_md5_mature,
162 128, 128, "keyed-md5", ah_keyed_md5_init,
163 ah_keyed_md5_loop, ah_keyed_md5_result,
164 NULL, NULL, NULL, };
165 static const struct ah_algorithm hmac_sha1 =
166 { ah_sumsiz_1216, ah_hmac_mature,
167 160, 160, "hmac-sha1", ah_hmac_state_init,
168 ah_hmac_loop, ah_hmac_result, ah_digest_sha1,
169 ah_hmac_schedlen, ah_hmac_schedule, };
170 static const struct ah_algorithm keyed_sha1 =
171 { ah_sumsiz_1216, ah_keyed_sha1_mature,
172 160, 160, "keyed-sha1", ah_keyed_sha1_init,
173 ah_keyed_sha1_loop, ah_keyed_sha1_result,
174 NULL, NULL, NULL, };
175 static const struct ah_algorithm ah_none =
176 { ah_sumsiz_zero, ah_none_mature,
177 0, 2048, "none", ah_none_init,
178 ah_none_loop, ah_none_result,
179 NULL, NULL, NULL, };
180#if AH_ALL_CRYPTO
181 static const struct ah_algorithm hmac_sha2_256 =
182 { ah_sumsiz_sha2_256, ah_hmac_mature,
183 256, 256, "hmac-sha2-256", ah_hmac_state_init,
184 ah_hmac_loop, ah_hmac_result, ah_digest_sha2_256,
185 ah_hmac_schedlen, ah_hmac_schedule, };
186 static const struct ah_algorithm hmac_sha2_384 =
187 { ah_sumsiz_sha2_384, ah_hmac_mature,
188 384, 384, "hmac-sha2-384", ah_hmac_state_init,
189 ah_hmac_loop, ah_hmac_result, ah_digest_sha2_384,
190 ah_hmac_schedlen, ah_hmac_schedule, };
191 static const struct ah_algorithm hmac_sha2_512 =
192 { ah_sumsiz_sha2_512, ah_hmac_mature,
193 512, 512, "hmac-sha2-512", ah_hmac_state_init,
194 ah_hmac_loop, ah_hmac_result, ah_digest_sha2_512,
195 ah_hmac_schedlen, ah_hmac_schedule, };
196#endif /* AH_ALL_CRYPTO */
197
198 switch (idx) {
199 case SADB_AALG_MD5HMAC:
200 return &hmac_md5;
201 case SADB_AALG_SHA1HMAC:
202 return &hmac_sha1;
203 case SADB_X_AALG_MD5:
204 return &keyed_md5;
205 case SADB_X_AALG_SHA:
206 return &keyed_sha1;
207 case SADB_X_AALG_NULL:
208 return &ah_none;
209#if AH_ALL_CRYPTO
210 case SADB_X_AALG_SHA2_256:
211 return &hmac_sha2_256;
212 case SADB_X_AALG_SHA2_384:
213 return &hmac_sha2_384;
214 case SADB_X_AALG_SHA2_512:
215 return &hmac_sha2_512;
216#endif /* AH_ALL_CRYPTO */
217 default:
218 return NULL;
219 }
220}
221
222
223int
224ah_schedule(
225 const struct ah_algorithm *algo,
226 struct secasvar *sav)
227{
228 void *sched = NULL;
229 size_t schedlen = 0;
230 int error;
231
232 lck_mtx_lock(sadb_mutex);
233 /* already allocated */
234 if (sav->sched_auth != NULL && sav->schedlen_auth != 0) {
235 lck_mtx_unlock(sadb_mutex);
236 return 0;
237 }
238
239 /* no schedule necessary */
240 if (algo->schedule == NULL || algo->schedlen == NULL) {
241 lck_mtx_unlock(sadb_mutex);
242 return 0;
243 }
244
245 schedlen = (*algo->schedlen)(algo);
246 if (__improbable((signed)schedlen < 0)) {
247 lck_mtx_unlock(sadb_mutex);
248 return EINVAL;
249 }
250
251 sched = kalloc_data(schedlen, Z_NOWAIT);
252 if (__improbable(sched == NULL)) {
253 lck_mtx_unlock(sadb_mutex);
254 return ENOBUFS;
255 }
256
257 sav->sched_auth = sched;
258 sav->schedlen_auth = schedlen;
259
260 error = (*algo->schedule)(algo, sav);
261 if (__improbable(error != 0)) {
262 ipseclog((LOG_ERR, "ah_schedule %s: error %d\n",
263 algo->name, error));
264 memset(s: sav->sched_auth, c: 0, n: sav->schedlen_auth);
265 kfree_data(sav->sched_auth, sav->schedlen_auth);
266 sav->sched_auth = NULL;
267 sav->schedlen_auth = 0;
268 }
269 lck_mtx_unlock(sadb_mutex);
270 return error;
271}
272
273static int
274ah_keyed_md5_mature(
275 __unused struct secasvar *sav)
276{
277 /* anything is okay */
278 return 0;
279}
280
281static int
282ah_keyed_md5_init(struct ah_algorithm_state *state, struct secasvar *sav)
283{
284 MD5_CTX *ctxt;
285 size_t keybitlen;
286 u_int8_t buf[32] __attribute__((aligned(4)));
287 unsigned int padlen;
288
289 if (!state) {
290 panic("ah_keyed_md5_init: what?");
291 }
292
293 state->sav = sav;
294 ctxt = &state->md5_ctx;
295 MD5Init(ctxt);
296
297 if (state->sav) {
298 MD5Update(ctxt,
299 (u_int8_t *)_KEYBUF(state->sav->key_auth),
300 (u_int)_KEYLEN(state->sav->key_auth));
301
302 /*
303 * Pad after the key.
304 * We cannot simply use md5_pad() since the function
305 * won't update the total length.
306 */
307 if (_KEYLEN(state->sav->key_auth) < 56) {
308 padlen = 64 - 8 - _KEYLEN(state->sav->key_auth);
309 } else {
310 padlen = 64 + 64 - 8 - _KEYLEN(state->sav->key_auth);
311 }
312 keybitlen = _KEYLEN(state->sav->key_auth);
313 keybitlen *= 8;
314
315 buf[0] = 0x80;
316 MD5Update(ctxt, &buf[0], 1);
317 padlen--;
318
319 bzero(s: buf, n: sizeof(buf));
320 while (sizeof(buf) < padlen) {
321 MD5Update(ctxt, &buf[0], sizeof(buf));
322 padlen -= sizeof(buf);
323 }
324 if (padlen) {
325 MD5Update(ctxt, &buf[0], padlen);
326 }
327
328 buf[0] = (keybitlen >> 0) & 0xff;
329 buf[1] = (keybitlen >> 8) & 0xff;
330 buf[2] = (keybitlen >> 16) & 0xff;
331 buf[3] = (keybitlen >> 24) & 0xff;
332 MD5Update(ctxt, buf, 8);
333 }
334
335 return 0;
336}
337
338static void
339ah_keyed_md5_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len)
340{
341 MD5_CTX *ctxt;
342
343 if (!state) {
344 panic("ah_keyed_md5_loop: what?");
345 }
346 ctxt = &state->md5_ctx;
347
348 VERIFY(len <= UINT_MAX);
349 MD5Update(ctxt, addr, (uint)len);
350}
351
352static void
353ah_keyed_md5_result(struct ah_algorithm_state *state, caddr_t addr, size_t len)
354{
355 u_char digest[16] __attribute__((aligned(4)));
356 MD5_CTX *ctxt;
357
358 if (!state) {
359 panic("ah_keyed_md5_result: what?");
360 }
361 ctxt = &state->md5_ctx;
362
363 if (state->sav) {
364 MD5Update(ctxt,
365 (u_int8_t *)_KEYBUF(state->sav->key_auth),
366 (u_int)_KEYLEN(state->sav->key_auth));
367 }
368 MD5Final(&digest[0], ctxt);
369 bcopy(src: &digest[0], dst: (void *)addr, n: sizeof(digest) > len ? len : sizeof(digest));
370}
371
372static int
373ah_keyed_sha1_mature(struct secasvar *sav)
374{
375 const struct ah_algorithm *algo;
376
377 if (!sav->key_auth) {
378 ipseclog((LOG_ERR, "ah_keyed_sha1_mature: no key is given.\n"));
379 return 1;
380 }
381
382 algo = ah_algorithm_lookup(idx: sav->alg_auth);
383 if (!algo) {
384 ipseclog((LOG_ERR, "ah_keyed_sha1_mature: unsupported algorithm.\n"));
385 return 1;
386 }
387
388 if (sav->key_auth->sadb_key_bits < algo->keymin
389 || algo->keymax < sav->key_auth->sadb_key_bits) {
390 ipseclog((LOG_ERR,
391 "ah_keyed_sha1_mature: invalid key length %d.\n",
392 sav->key_auth->sadb_key_bits));
393 return 1;
394 }
395
396 return 0;
397}
398
399static int
400ah_keyed_sha1_init(struct ah_algorithm_state *state, struct secasvar *sav)
401{
402 SHA1_CTX *ctxt;
403 size_t padlen;
404 size_t keybitlen;
405 u_int8_t buf[32] __attribute__((aligned(4)));
406
407 if (!state) {
408 panic("ah_keyed_sha1_init: what?");
409 }
410
411 state->sav = sav;
412 ctxt = &state->sha1_ctx;
413 SHA1Init(ctxt);
414
415 if (state->sav) {
416 SHA1Update(ctxt, (u_int8_t *)_KEYBUF(state->sav->key_auth),
417 (u_int)_KEYLEN(state->sav->key_auth));
418
419 /*
420 * Pad after the key.
421 */
422 if (_KEYLEN(state->sav->key_auth) < 56) {
423 padlen = 64 - 8 - _KEYLEN(state->sav->key_auth);
424 } else {
425 padlen = 64 + 64 - 8 - _KEYLEN(state->sav->key_auth);
426 }
427 keybitlen = _KEYLEN(state->sav->key_auth);
428 keybitlen *= 8;
429
430 buf[0] = 0x80;
431 SHA1Update(ctxt, &buf[0], 1);
432 padlen--;
433
434 bzero(s: buf, n: sizeof(buf));
435 while (sizeof(buf) < padlen) {
436 SHA1Update(ctxt, &buf[0], sizeof(buf));
437 padlen -= sizeof(buf);
438 }
439 if (padlen) {
440 SHA1Update(ctxt, &buf[0], padlen);
441 }
442
443 buf[0] = (keybitlen >> 0) & 0xff;
444 buf[1] = (keybitlen >> 8) & 0xff;
445 buf[2] = (keybitlen >> 16) & 0xff;
446 buf[3] = (keybitlen >> 24) & 0xff;
447 SHA1Update(ctxt, buf, 8);
448 }
449
450 return 0;
451}
452
453static void
454ah_keyed_sha1_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len)
455{
456 SHA1_CTX *ctxt;
457
458 if (!state) {
459 panic("ah_keyed_sha1_loop: what?");
460 }
461 ctxt = &state->sha1_ctx;
462
463 SHA1Update(ctxt, (caddr_t)addr, (size_t)len);
464}
465
466static void
467ah_keyed_sha1_result(struct ah_algorithm_state *state, caddr_t addr, size_t len)
468{
469 u_char digest[SHA1_RESULTLEN] __attribute__((aligned(4))); /* SHA-1 generates 160 bits */
470 SHA1_CTX *ctxt;
471
472 if (!state) {
473 panic("ah_keyed_sha1_result: what?");
474 }
475 ctxt = &state->sha1_ctx;
476
477 if (state->sav) {
478 SHA1Update(ctxt, (u_int8_t *)_KEYBUF(state->sav->key_auth),
479 (u_int)_KEYLEN(state->sav->key_auth));
480 }
481 SHA1Final((caddr_t)&digest[0], ctxt);
482 bcopy(src: &digest[0], dst: (void *)addr, n: sizeof(digest) > len ? len : sizeof(digest));
483}
484
485static int
486ah_hmac_mature(struct secasvar *sav)
487{
488 const struct ah_algorithm *algo;
489
490 if (__improbable(sav->key_auth == NULL)) {
491 ipseclog((LOG_ERR, "ah_hmac_mature: no key is given.\n"));
492 return 1;
493 }
494
495 algo = ah_algorithm_lookup(idx: sav->alg_auth);
496 if (__improbable(algo == NULL)) {
497 ipseclog((LOG_ERR, "ah_hmac_mature: unsupported algorithm.\n"));
498 return 1;
499 }
500
501 if (sav->key_auth->sadb_key_bits < algo->keymin
502 || algo->keymax < sav->key_auth->sadb_key_bits) {
503 ipseclog((LOG_ERR,
504 "ah_hmac_mature: invalid key length %d.\n",
505 sav->key_auth->sadb_key_bits));
506 return 1;
507 }
508
509 return 0;
510}
511
512static int
513ah_hmac_state_init(struct ah_algorithm_state *state, struct secasvar *sav)
514{
515 if (__improbable(state == NULL || sav == NULL)) {
516 panic("ah_hmac_state_init: what?");
517 }
518
519 const struct ah_algorithm *algo = ah_algorithm_lookup(idx: sav->alg_auth);
520 if (__improbable(algo == NULL)) {
521 ipseclog((LOG_ERR, "ah_hmac_state_init: unsupported algorithm.\n"));
522 return EINVAL;
523 }
524
525 const size_t schedlen = sav->schedlen_auth;
526 memcpy(dst: state->hmac_ctx, src: sav->sched_auth, n: schedlen);
527 state->digest = algo->digest();
528
529 return 0;
530}
531
532static size_t
533ah_hmac_schedlen(const struct ah_algorithm *algo)
534{
535 return cchmac_di_size(algo->digest());
536}
537
538static int
539ah_hmac_schedule(
540 const struct ah_algorithm *algo,
541 struct secasvar *sav)
542{
543 const struct ccdigest_info *di = algo->digest();
544 cchmac_ctx_t ctx = (cchmac_ctx_t)sav->sched_auth;
545
546 g_crypto_funcs->cchmac_init_fn(di, ctx,
547 _KEYLEN(sav->key_auth), _KEYBUF(sav->key_auth));
548
549 return 0;
550}
551
552static void
553ah_hmac_loop(
554 struct ah_algorithm_state *state, caddr_t addr, size_t len)
555{
556 if (__improbable(state == NULL || state->digest == NULL)) {
557 panic("ah_hmac_loop: what?");
558 }
559
560 VERIFY(len <= UINT_MAX);
561
562 g_crypto_funcs->cchmac_update_fn(state->digest, state->hmac_ctx, (uint)len, addr);
563}
564
565static void
566ah_hmac_result(
567 struct ah_algorithm_state *state, caddr_t addr, size_t len)
568{
569 if (__improbable(state == NULL || state->digest == NULL)) {
570 panic("ah_hmac_result: what?");
571 }
572
573 const size_t output_size = state->digest->output_size;
574 u_char digest[output_size] __attribute__((aligned(4)));
575
576 g_crypto_funcs->cchmac_final_fn(state->digest, state->hmac_ctx, &digest[0]);
577 cchmac_di_clear(state->digest, state->hmac_ctx);
578 memcpy(dst: (void *)addr, src: &digest[0], n: sizeof(digest) > len ? len : sizeof(digest));
579}
580
581static int
582ah_sumsiz_1216(struct secasvar *sav)
583{
584 if (!sav) {
585 return -1;
586 }
587 if (sav->flags & SADB_X_EXT_OLD) {
588 return 16;
589 } else {
590 return 12;
591 }
592}
593
594static const struct ccdigest_info *
595ah_digest_md5(void)
596{
597 return g_crypto_funcs->ccmd5_di;
598}
599
600static const struct ccdigest_info *
601ah_digest_sha1(void)
602{
603 return g_crypto_funcs->ccsha1_di;
604}
605
606#if AH_ALL_CRYPTO
607static int
608ah_sumsiz_sha2_256(struct secasvar *sav)
609{
610 if (!sav) {
611 return -1;
612 }
613 // return half the output size (in bytes), as per rfc 4868
614 return SHA256_DIGEST_LENGTH / 2;
615}
616
617static const struct ccdigest_info *
618ah_digest_sha2_256(void)
619{
620 return g_crypto_funcs->ccsha256_di;
621}
622
623static int
624ah_sumsiz_sha2_384(struct secasvar *sav)
625{
626 if (!sav) {
627 return -1;
628 }
629 // return half the output size (in bytes), as per rfc 4868
630 return SHA384_DIGEST_LENGTH / 2;
631}
632
633static const struct ccdigest_info *
634ah_digest_sha2_384(void)
635{
636 return g_crypto_funcs->ccsha384_di;
637}
638
639static int
640ah_sumsiz_sha2_512(struct secasvar *sav)
641{
642 if (!sav) {
643 return -1;
644 }
645 // return half the output size (in bytes), as per rfc 4868
646 return SHA512_DIGEST_LENGTH / 2;
647}
648
649static const struct ccdigest_info *
650ah_digest_sha2_512(void)
651{
652 return g_crypto_funcs->ccsha512_di;
653}
654#endif /* AH_ALL_CRYPTO */
655
656static int
657ah_sumsiz_zero(struct secasvar *sav)
658{
659 if (!sav) {
660 return -1;
661 }
662 return 0;
663}
664
665static int
666ah_none_mature(struct secasvar *sav)
667{
668 if (sav->sah->saidx.proto == IPPROTO_AH) {
669 ipseclog((LOG_ERR,
670 "ah_none_mature: protocol and algorithm mismatch.\n"));
671 return 1;
672 }
673 return 0;
674}
675
676static int
677ah_none_init(
678 struct ah_algorithm_state *state,
679 struct secasvar *sav)
680{
681 state->sav = sav;
682 return 0;
683}
684
685static void
686ah_none_loop(
687 __unused struct ah_algorithm_state *state,
688 __unused caddr_t addr,
689 __unused size_t len)
690{
691}
692
693static void
694ah_none_result(
695 __unused struct ah_algorithm_state *state,
696 __unused caddr_t addr,
697 __unused size_t len)
698{
699}
700
701/*------------------------------------------------------------*/
702
703/*
704 * go generate the checksum.
705 */
706static void
707ah_update_mbuf(struct mbuf *m, int off, int len,
708 const struct ah_algorithm *algo,
709 struct ah_algorithm_state *algos)
710{
711 struct mbuf *n;
712 int tlen;
713
714 /* easy case first */
715 if (off + len <= m->m_len) {
716 (algo->update)(algos, mtod(m, caddr_t) + off, len);
717 return;
718 }
719
720 for (n = m; n; n = n->m_next) {
721 if (off < n->m_len) {
722 break;
723 }
724
725 off -= n->m_len;
726 }
727
728 if (!n) {
729 panic("ah_update_mbuf: wrong offset specified");
730 }
731
732 for (/*nothing*/; n && len > 0; n = n->m_next) {
733 if (n->m_len == 0) {
734 continue;
735 }
736 if (n->m_len - off < len) {
737 tlen = n->m_len - off;
738 } else {
739 tlen = len;
740 }
741
742 (algo->update)(algos, mtod(n, caddr_t) + off, tlen);
743
744 len -= tlen;
745 off = 0;
746 }
747}
748
749#if INET
750/*
751 * Go generate the checksum. This function won't modify the mbuf chain
752 * except AH itself.
753 *
754 * NOTE: the function does not free mbuf on failure.
755 * Don't use m_copy(), it will try to share cluster mbuf by using refcnt.
756 */
757int
758ah4_calccksum(struct mbuf *m, caddr_t ahdat, size_t len,
759 const struct ah_algorithm *algo, struct secasvar *sav)
760{
761 int off;
762 int hdrtype;
763 size_t advancewidth;
764 struct ah_algorithm_state algos;
765 u_char sumbuf[AH_MAXSUMSIZE] __attribute__((aligned(4)));
766 int error = 0;
767 int ahseen;
768 struct mbuf *n = NULL;
769
770 if ((m->m_flags & M_PKTHDR) == 0) {
771 return EINVAL;
772 }
773
774 ahseen = 0;
775 hdrtype = -1; /*dummy, it is called IPPROTO_IP*/
776
777 off = 0;
778
779 /*
780 * pre-compute and cache intermediate key
781 */
782 if (__improbable((error = ah_schedule(algo, sav)) != 0)) {
783 return error;
784 }
785
786 error = (algo->init)(&algos, sav);
787 if (error) {
788 return error;
789 }
790
791 advancewidth = 0; /*safety*/
792
793again:
794 /* gory. */
795 switch (hdrtype) {
796 case -1: /*first one only*/
797 {
798 /*
799 * copy ip hdr, modify to fit the AH checksum rule,
800 * then take a checksum.
801 */
802 struct ip iphdr;
803 size_t hlen;
804
805 m_copydata(m, off, sizeof(iphdr), (caddr_t)&iphdr);
806#if _IP_VHL
807 hlen = IP_VHL_HL(iphdr.ip_vhl) << 2;
808#else
809 hlen = iphdr.ip_hl << 2;
810#endif
811 iphdr.ip_ttl = 0;
812 iphdr.ip_sum = htons(0);
813 if (ip4_ah_cleartos) {
814 iphdr.ip_tos = 0;
815 }
816 iphdr.ip_off = htons(ntohs(iphdr.ip_off) & ip4_ah_offsetmask);
817 (algo->update)(&algos, (caddr_t)&iphdr, sizeof(struct ip));
818
819 if (hlen != sizeof(struct ip)) {
820 u_char *p;
821 int i, l, skip;
822
823 if (hlen > MCLBYTES) {
824 error = EMSGSIZE;
825 goto fail;
826 }
827 MGET(n, M_DONTWAIT, MT_DATA);
828 if (n && hlen > MLEN) {
829 MCLGET(n, M_DONTWAIT);
830 if ((n->m_flags & M_EXT) == 0) {
831 m_free(n);
832 n = NULL;
833 }
834 }
835 if (n == NULL) {
836 error = ENOBUFS;
837 goto fail;
838 }
839 VERIFY(hlen <= INT_MAX);
840 m_copydata(m, off, (int)hlen, mtod(n, caddr_t));
841
842 /*
843 * IP options processing.
844 * See RFC2402 appendix A.
845 */
846 p = mtod(n, u_char *);
847 i = sizeof(struct ip);
848 while (i < hlen) {
849 if (i + IPOPT_OPTVAL >= hlen) {
850 ipseclog((LOG_ERR, "ah4_calccksum: "
851 "invalid IP option\n"));
852 error = EINVAL;
853 goto fail;
854 }
855 if (p[i + IPOPT_OPTVAL] == IPOPT_EOL ||
856 p[i + IPOPT_OPTVAL] == IPOPT_NOP ||
857 i + IPOPT_OLEN < hlen) {
858 ;
859 } else {
860 ipseclog((LOG_ERR,
861 "ah4_calccksum: invalid IP option "
862 "(type=%02x)\n",
863 p[i + IPOPT_OPTVAL]));
864 error = EINVAL;
865 goto fail;
866 }
867
868 skip = 1;
869 switch (p[i + IPOPT_OPTVAL]) {
870 case IPOPT_EOL:
871 case IPOPT_NOP:
872 l = 1;
873 skip = 0;
874 break;
875 case IPOPT_SECURITY: /* 0x82 */
876 case 0x85: /* Extended security */
877 case 0x86: /* Commercial security */
878 case 0x94: /* Router alert */
879 case 0x95: /* RFC1770 */
880 l = p[i + IPOPT_OLEN];
881 if (l < 2) {
882 goto invalopt;
883 }
884 skip = 0;
885 break;
886 default:
887 l = p[i + IPOPT_OLEN];
888 if (l < 2) {
889 goto invalopt;
890 }
891 skip = 1;
892 break;
893 }
894 if (l < 1 || hlen - i < l) {
895invalopt:
896 ipseclog((LOG_ERR,
897 "ah4_calccksum: invalid IP option "
898 "(type=%02x len=%02x)\n",
899 p[i + IPOPT_OPTVAL],
900 p[i + IPOPT_OLEN]));
901 error = EINVAL;
902 goto fail;
903 }
904 if (skip) {
905 bzero(s: p + i, n: l);
906 }
907 if (p[i + IPOPT_OPTVAL] == IPOPT_EOL) {
908 break;
909 }
910 i += l;
911 }
912
913 p = mtod(n, u_char *) + sizeof(struct ip);
914 (algo->update)(&algos, (caddr_t)p, hlen - sizeof(struct ip));
915
916 m_free(n);
917 n = NULL;
918 }
919
920 hdrtype = (iphdr.ip_p) & 0xff;
921 advancewidth = hlen;
922 break;
923 }
924
925 case IPPROTO_AH:
926 {
927 struct ah ah;
928 int siz;
929 int hdrsiz;
930 int totlen;
931
932 if (m->m_pkthdr.len - off < sizeof(ah)) {
933 error = EMSGSIZE;
934 goto fail;
935 }
936
937 m_copydata(m, off, sizeof(ah), (caddr_t)&ah);
938 hdrsiz = (sav->flags & SADB_X_EXT_OLD)
939 ? sizeof(struct ah)
940 : sizeof(struct newah);
941 siz = (*algo->sumsiz)(sav);
942 totlen = (ah.ah_len + 2) << 2;
943
944 if (totlen > m->m_pkthdr.len - off) {
945 error = EMSGSIZE;
946 goto fail;
947 }
948
949 /*
950 * special treatment is necessary for the first one, not others
951 */
952 if (!ahseen) {
953 if (totlen > MCLBYTES) {
954 error = EMSGSIZE;
955 goto fail;
956 }
957 MGET(n, M_DONTWAIT, MT_DATA);
958 if (n && totlen > MLEN) {
959 MCLGET(n, M_DONTWAIT);
960 if ((n->m_flags & M_EXT) == 0) {
961 m_free(n);
962 n = NULL;
963 }
964 }
965 if (n == NULL) {
966 error = ENOBUFS;
967 goto fail;
968 }
969 m_copydata(m, off, totlen, mtod(n, caddr_t));
970 n->m_len = totlen;
971 bzero(mtod(n, caddr_t) + hdrsiz, n: siz);
972 (algo->update)(&algos, mtod(n, caddr_t), n->m_len);
973 m_free(n);
974 n = NULL;
975 } else {
976 ah_update_mbuf(m, off, len: totlen, algo, algos: &algos);
977 }
978 ahseen++;
979
980 hdrtype = ah.ah_nxt;
981 advancewidth = totlen;
982 break;
983 }
984
985 default:
986 ah_update_mbuf(m, off, len: m->m_pkthdr.len - off, algo, algos: &algos);
987 advancewidth = m->m_pkthdr.len - off;
988 break;
989 }
990
991 off += advancewidth;
992 if (off < m->m_pkthdr.len) {
993 goto again;
994 }
995
996 if (len < (*algo->sumsiz)(sav)) {
997 error = EINVAL;
998 goto fail;
999 }
1000
1001 (algo->result)(&algos, (caddr_t) &sumbuf[0], sizeof(sumbuf));
1002 bcopy(src: &sumbuf[0], dst: ahdat, n: (*algo->sumsiz)(sav));
1003
1004 if (n) {
1005 m_free(n);
1006 }
1007 return error;
1008
1009fail:
1010 if (n) {
1011 m_free(n);
1012 }
1013 return error;
1014}
1015#endif
1016
1017/*
1018 * Go generate the checksum. This function won't modify the mbuf chain
1019 * except AH itself.
1020 *
1021 * NOTE: the function does not free mbuf on failure.
1022 * Don't use m_copy(), it will try to share cluster mbuf by using refcnt.
1023 */
1024int
1025ah6_calccksum(struct mbuf *m, caddr_t ahdat, size_t len,
1026 const struct ah_algorithm *algo, struct secasvar *sav)
1027{
1028 int newoff, off;
1029 int proto, nxt;
1030 struct mbuf *n = NULL;
1031 int error;
1032 int ahseen;
1033 struct ah_algorithm_state algos;
1034 u_char sumbuf[AH_MAXSUMSIZE] __attribute__((aligned(4)));
1035
1036 if ((m->m_flags & M_PKTHDR) == 0) {
1037 return EINVAL;
1038 }
1039
1040 /*
1041 * pre-compute and cache intermediate key
1042 */
1043 if (__improbable((error = ah_schedule(algo, sav)) != 0)) {
1044 return error;
1045 }
1046
1047 error = (algo->init)(&algos, sav);
1048 if (error) {
1049 return error;
1050 }
1051
1052 off = 0;
1053 proto = IPPROTO_IPV6;
1054 nxt = -1;
1055 ahseen = 0;
1056
1057again:
1058 newoff = ip6_nexthdr(m, off, proto, &nxt);
1059 if (newoff < 0) {
1060 newoff = m->m_pkthdr.len;
1061 } else if (newoff <= off) {
1062 error = EINVAL;
1063 goto fail;
1064 } else if (m->m_pkthdr.len < newoff) {
1065 error = EINVAL;
1066 goto fail;
1067 }
1068
1069 switch (proto) {
1070 case IPPROTO_IPV6:
1071 /*
1072 * special treatment is necessary for the first one, not others
1073 */
1074 if (off == 0) {
1075 struct ip6_hdr ip6copy;
1076
1077 if (newoff - off != sizeof(struct ip6_hdr)) {
1078 error = EINVAL;
1079 goto fail;
1080 }
1081
1082 m_copydata(m, off, newoff - off, (caddr_t)&ip6copy);
1083 /* RFC2402 */
1084 ip6copy.ip6_flow = 0;
1085 ip6copy.ip6_vfc &= ~IPV6_VERSION_MASK;
1086 ip6copy.ip6_vfc |= IPV6_VERSION;
1087 ip6copy.ip6_hlim = 0;
1088 if (IN6_IS_ADDR_LINKLOCAL(&ip6copy.ip6_src)) {
1089 ip6copy.ip6_src.s6_addr16[1] = 0x0000;
1090 }
1091 if (IN6_IS_ADDR_LINKLOCAL(&ip6copy.ip6_dst)) {
1092 ip6copy.ip6_dst.s6_addr16[1] = 0x0000;
1093 }
1094 (algo->update)(&algos, (caddr_t)&ip6copy,
1095 sizeof(struct ip6_hdr));
1096 } else {
1097 newoff = m->m_pkthdr.len;
1098 ah_update_mbuf(m, off, len: m->m_pkthdr.len - off, algo,
1099 algos: &algos);
1100 }
1101 break;
1102
1103 case IPPROTO_AH:
1104 {
1105 int siz;
1106 int hdrsiz;
1107
1108 hdrsiz = (sav->flags & SADB_X_EXT_OLD)
1109 ? sizeof(struct ah)
1110 : sizeof(struct newah);
1111 siz = (*algo->sumsiz)(sav);
1112
1113 /*
1114 * special treatment is necessary for the first one, not others
1115 */
1116 if (!ahseen) {
1117 if (newoff - off > MCLBYTES) {
1118 error = EMSGSIZE;
1119 goto fail;
1120 }
1121 MGET(n, M_DONTWAIT, MT_DATA);
1122 if (n && newoff - off > MLEN) {
1123 MCLGET(n, M_DONTWAIT);
1124 if ((n->m_flags & M_EXT) == 0) {
1125 m_free(n);
1126 n = NULL;
1127 }
1128 }
1129 if (n == NULL) {
1130 error = ENOBUFS;
1131 goto fail;
1132 }
1133 m_copydata(m, off, newoff - off, mtod(n, caddr_t));
1134 n->m_len = newoff - off;
1135 bzero(mtod(n, caddr_t) + hdrsiz, n: siz);
1136 (algo->update)(&algos, mtod(n, caddr_t), n->m_len);
1137 m_free(n);
1138 n = NULL;
1139 } else {
1140 ah_update_mbuf(m, off, len: newoff - off, algo, algos: &algos);
1141 }
1142 ahseen++;
1143 break;
1144 }
1145
1146 case IPPROTO_HOPOPTS:
1147 case IPPROTO_DSTOPTS:
1148 {
1149 struct ip6_ext *ip6e;
1150 int hdrlen, optlen;
1151 u_int8_t *p, *optend, *optp;
1152
1153 if (newoff - off > MCLBYTES) {
1154 error = EMSGSIZE;
1155 goto fail;
1156 }
1157 MGET(n, M_DONTWAIT, MT_DATA);
1158 if (n && newoff - off > MLEN) {
1159 MCLGET(n, M_DONTWAIT);
1160 if ((n->m_flags & M_EXT) == 0) {
1161 m_free(n);
1162 n = NULL;
1163 }
1164 }
1165 if (n == NULL) {
1166 error = ENOBUFS;
1167 goto fail;
1168 }
1169 m_copydata(m, off, newoff - off, mtod(n, caddr_t));
1170 n->m_len = newoff - off;
1171
1172 ip6e = mtod(n, struct ip6_ext *);
1173 hdrlen = (ip6e->ip6e_len + 1) << 3;
1174 if (newoff - off < hdrlen) {
1175 error = EINVAL;
1176 m_free(n);
1177 n = NULL;
1178 goto fail;
1179 }
1180 p = mtod(n, u_int8_t *);
1181 optend = p + hdrlen;
1182
1183 /*
1184 * ICV calculation for the options header including all
1185 * options. This part is a little tricky since there are
1186 * two type of options; mutable and immutable. We try to
1187 * null-out mutable ones here.
1188 */
1189 optp = p + 2;
1190 while (optp < optend) {
1191 if (optp[0] == IP6OPT_PAD1) {
1192 optlen = 1;
1193 } else {
1194 if (optp + 2 > optend) {
1195 error = EINVAL;
1196 m_free(n);
1197 n = NULL;
1198 goto fail;
1199 }
1200 optlen = optp[1] + 2;
1201 if (optp + optlen > optend) {
1202 error = EINVAL;
1203 m_free(n);
1204 n = NULL;
1205 goto fail;
1206 }
1207
1208 if (optp[0] & IP6OPT_MUTABLE) {
1209 bzero(s: optp + 2, n: optlen - 2);
1210 }
1211 }
1212
1213 optp += optlen;
1214 }
1215
1216 (algo->update)(&algos, mtod(n, caddr_t), n->m_len);
1217 m_free(n);
1218 n = NULL;
1219 break;
1220 }
1221
1222 case IPPROTO_ROUTING:
1223 /*
1224 * For an input packet, we can just calculate `as is'.
1225 * For an output packet, we assume ip6_output have already
1226 * made packet how it will be received at the final
1227 * destination.
1228 */
1229 /* FALLTHROUGH */
1230
1231 default:
1232 ah_update_mbuf(m, off, len: newoff - off, algo, algos: &algos);
1233 break;
1234 }
1235
1236 if (newoff < m->m_pkthdr.len) {
1237 proto = nxt;
1238 off = newoff;
1239 goto again;
1240 }
1241
1242 if (len < (*algo->sumsiz)(sav)) {
1243 error = EINVAL;
1244 goto fail;
1245 }
1246
1247 (algo->result)(&algos, (caddr_t) &sumbuf[0], sizeof(sumbuf));
1248 bcopy(src: &sumbuf[0], dst: ahdat, n: (*algo->sumsiz)(sav));
1249
1250 /* just in case */
1251 if (n) {
1252 m_free(n);
1253 }
1254 return 0;
1255fail:
1256 /* just in case */
1257 if (n) {
1258 m_free(n);
1259 }
1260 return error;
1261}
1262