Bug Summary

File:netinet/ip_esp.c
Warning:line 467, column 10
1st function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ip_esp.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/netinet/ip_esp.c
1/* $OpenBSD: ip_esp.c,v 1.193 2021/12/23 22:35:11 bluhm Exp $ */
2/*
3 * The authors of this code are John Ioannidis (ji@tla.org),
4 * Angelos D. Keromytis (kermit@csd.uch.gr) and
5 * Niels Provos (provos@physnet.uni-hamburg.de).
6 *
7 * The original version of this code was written by John Ioannidis
8 * for BSD/OS in Athens, Greece, in November 1995.
9 *
10 * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
11 * by Angelos D. Keromytis.
12 *
13 * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
14 * and Niels Provos.
15 *
16 * Additional features in 1999 by Angelos D. Keromytis.
17 *
18 * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
19 * Angelos D. Keromytis and Niels Provos.
20 * Copyright (c) 2001 Angelos D. Keromytis.
21 *
22 * Permission to use, copy, and modify this software with or without fee
23 * is hereby granted, provided that this entire notice is included in
24 * all copies of any software which is or includes a copy or
25 * modification of this software.
26 * You may use this code under the GNU public license if you so wish. Please
27 * contribute changes back to the authors under this freer than GPL license
28 * so that we may further the use of strong encryption without limitations to
29 * all.
30 *
31 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
32 * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
33 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
34 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
35 * PURPOSE.
36 */
37
38#include "pfsync.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/mbuf.h>
43#include <sys/socket.h>
44
45#include <net/if.h>
46#include <net/if_var.h>
47#include <net/bpf.h>
48
49#include <netinet/in.h>
50#include <netinet/ip.h>
51#include <netinet/ip_var.h>
52
53#ifdef INET61
54#include <netinet/ip6.h>
55#endif /* INET6 */
56
57#include <netinet/ip_ipsp.h>
58#include <netinet/ip_esp.h>
59#include <net/pfkeyv2.h>
60#include <net/if_enc.h>
61
62#if NPFSYNC1 > 0
63#include <net/pfvar.h>
64#include <net/if_pfsync.h>
65#endif /* NPFSYNC > 0 */
66
67#include <crypto/cryptodev.h>
68#include <crypto/xform.h>
69
70#include "bpfilter.h"
71
72#ifdef ENCDEBUG
73#define DPRINTF(fmt, args...)do { } while (0) \
74 do { \
75 if (encdebug) \
76 printf("%s: " fmt "\n", __func__, ## args); \
77 } while (0)
78#else
79#define DPRINTF(fmt, args...)do { } while (0) \
80 do { } while (0)
81#endif
82
83/*
84 * esp_attach() is called from the transformation initialization code.
85 */
86int
87esp_attach(void)
88{
89 return 0;
90}
91
92/*
93 * esp_init() is called when an SPI is being set up.
94 */
95int
96esp_init(struct tdb *tdbp, const struct xformsw *xsp, struct ipsecinit *ii)
97{
98 const struct enc_xform *txform = NULL((void *)0);
99 const struct auth_hash *thash = NULL((void *)0);
100 struct cryptoini cria, crie, crin;
101 int error;
102
103 if (!ii->ii_encalg && !ii->ii_authalg) {
104 DPRINTF("neither authentication nor encryption algorithm "do { } while (0)
105 "given")do { } while (0);
106 return EINVAL22;
107 }
108
109 if (ii->ii_encalg) {
110 switch (ii->ii_encalg) {
111 case SADB_EALG_NULL11:
112 txform = &enc_xform_null;
113 break;
114
115 case SADB_EALG_3DESCBC3:
116 txform = &enc_xform_3des;
117 break;
118
119 case SADB_X_EALG_AES12:
120 txform = &enc_xform_aes;
121 break;
122
123 case SADB_X_EALG_AESCTR13:
124 txform = &enc_xform_aes_ctr;
125 break;
126
127 case SADB_X_EALG_AESGCM1620:
128 txform = &enc_xform_aes_gcm;
129 break;
130
131 case SADB_X_EALG_AESGMAC21:
132 txform = &enc_xform_aes_gmac;
133 break;
134
135 case SADB_X_EALG_CHACHA20POLY130522:
136 txform = &enc_xform_chacha20_poly1305;
137 break;
138
139 case SADB_X_EALG_BLF7:
140 txform = &enc_xform_blf;
141 break;
142
143 case SADB_X_EALG_CAST6:
144 txform = &enc_xform_cast5;
145 break;
146
147 default:
148 DPRINTF("unsupported encryption algorithm %d "do { } while (0)
149 "specified",do { } while (0)
150 ii->ii_encalg)do { } while (0);
151 return EINVAL22;
152 }
153
154 if (ii->ii_enckeylen < txform->minkey) {
155 DPRINTF("keylength %d too small (min length is %d) "do { } while (0)
156 "for algorithm %s",do { } while (0)
157 ii->ii_enckeylen, txform->minkey, txform->name)do { } while (0);
158 return EINVAL22;
159 }
160
161 if (ii->ii_enckeylen > txform->maxkey) {
162 DPRINTF("keylength %d too large (max length is %d) "do { } while (0)
163 "for algorithm %s",do { } while (0)
164 ii->ii_enckeylen, txform->maxkey, txform->name)do { } while (0);
165 return EINVAL22;
166 }
167
168 if (ii->ii_encalg == SADB_X_EALG_AESGCM1620 ||
169 ii->ii_encalg == SADB_X_EALG_AESGMAC21) {
170 switch (ii->ii_enckeylen) {
171 case 20:
172 ii->ii_authalg = SADB_X_AALG_AES128GMAC9;
173 break;
174 case 28:
175 ii->ii_authalg = SADB_X_AALG_AES192GMAC10;
176 break;
177 case 36:
178 ii->ii_authalg = SADB_X_AALG_AES256GMAC11;
179 break;
180 }
181 ii->ii_authkeylen = ii->ii_enckeylen;
182 ii->ii_authkey = ii->ii_enckey;
183 } else if (ii->ii_encalg == SADB_X_EALG_CHACHA20POLY130522) {
184 ii->ii_authalg = SADB_X_AALG_CHACHA20POLY130512;
185 ii->ii_authkeylen = ii->ii_enckeylen;
186 ii->ii_authkey = ii->ii_enckey;
187 }
188
189 tdbp->tdb_encalgxform = txform;
190
191 DPRINTF("initialized TDB with enc algorithm %s", txform->name)do { } while (0);
192
193 tdbp->tdb_ivlen = txform->ivsize;
194 }
195
196 if (ii->ii_authalg) {
197 switch (ii->ii_authalg) {
198 case SADB_AALG_MD5HMAC2:
199 thash = &auth_hash_hmac_md5_96;
200 break;
201
202 case SADB_AALG_SHA1HMAC3:
203 thash = &auth_hash_hmac_sha1_96;
204 break;
205
206 case SADB_X_AALG_RIPEMD160HMAC8:
207 thash = &auth_hash_hmac_ripemd_160_96;
208 break;
209
210 case SADB_X_AALG_SHA2_2565:
211 thash = &auth_hash_hmac_sha2_256_128;
212 break;
213
214 case SADB_X_AALG_SHA2_3846:
215 thash = &auth_hash_hmac_sha2_384_192;
216 break;
217
218 case SADB_X_AALG_SHA2_5127:
219 thash = &auth_hash_hmac_sha2_512_256;
220 break;
221
222 case SADB_X_AALG_AES128GMAC9:
223 thash = &auth_hash_gmac_aes_128;
224 break;
225
226 case SADB_X_AALG_AES192GMAC10:
227 thash = &auth_hash_gmac_aes_192;
228 break;
229
230 case SADB_X_AALG_AES256GMAC11:
231 thash = &auth_hash_gmac_aes_256;
232 break;
233
234 case SADB_X_AALG_CHACHA20POLY130512:
235 thash = &auth_hash_chacha20_poly1305;
236 break;
237
238 default:
239 DPRINTF("unsupported authentication algorithm %d "do { } while (0)
240 "specified",do { } while (0)
241 ii->ii_authalg)do { } while (0);
242 return EINVAL22;
243 }
244
245 if (ii->ii_authkeylen != thash->keysize) {
246 DPRINTF("keylength %d doesn't match algorithm %s "do { } while (0)
247 "keysize (%d)",do { } while (0)
248 ii->ii_authkeylen, thash->name, thash->keysize)do { } while (0);
249 return EINVAL22;
250 }
251
252 tdbp->tdb_authalgxform = thash;
253
254 DPRINTF("initialized TDB with hash algorithm %s", thash->name)do { } while (0);
255 }
256
257 tdbp->tdb_xform = xsp;
258 tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL1;
259
260 /* Initialize crypto session */
261 if (tdbp->tdb_encalgxform) {
262 /* Save the raw keys */
263 tdbp->tdb_emxkeylen = ii->ii_enckeylen;
264 tdbp->tdb_emxkey = malloc(tdbp->tdb_emxkeylen, M_XDATA76,
265 M_WAITOK0x0001);
266 memcpy(tdbp->tdb_emxkey, ii->ii_enckey, tdbp->tdb_emxkeylen)__builtin_memcpy((tdbp->tdb_emxkey), (ii->ii_enckey), (
tdbp->tdb_emxkeylen))
;
267
268 memset(&crie, 0, sizeof(crie))__builtin_memset((&crie), (0), (sizeof(crie)));
269
270 crie.cri_alg = tdbp->tdb_encalgxform->type;
271
272 if (tdbp->tdb_authalgxform)
273 crie.cri_next = &cria;
274 else
275 crie.cri_next = NULL((void *)0);
276
277 crie.cri_klen = ii->ii_enckeylen * 8;
278 crie.cri_key = ii->ii_enckey;
279 /* XXX Rounds ? */
280 }
281
282 if (tdbp->tdb_authalgxform) {
283 /* Save the raw keys */
284 tdbp->tdb_amxkeylen = ii->ii_authkeylen;
285 tdbp->tdb_amxkey = malloc(tdbp->tdb_amxkeylen, M_XDATA76,
286 M_WAITOK0x0001);
287 memcpy(tdbp->tdb_amxkey, ii->ii_authkey, tdbp->tdb_amxkeylen)__builtin_memcpy((tdbp->tdb_amxkey), (ii->ii_authkey), (
tdbp->tdb_amxkeylen))
;
288
289 memset(&cria, 0, sizeof(cria))__builtin_memset((&cria), (0), (sizeof(cria)));
290
291 cria.cri_alg = tdbp->tdb_authalgxform->type;
292
293 if ((tdbp->tdb_wnd > 0) && (tdbp->tdb_flags & TDBF_ESN0x100000)) {
294 memset(&crin, 0, sizeof(crin))__builtin_memset((&crin), (0), (sizeof(crin)));
295 crin.cri_alg = CRYPTO_ESN23;
296 cria.cri_next = &crin;
297 }
298
299 cria.cri_klen = ii->ii_authkeylen * 8;
300 cria.cri_key = ii->ii_authkey;
301 }
302
303 KERNEL_LOCK()_kernel_lock();
304 error = crypto_newsession(&tdbp->tdb_cryptoid,
305 (tdbp->tdb_encalgxform ? &crie : &cria), 0);
306 KERNEL_UNLOCK()_kernel_unlock();
307 return error;
308}
309
310/*
311 * Paranoia.
312 */
313int
314esp_zeroize(struct tdb *tdbp)
315{
316 int error;
317
318 if (tdbp->tdb_amxkey) {
319 explicit_bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
320 free(tdbp->tdb_amxkey, M_XDATA76, tdbp->tdb_amxkeylen);
321 tdbp->tdb_amxkey = NULL((void *)0);
322 }
323
324 if (tdbp->tdb_emxkey) {
325 explicit_bzero(tdbp->tdb_emxkey, tdbp->tdb_emxkeylen);
326 free(tdbp->tdb_emxkey, M_XDATA76, tdbp->tdb_emxkeylen);
327 tdbp->tdb_emxkey = NULL((void *)0);
328 }
329
330 KERNEL_LOCK()_kernel_lock();
331 error = crypto_freesession(tdbp->tdb_cryptoid);
332 KERNEL_UNLOCK()_kernel_unlock();
333 tdbp->tdb_cryptoid = 0;
334 return error;
335}
336
337#define MAXBUFSIZ(64 > ESP_MAX_IVS ? 64 : ESP_MAX_IVS) (AH_ALEN_MAX64 > ESP_MAX_IVS ? AH_ALEN_MAX64 : ESP_MAX_IVS)
338
339/*
340 * ESP input processing, called (eventually) through the protocol switch.
341 */
342int
343esp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff)
344{
345 const struct auth_hash *esph = tdb->tdb_authalgxform;
346 const struct enc_xform *espx = tdb->tdb_encalgxform;
347 struct mbuf *m = *mp, *m1, *mo;
348 struct cryptodesc *crde = NULL((void *)0), *crda = NULL((void *)0);
349 struct cryptop *crp = NULL((void *)0);
350 int plen, alen, hlen, error, roff;
351 uint32_t btsx, esn;
1
'esn' declared without an initial value
352#ifdef ENCDEBUG
353 char buf[INET6_ADDRSTRLEN46];
354#endif
355 uint8_t abuf[AH_HMAC_MAX_HASHLEN32];
356 uint8_t lastthree[3], aalg[AH_HMAC_MAX_HASHLEN32];
357
358 /* Determine the ESP header length */
359 hlen = 2 * sizeof(u_int32_t) + tdb->tdb_ivlen; /* "new" ESP */
360 alen = esph ? esph->authsize : 0;
2
Assuming 'esph' is non-null
3
'?' condition is true
361 plen = m->m_pkthdrM_dat.MH.MH_pkthdr.len - (skip + hlen + alen);
362 if (plen <= 0) {
4
Assuming 'plen' is > 0
5
Taking false branch
363 DPRINTF("invalid payload length")do { } while (0);
364 espstat_inc(esps_badilen);
365 goto drop;
366 }
367
368 if (espx) {
6
Assuming 'espx' is null
7
Taking false branch
369 /*
370 * Verify payload length is multiple of encryption algorithm
371 * block size.
372 */
373 if (plen & (espx->blocksize - 1)) {
374 DPRINTF("payload of %d octets not a multiple "do { } while (0)
375 "of %d octets, SA %s/%08x",do { } while (0)
376 plen, espx->blocksize,do { } while (0)
377 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
378 ntohl(tdb->tdb_spi))do { } while (0);
379 espstat_inc(esps_badilen);
380 goto drop;
381 }
382 }
383
384 /* Replay window checking, if appropriate -- no value commitment. */
385 if (tdb->tdb_wnd > 0) {
8
Assuming field 'tdb_wnd' is <= 0
9
Taking false branch
386 m_copydata(m, skip + sizeof(u_int32_t), sizeof(u_int32_t),
387 &btsx);
388 btsx = ntohl(btsx)(__uint32_t)(__builtin_constant_p(btsx) ? (__uint32_t)(((__uint32_t
)(btsx) & 0xff) << 24 | ((__uint32_t)(btsx) & 0xff00
) << 8 | ((__uint32_t)(btsx) & 0xff0000) >> 8
| ((__uint32_t)(btsx) & 0xff000000) >> 24) : __swap32md
(btsx))
;
389
390 switch (checkreplaywindow(tdb, tdb->tdb_rpl, btsx, &esn, 0)) {
391 case 0: /* All's well */
392 break;
393 case 1:
394 DPRINTF("replay counter wrapped for SA %s/%08x",do { } while (0)
395 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
396 ntohl(tdb->tdb_spi))do { } while (0);
397 espstat_inc(esps_wrap);
398 goto drop;
399 case 2:
400 DPRINTF("old packet received in SA %s/%08x",do { } while (0)
401 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
402 ntohl(tdb->tdb_spi))do { } while (0);
403 espstat_inc(esps_replay);
404 goto drop;
405 case 3:
406 DPRINTF("duplicate packet received in SA %s/%08x",do { } while (0)
407 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
408 ntohl(tdb->tdb_spi))do { } while (0);
409 espstat_inc(esps_replay);
410 goto drop;
411 default:
412 DPRINTF("bogus value from checkreplaywindow() "do { } while (0)
413 "in SA %s/%08x",do { } while (0)
414 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
415 ntohl(tdb->tdb_spi))do { } while (0);
416 espstat_inc(esps_replay);
417 goto drop;
418 }
419 }
420
421 /* Update the counters */
422 tdb->tdb_cur_bytes += plen;
423 tdbstat_add(tdb, tdb_ibytes, plen);
424 espstat_add(esps_ibytes, plen);
425
426 /* Hard expiration */
427 if ((tdb->tdb_flags & TDBF_BYTES0x00004) &&
10
Assuming the condition is false
428 (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) {
429 ipsecstat_inc(ipsec_exctdb);
430 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD3);
431 tdb_delete(tdb);
432 goto drop;
433 }
434
435 /* Notify on soft expiration */
436 mtx_enter(&tdb->tdb_mtx);
437 if ((tdb->tdb_flags & TDBF_SOFT_BYTES0x00100) &&
11
Assuming the condition is false
438 (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) {
439 tdb->tdb_flags &= ~TDBF_SOFT_BYTES0x00100; /* Turn off checking */
440 mtx_leave(&tdb->tdb_mtx);
441 /* may sleep in solock() for the pfkey socket */
442 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT4);
443 } else
444 mtx_leave(&tdb->tdb_mtx);
445
446 /* Get crypto descriptors */
447 crp = crypto_getreq(esph
11.1
'esph' is non-null
&& espx
11.2
'espx' is null
? 2 : 1);
12
'?' condition is false
448 if (crp == NULL((void *)0)) {
13
Assuming 'crp' is not equal to NULL
14
Taking false branch
449 DPRINTF("failed to acquire crypto descriptors")do { } while (0);
450 espstat_inc(esps_crypto);
451 goto drop;
452 }
453
454 if (esph
14.1
'esph' is non-null
) {
15
Taking true branch
455 crda = &crp->crp_desc[0];
456 crde = &crp->crp_desc[1];
457
458 /* Authentication descriptor */
459 crda->crd_skip = skip;
460 crda->crd_inject = m->m_pkthdrM_dat.MH.MH_pkthdr.len - alen;
461
462 crda->crd_algCRD_INI.cri_alg = esph->type;
463 crda->crd_keyCRD_INI.cri_key = tdb->tdb_amxkey;
464 crda->crd_klenCRD_INI.cri_klen = tdb->tdb_amxkeylen * 8;
465
466 if ((tdb->tdb_wnd > 0) && (tdb->tdb_flags & TDBF_ESN0x100000)) {
16
Assuming field 'tdb_wnd' is > 0
17
Assuming the condition is true
18
Taking true branch
467 esn = htonl(esn)(__uint32_t)(__builtin_constant_p(esn) ? (__uint32_t)(((__uint32_t
)(esn) & 0xff) << 24 | ((__uint32_t)(esn) & 0xff00
) << 8 | ((__uint32_t)(esn) & 0xff0000) >> 8 |
((__uint32_t)(esn) & 0xff000000) >> 24) : __swap32md
(esn))
;
19
1st function call argument is an uninitialized value
468 memcpy(crda->crd_esn, &esn, 4)__builtin_memcpy((crda->CRD_INI.u.esn), (&esn), (4));
469 crda->crd_flags |= CRD_F_ESN0x20;
470 }
471
472 if (espx &&
473 (espx->type == CRYPTO_AES_GCM_1616 ||
474 espx->type == CRYPTO_CHACHA20_POLY130521))
475 crda->crd_len = hlen - tdb->tdb_ivlen;
476 else
477 crda->crd_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len - (skip + alen);
478
479 /* Copy the authenticator */
480 m_copydata(m, m->m_pkthdrM_dat.MH.MH_pkthdr.len - alen, alen, abuf);
481 } else
482 crde = &crp->crp_desc[0];
483
484 /* Crypto operation descriptor */
485 crp->crp_ilen = m->m_pkthdrM_dat.MH.MH_pkthdr.len; /* Total input length */
486 crp->crp_flags = CRYPTO_F_IMBUF0x0001 | CRYPTO_F_MPSAFE0x0004;
487 crp->crp_buf = (caddr_t)m;
488 crp->crp_sid = tdb->tdb_cryptoid;
489
490 /* Decryption descriptor */
491 if (espx) {
492 crde->crd_skip = skip + hlen;
493 crde->crd_inject = skip + hlen - tdb->tdb_ivlen;
494 crde->crd_algCRD_INI.cri_alg = espx->type;
495 crde->crd_keyCRD_INI.cri_key = tdb->tdb_emxkey;
496 crde->crd_klenCRD_INI.cri_klen = tdb->tdb_emxkeylen * 8;
497 /* XXX Rounds ? */
498
499 if (crde->crd_algCRD_INI.cri_alg == CRYPTO_AES_GMAC20)
500 crde->crd_len = 0;
501 else
502 crde->crd_len = plen;
503 }
504
505 while ((error = crypto_invoke(crp)) == EAGAIN35) {
506 /* Reset the session ID */
507 if (tdb->tdb_cryptoid != 0)
508 tdb->tdb_cryptoid = crp->crp_sid;
509 }
510 if (error) {
511 DPRINTF("crypto error %d", error)do { } while (0);
512 ipsecstat_inc(ipsec_noxform);
513 goto drop;
514 }
515
516 /* Release the crypto descriptors */
517 crypto_freereq(crp);
518 crp = NULL((void *)0);
519
520 /* If authentication was performed, check now. */
521 if (esph != NULL((void *)0)) {
522 /* Copy the authenticator from the packet */
523 m_copydata(m, m->m_pkthdrM_dat.MH.MH_pkthdr.len - esph->authsize,
524 esph->authsize, aalg);
525
526 /* Verify authenticator */
527 if (timingsafe_bcmp(abuf, aalg, esph->authsize)) {
528 DPRINTF("authentication failed for packet "do { } while (0)
529 "in SA %s/%08x",do { } while (0)
530 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
531 ntohl(tdb->tdb_spi))do { } while (0);
532 espstat_inc(esps_badauth);
533 goto drop;
534 }
535
536 /* Remove trailing authenticator */
537 m_adj(m, -(esph->authsize));
538 }
539
540 /* Replay window checking, if appropriate */
541 if (tdb->tdb_wnd > 0) {
542 m_copydata(m, skip + sizeof(u_int32_t), sizeof(u_int32_t),
543 &btsx);
544 btsx = ntohl(btsx)(__uint32_t)(__builtin_constant_p(btsx) ? (__uint32_t)(((__uint32_t
)(btsx) & 0xff) << 24 | ((__uint32_t)(btsx) & 0xff00
) << 8 | ((__uint32_t)(btsx) & 0xff0000) >> 8
| ((__uint32_t)(btsx) & 0xff000000) >> 24) : __swap32md
(btsx))
;
545
546 switch (checkreplaywindow(tdb, tdb->tdb_rpl, btsx, &esn, 1)) {
547 case 0: /* All's well */
548#if NPFSYNC1 > 0
549 pfsync_update_tdb(tdb,0);
550#endif
551 break;
552
553 case 1:
554 DPRINTF("replay counter wrapped for SA %s/%08x",do { } while (0)
555 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
556 ntohl(tdb->tdb_spi))do { } while (0);
557 espstat_inc(esps_wrap);
558 goto drop;
559 case 2:
560 DPRINTF("old packet received in SA %s/%08x",do { } while (0)
561 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
562 ntohl(tdb->tdb_spi))do { } while (0);
563 espstat_inc(esps_replay);
564 goto drop;
565 case 3:
566 DPRINTF("duplicate packet received in SA %s/%08x",do { } while (0)
567 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
568 ntohl(tdb->tdb_spi))do { } while (0);
569 espstat_inc(esps_replay);
570 goto drop;
571 default:
572 DPRINTF("bogus value from checkreplaywindow() "do { } while (0)
573 "in SA %s/%08x",do { } while (0)
574 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
575 ntohl(tdb->tdb_spi))do { } while (0);
576 espstat_inc(esps_replay);
577 goto drop;
578 }
579 }
580
581 /* Find beginning of ESP header */
582 m1 = m_getptr(m, skip, &roff);
583 if (m1 == NULL((void *)0)) {
584 DPRINTF("bad mbuf chain, SA %s/%08x",do { } while (0)
585 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
586 ntohl(tdb->tdb_spi))do { } while (0);
587 espstat_inc(esps_hdrops);
588 goto drop;
589 }
590
591 /* Remove the ESP header and IV from the mbuf. */
592 if (roff == 0) {
593 /* The ESP header was conveniently at the beginning of the mbuf */
594 m_adj(m1, hlen);
595 /*
596 * If m1 is the first mbuf, it has set M_PKTHDR and m_adj()
597 * has already adjusted the packet header length for us.
598 */
599 if (m1 != m)
600 m->m_pkthdrM_dat.MH.MH_pkthdr.len -= hlen;
601 } else if (roff + hlen >= m1->m_lenm_hdr.mh_len) {
602 int adjlen;
603
604 /*
605 * Part or all of the ESP header is at the end of this mbuf, so
606 * first let's remove the remainder of the ESP header from the
607 * beginning of the remainder of the mbuf chain, if any.
608 */
609 if (roff + hlen > m1->m_lenm_hdr.mh_len) {
610 adjlen = roff + hlen - m1->m_lenm_hdr.mh_len;
611
612 /* Adjust the next mbuf by the remainder */
613 m_adj(m1->m_nextm_hdr.mh_next, adjlen);
614
615 /* The second mbuf is guaranteed not to have a pkthdr */
616 m->m_pkthdrM_dat.MH.MH_pkthdr.len -= adjlen;
617 }
618
619 /* Now, let's unlink the mbuf chain for a second...*/
620 mo = m1->m_nextm_hdr.mh_next;
621 m1->m_nextm_hdr.mh_next = NULL((void *)0);
622
623 /* ...and trim the end of the first part of the chain...sick */
624 adjlen = m1->m_lenm_hdr.mh_len - roff;
625 m_adj(m1, -adjlen);
626 /*
627 * If m1 is the first mbuf, it has set M_PKTHDR and m_adj()
628 * has already adjusted the packet header length for us.
629 */
630 if (m1 != m)
631 m->m_pkthdrM_dat.MH.MH_pkthdr.len -= adjlen;
632
633 /* Finally, let's relink */
634 m1->m_nextm_hdr.mh_next = mo;
635 } else {
636 /*
637 * The ESP header lies in the "middle" of the mbuf...do an
638 * overlapping copy of the remainder of the mbuf over the ESP
639 * header.
640 */
641 memmove(mtod(m1, u_char *) + roff,__builtin_memmove((((u_char *)((m1)->m_hdr.mh_data)) + roff
), (((u_char *)((m1)->m_hdr.mh_data)) + roff + hlen), (m1->
m_hdr.mh_len - (roff + hlen)))
642 mtod(m1, u_char *) + roff + hlen,__builtin_memmove((((u_char *)((m1)->m_hdr.mh_data)) + roff
), (((u_char *)((m1)->m_hdr.mh_data)) + roff + hlen), (m1->
m_hdr.mh_len - (roff + hlen)))
643 m1->m_len - (roff + hlen))__builtin_memmove((((u_char *)((m1)->m_hdr.mh_data)) + roff
), (((u_char *)((m1)->m_hdr.mh_data)) + roff + hlen), (m1->
m_hdr.mh_len - (roff + hlen)))
;
644 m1->m_lenm_hdr.mh_len -= hlen;
645 m->m_pkthdrM_dat.MH.MH_pkthdr.len -= hlen;
646 }
647
648 /* Save the last three bytes of decrypted data */
649 m_copydata(m, m->m_pkthdrM_dat.MH.MH_pkthdr.len - 3, 3, lastthree);
650
651 /* Verify pad length */
652 if (lastthree[1] + 2 > m->m_pkthdrM_dat.MH.MH_pkthdr.len - skip) {
653 DPRINTF("invalid padding length %d for packet in SA %s/%08x",do { } while (0)
654 lastthree[1],do { } while (0)
655 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
656 ntohl(tdb->tdb_spi))do { } while (0);
657 espstat_inc(esps_badilen);
658 goto drop;
659 }
660
661 /* Verify correct decryption by checking the last padding bytes */
662 if ((lastthree[1] != lastthree[0]) && (lastthree[1] != 0)) {
663 DPRINTF("decryption failed for packet in SA %s/%08x",do { } while (0)
664 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
665 ntohl(tdb->tdb_spi))do { } while (0);
666 espstat_inc(esps_badenc);
667 goto drop;
668 }
669
670 /* Trim the mbuf chain to remove the padding */
671 m_adj(m, -(lastthree[1] + 2));
672
673 /* Restore the Next Protocol field */
674 m_copyback(m, protoff, sizeof(u_int8_t), lastthree + 2, M_NOWAIT0x0002);
675
676 /* Back to generic IPsec input processing */
677 return ipsec_common_input_cb(mp, tdb, skip, protoff);
678
679 drop:
680 m_freemp(mp);
681 crypto_freereq(crp);
682 return IPPROTO_DONE257;
683}
684
685/*
686 * ESP output routine, called by ipsp_process_packet().
687 */
688int
689esp_output(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
690{
691 const struct enc_xform *espx = tdb->tdb_encalgxform;
692 const struct auth_hash *esph = tdb->tdb_authalgxform;
693 int ilen, hlen, rlen, padding, blks, alen, roff, error;
694 uint64_t replay64;
695 uint32_t replay;
696 struct mbuf *mi, *mo = (struct mbuf *) NULL((void *)0);
697 unsigned char *pad;
698 uint8_t prot;
699#ifdef ENCDEBUG
700 char buf[INET6_ADDRSTRLEN46];
701#endif
702 struct cryptodesc *crde = NULL((void *)0), *crda = NULL((void *)0);
703 struct cryptop *crp = NULL((void *)0);
704#if NBPFILTER1 > 0
705 struct ifnet *encif;
706
707 if ((encif = enc_getif(tdb->tdb_rdomain, tdb->tdb_tap)) != NULL((void *)0)) {
708 encif->if_opacketsif_data.ifi_opackets++;
709 encif->if_obytesif_data.ifi_obytes += m->m_pkthdrM_dat.MH.MH_pkthdr.len;
710
711 if (encif->if_bpf) {
712 struct enchdr hdr;
713
714 memset(&hdr, 0, sizeof(hdr))__builtin_memset((&hdr), (0), (sizeof(hdr)));
715
716 hdr.af = tdb->tdb_dst.sa.sa_family;
717 hdr.spi = tdb->tdb_spi;
718 if (espx)
719 hdr.flags |= M_CONF0x0400;
720 if (esph)
721 hdr.flags |= M_AUTH0x0800;
722
723 bpf_mtap_hdr(encif->if_bpf, (char *)&hdr,
724 ENC_HDRLEN12, m, BPF_DIRECTION_OUT(1 << 1));
725 }
726 }
727#endif
728
729 hlen = 2 * sizeof(u_int32_t) + tdb->tdb_ivlen;
730
731 rlen = m->m_pkthdrM_dat.MH.MH_pkthdr.len - skip; /* Raw payload length. */
732 if (espx)
733 blks = MAX(espx->blocksize, 4)(((espx->blocksize)>(4))?(espx->blocksize):(4));
734 else
735 blks = 4; /* If no encryption, we have to be 4-byte aligned. */
736
737 padding = ((blks - ((rlen + 2) % blks)) % blks) + 2;
738
739 alen = esph ? esph->authsize : 0;
740 espstat_inc(esps_output);
741
742 switch (tdb->tdb_dst.sa.sa_family) {
743 case AF_INET2:
744 /* Check for IP maximum packet size violations. */
745 if (skip + hlen + rlen + padding + alen > IP_MAXPACKET65535) {
746 DPRINTF("packet in SA %s/%08x got too big",do { } while (0)
747 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
748 ntohl(tdb->tdb_spi))do { } while (0);
749 espstat_inc(esps_toobig);
750 error = EMSGSIZE40;
751 goto drop;
752 }
753 break;
754
755#ifdef INET61
756 case AF_INET624:
757 /* Check for IPv6 maximum packet size violations. */
758 if (skip + hlen + rlen + padding + alen > IPV6_MAXPACKET65535) {
759 DPRINTF("acket in SA %s/%08x got too big",do { } while (0)
760 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
761 ntohl(tdb->tdb_spi))do { } while (0);
762 espstat_inc(esps_toobig);
763 error = EMSGSIZE40;
764 goto drop;
765 }
766 break;
767#endif /* INET6 */
768
769 default:
770 DPRINTF("unknown/unsupported protocol family %d, SA %s/%08x",do { } while (0)
771 tdb->tdb_dst.sa.sa_family,do { } while (0)
772 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
773 ntohl(tdb->tdb_spi))do { } while (0);
774 espstat_inc(esps_nopf);
775 error = EPFNOSUPPORT46;
776 goto drop;
777 }
778
779 /* Update the counters. */
780 tdb->tdb_cur_bytes += m->m_pkthdrM_dat.MH.MH_pkthdr.len - skip;
781 espstat_add(esps_obytes, m->m_pkthdrM_dat.MH.MH_pkthdr.len - skip);
782
783 /* Hard byte expiration. */
784 if ((tdb->tdb_flags & TDBF_BYTES0x00004) &&
785 (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) {
786 ipsecstat_inc(ipsec_exctdb);
787 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD3);
788 tdb_delete(tdb);
789 error = EINVAL22;
790 goto drop;
791 }
792
793 /* Soft byte expiration. */
794 mtx_enter(&tdb->tdb_mtx);
795 if ((tdb->tdb_flags & TDBF_SOFT_BYTES0x00100) &&
796 (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) {
797 tdb->tdb_flags &= ~TDBF_SOFT_BYTES0x00100; /* Turn off checking */
798 mtx_leave(&tdb->tdb_mtx);
799 /* may sleep in solock() for the pfkey socket */
800 pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT4);
801 } else
802 mtx_leave(&tdb->tdb_mtx);
803
804 /*
805 * Loop through mbuf chain; if we find a readonly mbuf,
806 * copy the packet.
807 */
808 mi = m;
809 while (mi != NULL((void *)0) && !M_READONLY(mi)(((mi)->m_hdr.mh_flags & 0x0001) != 0 && (((mi
)->m_hdr.mh_flags & 0x0008) == 0 || ((mi)->M_dat.MH
.MH_dat.MH_ext.ext_nextref != (mi))))
)
810 mi = mi->m_nextm_hdr.mh_next;
811
812 if (mi != NULL((void *)0)) {
813 struct mbuf *n = m_dup_pkt(m, 0, M_DONTWAIT0x0002);
814
815 if (n == NULL((void *)0)) {
816 DPRINTF("bad mbuf chain, SA %s/%08x",do { } while (0)
817 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
818 ntohl(tdb->tdb_spi))do { } while (0);
819 espstat_inc(esps_hdrops);
820 error = ENOBUFS55;
821 goto drop;
822 }
823
824 m_freem(m);
825 m = n;
826 }
827
828 /* Inject ESP header. */
829 mo = m_makespace(m, skip, hlen, &roff);
830 if (mo == NULL((void *)0)) {
831 DPRINTF("failed to inject ESP header for SA %s/%08x",do { } while (0)
832 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
833 ntohl(tdb->tdb_spi))do { } while (0);
834 espstat_inc(esps_hdrops);
835 error = ENOBUFS55;
836 goto drop;
837 }
838
839 /* Initialize ESP header. */
840 memcpy(mtod(mo, caddr_t) + roff, (caddr_t) &tdb->tdb_spi,__builtin_memcpy((((caddr_t)((mo)->m_hdr.mh_data)) + roff)
, ((caddr_t) &tdb->tdb_spi), (sizeof(u_int32_t)))
841 sizeof(u_int32_t))__builtin_memcpy((((caddr_t)((mo)->m_hdr.mh_data)) + roff)
, ((caddr_t) &tdb->tdb_spi), (sizeof(u_int32_t)))
;
842 replay64 = tdb->tdb_rpl++; /* used for both header and ESN */
843 replay = htonl((u_int32_t)replay64)(__uint32_t)(__builtin_constant_p((u_int32_t)replay64) ? (__uint32_t
)(((__uint32_t)((u_int32_t)replay64) & 0xff) << 24 |
((__uint32_t)((u_int32_t)replay64) & 0xff00) << 8 |
((__uint32_t)((u_int32_t)replay64) & 0xff0000) >> 8
| ((__uint32_t)((u_int32_t)replay64) & 0xff000000) >>
24) : __swap32md((u_int32_t)replay64))
;
844 memcpy(mtod(mo, caddr_t) + roff + sizeof(u_int32_t), (caddr_t) &replay,__builtin_memcpy((((caddr_t)((mo)->m_hdr.mh_data)) + roff +
sizeof(u_int32_t)), ((caddr_t) &replay), (sizeof(u_int32_t
)))
845 sizeof(u_int32_t))__builtin_memcpy((((caddr_t)((mo)->m_hdr.mh_data)) + roff +
sizeof(u_int32_t)), ((caddr_t) &replay), (sizeof(u_int32_t
)))
;
846
847#if NPFSYNC1 > 0
848 pfsync_update_tdb(tdb,1);
849#endif
850
851 /*
852 * Add padding -- better to do it ourselves than use the crypto engine,
853 * although if/when we support compression, we'd have to do that.
854 */
855 mo = m_makespace(m, m->m_pkthdrM_dat.MH.MH_pkthdr.len, padding + alen, &roff);
856 if (mo == NULL((void *)0)) {
857 DPRINTF("m_makespace() failed for SA %s/%08x",do { } while (0)
858 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),do { } while (0)
859 ntohl(tdb->tdb_spi))do { } while (0);
860 espstat_inc(esps_hdrops);
861 error = ENOBUFS55;
862 goto drop;
863 }
864 pad = mtod(mo, caddr_t)((caddr_t)((mo)->m_hdr.mh_data)) + roff;
865
866 /* Apply self-describing padding */
867 for (ilen = 0; ilen < padding - 2; ilen++)
868 pad[ilen] = ilen + 1;
869
870 /* Fix padding length and Next Protocol in padding itself. */
871 pad[padding - 2] = padding - 2;
872 m_copydata(m, protoff, sizeof(u_int8_t), pad + padding - 1);
873
874 /* Fix Next Protocol in IPv4/IPv6 header. */
875 prot = IPPROTO_ESP50;
876 m_copyback(m, protoff, sizeof(u_int8_t), &prot, M_NOWAIT0x0002);
877
878 /* Get crypto descriptors. */
879 crp = crypto_getreq(esph && espx ? 2 : 1);
880 if (crp == NULL((void *)0)) {
881 DPRINTF("failed to acquire crypto descriptors")do { } while (0);
882 espstat_inc(esps_crypto);
883 error = ENOBUFS55;
884 goto drop;
885 }
886
887 if (espx) {
888 crde = &crp->crp_desc[0];
889 crda = &crp->crp_desc[1];
890
891 /* Encryption descriptor. */
892 crde->crd_skip = skip + hlen;
893 crde->crd_flags = CRD_F_ENCRYPT0x01 | CRD_F_IV_EXPLICIT0x04;
894 crde->crd_inject = skip + hlen - tdb->tdb_ivlen;
895
896 /* Encryption operation. */
897 crde->crd_algCRD_INI.cri_alg = espx->type;
898 crde->crd_keyCRD_INI.cri_key = tdb->tdb_emxkey;
899 crde->crd_klenCRD_INI.cri_klen = tdb->tdb_emxkeylen * 8;
900 /* XXX Rounds ? */
901
902 if (crde->crd_algCRD_INI.cri_alg == CRYPTO_AES_GMAC20)
903 crde->crd_len = 0;
904 else
905 crde->crd_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len - (skip + hlen + alen);
906
907 /* GCM & friends just require a NONCE (non-repeating!) */
908 if (espx->type == CRYPTO_AES_CTR14 ||
909 espx->type == CRYPTO_AES_GCM_1616 ||
910 espx->type == CRYPTO_CHACHA20_POLY130521)
911 bcopy(&replay64, crde->crd_ivCRD_INI.u.iv, sizeof(replay64));
912 else
913 arc4random_buf(crde->crd_ivCRD_INI.u.iv, espx->ivsize);
914 } else
915 crda = &crp->crp_desc[0];
916
917 /* Crypto operation descriptor. */
918 crp->crp_ilen = m->m_pkthdrM_dat.MH.MH_pkthdr.len; /* Total input length. */
919 crp->crp_flags = CRYPTO_F_IMBUF0x0001 | CRYPTO_F_MPSAFE0x0004;
920 crp->crp_buf = (caddr_t)m;
921 crp->crp_sid = tdb->tdb_cryptoid;
922
923 if (esph) {
924 /* Authentication descriptor. */
925 crda->crd_skip = skip;
926 crda->crd_inject = m->m_pkthdrM_dat.MH.MH_pkthdr.len - alen;
927
928 /* Authentication operation. */
929 crda->crd_algCRD_INI.cri_alg = esph->type;
930 crda->crd_keyCRD_INI.cri_key = tdb->tdb_amxkey;
931 crda->crd_klenCRD_INI.cri_klen = tdb->tdb_amxkeylen * 8;
932
933 if ((tdb->tdb_wnd > 0) && (tdb->tdb_flags & TDBF_ESN0x100000)) {
934 u_int32_t esn;
935
936 esn = htonl((u_int32_t)(replay64 >> 32))(__uint32_t)(__builtin_constant_p((u_int32_t)(replay64 >>
32)) ? (__uint32_t)(((__uint32_t)((u_int32_t)(replay64 >>
32)) & 0xff) << 24 | ((__uint32_t)((u_int32_t)(replay64
>> 32)) & 0xff00) << 8 | ((__uint32_t)((u_int32_t
)(replay64 >> 32)) & 0xff0000) >> 8 | ((__uint32_t
)((u_int32_t)(replay64 >> 32)) & 0xff000000) >>
24) : __swap32md((u_int32_t)(replay64 >> 32)))
;
937 memcpy(crda->crd_esn, &esn, 4)__builtin_memcpy((crda->CRD_INI.u.esn), (&esn), (4));
938 crda->crd_flags |= CRD_F_ESN0x20;
939 }
940
941 if (espx &&
942 (espx->type == CRYPTO_AES_GCM_1616 ||
943 espx->type == CRYPTO_CHACHA20_POLY130521))
944 crda->crd_len = hlen - tdb->tdb_ivlen;
945 else
946 crda->crd_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len - (skip + alen);
947 }
948
949 while ((error = crypto_invoke(crp)) == EAGAIN35) {
950 /* Reset the session ID */
951 if (tdb->tdb_cryptoid != 0)
952 tdb->tdb_cryptoid = crp->crp_sid;
953 }
954 if (error) {
955 DPRINTF("crypto error %d", error)do { } while (0);
956 ipsecstat_inc(ipsec_noxform);
957 goto drop;
958 }
959
960 /* Release the crypto descriptors */
961 crypto_freereq(crp);
962
963 /* Call the IPsec input callback. */
964 error = ipsp_process_done(m, tdb);
965 if (error)
966 espstat_inc(esps_outfail);
967 return (error);
968
969 drop:
970 m_freem(m);
971 crypto_freereq(crp);
972 return error;
973}
974
975#define SEEN_SIZE((((2100+32)) + ((32) - 1)) / (32)) howmany(TDB_REPLAYMAX, 32)((((2100+32)) + ((32) - 1)) / (32))
976
977/*
978 * return 0 on success
979 * return 1 for counter == 0
980 * return 2 for very old packet
981 * return 3 for packet within current window but already received
982 */
983int
984checkreplaywindow(struct tdb *tdb, u_int64_t t, u_int32_t seq, u_int32_t *seqh,
985 int commit)
986{
987 u_int32_t tl, th, wl;
988 u_int32_t packet, window = TDB_REPLAYMAX(2100+32) - TDB_REPLAYWASTE32;
989 int idx, esn = tdb->tdb_flags & TDBF_ESN0x100000;
990
991 tl = (u_int32_t)t;
992 th = (u_int32_t)(t >> 32);
993
994 /* Zero SN is not allowed */
995 if ((esn && seq == 0 && tl <= AH_HMAC_INITIAL_RPL1 && th == 0) ||
996 (!esn && seq == 0))
997 return (1);
998
999 if (th == 0 && tl < window)
1000 window = tl;
1001 /* Current replay window starts here */
1002 wl = tl - window + 1;
1003
1004 idx = (seq % TDB_REPLAYMAX(2100+32)) / 32;
1005 packet = 1 << (31 - (seq & 31));
1006
1007 /*
1008 * We keep the high part intact when:
1009 * 1) the SN is within [wl, 0xffffffff] and the whole window is
1010 * within one subspace;
1011 * 2) the SN is within [0, wl) and window spans two subspaces.
1012 */
1013 if ((tl >= window - 1 && seq >= wl) ||
1014 (tl < window - 1 && seq < wl)) {
1015 *seqh = th;
1016 if (seq > tl) {
1017 if (commit) {
1018 if (seq - tl > window)
1019 memset(tdb->tdb_seen, 0,__builtin_memset((tdb->tdb_seen), (0), (sizeof(tdb->tdb_seen
)))
1020 sizeof(tdb->tdb_seen))__builtin_memset((tdb->tdb_seen), (0), (sizeof(tdb->tdb_seen
)))
;
1021 else {
1022 int i = (tl % TDB_REPLAYMAX(2100+32)) / 32;
1023
1024 while (i != idx) {
1025 i = (i + 1) % SEEN_SIZE((((2100+32)) + ((32) - 1)) / (32));
1026 tdb->tdb_seen[i] = 0;
1027 }
1028 }
1029 tdb->tdb_seen[idx] |= packet;
1030 tdb->tdb_rpl = ((u_int64_t)*seqh << 32) | seq;
1031 }
1032 } else {
1033 if (tl - seq >= window)
1034 return (2);
1035 if (tdb->tdb_seen[idx] & packet)
1036 return (3);
1037 if (commit)
1038 tdb->tdb_seen[idx] |= packet;
1039 }
1040 return (0);
1041 }
1042
1043 /* Can't wrap if not doing ESN */
1044 if (!esn)
1045 return (2);
1046
1047 /*
1048 * (3) SN is within [wl, 0xffffffff] and wl is within
1049 * (0xffffffff-window+1, 0xffffffff].
1050 * This means we got a SN which is within our replay window,
1051 * but in the previous subspace.
1052 */
1053 if (tl < window - 1 && seq >= wl) {
1054 if (tdb->tdb_seen[idx] & packet)
1055 return (3);
1056 *seqh = th - 1;
1057 if (commit)
1058 tdb->tdb_seen[idx] |= packet;
1059 return (0);
1060 }
1061
1062 /*
1063 * (4) SN has wrapped and the last authenticated SN is in the old
1064 * subspace.
1065 */
1066 *seqh = th + 1;
1067 if (*seqh == 0) /* Don't let high bit to wrap */
1068 return (1);
1069 if (commit) {
1070 if (seq - tl > window)
1071 memset(tdb->tdb_seen, 0, sizeof(tdb->tdb_seen))__builtin_memset((tdb->tdb_seen), (0), (sizeof(tdb->tdb_seen
)))
;
1072 else {
1073 int i = (tl % TDB_REPLAYMAX(2100+32)) / 32;
1074
1075 while (i != idx) {
1076 i = (i + 1) % SEEN_SIZE((((2100+32)) + ((32) - 1)) / (32));
1077 tdb->tdb_seen[i] = 0;
1078 }
1079 }
1080 tdb->tdb_seen[idx] |= packet;
1081 tdb->tdb_rpl = ((u_int64_t)*seqh << 32) | seq;
1082 }
1083
1084 return (0);
1085}