xref: /xnu-10063.141.1/bsd/netinet6/ah_core.c (revision d8b80295118ef25ac3a784134bcf95cd8e88109f)
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_keyed_md5_mature(struct secasvar *);
110 static int ah_keyed_md5_init(struct ah_algorithm_state *, struct secasvar *);
111 static void ah_keyed_md5_loop(struct ah_algorithm_state *, caddr_t, size_t);
112 static void ah_keyed_md5_result(struct ah_algorithm_state *, caddr_t, size_t);
113 
114 static int ah_keyed_sha1_mature(struct secasvar *);
115 static int ah_keyed_sha1_init(struct ah_algorithm_state *, struct secasvar *);
116 static void ah_keyed_sha1_loop(struct ah_algorithm_state *, caddr_t, size_t);
117 static void ah_keyed_sha1_result(struct ah_algorithm_state *, caddr_t, size_t);
118 
119 static int ah_hmac_mature(struct secasvar *);
120 static int ah_hmac_state_init(struct ah_algorithm_state *, struct secasvar *);
121 static size_t ah_hmac_schedlen(const struct ah_algorithm *);
122 static int ah_hmac_schedule(const struct ah_algorithm *, struct secasvar *);
123 static void ah_hmac_loop(struct ah_algorithm_state *, caddr_t, size_t);
124 static void ah_hmac_result(struct ah_algorithm_state *, caddr_t, size_t);
125 
126 static int ah_sumsiz_1216(struct secasvar *);
127 static const struct ccdigest_info *ah_digest_md5(void);
128 static const struct ccdigest_info *ah_digest_sha1(void);
129 #if AH_ALL_CRYPTO
130 static int ah_sumsiz_sha2_256(struct secasvar *);
131 static const struct ccdigest_info *ah_digest_sha2_256(void);
132 static int ah_sumsiz_sha2_384(struct secasvar *);
133 static const struct ccdigest_info *ah_digest_sha2_384(void);
134 static int ah_sumsiz_sha2_512(struct secasvar *);
135 static const struct ccdigest_info *ah_digest_sha2_512(void);
136 #endif /* AH_ALL_CRYPTO */
137 
138 static int ah_sumsiz_zero(struct secasvar *);
139 static int ah_none_mature(struct secasvar *);
140 static int ah_none_init(struct ah_algorithm_state *, struct secasvar *);
141 static void ah_none_loop(struct ah_algorithm_state *, caddr_t, size_t);
142 static void ah_none_result(struct ah_algorithm_state *, caddr_t, size_t);
143 
144 static 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  */
151 const struct ah_algorithm *
ah_algorithm_lookup(int idx)152 ah_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 
223 int
ah_schedule(const struct ah_algorithm * algo,struct secasvar * sav)224 ah_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(sav->sched_auth, 0, 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 
273 static int
ah_keyed_md5_mature(__unused struct secasvar * sav)274 ah_keyed_md5_mature(
275 	__unused struct secasvar *sav)
276 {
277 	/* anything is okay */
278 	return 0;
279 }
280 
281 static int
ah_keyed_md5_init(struct ah_algorithm_state * state,struct secasvar * sav)282 ah_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(buf, 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 
338 static void
ah_keyed_md5_loop(struct ah_algorithm_state * state,caddr_t addr,size_t len)339 ah_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 
352 static void
ah_keyed_md5_result(struct ah_algorithm_state * state,caddr_t addr,size_t len)353 ah_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(&digest[0], (void *)addr, sizeof(digest) > len ? len : sizeof(digest));
370 }
371 
372 static int
ah_keyed_sha1_mature(struct secasvar * sav)373 ah_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(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 
399 static int
ah_keyed_sha1_init(struct ah_algorithm_state * state,struct secasvar * sav)400 ah_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(buf, 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 
453 static void
ah_keyed_sha1_loop(struct ah_algorithm_state * state,caddr_t addr,size_t len)454 ah_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 
466 static void
ah_keyed_sha1_result(struct ah_algorithm_state * state,caddr_t addr,size_t len)467 ah_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(&digest[0], (void *)addr, sizeof(digest) > len ? len : sizeof(digest));
483 }
484 
485 static int
ah_hmac_mature(struct secasvar * sav)486 ah_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(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 
512 static int
ah_hmac_state_init(struct ah_algorithm_state * state,struct secasvar * sav)513 ah_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(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(state->hmac_ctx, sav->sched_auth, schedlen);
527 	state->digest = algo->digest();
528 
529 	return 0;
530 }
531 
532 static size_t
ah_hmac_schedlen(const struct ah_algorithm * algo)533 ah_hmac_schedlen(const struct ah_algorithm *algo)
534 {
535 	return cchmac_di_size(algo->digest());
536 }
537 
538 static int
ah_hmac_schedule(const struct ah_algorithm * algo,struct secasvar * sav)539 ah_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 
552 static void
ah_hmac_loop(struct ah_algorithm_state * state,caddr_t addr,size_t len)553 ah_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 
565 static void
ah_hmac_result(struct ah_algorithm_state * state,caddr_t addr,size_t len)566 ah_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((void *)addr, &digest[0], sizeof(digest) > len ? len : sizeof(digest));
579 }
580 
581 static int
ah_sumsiz_1216(struct secasvar * sav)582 ah_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 
594 static const struct ccdigest_info *
ah_digest_md5(void)595 ah_digest_md5(void)
596 {
597 	return g_crypto_funcs->ccmd5_di;
598 }
599 
600 static const struct ccdigest_info *
ah_digest_sha1(void)601 ah_digest_sha1(void)
602 {
603 	return g_crypto_funcs->ccsha1_di;
604 }
605 
606 #if AH_ALL_CRYPTO
607 static int
ah_sumsiz_sha2_256(struct secasvar * sav)608 ah_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 
617 static const struct ccdigest_info *
ah_digest_sha2_256(void)618 ah_digest_sha2_256(void)
619 {
620 	return g_crypto_funcs->ccsha256_di;
621 }
622 
623 static int
ah_sumsiz_sha2_384(struct secasvar * sav)624 ah_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 
633 static const struct ccdigest_info *
ah_digest_sha2_384(void)634 ah_digest_sha2_384(void)
635 {
636 	return g_crypto_funcs->ccsha384_di;
637 }
638 
639 static int
ah_sumsiz_sha2_512(struct secasvar * sav)640 ah_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 
649 static const struct ccdigest_info *
ah_digest_sha2_512(void)650 ah_digest_sha2_512(void)
651 {
652 	return g_crypto_funcs->ccsha512_di;
653 }
654 #endif /* AH_ALL_CRYPTO */
655 
656 static int
ah_sumsiz_zero(struct secasvar * sav)657 ah_sumsiz_zero(struct secasvar *sav)
658 {
659 	if (!sav) {
660 		return -1;
661 	}
662 	return 0;
663 }
664 
665 static int
ah_none_mature(struct secasvar * sav)666 ah_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 
676 static int
ah_none_init(struct ah_algorithm_state * state,struct secasvar * sav)677 ah_none_init(
678 	struct ah_algorithm_state *state,
679 	struct secasvar *sav)
680 {
681 	state->sav = sav;
682 	return 0;
683 }
684 
685 static void
ah_none_loop(__unused struct ah_algorithm_state * state,__unused caddr_t addr,__unused size_t len)686 ah_none_loop(
687 	__unused struct ah_algorithm_state *state,
688 	__unused caddr_t addr,
689 	__unused size_t len)
690 {
691 }
692 
693 static void
ah_none_result(__unused struct ah_algorithm_state * state,__unused caddr_t addr,__unused size_t len)694 ah_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  */
706 static void
ah_update_mbuf(struct mbuf * m,int off,int len,const struct ah_algorithm * algo,struct ah_algorithm_state * algos)707 ah_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  */
757 int
ah4_calccksum(struct mbuf * m,caddr_t ahdat,size_t len,const struct ah_algorithm * algo,struct secasvar * sav)758 ah4_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 
793 again:
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) {
895 invalopt:
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(p + i, 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, 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, totlen, algo, &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, m->m_pkthdr.len - off, algo, &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(&sumbuf[0], ahdat, (*algo->sumsiz)(sav));
1003 
1004 	if (n) {
1005 		m_free(n);
1006 	}
1007 	return error;
1008 
1009 fail:
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  */
1024 int
ah6_calccksum(struct mbuf * m,caddr_t ahdat,size_t len,const struct ah_algorithm * algo,struct secasvar * sav)1025 ah6_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 
1057 again:
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, m->m_pkthdr.len - off, algo,
1099 			    &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, 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, newoff - off, algo, &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(optp + 2, 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, newoff - off, algo, &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(&sumbuf[0], ahdat, (*algo->sumsiz)(sav));
1249 
1250 	/* just in case */
1251 	if (n) {
1252 		m_free(n);
1253 	}
1254 	return 0;
1255 fail:
1256 	/* just in case */
1257 	if (n) {
1258 		m_free(n);
1259 	}
1260 	return error;
1261 }
1262