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