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