xref: /xnu-8792.81.2/bsd/netinet6/esp_chachapoly.c (revision 19c3b8c28c31cb8130e034cfb5df6bf9ba342d90)
1*19c3b8c2SApple OSS Distributions /*
2*19c3b8c2SApple OSS Distributions  * Copyright (c) 2017, 2021 Apple Inc. All rights reserved.
3*19c3b8c2SApple OSS Distributions  *
4*19c3b8c2SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*19c3b8c2SApple OSS Distributions  *
6*19c3b8c2SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*19c3b8c2SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*19c3b8c2SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*19c3b8c2SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*19c3b8c2SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*19c3b8c2SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*19c3b8c2SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*19c3b8c2SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*19c3b8c2SApple OSS Distributions  *
15*19c3b8c2SApple OSS Distributions  * Please obtain a copy of the License at
16*19c3b8c2SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*19c3b8c2SApple OSS Distributions  *
18*19c3b8c2SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*19c3b8c2SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*19c3b8c2SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*19c3b8c2SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*19c3b8c2SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*19c3b8c2SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*19c3b8c2SApple OSS Distributions  * limitations under the License.
25*19c3b8c2SApple OSS Distributions  *
26*19c3b8c2SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*19c3b8c2SApple OSS Distributions  */
28*19c3b8c2SApple OSS Distributions 
29*19c3b8c2SApple OSS Distributions #include <sys/param.h>
30*19c3b8c2SApple OSS Distributions #include <sys/systm.h>
31*19c3b8c2SApple OSS Distributions #include <sys/socket.h>
32*19c3b8c2SApple OSS Distributions #include <sys/queue.h>
33*19c3b8c2SApple OSS Distributions #include <sys/syslog.h>
34*19c3b8c2SApple OSS Distributions #include <sys/errno.h>
35*19c3b8c2SApple OSS Distributions #include <sys/mbuf.h>
36*19c3b8c2SApple OSS Distributions #include <sys/mcache.h>
37*19c3b8c2SApple OSS Distributions #include <mach/vm_param.h>
38*19c3b8c2SApple OSS Distributions #include <kern/locks.h>
39*19c3b8c2SApple OSS Distributions #include <string.h>
40*19c3b8c2SApple OSS Distributions #include <net/if.h>
41*19c3b8c2SApple OSS Distributions #include <net/route.h>
42*19c3b8c2SApple OSS Distributions #include <net/net_osdep.h>
43*19c3b8c2SApple OSS Distributions #include <netinet6/ipsec.h>
44*19c3b8c2SApple OSS Distributions #include <netinet6/esp.h>
45*19c3b8c2SApple OSS Distributions #include <netinet6/esp_chachapoly.h>
46*19c3b8c2SApple OSS Distributions #include <netkey/key.h>
47*19c3b8c2SApple OSS Distributions #include <netkey/keydb.h>
48*19c3b8c2SApple OSS Distributions #include <corecrypto/cc.h>
49*19c3b8c2SApple OSS Distributions #include <libkern/crypto/chacha20poly1305.h>
50*19c3b8c2SApple OSS Distributions 
51*19c3b8c2SApple OSS Distributions #define ESP_CHACHAPOLY_SALT_LEN         4
52*19c3b8c2SApple OSS Distributions #define ESP_CHACHAPOLY_KEY_LEN          32
53*19c3b8c2SApple OSS Distributions #define ESP_CHACHAPOLY_NONCE_LEN        12
54*19c3b8c2SApple OSS Distributions 
55*19c3b8c2SApple OSS Distributions // The minimum alignment is documented in KALLOC_LOG2_MINALIGN
56*19c3b8c2SApple OSS Distributions // which isn't accessible from here. Current minimum is 8.
57*19c3b8c2SApple OSS Distributions _Static_assert(_Alignof(chacha20poly1305_ctx) <= 8,
58*19c3b8c2SApple OSS Distributions     "Alignment guarantee is broken");
59*19c3b8c2SApple OSS Distributions 
60*19c3b8c2SApple OSS Distributions #if (((8 * (ESP_CHACHAPOLY_KEY_LEN + ESP_CHACHAPOLY_SALT_LEN)) != ESP_CHACHAPOLY_KEYBITS_WITH_SALT) || \
61*19c3b8c2SApple OSS Distributions         (ESP_CHACHAPOLY_KEY_LEN != CCCHACHA20_KEY_NBYTES) || \
62*19c3b8c2SApple OSS Distributions         (ESP_CHACHAPOLY_NONCE_LEN != CCCHACHA20POLY1305_NONCE_NBYTES))
63*19c3b8c2SApple OSS Distributions #error "Invalid sizes"
64*19c3b8c2SApple OSS Distributions #endif
65*19c3b8c2SApple OSS Distributions 
66*19c3b8c2SApple OSS Distributions typedef struct _esp_chachapoly_ctx {
67*19c3b8c2SApple OSS Distributions 	chacha20poly1305_ctx ccp_ctx;
68*19c3b8c2SApple OSS Distributions 	uint8_t ccp_salt[ESP_CHACHAPOLY_SALT_LEN];
69*19c3b8c2SApple OSS Distributions 	bool ccp_implicit_iv;
70*19c3b8c2SApple OSS Distributions } esp_chachapoly_ctx_s, *esp_chachapoly_ctx_t;
71*19c3b8c2SApple OSS Distributions 
72*19c3b8c2SApple OSS Distributions 
73*19c3b8c2SApple OSS Distributions #define ESP_ASSERT(_cond, _format, ...)                                                                                 \
74*19c3b8c2SApple OSS Distributions 	do {                                                                                                                                            \
75*19c3b8c2SApple OSS Distributions 	        if (!(_cond)) {                                                                                                                 \
76*19c3b8c2SApple OSS Distributions 	                panic("%s:%d " _format, __FUNCTION__, __LINE__, ##__VA_ARGS__);         \
77*19c3b8c2SApple OSS Distributions 	        }                                                                                                                                               \
78*19c3b8c2SApple OSS Distributions 	} while (0)
79*19c3b8c2SApple OSS Distributions 
80*19c3b8c2SApple OSS Distributions #define ESP_CHECK_ARG(_arg) ESP_ASSERT(_arg != NULL, #_arg " is NULL")
81*19c3b8c2SApple OSS Distributions 
82*19c3b8c2SApple OSS Distributions #define _esp_log(_level, _format, ...)  \
83*19c3b8c2SApple OSS Distributions 	log(_level, "%s:%d " _format, __FUNCTION__, __LINE__, ##__VA_ARGS__)
84*19c3b8c2SApple OSS Distributions #define esp_log_err(_format, ...) _esp_log(LOG_ERR, _format, ##__VA_ARGS__)
85*19c3b8c2SApple OSS Distributions #define esp_log_default(_format, ...) _esp_log(LOG_NOTICE, _format, ##__VA_ARGS__)
86*19c3b8c2SApple OSS Distributions 
87*19c3b8c2SApple OSS Distributions #define _esp_packet_log(_level, _format, ...)  \
88*19c3b8c2SApple OSS Distributions 	ipseclog((_level, "%s:%d " _format, __FUNCTION__, __LINE__, ##__VA_ARGS__))
89*19c3b8c2SApple OSS Distributions #define esp_packet_log_err(_format, ...) _esp_packet_log(LOG_ERR, _format, ##__VA_ARGS__)
90*19c3b8c2SApple OSS Distributions 
91*19c3b8c2SApple OSS Distributions int
esp_chachapoly_mature(struct secasvar * sav)92*19c3b8c2SApple OSS Distributions esp_chachapoly_mature(struct secasvar *sav)
93*19c3b8c2SApple OSS Distributions {
94*19c3b8c2SApple OSS Distributions 	const struct esp_algorithm *algo;
95*19c3b8c2SApple OSS Distributions 
96*19c3b8c2SApple OSS Distributions 	ESP_CHECK_ARG(sav);
97*19c3b8c2SApple OSS Distributions 
98*19c3b8c2SApple OSS Distributions 	if ((sav->flags & SADB_X_EXT_OLD) != 0) {
99*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly is incompatible with SADB_X_EXT_OLD, SPI 0x%08x",
100*19c3b8c2SApple OSS Distributions 		    ntohl(sav->spi));
101*19c3b8c2SApple OSS Distributions 		return 1;
102*19c3b8c2SApple OSS Distributions 	}
103*19c3b8c2SApple OSS Distributions 	if ((sav->flags & SADB_X_EXT_DERIV) != 0) {
104*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly is incompatible with SADB_X_EXT_DERIV, SPI 0x%08x",
105*19c3b8c2SApple OSS Distributions 		    ntohl(sav->spi));
106*19c3b8c2SApple OSS Distributions 		return 1;
107*19c3b8c2SApple OSS Distributions 	}
108*19c3b8c2SApple OSS Distributions 
109*19c3b8c2SApple OSS Distributions 	if (sav->alg_enc != SADB_X_EALG_CHACHA20POLY1305) {
110*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly unsupported algorithm %d, SPI 0x%08x",
111*19c3b8c2SApple OSS Distributions 		    sav->alg_enc, ntohl(sav->spi));
112*19c3b8c2SApple OSS Distributions 		return 1;
113*19c3b8c2SApple OSS Distributions 	}
114*19c3b8c2SApple OSS Distributions 
115*19c3b8c2SApple OSS Distributions 	if (sav->key_enc == NULL) {
116*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly key is missing, SPI 0x%08x",
117*19c3b8c2SApple OSS Distributions 		    ntohl(sav->spi));
118*19c3b8c2SApple OSS Distributions 		return 1;
119*19c3b8c2SApple OSS Distributions 	}
120*19c3b8c2SApple OSS Distributions 
121*19c3b8c2SApple OSS Distributions 	algo = esp_algorithm_lookup(sav->alg_enc);
122*19c3b8c2SApple OSS Distributions 	if (algo == NULL) {
123*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly lookup failed for algorithm %d, SPI 0x%08x",
124*19c3b8c2SApple OSS Distributions 		    sav->alg_enc, ntohl(sav->spi));
125*19c3b8c2SApple OSS Distributions 		return 1;
126*19c3b8c2SApple OSS Distributions 	}
127*19c3b8c2SApple OSS Distributions 
128*19c3b8c2SApple OSS Distributions 	if (sav->key_enc->sadb_key_bits != ESP_CHACHAPOLY_KEYBITS_WITH_SALT) {
129*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly invalid key length %d bits, SPI 0x%08x",
130*19c3b8c2SApple OSS Distributions 		    sav->key_enc->sadb_key_bits, ntohl(sav->spi));
131*19c3b8c2SApple OSS Distributions 		return 1;
132*19c3b8c2SApple OSS Distributions 	}
133*19c3b8c2SApple OSS Distributions 
134*19c3b8c2SApple OSS Distributions 	esp_log_default("ChaChaPoly Mature SPI 0x%08x%s %s dir %u state %u mode %u",
135*19c3b8c2SApple OSS Distributions 	    ntohl(sav->spi),
136*19c3b8c2SApple OSS Distributions 	    (((sav->flags & SADB_X_EXT_IIV) != 0) ? " IIV" : ""),
137*19c3b8c2SApple OSS Distributions 	    ((sav->sah->ipsec_if != NULL) ? if_name(sav->sah->ipsec_if) : "NONE"),
138*19c3b8c2SApple OSS Distributions 	    sav->sah->dir, sav->sah->state, sav->sah->saidx.mode);
139*19c3b8c2SApple OSS Distributions 
140*19c3b8c2SApple OSS Distributions 	return 0;
141*19c3b8c2SApple OSS Distributions }
142*19c3b8c2SApple OSS Distributions 
143*19c3b8c2SApple OSS Distributions size_t
esp_chachapoly_schedlen(__unused const struct esp_algorithm * algo)144*19c3b8c2SApple OSS Distributions esp_chachapoly_schedlen(__unused const struct esp_algorithm *algo)
145*19c3b8c2SApple OSS Distributions {
146*19c3b8c2SApple OSS Distributions 	return sizeof(esp_chachapoly_ctx_s);
147*19c3b8c2SApple OSS Distributions }
148*19c3b8c2SApple OSS Distributions 
149*19c3b8c2SApple OSS Distributions int
esp_chachapoly_schedule(__unused const struct esp_algorithm * algo,struct secasvar * sav)150*19c3b8c2SApple OSS Distributions esp_chachapoly_schedule(__unused const struct esp_algorithm *algo,
151*19c3b8c2SApple OSS Distributions     struct secasvar *sav)
152*19c3b8c2SApple OSS Distributions {
153*19c3b8c2SApple OSS Distributions 	esp_chachapoly_ctx_t esp_ccp_ctx;
154*19c3b8c2SApple OSS Distributions 	int rc = 0;
155*19c3b8c2SApple OSS Distributions 
156*19c3b8c2SApple OSS Distributions 	ESP_CHECK_ARG(sav);
157*19c3b8c2SApple OSS Distributions 	if (_KEYLEN(sav->key_enc) != ESP_CHACHAPOLY_KEY_LEN + ESP_CHACHAPOLY_SALT_LEN) {
158*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly Invalid key len %u, SPI 0x%08x",
159*19c3b8c2SApple OSS Distributions 		    _KEYLEN(sav->key_enc), ntohl(sav->spi));
160*19c3b8c2SApple OSS Distributions 		return EINVAL;
161*19c3b8c2SApple OSS Distributions 	}
162*19c3b8c2SApple OSS Distributions 	LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
163*19c3b8c2SApple OSS Distributions 
164*19c3b8c2SApple OSS Distributions 	esp_ccp_ctx = (esp_chachapoly_ctx_t)sav->sched;
165*19c3b8c2SApple OSS Distributions 	esp_ccp_ctx->ccp_implicit_iv = ((sav->flags & SADB_X_EXT_IIV) != 0);
166*19c3b8c2SApple OSS Distributions 
167*19c3b8c2SApple OSS Distributions 	if (sav->ivlen != (esp_ccp_ctx->ccp_implicit_iv ? 0 : ESP_CHACHAPOLY_IV_LEN)) {
168*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly Invalid ivlen %u, SPI 0x%08x",
169*19c3b8c2SApple OSS Distributions 		    sav->ivlen, ntohl(sav->spi));
170*19c3b8c2SApple OSS Distributions 		return EINVAL;
171*19c3b8c2SApple OSS Distributions 	}
172*19c3b8c2SApple OSS Distributions 
173*19c3b8c2SApple OSS Distributions 	rc = chacha20poly1305_init(&esp_ccp_ctx->ccp_ctx,
174*19c3b8c2SApple OSS Distributions 	    (const uint8_t *)_KEYBUF(sav->key_enc));
175*19c3b8c2SApple OSS Distributions 	if (rc != 0) {
176*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly chacha20poly1305_init failed %d, SPI 0x%08x",
177*19c3b8c2SApple OSS Distributions 		    rc, ntohl(sav->spi));
178*19c3b8c2SApple OSS Distributions 		return rc;
179*19c3b8c2SApple OSS Distributions 	}
180*19c3b8c2SApple OSS Distributions 
181*19c3b8c2SApple OSS Distributions 	memcpy(esp_ccp_ctx->ccp_salt,
182*19c3b8c2SApple OSS Distributions 	    (const uint8_t *)_KEYBUF(sav->key_enc) + ESP_CHACHAPOLY_KEY_LEN,
183*19c3b8c2SApple OSS Distributions 	    sizeof(esp_ccp_ctx->ccp_salt));
184*19c3b8c2SApple OSS Distributions 
185*19c3b8c2SApple OSS Distributions 
186*19c3b8c2SApple OSS Distributions 	esp_log_default("ChaChaPoly Schedule SPI 0x%08x%s %s dir %u state %u mode %u",
187*19c3b8c2SApple OSS Distributions 	    ntohl(sav->spi), (esp_ccp_ctx->ccp_implicit_iv ? " IIV" : ""),
188*19c3b8c2SApple OSS Distributions 	    ((sav->sah->ipsec_if != NULL) ? if_name(sav->sah->ipsec_if) : "NONE"),
189*19c3b8c2SApple OSS Distributions 	    sav->sah->dir, sav->sah->state, sav->sah->saidx.mode);
190*19c3b8c2SApple OSS Distributions 
191*19c3b8c2SApple OSS Distributions 	return 0;
192*19c3b8c2SApple OSS Distributions }
193*19c3b8c2SApple OSS Distributions 
194*19c3b8c2SApple OSS Distributions int
esp_chachapoly_ivlen(const struct esp_algorithm * algo,struct secasvar * sav)195*19c3b8c2SApple OSS Distributions esp_chachapoly_ivlen(const struct esp_algorithm *algo,
196*19c3b8c2SApple OSS Distributions     struct secasvar *sav)
197*19c3b8c2SApple OSS Distributions {
198*19c3b8c2SApple OSS Distributions 	ESP_CHECK_ARG(algo);
199*19c3b8c2SApple OSS Distributions 
200*19c3b8c2SApple OSS Distributions 	if (sav != NULL &&
201*19c3b8c2SApple OSS Distributions 	    ((sav->sched != NULL && ((esp_chachapoly_ctx_t)sav->sched)->ccp_implicit_iv) ||
202*19c3b8c2SApple OSS Distributions 	    ((sav->flags & SADB_X_EXT_IIV) != 0))) {
203*19c3b8c2SApple OSS Distributions 		return 0;
204*19c3b8c2SApple OSS Distributions 	} else {
205*19c3b8c2SApple OSS Distributions 		return algo->ivlenval;
206*19c3b8c2SApple OSS Distributions 	}
207*19c3b8c2SApple OSS Distributions }
208*19c3b8c2SApple OSS Distributions 
209*19c3b8c2SApple OSS Distributions int
esp_chachapoly_encrypt_finalize(struct secasvar * sav,unsigned char * tag,size_t tag_bytes)210*19c3b8c2SApple OSS Distributions esp_chachapoly_encrypt_finalize(struct secasvar *sav,
211*19c3b8c2SApple OSS Distributions     unsigned char *tag,
212*19c3b8c2SApple OSS Distributions     size_t tag_bytes)
213*19c3b8c2SApple OSS Distributions {
214*19c3b8c2SApple OSS Distributions 	esp_chachapoly_ctx_t esp_ccp_ctx;
215*19c3b8c2SApple OSS Distributions 	int rc = 0;
216*19c3b8c2SApple OSS Distributions 
217*19c3b8c2SApple OSS Distributions 	ESP_CHECK_ARG(sav);
218*19c3b8c2SApple OSS Distributions 	ESP_CHECK_ARG(tag);
219*19c3b8c2SApple OSS Distributions 	if (tag_bytes != ESP_CHACHAPOLY_ICV_LEN) {
220*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly Invalid tag_bytes %zu, SPI 0x%08x",
221*19c3b8c2SApple OSS Distributions 		    tag_bytes, ntohl(sav->spi));
222*19c3b8c2SApple OSS Distributions 		return EINVAL;
223*19c3b8c2SApple OSS Distributions 	}
224*19c3b8c2SApple OSS Distributions 
225*19c3b8c2SApple OSS Distributions 	esp_ccp_ctx = (esp_chachapoly_ctx_t)sav->sched;
226*19c3b8c2SApple OSS Distributions 	rc = chacha20poly1305_finalize(&esp_ccp_ctx->ccp_ctx, tag);
227*19c3b8c2SApple OSS Distributions 	if (rc != 0) {
228*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly chacha20poly1305_finalize failed %d, SPI 0x%08x",
229*19c3b8c2SApple OSS Distributions 		    rc, ntohl(sav->spi));
230*19c3b8c2SApple OSS Distributions 		return rc;
231*19c3b8c2SApple OSS Distributions 	}
232*19c3b8c2SApple OSS Distributions 	return 0;
233*19c3b8c2SApple OSS Distributions }
234*19c3b8c2SApple OSS Distributions 
235*19c3b8c2SApple OSS Distributions int
esp_chachapoly_decrypt_finalize(struct secasvar * sav,unsigned char * tag,size_t tag_bytes)236*19c3b8c2SApple OSS Distributions esp_chachapoly_decrypt_finalize(struct secasvar *sav,
237*19c3b8c2SApple OSS Distributions     unsigned char *tag,
238*19c3b8c2SApple OSS Distributions     size_t tag_bytes)
239*19c3b8c2SApple OSS Distributions {
240*19c3b8c2SApple OSS Distributions 	esp_chachapoly_ctx_t esp_ccp_ctx;
241*19c3b8c2SApple OSS Distributions 	int rc = 0;
242*19c3b8c2SApple OSS Distributions 
243*19c3b8c2SApple OSS Distributions 	ESP_CHECK_ARG(sav);
244*19c3b8c2SApple OSS Distributions 	ESP_CHECK_ARG(tag);
245*19c3b8c2SApple OSS Distributions 	if (tag_bytes != ESP_CHACHAPOLY_ICV_LEN) {
246*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly Invalid tag_bytes %zu, SPI 0x%08x",
247*19c3b8c2SApple OSS Distributions 		    tag_bytes, ntohl(sav->spi));
248*19c3b8c2SApple OSS Distributions 		return EINVAL;
249*19c3b8c2SApple OSS Distributions 	}
250*19c3b8c2SApple OSS Distributions 
251*19c3b8c2SApple OSS Distributions 	esp_ccp_ctx = (esp_chachapoly_ctx_t)sav->sched;
252*19c3b8c2SApple OSS Distributions 	rc = chacha20poly1305_verify(&esp_ccp_ctx->ccp_ctx, tag);
253*19c3b8c2SApple OSS Distributions 	if (rc != 0) {
254*19c3b8c2SApple OSS Distributions 		esp_packet_log_err("ChaChaPoly chacha20poly1305_verify failed %d, SPI 0x%08x",
255*19c3b8c2SApple OSS Distributions 		    rc, ntohl(sav->spi));
256*19c3b8c2SApple OSS Distributions 		return rc;
257*19c3b8c2SApple OSS Distributions 	}
258*19c3b8c2SApple OSS Distributions 	return 0;
259*19c3b8c2SApple OSS Distributions }
260*19c3b8c2SApple OSS Distributions 
261*19c3b8c2SApple OSS Distributions int
esp_chachapoly_encrypt(struct mbuf * m,size_t off,__unused size_t plen,struct secasvar * sav,__unused const struct esp_algorithm * algo,int ivlen)262*19c3b8c2SApple OSS Distributions esp_chachapoly_encrypt(struct mbuf *m, // head of mbuf chain
263*19c3b8c2SApple OSS Distributions     size_t off,                                        // offset to ESP header
264*19c3b8c2SApple OSS Distributions     __unused size_t plen,
265*19c3b8c2SApple OSS Distributions     struct secasvar *sav,
266*19c3b8c2SApple OSS Distributions     __unused const struct esp_algorithm *algo,
267*19c3b8c2SApple OSS Distributions     int ivlen)
268*19c3b8c2SApple OSS Distributions {
269*19c3b8c2SApple OSS Distributions 	struct mbuf *s = m; // this mbuf
270*19c3b8c2SApple OSS Distributions 	int32_t soff = 0; // offset from the head of mbuf chain (m) to head of this mbuf (s)
271*19c3b8c2SApple OSS Distributions 	int32_t sn = 0; // offset from the head of this mbuf (s) to the body
272*19c3b8c2SApple OSS Distributions 	uint8_t *sp; // buffer of a given encryption round
273*19c3b8c2SApple OSS Distributions 	size_t len; // length of a given encryption round
274*19c3b8c2SApple OSS Distributions 	const int32_t ivoff = (int32_t)off + (int32_t)sizeof(struct newesp); // IV offset
275*19c3b8c2SApple OSS Distributions 	const size_t bodyoff = ivoff + ivlen; // body offset
276*19c3b8c2SApple OSS Distributions 	int rc = 0; // return code of corecrypto operations
277*19c3b8c2SApple OSS Distributions 	struct newesp esp_hdr; // ESP header for AAD
278*19c3b8c2SApple OSS Distributions 	_Static_assert(sizeof(esp_hdr) == 8, "Bad size");
279*19c3b8c2SApple OSS Distributions 	uint32_t nonce[ESP_CHACHAPOLY_NONCE_LEN / 4]; // ensure 32bit alignment
280*19c3b8c2SApple OSS Distributions 	_Static_assert(sizeof(nonce) == ESP_CHACHAPOLY_NONCE_LEN, "Bad nonce length");
281*19c3b8c2SApple OSS Distributions 	_Static_assert(ESP_CHACHAPOLY_SALT_LEN + ESP_CHACHAPOLY_IV_LEN == sizeof(nonce),
282*19c3b8c2SApple OSS Distributions 	    "Bad nonce length");
283*19c3b8c2SApple OSS Distributions 	esp_chachapoly_ctx_t esp_ccp_ctx;
284*19c3b8c2SApple OSS Distributions 
285*19c3b8c2SApple OSS Distributions 	ESP_CHECK_ARG(m);
286*19c3b8c2SApple OSS Distributions 	ESP_CHECK_ARG(sav);
287*19c3b8c2SApple OSS Distributions 
288*19c3b8c2SApple OSS Distributions 	esp_ccp_ctx = (esp_chachapoly_ctx_t)sav->sched;
289*19c3b8c2SApple OSS Distributions 
290*19c3b8c2SApple OSS Distributions 	if (ivlen != (esp_ccp_ctx->ccp_implicit_iv ? 0 : ESP_CHACHAPOLY_IV_LEN)) {
291*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly Invalid ivlen %u, SPI 0x%08x",
292*19c3b8c2SApple OSS Distributions 		    ivlen, ntohl(sav->spi));
293*19c3b8c2SApple OSS Distributions 		m_freem(m);
294*19c3b8c2SApple OSS Distributions 		return EINVAL;
295*19c3b8c2SApple OSS Distributions 	}
296*19c3b8c2SApple OSS Distributions 	if (sav->ivlen != ivlen) {
297*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly Invalid sav->ivlen %u, SPI 0x%08x",
298*19c3b8c2SApple OSS Distributions 		    sav->ivlen, ntohl(sav->spi));
299*19c3b8c2SApple OSS Distributions 		m_freem(m);
300*19c3b8c2SApple OSS Distributions 		return EINVAL;
301*19c3b8c2SApple OSS Distributions 	}
302*19c3b8c2SApple OSS Distributions 
303*19c3b8c2SApple OSS Distributions 	// check if total packet length is enough to contain ESP + IV
304*19c3b8c2SApple OSS Distributions 	if (m->m_pkthdr.len < bodyoff) {
305*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly Packet too short %d < %zu, SPI 0x%08x",
306*19c3b8c2SApple OSS Distributions 		    m->m_pkthdr.len, bodyoff, ntohl(sav->spi));
307*19c3b8c2SApple OSS Distributions 		m_freem(m);
308*19c3b8c2SApple OSS Distributions 		return EINVAL;
309*19c3b8c2SApple OSS Distributions 	}
310*19c3b8c2SApple OSS Distributions 
311*19c3b8c2SApple OSS Distributions 	rc = chacha20poly1305_reset(&esp_ccp_ctx->ccp_ctx);
312*19c3b8c2SApple OSS Distributions 	if (rc != 0) {
313*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly chacha20poly1305_reset failed %d, SPI 0x%08x",
314*19c3b8c2SApple OSS Distributions 		    rc, ntohl(sav->spi));
315*19c3b8c2SApple OSS Distributions 		m_freem(m);
316*19c3b8c2SApple OSS Distributions 		return rc;
317*19c3b8c2SApple OSS Distributions 	}
318*19c3b8c2SApple OSS Distributions 
319*19c3b8c2SApple OSS Distributions 	// esp_hdr is used for nonce and AAD
320*19c3b8c2SApple OSS Distributions 	m_copydata(m, (int)off, sizeof(esp_hdr), (void *)&esp_hdr);
321*19c3b8c2SApple OSS Distributions 
322*19c3b8c2SApple OSS Distributions 	// RFC 7634 dictates that the 12 byte nonce must be
323*19c3b8c2SApple OSS Distributions 	// the 4 byte salt followed by the 8 byte IV.
324*19c3b8c2SApple OSS Distributions 	memset(nonce, 0, ESP_CHACHAPOLY_NONCE_LEN);
325*19c3b8c2SApple OSS Distributions 	memcpy(nonce, esp_ccp_ctx->ccp_salt, ESP_CHACHAPOLY_SALT_LEN);
326*19c3b8c2SApple OSS Distributions 	if (!esp_ccp_ctx->ccp_implicit_iv) {
327*19c3b8c2SApple OSS Distributions 		// Increment IV and save back new value
328*19c3b8c2SApple OSS Distributions 		uint64_t iv = 0;
329*19c3b8c2SApple OSS Distributions 		_Static_assert(ESP_CHACHAPOLY_IV_LEN == sizeof(iv), "Bad IV length");
330*19c3b8c2SApple OSS Distributions 		memcpy(&iv, sav->iv, sizeof(iv));
331*19c3b8c2SApple OSS Distributions 		iv++;
332*19c3b8c2SApple OSS Distributions 		memcpy(sav->iv, &iv, sizeof(iv));
333*19c3b8c2SApple OSS Distributions 
334*19c3b8c2SApple OSS Distributions 		// Copy the new IV into the nonce and the packet
335*19c3b8c2SApple OSS Distributions 		memcpy(((uint8_t *)nonce) + ESP_CHACHAPOLY_SALT_LEN, &iv, sizeof(iv));
336*19c3b8c2SApple OSS Distributions 		m_copyback(m, ivoff, ivlen, sav->iv);
337*19c3b8c2SApple OSS Distributions 	} else {
338*19c3b8c2SApple OSS Distributions 		// Use the sequence number in the ESP header to form the
339*19c3b8c2SApple OSS Distributions 		// nonce according to RFC 8750. The first 4 bytes are the
340*19c3b8c2SApple OSS Distributions 		// salt value, the next 4 bytes are zeroes, and the final
341*19c3b8c2SApple OSS Distributions 		// 4 bytes are the ESP sequence number.
342*19c3b8c2SApple OSS Distributions 		_Static_assert(4 + sizeof(esp_hdr.esp_seq) == ESP_CHACHAPOLY_IV_LEN,
343*19c3b8c2SApple OSS Distributions 		    "Bad IV length");
344*19c3b8c2SApple OSS Distributions 		memcpy(((uint8_t *)nonce) + ESP_CHACHAPOLY_SALT_LEN + 4,
345*19c3b8c2SApple OSS Distributions 		    &esp_hdr.esp_seq, sizeof(esp_hdr.esp_seq));
346*19c3b8c2SApple OSS Distributions 	}
347*19c3b8c2SApple OSS Distributions 
348*19c3b8c2SApple OSS Distributions 	rc = chacha20poly1305_setnonce(&esp_ccp_ctx->ccp_ctx, (uint8_t *)nonce);
349*19c3b8c2SApple OSS Distributions 	cc_clear(sizeof(nonce), nonce);
350*19c3b8c2SApple OSS Distributions 	if (rc != 0) {
351*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly chacha20poly1305_setnonce failed %d, SPI 0x%08x",
352*19c3b8c2SApple OSS Distributions 		    rc, ntohl(sav->spi));
353*19c3b8c2SApple OSS Distributions 		m_freem(m);
354*19c3b8c2SApple OSS Distributions 		return rc;
355*19c3b8c2SApple OSS Distributions 	}
356*19c3b8c2SApple OSS Distributions 
357*19c3b8c2SApple OSS Distributions 	// Set Additional Authentication Data (AAD)
358*19c3b8c2SApple OSS Distributions 	rc = chacha20poly1305_aad(&esp_ccp_ctx->ccp_ctx,
359*19c3b8c2SApple OSS Distributions 	    sizeof(esp_hdr),
360*19c3b8c2SApple OSS Distributions 	    (void *)&esp_hdr);
361*19c3b8c2SApple OSS Distributions 	if (rc != 0) {
362*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly chacha20poly1305_aad failed %d, SPI 0x%08x",
363*19c3b8c2SApple OSS Distributions 		    rc, ntohl(sav->spi));
364*19c3b8c2SApple OSS Distributions 		m_freem(m);
365*19c3b8c2SApple OSS Distributions 		return rc;
366*19c3b8c2SApple OSS Distributions 	}
367*19c3b8c2SApple OSS Distributions 
368*19c3b8c2SApple OSS Distributions 	// skip headers/IV
369*19c3b8c2SApple OSS Distributions 	while (s != NULL && soff < bodyoff) {
370*19c3b8c2SApple OSS Distributions 		if (soff + s->m_len > bodyoff) {
371*19c3b8c2SApple OSS Distributions 			sn = bodyoff - soff;
372*19c3b8c2SApple OSS Distributions 			break;
373*19c3b8c2SApple OSS Distributions 		}
374*19c3b8c2SApple OSS Distributions 
375*19c3b8c2SApple OSS Distributions 		soff += s->m_len;
376*19c3b8c2SApple OSS Distributions 		s = s->m_next;
377*19c3b8c2SApple OSS Distributions 	}
378*19c3b8c2SApple OSS Distributions 
379*19c3b8c2SApple OSS Distributions 	while (s != NULL && soff < m->m_pkthdr.len) {
380*19c3b8c2SApple OSS Distributions 		len = (size_t)(s->m_len - sn);
381*19c3b8c2SApple OSS Distributions 		if (len == 0) {
382*19c3b8c2SApple OSS Distributions 			// skip empty mbufs
383*19c3b8c2SApple OSS Distributions 			continue;
384*19c3b8c2SApple OSS Distributions 		}
385*19c3b8c2SApple OSS Distributions 		sp = mtod(s, uint8_t *) + sn;
386*19c3b8c2SApple OSS Distributions 
387*19c3b8c2SApple OSS Distributions 		rc = chacha20poly1305_encrypt(&esp_ccp_ctx->ccp_ctx,
388*19c3b8c2SApple OSS Distributions 		    len, sp, sp);
389*19c3b8c2SApple OSS Distributions 		if (rc != 0) {
390*19c3b8c2SApple OSS Distributions 			esp_log_err("ChaChaPoly chacha20poly1305_encrypt failed %d, SPI 0x%08x",
391*19c3b8c2SApple OSS Distributions 			    rc, ntohl(sav->spi));
392*19c3b8c2SApple OSS Distributions 			m_freem(m);
393*19c3b8c2SApple OSS Distributions 			return rc;
394*19c3b8c2SApple OSS Distributions 		}
395*19c3b8c2SApple OSS Distributions 
396*19c3b8c2SApple OSS Distributions 		sn = 0;
397*19c3b8c2SApple OSS Distributions 		soff += s->m_len;
398*19c3b8c2SApple OSS Distributions 		s = s->m_next;
399*19c3b8c2SApple OSS Distributions 	}
400*19c3b8c2SApple OSS Distributions 	if (s == NULL && soff != m->m_pkthdr.len) {
401*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly not enough mbufs %d %d, SPI 0x%08x",
402*19c3b8c2SApple OSS Distributions 		    soff, m->m_pkthdr.len, ntohl(sav->spi));
403*19c3b8c2SApple OSS Distributions 		m_freem(m);
404*19c3b8c2SApple OSS Distributions 		return EFBIG;
405*19c3b8c2SApple OSS Distributions 	}
406*19c3b8c2SApple OSS Distributions 	return 0;
407*19c3b8c2SApple OSS Distributions }
408*19c3b8c2SApple OSS Distributions 
409*19c3b8c2SApple OSS Distributions int
esp_chachapoly_decrypt(struct mbuf * m,size_t off,struct secasvar * sav,__unused const struct esp_algorithm * algo,int ivlen)410*19c3b8c2SApple OSS Distributions esp_chachapoly_decrypt(struct mbuf *m, // head of mbuf chain
411*19c3b8c2SApple OSS Distributions     size_t off,                                        // offset to ESP header
412*19c3b8c2SApple OSS Distributions     struct secasvar *sav,
413*19c3b8c2SApple OSS Distributions     __unused const struct esp_algorithm *algo,
414*19c3b8c2SApple OSS Distributions     int ivlen)
415*19c3b8c2SApple OSS Distributions {
416*19c3b8c2SApple OSS Distributions 	struct mbuf *s = m; // this mbuf
417*19c3b8c2SApple OSS Distributions 	int32_t soff = 0; // offset from the head of mbuf chain (m) to head of this mbuf (s)
418*19c3b8c2SApple OSS Distributions 	int32_t sn = 0; // offset from the head of this mbuf (s) to the body
419*19c3b8c2SApple OSS Distributions 	uint8_t *sp; // buffer of a given encryption round
420*19c3b8c2SApple OSS Distributions 	size_t len; // length of a given encryption round
421*19c3b8c2SApple OSS Distributions 	const int32_t ivoff = (int32_t)off + (int32_t)sizeof(struct newesp); // IV offset
422*19c3b8c2SApple OSS Distributions 	const int32_t bodyoff = ivoff + ivlen; // body offset
423*19c3b8c2SApple OSS Distributions 	int rc = 0; // return code of corecrypto operations
424*19c3b8c2SApple OSS Distributions 	struct newesp esp_hdr; // ESP header for AAD
425*19c3b8c2SApple OSS Distributions 	_Static_assert(sizeof(esp_hdr) == 8, "Bad size");
426*19c3b8c2SApple OSS Distributions 	uint32_t nonce[ESP_CHACHAPOLY_NONCE_LEN / 4]; // ensure 32bit alignment
427*19c3b8c2SApple OSS Distributions 	_Static_assert(sizeof(nonce) == ESP_CHACHAPOLY_NONCE_LEN, "Bad nonce length");
428*19c3b8c2SApple OSS Distributions 	esp_chachapoly_ctx_t esp_ccp_ctx;
429*19c3b8c2SApple OSS Distributions 
430*19c3b8c2SApple OSS Distributions 	ESP_CHECK_ARG(m);
431*19c3b8c2SApple OSS Distributions 	ESP_CHECK_ARG(sav);
432*19c3b8c2SApple OSS Distributions 
433*19c3b8c2SApple OSS Distributions 	esp_ccp_ctx = (esp_chachapoly_ctx_t)sav->sched;
434*19c3b8c2SApple OSS Distributions 
435*19c3b8c2SApple OSS Distributions 	if (ivlen != (esp_ccp_ctx->ccp_implicit_iv ? 0 : ESP_CHACHAPOLY_IV_LEN)) {
436*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly Invalid ivlen %u, SPI 0x%08x",
437*19c3b8c2SApple OSS Distributions 		    ivlen, ntohl(sav->spi));
438*19c3b8c2SApple OSS Distributions 		m_freem(m);
439*19c3b8c2SApple OSS Distributions 		return EINVAL;
440*19c3b8c2SApple OSS Distributions 	}
441*19c3b8c2SApple OSS Distributions 	if (sav->ivlen != ivlen) {
442*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly Invalid sav->ivlen %u, SPI 0x%08x",
443*19c3b8c2SApple OSS Distributions 		    sav->ivlen, ntohl(sav->spi));
444*19c3b8c2SApple OSS Distributions 		m_freem(m);
445*19c3b8c2SApple OSS Distributions 		return EINVAL;
446*19c3b8c2SApple OSS Distributions 	}
447*19c3b8c2SApple OSS Distributions 
448*19c3b8c2SApple OSS Distributions 	// check if total packet length is enough to contain ESP + IV
449*19c3b8c2SApple OSS Distributions 	if (m->m_pkthdr.len < bodyoff) {
450*19c3b8c2SApple OSS Distributions 		esp_packet_log_err("ChaChaPoly Packet too short %d < %u, SPI 0x%08x",
451*19c3b8c2SApple OSS Distributions 		    m->m_pkthdr.len, bodyoff, ntohl(sav->spi));
452*19c3b8c2SApple OSS Distributions 		m_freem(m);
453*19c3b8c2SApple OSS Distributions 		return EINVAL;
454*19c3b8c2SApple OSS Distributions 	}
455*19c3b8c2SApple OSS Distributions 
456*19c3b8c2SApple OSS Distributions 	rc = chacha20poly1305_reset(&esp_ccp_ctx->ccp_ctx);
457*19c3b8c2SApple OSS Distributions 	if (rc != 0) {
458*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly chacha20poly1305_reset failed %d, SPI 0x%08x",
459*19c3b8c2SApple OSS Distributions 		    rc, ntohl(sav->spi));
460*19c3b8c2SApple OSS Distributions 		m_freem(m);
461*19c3b8c2SApple OSS Distributions 		return rc;
462*19c3b8c2SApple OSS Distributions 	}
463*19c3b8c2SApple OSS Distributions 
464*19c3b8c2SApple OSS Distributions 	m_copydata(m, (int)off, sizeof(esp_hdr), (void *)&esp_hdr);
465*19c3b8c2SApple OSS Distributions 
466*19c3b8c2SApple OSS Distributions 	// RFC 7634 dictates that the 12 byte nonce must be
467*19c3b8c2SApple OSS Distributions 	// the 4 byte salt followed by the 8 byte IV.
468*19c3b8c2SApple OSS Distributions 	memcpy(nonce, esp_ccp_ctx->ccp_salt, ESP_CHACHAPOLY_SALT_LEN);
469*19c3b8c2SApple OSS Distributions 	if (esp_ccp_ctx->ccp_implicit_iv) {
470*19c3b8c2SApple OSS Distributions 		// IV is implicit (4 zero bytes followed by the ESP sequence number)
471*19c3b8c2SApple OSS Distributions 		memset(((uint8_t *)nonce) + ESP_CHACHAPOLY_SALT_LEN, 0, 4);
472*19c3b8c2SApple OSS Distributions 		memcpy(((uint8_t *)nonce) + ESP_CHACHAPOLY_SALT_LEN + 4,
473*19c3b8c2SApple OSS Distributions 		    &esp_hdr.esp_seq, sizeof(esp_hdr.esp_seq));
474*19c3b8c2SApple OSS Distributions 		_Static_assert(4 + sizeof(esp_hdr.esp_seq) == ESP_CHACHAPOLY_IV_LEN, "Bad IV length");
475*19c3b8c2SApple OSS Distributions 	} else {
476*19c3b8c2SApple OSS Distributions 		// copy IV from packet
477*19c3b8c2SApple OSS Distributions 		m_copydata(m, ivoff, ESP_CHACHAPOLY_IV_LEN, ((uint8_t *)nonce) + ESP_CHACHAPOLY_SALT_LEN);
478*19c3b8c2SApple OSS Distributions 	}
479*19c3b8c2SApple OSS Distributions 	_Static_assert(ESP_CHACHAPOLY_SALT_LEN + ESP_CHACHAPOLY_IV_LEN == sizeof(nonce),
480*19c3b8c2SApple OSS Distributions 	    "Bad nonce length");
481*19c3b8c2SApple OSS Distributions 
482*19c3b8c2SApple OSS Distributions 	rc = chacha20poly1305_setnonce(&esp_ccp_ctx->ccp_ctx, (uint8_t *)nonce);
483*19c3b8c2SApple OSS Distributions 	if (rc != 0) {
484*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly chacha20poly1305_setnonce failed %d, SPI 0x%08x",
485*19c3b8c2SApple OSS Distributions 		    rc, ntohl(sav->spi));
486*19c3b8c2SApple OSS Distributions 		m_freem(m);
487*19c3b8c2SApple OSS Distributions 		return rc;
488*19c3b8c2SApple OSS Distributions 	}
489*19c3b8c2SApple OSS Distributions 	cc_clear(sizeof(nonce), nonce);
490*19c3b8c2SApple OSS Distributions 
491*19c3b8c2SApple OSS Distributions 	// Set Additional Authentication Data (AAD)
492*19c3b8c2SApple OSS Distributions 	rc = chacha20poly1305_aad(&esp_ccp_ctx->ccp_ctx,
493*19c3b8c2SApple OSS Distributions 	    sizeof(esp_hdr),
494*19c3b8c2SApple OSS Distributions 	    (void *)&esp_hdr);
495*19c3b8c2SApple OSS Distributions 	if (rc != 0) {
496*19c3b8c2SApple OSS Distributions 		esp_log_err("ChaChaPoly chacha20poly1305_aad failed %d, SPI 0x%08x",
497*19c3b8c2SApple OSS Distributions 		    rc, ntohl(sav->spi));
498*19c3b8c2SApple OSS Distributions 		m_freem(m);
499*19c3b8c2SApple OSS Distributions 		return rc;
500*19c3b8c2SApple OSS Distributions 	}
501*19c3b8c2SApple OSS Distributions 
502*19c3b8c2SApple OSS Distributions 	// skip headers/IV
503*19c3b8c2SApple OSS Distributions 	while (s != NULL && soff < bodyoff) {
504*19c3b8c2SApple OSS Distributions 		if (soff + s->m_len > bodyoff) {
505*19c3b8c2SApple OSS Distributions 			sn = bodyoff - soff;
506*19c3b8c2SApple OSS Distributions 			break;
507*19c3b8c2SApple OSS Distributions 		}
508*19c3b8c2SApple OSS Distributions 
509*19c3b8c2SApple OSS Distributions 		soff += s->m_len;
510*19c3b8c2SApple OSS Distributions 		s = s->m_next;
511*19c3b8c2SApple OSS Distributions 	}
512*19c3b8c2SApple OSS Distributions 
513*19c3b8c2SApple OSS Distributions 	while (s != NULL && soff < m->m_pkthdr.len) {
514*19c3b8c2SApple OSS Distributions 		len = (size_t)(s->m_len - sn);
515*19c3b8c2SApple OSS Distributions 		if (len == 0) {
516*19c3b8c2SApple OSS Distributions 			// skip empty mbufs
517*19c3b8c2SApple OSS Distributions 			continue;
518*19c3b8c2SApple OSS Distributions 		}
519*19c3b8c2SApple OSS Distributions 		sp = mtod(s, uint8_t *) + sn;
520*19c3b8c2SApple OSS Distributions 
521*19c3b8c2SApple OSS Distributions 		rc = chacha20poly1305_decrypt(&esp_ccp_ctx->ccp_ctx,
522*19c3b8c2SApple OSS Distributions 		    len, sp, sp);
523*19c3b8c2SApple OSS Distributions 		if (rc != 0) {
524*19c3b8c2SApple OSS Distributions 			esp_packet_log_err("chacha20poly1305_decrypt failed %d, SPI 0x%08x",
525*19c3b8c2SApple OSS Distributions 			    rc, ntohl(sav->spi));
526*19c3b8c2SApple OSS Distributions 			m_freem(m);
527*19c3b8c2SApple OSS Distributions 			return rc;
528*19c3b8c2SApple OSS Distributions 		}
529*19c3b8c2SApple OSS Distributions 
530*19c3b8c2SApple OSS Distributions 		sn = 0;
531*19c3b8c2SApple OSS Distributions 		soff += s->m_len;
532*19c3b8c2SApple OSS Distributions 		s = s->m_next;
533*19c3b8c2SApple OSS Distributions 	}
534*19c3b8c2SApple OSS Distributions 	if (s == NULL && soff != m->m_pkthdr.len) {
535*19c3b8c2SApple OSS Distributions 		esp_packet_log_err("not enough mbufs %d %d, SPI 0x%08x",
536*19c3b8c2SApple OSS Distributions 		    soff, m->m_pkthdr.len, ntohl(sav->spi));
537*19c3b8c2SApple OSS Distributions 		m_freem(m);
538*19c3b8c2SApple OSS Distributions 		return EFBIG;
539*19c3b8c2SApple OSS Distributions 	}
540*19c3b8c2SApple OSS Distributions 	return 0;
541*19c3b8c2SApple OSS Distributions }
542