1/*
2 * Copyright (c) 2008-2023 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29/* $FreeBSD: src/sys/netinet6/esp_core.c,v 1.1.2.4 2002/03/26 10:12:29 ume Exp $ */
30/* $KAME: esp_core.c,v 1.50 2000/11/02 12:27:38 itojun Exp $ */
31
32/*
33 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the project nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 */
60
61#define _IP_VHL
62
63#include <sys/param.h>
64#include <sys/systm.h>
65#include <sys/malloc.h>
66#include <sys/mbuf.h>
67#include <sys/domain.h>
68#include <sys/protosw.h>
69#include <sys/socket.h>
70#include <sys/errno.h>
71#include <sys/time.h>
72#include <sys/kernel.h>
73#include <sys/syslog.h>
74
75#include <kern/locks.h>
76
77#include <net/if.h>
78#include <net/multi_layer_pkt_log.h>
79#include <net/route.h>
80
81#include <netinet/in.h>
82#include <netinet/in_var.h>
83#include <netinet/ip6.h>
84#include <netinet6/ip6_var.h>
85#include <netinet/icmp6.h>
86
87#include <netinet6/ipsec.h>
88#include <netinet6/ipsec6.h>
89#include <netinet6/ah.h>
90#include <netinet6/ah6.h>
91#include <netinet6/esp.h>
92#include <netinet6/esp6.h>
93#include <netinet6/esp_rijndael.h>
94#include <netinet6/esp_chachapoly.h>
95#include <net/pfkeyv2.h>
96#include <netkey/keydb.h>
97#include <netkey/key.h>
98#include <libkern/crypto/des.h>
99
100#include <net/net_osdep.h>
101
102#include <sys/kdebug.h>
103#define DBG_LAYER_BEG NETDBG_CODE(DBG_NETIPSEC, 1)
104#define DBG_LAYER_END NETDBG_CODE(DBG_NETIPSEC, 3)
105#define DBG_FNC_ESPAUTH NETDBG_CODE(DBG_NETIPSEC, (8 << 8))
106#define MAX_SBUF_LEN 2000
107
108os_log_t esp_mpkl_log_object = NULL;
109
110static int esp_null_mature(struct secasvar *);
111static int esp_null_decrypt(struct mbuf *, size_t,
112 struct secasvar *, const struct esp_algorithm *, int);
113static int esp_null_encrypt(struct mbuf *, size_t, size_t,
114 struct secasvar *, const struct esp_algorithm *, int);
115static int esp_descbc_mature(struct secasvar *);
116static int esp_descbc_ivlen(const struct esp_algorithm *,
117 struct secasvar *);
118static int esp_des_schedule(const struct esp_algorithm *,
119 struct secasvar *);
120static size_t esp_des_schedlen(const struct esp_algorithm *);
121static int esp_des_blockdecrypt(const struct esp_algorithm *,
122 struct secasvar *, u_int8_t *, u_int8_t *);
123static int esp_des_blockencrypt(const struct esp_algorithm *,
124 struct secasvar *, u_int8_t *, u_int8_t *);
125static int esp_cbc_mature(struct secasvar *);
126static int esp_3des_schedule(const struct esp_algorithm *,
127 struct secasvar *);
128static size_t esp_3des_schedlen(const struct esp_algorithm *);
129static int esp_3des_blockdecrypt(const struct esp_algorithm *,
130 struct secasvar *, u_int8_t *, u_int8_t *);
131static int esp_3des_blockencrypt(const struct esp_algorithm *,
132 struct secasvar *, u_int8_t *, u_int8_t *);
133static int esp_common_ivlen(const struct esp_algorithm *,
134 struct secasvar *);
135static int esp_cbc_decrypt(struct mbuf *, size_t,
136 struct secasvar *, const struct esp_algorithm *, int);
137static int esp_cbc_encrypt(struct mbuf *, size_t, size_t,
138 struct secasvar *, const struct esp_algorithm *, int);
139static int esp_gcm_mature(struct secasvar *);
140static int esp_cbc_des_encrypt_data(struct secasvar *, uint8_t *,
141 size_t, struct newesp *, uint8_t *, size_t, uint8_t *, size_t);
142static int esp_cbc_des_decrypt_data(struct secasvar *, uint8_t *,
143 size_t, struct newesp *, uint8_t *, size_t, uint8_t *, size_t);
144static int esp_cbc_3des_encrypt_data(struct secasvar *, uint8_t *,
145 size_t, struct newesp *, uint8_t *, size_t, uint8_t *, size_t);
146static int esp_cbc_3des_decrypt_data(struct secasvar *, uint8_t *,
147 size_t, struct newesp *, uint8_t *, size_t, uint8_t *, size_t);
148static int esp_null_encrypt_data(struct secasvar *, uint8_t *,
149 size_t, struct newesp *, uint8_t *, size_t, uint8_t *, size_t);
150static int esp_null_decrypt_data(struct secasvar *, uint8_t *,
151 size_t, struct newesp *, uint8_t *, size_t, uint8_t *, size_t);
152
153#define MAXIVLEN 16
154
155#define ESP_AESGCM_KEYLEN128 160 // 16-bytes key + 4 bytes salt
156#define ESP_AESGCM_KEYLEN192 224 // 24-bytes key + 4 bytes salt
157#define ESP_AESGCM_KEYLEN256 288 // 32-bytes key + 4 bytes salt
158
159static const struct esp_algorithm des_cbc = {
160 .padbound = 8,
161 .ivlenval = -1,
162 .mature = esp_descbc_mature,
163 .keymin = 64,
164 .keymax = 64,
165 .schedlen = esp_des_schedlen,
166 .name = "des-cbc",
167 .ivlen = esp_descbc_ivlen,
168 .decrypt = esp_cbc_decrypt,
169 .encrypt = esp_cbc_encrypt,
170 .schedule = esp_des_schedule,
171 .blockdecrypt = esp_des_blockdecrypt,
172 .blockencrypt = esp_des_blockencrypt,
173 .icvlen = 0,
174 .finalizedecrypt = NULL,
175 .finalizeencrypt = NULL,
176 .encrypt_pkt = esp_cbc_des_encrypt_data,
177 .decrypt_pkt = esp_cbc_des_decrypt_data
178};
179
180static const struct esp_algorithm des3_cbc = {
181 .padbound = 8,
182 .ivlenval = 8,
183 .mature = esp_cbc_mature,
184 .keymin = 192,
185 .keymax = 192,
186 .schedlen = esp_3des_schedlen,
187 .name = "3des-cbc",
188 .ivlen = esp_common_ivlen,
189 .decrypt = esp_cbc_decrypt,
190 .encrypt = esp_cbc_encrypt,
191 .schedule = esp_3des_schedule,
192 .blockdecrypt = esp_3des_blockdecrypt,
193 .blockencrypt = esp_3des_blockencrypt,
194 .icvlen = 0,
195 .finalizedecrypt = NULL,
196 .finalizeencrypt = NULL,
197 .encrypt_pkt = esp_cbc_3des_encrypt_data,
198 .decrypt_pkt = esp_cbc_3des_decrypt_data
199};
200
201static const struct esp_algorithm null_esp = {
202 .padbound = 1,
203 .ivlenval = 0,
204 .mature = esp_null_mature,
205 .keymin = 0,
206 .keymax = 2048,
207 .schedlen = NULL,
208 .name = "null",
209 .ivlen = esp_common_ivlen,
210 .decrypt = esp_null_decrypt,
211 .encrypt = esp_null_encrypt,
212 .schedule = NULL,
213 .blockdecrypt = NULL,
214 .blockencrypt = NULL,
215 .icvlen = 0,
216 .finalizedecrypt = NULL,
217 .finalizeencrypt = NULL,
218 .encrypt_pkt = esp_null_encrypt_data,
219 .decrypt_pkt = esp_null_decrypt_data
220};
221
222static const struct esp_algorithm aes_cbc = {
223 .padbound = 16,
224 .ivlenval = 16,
225 .mature = esp_cbc_mature,
226 .keymin = 128,
227 .keymax = 256,
228 .schedlen = esp_aes_schedlen,
229 .name = "aes-cbc",
230 .ivlen = esp_common_ivlen,
231 .decrypt = esp_cbc_decrypt_aes,
232 .encrypt = esp_cbc_encrypt_aes,
233 .schedule = esp_aes_schedule,
234 .blockdecrypt = NULL,
235 .blockencrypt = NULL,
236 .icvlen = 0,
237 .finalizedecrypt = NULL,
238 .finalizeencrypt = NULL,
239 .encrypt_pkt = esp_aes_cbc_encrypt_data,
240 .decrypt_pkt = esp_aes_cbc_decrypt_data
241};
242
243static const struct esp_algorithm aes_gcm = {
244 .padbound = 4,
245 .ivlenval = 8,
246 .mature = esp_gcm_mature,
247 .keymin = ESP_AESGCM_KEYLEN128,
248 .keymax = ESP_AESGCM_KEYLEN256,
249 .schedlen = esp_gcm_schedlen,
250 .name = "aes-gcm",
251 .ivlen = esp_gcm_ivlen,
252 .decrypt = esp_gcm_decrypt_aes,
253 .encrypt = esp_gcm_encrypt_aes,
254 .schedule = esp_gcm_schedule,
255 .blockdecrypt = NULL,
256 .blockencrypt = NULL,
257 .icvlen = 16,
258 .finalizedecrypt = esp_gcm_decrypt_finalize,
259 .finalizeencrypt = esp_gcm_encrypt_finalize,
260 .encrypt_pkt = esp_aes_gcm_encrypt_data,
261 .decrypt_pkt = esp_aes_gcm_decrypt_data
262};
263
264static const struct esp_algorithm chacha_poly = {
265 .padbound = ESP_CHACHAPOLY_PAD_BOUND,
266 .ivlenval = ESP_CHACHAPOLY_IV_LEN,
267 .mature = esp_chachapoly_mature,
268 .keymin = ESP_CHACHAPOLY_KEYBITS_WITH_SALT,
269 .keymax = ESP_CHACHAPOLY_KEYBITS_WITH_SALT,
270 .schedlen = esp_chachapoly_schedlen,
271 .name = "chacha-poly",
272 .ivlen = esp_chachapoly_ivlen,
273 .decrypt = esp_chachapoly_decrypt,
274 .encrypt = esp_chachapoly_encrypt,
275 .schedule = esp_chachapoly_schedule,
276 .blockdecrypt = NULL,
277 .blockencrypt = NULL,
278 .icvlen = ESP_CHACHAPOLY_ICV_LEN,
279 .finalizedecrypt = esp_chachapoly_decrypt_finalize,
280 .finalizeencrypt = esp_chachapoly_encrypt_finalize,
281 .encrypt_pkt = esp_chachapoly_encrypt_data,
282 .decrypt_pkt = esp_chachapoly_decrypt_data
283};
284
285/*
286 * If any algorithm requires more than 2048 bits (256 bytes) of key material,
287 * update IPSEC_KEY_ENCRYPT_MAX_BYTES in ipsec.h
288 */
289static const struct esp_algorithm *esp_algorithms[] = {
290 &des_cbc,
291 &des3_cbc,
292 &null_esp,
293 &aes_cbc,
294 &aes_gcm,
295 &chacha_poly,
296};
297
298const struct esp_algorithm *
299esp_algorithm_lookup(int idx)
300{
301 switch (idx) {
302 case SADB_EALG_DESCBC:
303 return &des_cbc;
304 case SADB_EALG_3DESCBC:
305 return &des3_cbc;
306 case SADB_EALG_NULL:
307 return &null_esp;
308 case SADB_X_EALG_RIJNDAELCBC:
309 return &aes_cbc;
310 case SADB_X_EALG_AES_GCM:
311 case SADB_X_EALG_AES_GMAC:
312 return &aes_gcm;
313 case SADB_X_EALG_CHACHA20POLY1305:
314 return &chacha_poly;
315 default:
316 return NULL;
317 }
318}
319
320int
321esp_max_ivlen(void)
322{
323 int idx;
324 int ivlen;
325
326 ivlen = 0;
327 for (idx = 0; idx < sizeof(esp_algorithms) / sizeof(esp_algorithms[0]);
328 idx++) {
329 if (esp_algorithms[idx]->ivlenval > ivlen) {
330 ivlen = esp_algorithms[idx]->ivlenval;
331 }
332 }
333
334 return ivlen;
335}
336
337int
338esp_schedule(const struct esp_algorithm *algo, struct secasvar *sav)
339{
340 int error;
341
342 /* check for key length */
343 if (_KEYBITS(sav->key_enc) < algo->keymin ||
344 _KEYBITS(sav->key_enc) > algo->keymax) {
345 ipseclog((LOG_ERR,
346 "esp_schedule %s: unsupported key length %d: "
347 "needs %d to %d bits\n", algo->name, _KEYBITS(sav->key_enc),
348 algo->keymin, algo->keymax));
349 return EINVAL;
350 }
351
352 lck_mtx_lock(sadb_mutex);
353 /* already allocated */
354 if (sav->sched_enc && sav->schedlen_enc != 0) {
355 lck_mtx_unlock(sadb_mutex);
356 return 0;
357 }
358
359 /* prevent disallowed implicit IV */
360 if (((sav->flags & SADB_X_EXT_IIV) != 0) &&
361 (sav->alg_enc != SADB_X_EALG_AES_GCM) &&
362 (sav->alg_enc != SADB_X_EALG_CHACHA20POLY1305)) {
363 ipseclog((LOG_ERR,
364 "esp_schedule %s: implicit IV not allowed\n",
365 algo->name));
366 lck_mtx_unlock(sadb_mutex);
367 return EINVAL;
368 }
369
370 /* no schedule necessary */
371 if (!algo->schedule || !algo->schedlen) {
372 lck_mtx_unlock(sadb_mutex);
373 return 0;
374 }
375
376 sav->schedlen_enc = (*algo->schedlen)(algo);
377 if ((signed) sav->schedlen_enc < 0) {
378 lck_mtx_unlock(sadb_mutex);
379 return EINVAL;
380 }
381
382//#### that malloc should be replaced by a saved buffer...
383 sav->sched_enc = kalloc_data(sav->schedlen_enc, Z_NOWAIT);
384 if (!sav->sched_enc) {
385 sav->schedlen_enc = 0;
386 lck_mtx_unlock(sadb_mutex);
387 return ENOBUFS;
388 }
389
390 error = (*algo->schedule)(algo, sav);
391 if (error) {
392 ipseclog((LOG_ERR, "esp_schedule %s: error %d\n",
393 algo->name, error));
394 bzero(s: sav->sched_enc, n: sav->schedlen_enc);
395 kfree_data(sav->sched_enc, sav->schedlen_enc);
396 sav->sched_enc = NULL;
397 sav->schedlen_enc = 0;
398 }
399 lck_mtx_unlock(sadb_mutex);
400 return error;
401}
402
403static int
404esp_null_mature(
405 __unused struct secasvar *sav)
406{
407 /* anything is okay */
408 return 0;
409}
410
411static int
412esp_null_decrypt(
413 __unused struct mbuf *m,
414 __unused size_t off, /* offset to ESP header */
415 __unused struct secasvar *sav,
416 __unused const struct esp_algorithm *algo,
417 __unused int ivlen)
418{
419 return 0; /* do nothing */
420}
421
422static int
423esp_null_encrypt(
424 __unused struct mbuf *m,
425 __unused size_t off, /* offset to ESP header */
426 __unused size_t plen, /* payload length (to be encrypted) */
427 __unused struct secasvar *sav,
428 __unused const struct esp_algorithm *algo,
429 __unused int ivlen)
430{
431 return 0; /* do nothing */
432}
433
434static int
435esp_null_encrypt_data(__unused struct secasvar *sav,
436 __unused uint8_t *input_data, __unused size_t input_data_len,
437 __unused struct newesp *esp_hdr, __unused uint8_t *out_iv,
438 __unused size_t out_ivlen, __unused uint8_t *output_data,
439 __unused size_t output_data_len)
440{
441 return 0; /* do nothing */
442}
443
444static int
445esp_null_decrypt_data(__unused struct secasvar *sav,
446 __unused uint8_t *input_data, __unused size_t input_data_len,
447 __unused struct newesp *esp_hdr, __unused uint8_t *iv,
448 __unused size_t ivlen, __unused uint8_t *output_data,
449 __unused size_t output_data_len)
450{
451 return 0; /* do nothing */
452}
453
454static int
455esp_descbc_mature(struct secasvar *sav)
456{
457 const struct esp_algorithm *algo;
458
459 if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B)) {
460 ipseclog((LOG_ERR, "esp_cbc_mature: "
461 "algorithm incompatible with 4 octets IV length\n"));
462 return 1;
463 }
464
465 if (!sav->key_enc) {
466 ipseclog((LOG_ERR, "esp_descbc_mature: no key is given.\n"));
467 return 1;
468 }
469
470 algo = esp_algorithm_lookup(idx: sav->alg_enc);
471 if (!algo) {
472 ipseclog((LOG_ERR,
473 "esp_descbc_mature: unsupported algorithm.\n"));
474 return 1;
475 }
476
477 if (_KEYBITS(sav->key_enc) < algo->keymin ||
478 _KEYBITS(sav->key_enc) > algo->keymax) {
479 ipseclog((LOG_ERR,
480 "esp_descbc_mature: invalid key length %d.\n",
481 _KEYBITS(sav->key_enc)));
482 return 1;
483 }
484
485 /* weak key check */
486 if (des_is_weak_key(key: (des_cblock *)_KEYBUF(sav->key_enc))) {
487 ipseclog((LOG_ERR,
488 "esp_descbc_mature: weak key was passed.\n"));
489 return 1;
490 }
491
492 return 0;
493}
494
495static int
496esp_descbc_ivlen(
497 __unused const struct esp_algorithm *algo,
498 struct secasvar *sav)
499{
500 if (!sav) {
501 return 8;
502 }
503 if ((sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B)) {
504 return 4;
505 }
506 if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_DERIV)) {
507 return 4;
508 }
509 return 8;
510}
511
512static size_t
513esp_des_schedlen(
514 __unused const struct esp_algorithm *algo)
515{
516 return sizeof(des_ecb_key_schedule);
517}
518
519static int
520esp_des_schedule(
521 __unused const struct esp_algorithm *algo,
522 struct secasvar *sav)
523{
524 LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
525 if (des_ecb_key_sched(key: (des_cblock *)_KEYBUF(sav->key_enc),
526 ks: (des_ecb_key_schedule *)sav->sched_enc)) {
527 return EINVAL;
528 } else {
529 return 0;
530 }
531}
532
533static int
534esp_des_blockdecrypt(
535 __unused const struct esp_algorithm *algo,
536 struct secasvar *sav,
537 u_int8_t *s,
538 u_int8_t *d)
539{
540 /* assumption: d has a good alignment */
541 bcopy(src: s, dst: d, n: sizeof(DES_LONG) * 2);
542 return des_ecb_encrypt(in: (des_cblock *)d, out: (des_cblock *)d,
543 ks: (des_ecb_key_schedule *)sav->sched_enc, DES_DECRYPT);
544}
545
546static int
547esp_des_blockencrypt(
548 __unused const struct esp_algorithm *algo,
549 struct secasvar *sav,
550 u_int8_t *s,
551 u_int8_t *d)
552{
553 /* assumption: d has a good alignment */
554 bcopy(src: s, dst: d, n: sizeof(DES_LONG) * 2);
555 return des_ecb_encrypt(in: (des_cblock *)d, out: (des_cblock *)d,
556 ks: (des_ecb_key_schedule *)sav->sched_enc, DES_ENCRYPT);
557}
558
559static int
560esp_cbc_mature(struct secasvar *sav)
561{
562 int keylen;
563 const struct esp_algorithm *algo;
564
565 if (sav->flags & SADB_X_EXT_OLD) {
566 ipseclog((LOG_ERR,
567 "esp_cbc_mature: algorithm incompatible with esp-old\n"));
568 return 1;
569 }
570 if (sav->flags & SADB_X_EXT_DERIV) {
571 ipseclog((LOG_ERR,
572 "esp_cbc_mature: algorithm incompatible with derived\n"));
573 return 1;
574 }
575
576 if (!sav->key_enc) {
577 ipseclog((LOG_ERR, "esp_cbc_mature: no key is given.\n"));
578 return 1;
579 }
580
581 algo = esp_algorithm_lookup(idx: sav->alg_enc);
582 if (!algo) {
583 ipseclog((LOG_ERR,
584 "esp_cbc_mature: unsupported algorithm.\n"));
585 return 1;
586 }
587
588 keylen = sav->key_enc->sadb_key_bits;
589 if (keylen < algo->keymin || algo->keymax < keylen) {
590 ipseclog((LOG_ERR,
591 "esp_cbc_mature %s: invalid key length %d.\n",
592 algo->name, sav->key_enc->sadb_key_bits));
593 return 1;
594 }
595 switch (sav->alg_enc) {
596 case SADB_EALG_3DESCBC:
597 /* weak key check */
598 if (des_is_weak_key(key: (des_cblock *)_KEYBUF(sav->key_enc)) ||
599 des_is_weak_key(key: (des_cblock *)(_KEYBUF(sav->key_enc) + 8)) ||
600 des_is_weak_key(key: (des_cblock *)(_KEYBUF(sav->key_enc) + 16))) {
601 ipseclog((LOG_ERR,
602 "esp_cbc_mature %s: weak key was passed.\n",
603 algo->name));
604 return 1;
605 }
606 break;
607 case SADB_X_EALG_RIJNDAELCBC:
608 /* allows specific key sizes only */
609 if (!(keylen == 128 || keylen == 192 || keylen == 256)) {
610 ipseclog((LOG_ERR,
611 "esp_cbc_mature %s: invalid key length %d.\n",
612 algo->name, keylen));
613 return 1;
614 }
615 break;
616 }
617
618 return 0;
619}
620
621static int
622esp_gcm_mature(struct secasvar *sav)
623{
624 int keylen;
625 const struct esp_algorithm *algo;
626
627 if (sav->flags & SADB_X_EXT_OLD) {
628 ipseclog((LOG_ERR,
629 "esp_gcm_mature: algorithm incompatible with esp-old\n"));
630 return 1;
631 }
632 if (sav->flags & SADB_X_EXT_DERIV) {
633 ipseclog((LOG_ERR,
634 "esp_gcm_mature: algorithm incompatible with derived\n"));
635 return 1;
636 }
637
638 if (!sav->key_enc) {
639 ipseclog((LOG_ERR, "esp_gcm_mature: no key is given.\n"));
640 return 1;
641 }
642
643 algo = esp_algorithm_lookup(idx: sav->alg_enc);
644 if (!algo) {
645 ipseclog((LOG_ERR,
646 "esp_gcm_mature: unsupported algorithm.\n"));
647 return 1;
648 }
649
650 keylen = sav->key_enc->sadb_key_bits;
651 if (keylen < algo->keymin || algo->keymax < keylen) {
652 ipseclog((LOG_ERR,
653 "esp_gcm_mature %s: invalid key length %d.\n",
654 algo->name, sav->key_enc->sadb_key_bits));
655 return 1;
656 }
657 switch (sav->alg_enc) {
658 case SADB_X_EALG_AES_GCM:
659 case SADB_X_EALG_AES_GMAC:
660 /* allows specific key sizes only */
661 if (!(keylen == ESP_AESGCM_KEYLEN128 || keylen == ESP_AESGCM_KEYLEN192 || keylen == ESP_AESGCM_KEYLEN256)) {
662 ipseclog((LOG_ERR,
663 "esp_gcm_mature %s: invalid key length %d.\n",
664 algo->name, keylen));
665 return 1;
666 }
667 break;
668 default:
669 ipseclog((LOG_ERR,
670 "esp_gcm_mature %s: invalid algo %d.\n", algo->name, sav->alg_enc));
671 return 1;
672 }
673
674 return 0;
675}
676
677static size_t
678esp_3des_schedlen(
679 __unused const struct esp_algorithm *algo)
680{
681 return sizeof(des3_ecb_key_schedule);
682}
683
684static int
685esp_3des_schedule(
686 __unused const struct esp_algorithm *algo,
687 struct secasvar *sav)
688{
689 LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
690
691 if (des3_ecb_key_sched(key: (des_cblock *)_KEYBUF(sav->key_enc),
692 ks: (des3_ecb_key_schedule *)sav->sched_enc)) {
693 return EINVAL;
694 } else {
695 return 0;
696 }
697}
698
699static int
700esp_3des_blockdecrypt(
701 __unused const struct esp_algorithm *algo,
702 struct secasvar *sav,
703 u_int8_t *s,
704 u_int8_t *d)
705{
706 /* assumption: d has a good alignment */
707 bcopy(src: s, dst: d, n: sizeof(DES_LONG) * 2);
708 return des3_ecb_encrypt(block: (des_cblock *)d, (des_cblock *)d,
709 ks: (des3_ecb_key_schedule *)sav->sched_enc, DES_DECRYPT);
710}
711
712static int
713esp_3des_blockencrypt(
714 __unused const struct esp_algorithm *algo,
715 struct secasvar *sav,
716 u_int8_t *s,
717 u_int8_t *d)
718{
719 /* assumption: d has a good alignment */
720 bcopy(src: s, dst: d, n: sizeof(DES_LONG) * 2);
721 return des3_ecb_encrypt(block: (des_cblock *)d, (des_cblock *)d,
722 ks: (des3_ecb_key_schedule *)sav->sched_enc, DES_ENCRYPT);
723}
724
725static int
726esp_common_ivlen(
727 const struct esp_algorithm *algo,
728 __unused struct secasvar *sav)
729{
730 if (!algo) {
731 panic("esp_common_ivlen: unknown algorithm");
732 }
733 return algo->ivlenval;
734}
735
736static int
737esp_cbc_decrypt(struct mbuf *m, size_t off, struct secasvar *sav,
738 const struct esp_algorithm *algo, int ivlen)
739{
740 struct mbuf *s;
741 struct mbuf *d, *d0, *dp;
742 int soff, doff; /* offset from the head of chain, to head of this mbuf */
743 int sn, dn; /* offset from the head of the mbuf, to meat */
744 size_t ivoff, bodyoff;
745 u_int8_t iv[MAXIVLEN] __attribute__((aligned(4))), *ivp;
746 u_int8_t *sbuf = NULL, *sp, *sp_unaligned;
747 u_int8_t *p, *q;
748 struct mbuf *scut;
749 int scutoff;
750 int i, result = 0;
751 int blocklen;
752 int derived;
753
754 if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
755 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
756 "unsupported ivlen %d\n", algo->name, ivlen));
757 m_freem(m);
758 return EINVAL;
759 }
760
761 /* assumes blocklen == padbound */
762 blocklen = algo->padbound;
763
764#if DIAGNOSTIC
765 if (blocklen > sizeof(iv)) {
766 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
767 "unsupported blocklen %d\n", algo->name, blocklen));
768 m_freem(m);
769 return EINVAL;
770 }
771#endif
772
773 if (sav->flags & SADB_X_EXT_OLD) {
774 /* RFC 1827 */
775 ivoff = off + sizeof(struct esp);
776 bodyoff = off + sizeof(struct esp) + ivlen;
777 derived = 0;
778 } else {
779 /* RFC 2406 */
780 if (sav->flags & SADB_X_EXT_DERIV) {
781 /*
782 * draft-ietf-ipsec-ciph-des-derived-00.txt
783 * uses sequence number field as IV field.
784 */
785 ivoff = off + sizeof(struct esp);
786 bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
787 ivlen = sizeof(u_int32_t);
788 derived = 1;
789 } else {
790 ivoff = off + sizeof(struct newesp);
791 bodyoff = off + sizeof(struct newesp) + ivlen;
792 derived = 0;
793 }
794 }
795
796 VERIFY(ivoff <= INT_MAX);
797 /* grab iv */
798 m_copydata(m, (int)ivoff, ivlen, (caddr_t) iv);
799
800 /* extend iv */
801 if (ivlen == blocklen) {
802 ;
803 } else if (ivlen == 4 && blocklen == 8) {
804 bcopy(src: &iv[0], dst: &iv[4], n: 4);
805 iv[4] ^= 0xff;
806 iv[5] ^= 0xff;
807 iv[6] ^= 0xff;
808 iv[7] ^= 0xff;
809 } else {
810 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
811 "unsupported ivlen/blocklen: %d %d\n",
812 algo->name, ivlen, blocklen));
813 m_freem(m);
814 return EINVAL;
815 }
816
817 if (m->m_pkthdr.len < bodyoff) {
818 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: bad len %d/%u\n",
819 algo->name, m->m_pkthdr.len, (u_int32_t)bodyoff));
820 m_freem(m);
821 return EINVAL;
822 }
823 if ((m->m_pkthdr.len - bodyoff) % blocklen) {
824 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
825 "payload length must be multiple of %d\n",
826 algo->name, blocklen));
827 m_freem(m);
828 return EINVAL;
829 }
830
831 s = m;
832 d = d0 = dp = NULL;
833 soff = doff = sn = dn = 0;
834 ivp = sp = NULL;
835
836 /* skip bodyoff */
837 while (soff < bodyoff) {
838 if (soff + s->m_len > bodyoff) {
839 sn = (int)(bodyoff - soff);
840 break;
841 }
842
843 soff += s->m_len;
844 s = s->m_next;
845 }
846 scut = s;
847 scutoff = sn;
848
849 /* skip over empty mbuf */
850 while (s && s->m_len == 0) {
851 s = s->m_next;
852 }
853
854 // Allocate blocksized buffer for unaligned or non-contiguous access
855 sbuf = (u_int8_t *)kalloc_data(blocklen, Z_NOWAIT);
856 if (sbuf == NULL) {
857 return ENOBUFS;
858 }
859 while (soff < m->m_pkthdr.len) {
860 /* source */
861 if (sn + blocklen <= s->m_len) {
862 /* body is continuous */
863 sp = mtod(s, u_int8_t *) + sn;
864 } else {
865 /* body is non-continuous */
866 m_copydata(s, sn, blocklen, (caddr_t) sbuf);
867 sp = sbuf;
868 }
869
870 /* destination */
871 if (!d || dn + blocklen > d->m_len) {
872 if (d) {
873 dp = d;
874 }
875 MGET(d, M_DONTWAIT, MT_DATA);
876 i = m->m_pkthdr.len - (soff + sn);
877 if (d && i > MLEN) {
878 MCLGET(d, M_DONTWAIT);
879 if ((d->m_flags & M_EXT) == 0) {
880 m_free(d);
881 d = NULL;
882 }
883 }
884 if (!d) {
885 m_freem(m);
886 if (d0) {
887 m_freem(d0);
888 }
889 result = ENOBUFS;
890 goto end;
891 }
892 if (!d0) {
893 d0 = d;
894 }
895 if (dp) {
896 dp->m_next = d;
897 }
898
899 // try to make mbuf data aligned
900 if (!IPSEC_IS_P2ALIGNED(d->m_data)) {
901 m_adj(d, IPSEC_GET_P2UNALIGNED_OFS(d->m_data));
902 }
903
904 d->m_len = 0;
905 d->m_len = (int)((M_TRAILINGSPACE(d) / blocklen) * blocklen);
906 if (d->m_len > i) {
907 d->m_len = i;
908 }
909 dn = 0;
910 }
911
912 /* decrypt */
913 // check input pointer alignment and use a separate aligned buffer (if sp is unaligned on 4-byte boundary).
914 if (IPSEC_IS_P2ALIGNED(sp)) {
915 sp_unaligned = NULL;
916 } else {
917 sp_unaligned = sp;
918 sp = sbuf;
919 memcpy(dst: sp, src: sp_unaligned, n: blocklen);
920 }
921 // no need to check output pointer alignment
922 (*algo->blockdecrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
923
924 // update unaligned pointers
925 if (!IPSEC_IS_P2ALIGNED(sp_unaligned)) {
926 sp = sp_unaligned;
927 }
928
929 /* xor */
930 p = ivp ? ivp : iv;
931 q = mtod(d, u_int8_t *) + dn;
932 for (i = 0; i < blocklen; i++) {
933 q[i] ^= p[i];
934 }
935
936 /* next iv */
937 if (sp == sbuf) {
938 bcopy(src: sbuf, dst: iv, n: blocklen);
939 ivp = NULL;
940 } else {
941 ivp = sp;
942 }
943
944 sn += blocklen;
945 dn += blocklen;
946
947 /* find the next source block */
948 while (s && sn >= s->m_len) {
949 sn -= s->m_len;
950 soff += s->m_len;
951 s = s->m_next;
952 }
953 }
954
955 m_freem(scut->m_next);
956 scut->m_len = scutoff;
957 scut->m_next = d0;
958
959 /* just in case */
960 bzero(s: iv, n: sizeof(iv));
961 bzero(s: sbuf, n: blocklen);
962end:
963 if (sbuf != NULL) {
964 kfree_data(sbuf, blocklen);
965 }
966 return result;
967}
968
969static int
970esp_cbc_encrypt(
971 struct mbuf *m,
972 size_t off,
973 __unused size_t plen,
974 struct secasvar *sav,
975 const struct esp_algorithm *algo,
976 int ivlen)
977{
978 struct mbuf *s;
979 struct mbuf *d, *d0, *dp;
980 int soff, doff; /* offset from the head of chain, to head of this mbuf */
981 int sn, dn; /* offset from the head of the mbuf, to meat */
982 size_t ivoff, bodyoff;
983 u_int8_t iv[MAXIVLEN] __attribute__((aligned(4))), *ivp;
984 u_int8_t *sbuf = NULL, *sp, *sp_unaligned;
985 u_int8_t *p, *q;
986 struct mbuf *scut;
987 int scutoff;
988 int i, result = 0;
989 int blocklen;
990 int derived;
991
992 if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
993 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
994 "unsupported ivlen %d\n", algo->name, ivlen));
995 m_freem(m);
996 return EINVAL;
997 }
998
999 /* assumes blocklen == padbound */
1000 blocklen = algo->padbound;
1001
1002#if DIAGNOSTIC
1003 if (blocklen > sizeof(iv)) {
1004 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
1005 "unsupported blocklen %d\n", algo->name, blocklen));
1006 m_freem(m);
1007 return EINVAL;
1008 }
1009#endif
1010
1011 if (sav->flags & SADB_X_EXT_OLD) {
1012 /* RFC 1827 */
1013 ivoff = off + sizeof(struct esp);
1014 bodyoff = off + sizeof(struct esp) + ivlen;
1015 derived = 0;
1016 } else {
1017 /* RFC 2406 */
1018 if (sav->flags & SADB_X_EXT_DERIV) {
1019 /*
1020 * draft-ietf-ipsec-ciph-des-derived-00.txt
1021 * uses sequence number field as IV field.
1022 */
1023 ivoff = off + sizeof(struct esp);
1024 bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
1025 ivlen = sizeof(u_int32_t);
1026 derived = 1;
1027 } else {
1028 ivoff = off + sizeof(struct newesp);
1029 bodyoff = off + sizeof(struct newesp) + ivlen;
1030 derived = 0;
1031 }
1032 }
1033
1034 VERIFY(ivoff <= INT_MAX);
1035
1036 /* put iv into the packet. if we are in derived mode, use seqno. */
1037 if (derived) {
1038 m_copydata(m, (int)ivoff, ivlen, (caddr_t) iv);
1039 } else {
1040 bcopy(src: sav->iv, dst: iv, n: ivlen);
1041 /* maybe it is better to overwrite dest, not source */
1042 m_copyback(m, (int)ivoff, ivlen, (caddr_t) iv);
1043 }
1044
1045 /* extend iv */
1046 if (ivlen == blocklen) {
1047 ;
1048 } else if (ivlen == 4 && blocklen == 8) {
1049 bcopy(src: &iv[0], dst: &iv[4], n: 4);
1050 iv[4] ^= 0xff;
1051 iv[5] ^= 0xff;
1052 iv[6] ^= 0xff;
1053 iv[7] ^= 0xff;
1054 } else {
1055 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
1056 "unsupported ivlen/blocklen: %d %d\n",
1057 algo->name, ivlen, blocklen));
1058 m_freem(m);
1059 return EINVAL;
1060 }
1061
1062 if (m->m_pkthdr.len < bodyoff) {
1063 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: bad len %d/%u\n",
1064 algo->name, m->m_pkthdr.len, (u_int32_t)bodyoff));
1065 m_freem(m);
1066 return EINVAL;
1067 }
1068 if ((m->m_pkthdr.len - bodyoff) % blocklen) {
1069 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
1070 "payload length must be multiple of %u\n",
1071 algo->name, (u_int32_t)algo->padbound));
1072 m_freem(m);
1073 return EINVAL;
1074 }
1075
1076 s = m;
1077 d = d0 = dp = NULL;
1078 soff = doff = sn = dn = 0;
1079 ivp = sp = NULL;
1080
1081 /* skip bodyoff */
1082 while (soff < bodyoff) {
1083 if (soff + s->m_len > bodyoff) {
1084 sn = (int)(bodyoff - soff);
1085 break;
1086 }
1087
1088 soff += s->m_len;
1089 s = s->m_next;
1090 }
1091 scut = s;
1092 scutoff = sn;
1093
1094 /* skip over empty mbuf */
1095 while (s && s->m_len == 0) {
1096 s = s->m_next;
1097 }
1098
1099 // Allocate blocksized buffer for unaligned or non-contiguous access
1100 sbuf = (u_int8_t *)kalloc_data(blocklen, Z_NOWAIT);
1101 if (sbuf == NULL) {
1102 return ENOBUFS;
1103 }
1104 while (soff < m->m_pkthdr.len) {
1105 /* source */
1106 if (sn + blocklen <= s->m_len) {
1107 /* body is continuous */
1108 sp = mtod(s, u_int8_t *) + sn;
1109 } else {
1110 /* body is non-continuous */
1111 m_copydata(s, sn, blocklen, (caddr_t) sbuf);
1112 sp = sbuf;
1113 }
1114
1115 /* destination */
1116 if (!d || dn + blocklen > d->m_len) {
1117 if (d) {
1118 dp = d;
1119 }
1120 MGET(d, M_DONTWAIT, MT_DATA);
1121 i = m->m_pkthdr.len - (soff + sn);
1122 if (d && i > MLEN) {
1123 MCLGET(d, M_DONTWAIT);
1124 if ((d->m_flags & M_EXT) == 0) {
1125 m_free(d);
1126 d = NULL;
1127 }
1128 }
1129 if (!d) {
1130 m_freem(m);
1131 if (d0) {
1132 m_freem(d0);
1133 }
1134 result = ENOBUFS;
1135 goto end;
1136 }
1137 if (!d0) {
1138 d0 = d;
1139 }
1140 if (dp) {
1141 dp->m_next = d;
1142 }
1143
1144 // try to make mbuf data aligned
1145 if (!IPSEC_IS_P2ALIGNED(d->m_data)) {
1146 m_adj(d, IPSEC_GET_P2UNALIGNED_OFS(d->m_data));
1147 }
1148
1149 d->m_len = 0;
1150 d->m_len = (int)((M_TRAILINGSPACE(d) / blocklen) * blocklen);
1151 if (d->m_len > i) {
1152 d->m_len = i;
1153 }
1154 dn = 0;
1155 }
1156
1157 /* xor */
1158 p = ivp ? ivp : iv;
1159 q = sp;
1160 for (i = 0; i < blocklen; i++) {
1161 q[i] ^= p[i];
1162 }
1163
1164 /* encrypt */
1165 // check input pointer alignment and use a separate aligned buffer (if sp is not aligned on 4-byte boundary).
1166 if (IPSEC_IS_P2ALIGNED(sp)) {
1167 sp_unaligned = NULL;
1168 } else {
1169 sp_unaligned = sp;
1170 sp = sbuf;
1171 memcpy(dst: sp, src: sp_unaligned, n: blocklen);
1172 }
1173 // no need to check output pointer alignment
1174 (*algo->blockencrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
1175
1176 // update unaligned pointers
1177 if (!IPSEC_IS_P2ALIGNED(sp_unaligned)) {
1178 sp = sp_unaligned;
1179 }
1180
1181 /* next iv */
1182 ivp = mtod(d, u_int8_t *) + dn;
1183
1184 sn += blocklen;
1185 dn += blocklen;
1186
1187 /* find the next source block */
1188 while (s && sn >= s->m_len) {
1189 sn -= s->m_len;
1190 soff += s->m_len;
1191 s = s->m_next;
1192 }
1193 }
1194
1195 m_freem(scut->m_next);
1196 scut->m_len = scutoff;
1197 scut->m_next = d0;
1198
1199 /* just in case */
1200 bzero(s: iv, n: sizeof(iv));
1201 bzero(s: sbuf, n: blocklen);
1202
1203 key_sa_stir_iv(sav);
1204end:
1205 if (sbuf != NULL) {
1206 kfree_data(sbuf, blocklen);
1207 }
1208 return result;
1209}
1210
1211#define ESP_CBC_DES_BLOCKLEN 8
1212static int
1213esp_cbc_des_encrypt_data(struct secasvar *sav, uint8_t *input_data,
1214 size_t input_data_len, struct newesp *esp_hdr, uint8_t *out_iv,
1215 size_t ivlen, uint8_t *output_data, size_t output_data_len)
1216{
1217 uint8_t *ivp = NULL;
1218 size_t soff = 0;
1219 int rc = 0;
1220
1221 ESP_CHECK_ARG(sav);
1222 ESP_CHECK_ARG(input_data);
1223 ESP_CHECK_ARG(esp_hdr);
1224 ESP_CHECK_ARG(output_data);
1225
1226 VERIFY(input_data_len > 0);
1227 VERIFY(output_data_len >= input_data_len);
1228 VERIFY(sav->ivlen == ivlen);
1229 VERIFY(ivlen == ESP_CBC_DES_BLOCKLEN);
1230
1231 if (input_data_len % ESP_CBC_DES_BLOCKLEN) {
1232 esp_log_err("payload length %zu must be a multiple of "
1233 "ESP_CBC_DES_BLOCKLEN, SPI 0x%08x", input_data_len, ntohl(sav->spi));
1234 return EINVAL;
1235 }
1236
1237 memcpy(dst: out_iv, src: sav->iv, n: ivlen);
1238 ivp = out_iv;
1239
1240 while (soff < input_data_len) {
1241 for (int i = 0; i < ESP_CBC_DES_BLOCKLEN; i++) {
1242 input_data[soff + i] ^= ivp[i];
1243 }
1244
1245 /* encrypt */
1246 if (__improbable((rc = des_ecb_encrypt((des_cblock *)&input_data[soff],
1247 (des_cblock *)&output_data[soff], (des_ecb_key_schedule *)sav->sched_enc,
1248 DES_ENCRYPT)) != 0)) {
1249 esp_log_err("encrypt failed %d, SPI 0x%08x", rc, ntohl(sav->spi));
1250 return rc;
1251 }
1252
1253 ivp = &output_data[soff];
1254 soff += ESP_CBC_DES_BLOCKLEN;
1255 }
1256
1257 key_sa_stir_iv(sav);
1258 return 0;
1259}
1260
1261static int
1262esp_cbc_des_decrypt_data(struct secasvar *sav, uint8_t *input_data,
1263 size_t input_data_len, struct newesp *esp_hdr, uint8_t *iv,
1264 size_t ivlen, uint8_t *output_data, size_t output_data_len)
1265{
1266 uint8_t *ivp = NULL;
1267 size_t soff = 0;
1268 int rc = 0;
1269
1270 ESP_CHECK_ARG(sav);
1271 ESP_CHECK_ARG(input_data);
1272 ESP_CHECK_ARG(esp_hdr);
1273 ESP_CHECK_ARG(output_data);
1274
1275 VERIFY(input_data_len > 0);
1276 VERIFY(output_data_len >= input_data_len);
1277 VERIFY(sav->ivlen == ivlen);
1278 VERIFY(ivlen == ESP_CBC_DES_BLOCKLEN);
1279
1280 if (input_data_len % ESP_CBC_DES_BLOCKLEN) {
1281 esp_packet_log_err("payload length %zu must be a multiple of "
1282 "ESP_CBC_DES_BLOCKLEN, SPI 0x%08x", input_data_len, ntohl(sav->spi));
1283 return EINVAL;
1284 }
1285
1286 ivp = iv;
1287
1288 while (soff < input_data_len) {
1289 /* decrypt */
1290 if (__improbable((rc = des_ecb_encrypt((des_cblock *)&input_data[soff],
1291 (des_cblock *)&output_data[soff], (des_ecb_key_schedule *)sav->sched_enc,
1292 DES_DECRYPT)) != 0)) {
1293 esp_log_err("decrypt failed %d, SPI 0x%08x", rc, ntohl(sav->spi));
1294 return rc;
1295 }
1296
1297 for (int i = 0; i < ESP_CBC_DES_BLOCKLEN; i++) {
1298 output_data[soff + i] ^= ivp[i];
1299 }
1300
1301 ivp = &input_data[soff];
1302 soff += ESP_CBC_DES_BLOCKLEN;
1303 }
1304
1305 return 0;
1306}
1307
1308#define ESP_CBC_3DES_BLOCKLEN 8
1309static int
1310esp_cbc_3des_encrypt_data(struct secasvar *sav, uint8_t *input_data,
1311 size_t input_data_len, struct newesp *esp_hdr, uint8_t *out_iv,
1312 size_t ivlen, uint8_t *output_data, size_t output_data_len)
1313{
1314 uint8_t *ivp = NULL;
1315 size_t soff = 0;
1316 int rc = 0;
1317
1318 ESP_CHECK_ARG(sav);
1319 ESP_CHECK_ARG(input_data);
1320 ESP_CHECK_ARG(esp_hdr);
1321 ESP_CHECK_ARG(output_data);
1322
1323 VERIFY(input_data_len > 0);
1324 VERIFY(output_data_len >= input_data_len);
1325 VERIFY(sav->ivlen == ivlen);
1326 VERIFY(ivlen == ESP_CBC_3DES_BLOCKLEN);
1327
1328 if (input_data_len % ESP_CBC_3DES_BLOCKLEN) {
1329 esp_log_err("payload length %zu must be a multiple of "
1330 "ESP_CBC_3DES_BLOCKLEN, SPI 0x%08x", input_data_len, ntohl(sav->spi));
1331 return EINVAL;
1332 }
1333
1334 memcpy(dst: out_iv, src: sav->iv, n: ivlen);
1335 ivp = out_iv;
1336
1337 while (soff < input_data_len) {
1338 for (int i = 0; i < ESP_CBC_3DES_BLOCKLEN; i++) {
1339 input_data[soff + i] ^= ivp[i];
1340 }
1341
1342 /* encrypt */
1343 if (__improbable((rc = des3_ecb_encrypt((des_cblock *)&input_data[soff],
1344 (des_cblock *)&output_data[soff], (des3_ecb_key_schedule *)sav->sched_enc,
1345 DES_ENCRYPT)) != 0)) {
1346 esp_log_err("encrypt failed %d, SPI 0x%08x", rc, ntohl(sav->spi));
1347 return rc;
1348 }
1349
1350 ivp = &output_data[soff];
1351 soff += ESP_CBC_3DES_BLOCKLEN;
1352 }
1353
1354 key_sa_stir_iv(sav);
1355 return 0;
1356}
1357
1358static int
1359esp_cbc_3des_decrypt_data(struct secasvar *sav, uint8_t *input_data,
1360 size_t input_data_len, struct newesp *esp_hdr, uint8_t *iv,
1361 size_t ivlen, uint8_t *output_data, size_t output_data_len)
1362{
1363 uint8_t *ivp = NULL;
1364 size_t soff = 0;
1365 int rc = 0;
1366
1367 ESP_CHECK_ARG(sav);
1368 ESP_CHECK_ARG(input_data);
1369 ESP_CHECK_ARG(esp_hdr);
1370 ESP_CHECK_ARG(output_data);
1371
1372 VERIFY(input_data_len > 0);
1373 VERIFY(output_data_len >= input_data_len);
1374 VERIFY(sav->ivlen == ivlen);
1375 VERIFY(ivlen == ESP_CBC_3DES_BLOCKLEN);
1376
1377 if (input_data_len % ESP_CBC_3DES_BLOCKLEN) {
1378 esp_packet_log_err("payload length %zu must be a multiple of "
1379 "ESP_CBC_3DES_BLOCKLEN, SPI 0x%08x", input_data_len, ntohl(sav->spi));
1380 return EINVAL;
1381 }
1382
1383 ivp = iv;
1384
1385 while (soff < input_data_len) {
1386 /* decrypt */
1387 if (__improbable((rc = des3_ecb_encrypt((des_cblock *)&input_data[soff],
1388 (des_cblock *)&output_data[soff], (des3_ecb_key_schedule *)sav->sched_enc,
1389 DES_DECRYPT)) != 0)) {
1390 esp_log_err("decrypt failed %d, SPI 0x%08x", rc, ntohl(sav->spi));
1391 return rc;
1392 }
1393
1394 for (int i = 0; i < ESP_CBC_3DES_BLOCKLEN; i++) {
1395 output_data[soff + i] ^= ivp[i];
1396 }
1397
1398 ivp = &input_data[soff];
1399 soff += ESP_CBC_3DES_BLOCKLEN;
1400 }
1401
1402 return 0;
1403}
1404
1405/*------------------------------------------------------------*/
1406
1407/* does not free m0 on error */
1408int
1409esp_auth(
1410 struct mbuf *m0,
1411 size_t skip, /* offset to ESP header */
1412 size_t length, /* payload length */
1413 struct secasvar *sav,
1414 u_char *sum)
1415{
1416 struct mbuf *m;
1417 size_t off;
1418 struct ah_algorithm_state s;
1419 u_char sumbuf[AH_MAXSUMSIZE] __attribute__((aligned(4)));
1420 const struct ah_algorithm *algo;
1421 size_t siz;
1422 int error;
1423
1424 /* sanity checks */
1425 if (m0->m_pkthdr.len < skip) {
1426 ipseclog((LOG_DEBUG, "esp_auth: mbuf length < skip\n"));
1427 return EINVAL;
1428 }
1429 if (m0->m_pkthdr.len < skip + length) {
1430 ipseclog((LOG_DEBUG,
1431 "esp_auth: mbuf length < skip + length\n"));
1432 return EINVAL;
1433 }
1434
1435 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_START, skip, length, 0, 0, 0);
1436 /*
1437 * length of esp part (excluding authentication data) must be 4n,
1438 * since nexthdr must be at offset 4n+3.
1439 */
1440 if (length % 4) {
1441 ipseclog((LOG_ERR, "esp_auth: length is not multiple of 4\n"));
1442 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 1, 0, 0, 0, 0);
1443 return EINVAL;
1444 }
1445 if (!sav) {
1446 ipseclog((LOG_DEBUG, "esp_auth: NULL SA passed\n"));
1447 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 2, 0, 0, 0, 0);
1448 return EINVAL;
1449 }
1450 algo = ah_algorithm_lookup(sav->alg_auth);
1451 if (!algo) {
1452 ipseclog((LOG_ERR,
1453 "esp_auth: bad ESP auth algorithm passed: %d\n",
1454 sav->alg_auth));
1455 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 3, 0, 0, 0, 0);
1456 return EINVAL;
1457 }
1458
1459 m = m0;
1460 off = 0;
1461
1462 siz = (((*algo->sumsiz)(sav) + 3) & ~(4 - 1));
1463 if (sizeof(sumbuf) < siz) {
1464 ipseclog((LOG_DEBUG,
1465 "esp_auth: AH_MAXSUMSIZE is too small: siz=%u\n",
1466 (u_int32_t)siz));
1467 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 4, 0, 0, 0, 0);
1468 return EINVAL;
1469 }
1470
1471 /* skip the header */
1472 while (skip) {
1473 if (!m) {
1474 panic("mbuf chain?");
1475 }
1476 if (m->m_len <= skip) {
1477 skip -= m->m_len;
1478 m = m->m_next;
1479 off = 0;
1480 } else {
1481 off = skip;
1482 skip = 0;
1483 }
1484 }
1485
1486 /*
1487 * pre-compute and cache intermediate key
1488 */
1489 if (__improbable((error = ah_schedule(algo, sav)) != 0)) {
1490 esp_log_info("ah schedule failed %d, SPI 0x%08x\n", error, ntohl(sav->spi));
1491 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 5, error, 0, 0, 0);
1492 return error;
1493 }
1494
1495 error = (*algo->init)(&s, sav);
1496 if (error) {
1497 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 6, error, 0, 0, 0);
1498 return error;
1499 }
1500 while (0 < length) {
1501 if (!m) {
1502 panic("mbuf chain?");
1503 }
1504
1505 if (m->m_len - off < length) {
1506 (*algo->update)(&s, (caddr_t)(mtod(m, u_char *) + off),
1507 m->m_len - off);
1508 length -= m->m_len - off;
1509 m = m->m_next;
1510 off = 0;
1511 } else {
1512 (*algo->update)(&s, (caddr_t)(mtod(m, u_char *) + off), length);
1513 break;
1514 }
1515 }
1516 (*algo->result)(&s, (caddr_t) sumbuf, sizeof(sumbuf));
1517 bcopy(src: sumbuf, dst: sum, n: siz); /*XXX*/
1518 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 7, 0, 0, 0, 0);
1519 return 0;
1520}
1521
1522int
1523esp_auth_data(struct secasvar *sav, uint8_t *input_data, size_t input_data_len,
1524 uint8_t *out_auth, size_t auth_size)
1525{
1526 struct ah_algorithm_state state = {};
1527 const struct ah_algorithm *algo = NULL;
1528 size_t siz = 0;
1529 int err = 0;
1530
1531 ESP_CHECK_ARG(sav);
1532 ESP_CHECK_ARG(input_data);
1533 ESP_CHECK_ARG(out_auth);
1534
1535 VERIFY(input_data_len > 0);
1536
1537 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_START, 0, length, 0, 0, 0);
1538
1539 /*
1540 * Length of ESP part (excluding authentication data) must be 4n,
1541 * since nexthdr must be at offset 4n + 3.
1542 */
1543 if (__improbable(input_data_len % 4)) {
1544 esp_packet_log_err("esp auth: input data length %zu is not a multiple 4, "
1545 "SPI 0x%08x\n", input_data_len, ntohl(sav->spi));
1546 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 1, EINVAL, 0, 0, 0);
1547 return EINVAL;
1548 }
1549
1550 algo = ah_algorithm_lookup(sav->alg_auth);
1551 VERIFY(algo != NULL);
1552
1553 siz = (((*algo->sumsiz)(sav) + 3) & ~(4 - 1));
1554 if (__improbable(auth_size < siz)) {
1555 esp_log_err("esp auth: auth size=%zu is lesser than siz=%zu "
1556 "SPI 0x%08x\n", input_data_len, siz, ntohl(sav->spi));
1557 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 2, EINVAL, 0, 0, 0);
1558 return EINVAL;
1559 }
1560
1561 /*
1562 * pre-compute and cache intermediate key
1563 */
1564 if (__improbable((err = ah_schedule(algo, sav)) != 0)) {
1565 esp_log_info("ah schedule failed %d, SPI 0x%08x\n", err, ntohl(sav->spi));
1566 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 3, err, 0, 0, 0);
1567 return err;
1568 }
1569
1570 err = (*algo->init)(&state, sav);
1571 if (__improbable(err != 0)) {
1572 esp_log_err("esp auth: algo init failed with error %d, "
1573 "SPI 0x%08x\n", err, ntohl(sav->spi));
1574 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 4, err, 0, 0, 0);
1575 return err;
1576 }
1577
1578 (*algo->update)(&state, (caddr_t)input_data, input_data_len);
1579 (*algo->result)(&state, (caddr_t)out_auth, auth_size);
1580 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 5, 0, 0, 0, 0);
1581 return 0;
1582}
1583
1584void
1585esp_init(void)
1586{
1587 static int esp_initialized = 0;
1588
1589 if (esp_initialized) {
1590 return;
1591 }
1592
1593 esp_initialized = 1;
1594
1595 esp_mpkl_log_object = MPKL_CREATE_LOGOBJECT("com.apple.xnu.esp");
1596 if (esp_mpkl_log_object == NULL) {
1597 panic("MPKL_CREATE_LOGOBJECT for ESP failed");
1598 }
1599
1600 return;
1601}
1602