]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/esp_core.c
17bd8e242007cd75c1a75ef10a61ecb2b8abdc66
[apple/xnu.git] / bsd / netinet6 / esp_core.c
1 /*
2 * Copyright (c) 2008-2019 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/route.h>
79
80 #include <netinet/in.h>
81 #include <netinet/in_var.h>
82 #if INET6
83 #include <netinet/ip6.h>
84 #include <netinet6/ip6_var.h>
85 #include <netinet/icmp6.h>
86 #endif
87
88 #include <netinet6/ipsec.h>
89 #if INET6
90 #include <netinet6/ipsec6.h>
91 #endif
92 #include <netinet6/ah.h>
93 #if INET6
94 #include <netinet6/ah6.h>
95 #endif
96 #include <netinet6/esp.h>
97 #if INET6
98 #include <netinet6/esp6.h>
99 #endif
100 #include <netinet6/esp_rijndael.h>
101 #include <netinet6/esp_chachapoly.h>
102 #include <net/pfkeyv2.h>
103 #include <netkey/keydb.h>
104 #include <netkey/key.h>
105 #include <libkern/crypto/des.h>
106
107 #include <net/net_osdep.h>
108
109 #include <sys/kdebug.h>
110 #define DBG_LAYER_BEG NETDBG_CODE(DBG_NETIPSEC, 1)
111 #define DBG_LAYER_END NETDBG_CODE(DBG_NETIPSEC, 3)
112 #define DBG_FNC_ESPAUTH NETDBG_CODE(DBG_NETIPSEC, (8 << 8))
113 #define MAX_SBUF_LEN 2000
114
115 extern lck_mtx_t *sadb_mutex;
116 os_log_t esp_mpkl_log_object = NULL;
117
118 static int esp_null_mature(struct secasvar *);
119 static int esp_null_decrypt(struct mbuf *, size_t,
120 struct secasvar *, const struct esp_algorithm *, int);
121 static int esp_null_encrypt(struct mbuf *, size_t, size_t,
122 struct secasvar *, const struct esp_algorithm *, int);
123 static int esp_descbc_mature(struct secasvar *);
124 static int esp_descbc_ivlen(const struct esp_algorithm *,
125 struct secasvar *);
126 static int esp_des_schedule(const struct esp_algorithm *,
127 struct secasvar *);
128 static int esp_des_schedlen(const struct esp_algorithm *);
129 static int esp_des_blockdecrypt(const struct esp_algorithm *,
130 struct secasvar *, u_int8_t *, u_int8_t *);
131 static int esp_des_blockencrypt(const struct esp_algorithm *,
132 struct secasvar *, u_int8_t *, u_int8_t *);
133 static int esp_cbc_mature(struct secasvar *);
134 static int esp_3des_schedule(const struct esp_algorithm *,
135 struct secasvar *);
136 static int esp_3des_schedlen(const struct esp_algorithm *);
137 static int esp_3des_blockdecrypt(const struct esp_algorithm *,
138 struct secasvar *, u_int8_t *, u_int8_t *);
139 static int esp_3des_blockencrypt(const struct esp_algorithm *,
140 struct secasvar *, u_int8_t *, u_int8_t *);
141 static int esp_common_ivlen(const struct esp_algorithm *,
142 struct secasvar *);
143 static int esp_cbc_decrypt(struct mbuf *, size_t,
144 struct secasvar *, const struct esp_algorithm *, int);
145 static int esp_cbc_encrypt(struct mbuf *, size_t, size_t,
146 struct secasvar *, const struct esp_algorithm *, int);
147 static int esp_gcm_mature(struct secasvar *);
148
149 #define MAXIVLEN 16
150
151 #define ESP_AESGCM_KEYLEN128 160 // 16-bytes key + 4 bytes salt
152 #define ESP_AESGCM_KEYLEN192 224 // 24-bytes key + 4 bytes salt
153 #define ESP_AESGCM_KEYLEN256 288 // 32-bytes key + 4 bytes salt
154
155 static const struct esp_algorithm des_cbc = {
156 .padbound = 8,
157 .ivlenval = -1,
158 .mature = esp_descbc_mature,
159 .keymin = 64,
160 .keymax = 64,
161 .schedlen = esp_des_schedlen,
162 .name = "des-cbc",
163 .ivlen = esp_descbc_ivlen,
164 .decrypt = esp_cbc_decrypt,
165 .encrypt = esp_cbc_encrypt,
166 .schedule = esp_des_schedule,
167 .blockdecrypt = esp_des_blockdecrypt,
168 .blockencrypt = esp_des_blockencrypt,
169 .icvlen = 0,
170 .finalizedecrypt = NULL,
171 .finalizeencrypt = NULL
172 };
173
174 static const struct esp_algorithm des3_cbc = {
175 .padbound = 8,
176 .ivlenval = 8,
177 .mature = esp_cbc_mature,
178 .keymin = 192,
179 .keymax = 192,
180 .schedlen = esp_3des_schedlen,
181 .name = "3des-cbc",
182 .ivlen = esp_common_ivlen,
183 .decrypt = esp_cbc_decrypt,
184 .encrypt = esp_cbc_encrypt,
185 .schedule = esp_3des_schedule,
186 .blockdecrypt = esp_3des_blockdecrypt,
187 .blockencrypt = esp_3des_blockencrypt,
188 .icvlen = 0,
189 .finalizedecrypt = NULL,
190 .finalizeencrypt = NULL
191 };
192
193 static const struct esp_algorithm null_esp = {
194 .padbound = 1,
195 .ivlenval = 0,
196 .mature = esp_null_mature,
197 .keymin = 0,
198 .keymax = 2048,
199 .schedlen = NULL,
200 .name = "null",
201 .ivlen = esp_common_ivlen,
202 .decrypt = esp_null_decrypt,
203 .encrypt = esp_null_encrypt,
204 .schedule = NULL,
205 .blockdecrypt = NULL,
206 .blockencrypt = NULL,
207 .icvlen = 0,
208 .finalizedecrypt = NULL,
209 .finalizeencrypt = NULL
210 };
211
212 static const struct esp_algorithm aes_cbc = {
213 .padbound = 16,
214 .ivlenval = 16,
215 .mature = esp_cbc_mature,
216 .keymin = 128,
217 .keymax = 256,
218 .schedlen = esp_aes_schedlen,
219 .name = "aes-cbc",
220 .ivlen = esp_common_ivlen,
221 .decrypt = esp_cbc_decrypt_aes,
222 .encrypt = esp_cbc_encrypt_aes,
223 .schedule = esp_aes_schedule,
224 .blockdecrypt = NULL,
225 .blockencrypt = NULL,
226 .icvlen = 0,
227 .finalizedecrypt = NULL,
228 .finalizeencrypt = NULL
229 };
230
231 static const struct esp_algorithm aes_gcm = {
232 .padbound = 4,
233 .ivlenval = 8,
234 .mature = esp_gcm_mature,
235 .keymin = ESP_AESGCM_KEYLEN128,
236 .keymax = ESP_AESGCM_KEYLEN256,
237 .schedlen = esp_gcm_schedlen,
238 .name = "aes-gcm",
239 .ivlen = esp_common_ivlen,
240 .decrypt = esp_gcm_decrypt_aes,
241 .encrypt = esp_gcm_encrypt_aes,
242 .schedule = esp_gcm_schedule,
243 .blockdecrypt = NULL,
244 .blockencrypt = NULL,
245 .icvlen = 16,
246 .finalizedecrypt = esp_gcm_decrypt_finalize,
247 .finalizeencrypt = esp_gcm_encrypt_finalize
248 };
249
250 static const struct esp_algorithm chacha_poly = {
251 .padbound = ESP_CHACHAPOLY_PAD_BOUND,
252 .ivlenval = ESP_CHACHAPOLY_IV_LEN,
253 .mature = esp_chachapoly_mature,
254 .keymin = ESP_CHACHAPOLY_KEYBITS_WITH_SALT,
255 .keymax = ESP_CHACHAPOLY_KEYBITS_WITH_SALT,
256 .schedlen = esp_chachapoly_schedlen,
257 .name = "chacha-poly",
258 .ivlen = esp_chachapoly_ivlen,
259 .decrypt = esp_chachapoly_decrypt,
260 .encrypt = esp_chachapoly_encrypt,
261 .schedule = esp_chachapoly_schedule,
262 .blockdecrypt = NULL,
263 .blockencrypt = NULL,
264 .icvlen = ESP_CHACHAPOLY_ICV_LEN,
265 .finalizedecrypt = esp_chachapoly_decrypt_finalize,
266 .finalizeencrypt = esp_chachapoly_encrypt_finalize
267 };
268
269 static const struct esp_algorithm *esp_algorithms[] = {
270 &des_cbc,
271 &des3_cbc,
272 &null_esp,
273 &aes_cbc,
274 &aes_gcm,
275 &chacha_poly,
276 };
277
278 const struct esp_algorithm *
279 esp_algorithm_lookup(int idx)
280 {
281 switch (idx) {
282 case SADB_EALG_DESCBC:
283 return &des_cbc;
284 case SADB_EALG_3DESCBC:
285 return &des3_cbc;
286 case SADB_EALG_NULL:
287 return &null_esp;
288 case SADB_X_EALG_RIJNDAELCBC:
289 return &aes_cbc;
290 case SADB_X_EALG_AES_GCM:
291 return &aes_gcm;
292 case SADB_X_EALG_CHACHA20POLY1305:
293 return &chacha_poly;
294 default:
295 return NULL;
296 }
297 }
298
299 int
300 esp_max_ivlen(void)
301 {
302 int idx;
303 int ivlen;
304
305 ivlen = 0;
306 for (idx = 0; idx < sizeof(esp_algorithms) / sizeof(esp_algorithms[0]);
307 idx++) {
308 if (esp_algorithms[idx]->ivlenval > ivlen) {
309 ivlen = esp_algorithms[idx]->ivlenval;
310 }
311 }
312
313 return ivlen;
314 }
315
316 int
317 esp_schedule(const struct esp_algorithm *algo, struct secasvar *sav)
318 {
319 int error;
320
321 /* check for key length */
322 if (_KEYBITS(sav->key_enc) < algo->keymin ||
323 _KEYBITS(sav->key_enc) > algo->keymax) {
324 ipseclog((LOG_ERR,
325 "esp_schedule %s: unsupported key length %d: "
326 "needs %d to %d bits\n", algo->name, _KEYBITS(sav->key_enc),
327 algo->keymin, algo->keymax));
328 return EINVAL;
329 }
330
331 lck_mtx_lock(sadb_mutex);
332 /* already allocated */
333 if (sav->sched && sav->schedlen != 0) {
334 lck_mtx_unlock(sadb_mutex);
335 return 0;
336 }
337
338 /* prevent disallowed implicit IV */
339 if (((sav->flags & SADB_X_EXT_IIV) != 0) &&
340 (sav->alg_enc != SADB_X_EALG_AES_GCM) &&
341 (sav->alg_enc != SADB_X_EALG_CHACHA20POLY1305)) {
342 ipseclog((LOG_ERR,
343 "esp_schedule %s: implicit IV not allowed\n",
344 algo->name));
345 lck_mtx_unlock(sadb_mutex);
346 return EINVAL;
347 }
348
349 /* no schedule necessary */
350 if (!algo->schedule || !algo->schedlen) {
351 lck_mtx_unlock(sadb_mutex);
352 return 0;
353 }
354
355 sav->schedlen = (*algo->schedlen)(algo);
356 if ((signed) sav->schedlen < 0) {
357 lck_mtx_unlock(sadb_mutex);
358 return EINVAL;
359 }
360
361 //#### that malloc should be replaced by a saved buffer...
362 sav->sched = _MALLOC(sav->schedlen, M_SECA, M_DONTWAIT);
363 if (!sav->sched) {
364 sav->schedlen = 0;
365 lck_mtx_unlock(sadb_mutex);
366 return ENOBUFS;
367 }
368
369 error = (*algo->schedule)(algo, sav);
370 if (error) {
371 ipseclog((LOG_ERR, "esp_schedule %s: error %d\n",
372 algo->name, error));
373 bzero(sav->sched, sav->schedlen);
374 FREE(sav->sched, M_SECA);
375 sav->sched = NULL;
376 sav->schedlen = 0;
377 }
378 lck_mtx_unlock(sadb_mutex);
379 return error;
380 }
381
382 static int
383 esp_null_mature(
384 __unused struct secasvar *sav)
385 {
386 /* anything is okay */
387 return 0;
388 }
389
390 static int
391 esp_null_decrypt(
392 __unused struct mbuf *m,
393 __unused size_t off, /* offset to ESP header */
394 __unused struct secasvar *sav,
395 __unused const struct esp_algorithm *algo,
396 __unused int ivlen)
397 {
398 return 0; /* do nothing */
399 }
400
401 static int
402 esp_null_encrypt(
403 __unused struct mbuf *m,
404 __unused size_t off, /* offset to ESP header */
405 __unused size_t plen, /* payload length (to be encrypted) */
406 __unused struct secasvar *sav,
407 __unused const struct esp_algorithm *algo,
408 __unused int ivlen)
409 {
410 return 0; /* do nothing */
411 }
412
413 static int
414 esp_descbc_mature(struct secasvar *sav)
415 {
416 const struct esp_algorithm *algo;
417
418 if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B)) {
419 ipseclog((LOG_ERR, "esp_cbc_mature: "
420 "algorithm incompatible with 4 octets IV length\n"));
421 return 1;
422 }
423
424 if (!sav->key_enc) {
425 ipseclog((LOG_ERR, "esp_descbc_mature: no key is given.\n"));
426 return 1;
427 }
428
429 algo = esp_algorithm_lookup(sav->alg_enc);
430 if (!algo) {
431 ipseclog((LOG_ERR,
432 "esp_descbc_mature: unsupported algorithm.\n"));
433 return 1;
434 }
435
436 if (_KEYBITS(sav->key_enc) < algo->keymin ||
437 _KEYBITS(sav->key_enc) > algo->keymax) {
438 ipseclog((LOG_ERR,
439 "esp_descbc_mature: invalid key length %d.\n",
440 _KEYBITS(sav->key_enc)));
441 return 1;
442 }
443
444 /* weak key check */
445 if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc))) {
446 ipseclog((LOG_ERR,
447 "esp_descbc_mature: weak key was passed.\n"));
448 return 1;
449 }
450
451 return 0;
452 }
453
454 static int
455 esp_descbc_ivlen(
456 __unused const struct esp_algorithm *algo,
457 struct secasvar *sav)
458 {
459 if (!sav) {
460 return 8;
461 }
462 if ((sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B)) {
463 return 4;
464 }
465 if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_DERIV)) {
466 return 4;
467 }
468 return 8;
469 }
470
471 static int
472 esp_des_schedlen(
473 __unused const struct esp_algorithm *algo)
474 {
475 return sizeof(des_ecb_key_schedule);
476 }
477
478 static int
479 esp_des_schedule(
480 __unused const struct esp_algorithm *algo,
481 struct secasvar *sav)
482 {
483 LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
484 if (des_ecb_key_sched((des_cblock *)_KEYBUF(sav->key_enc),
485 (des_ecb_key_schedule *)sav->sched)) {
486 return EINVAL;
487 } else {
488 return 0;
489 }
490 }
491
492 static int
493 esp_des_blockdecrypt(
494 __unused const struct esp_algorithm *algo,
495 struct secasvar *sav,
496 u_int8_t *s,
497 u_int8_t *d)
498 {
499 /* assumption: d has a good alignment */
500 bcopy(s, d, sizeof(DES_LONG) * 2);
501 return des_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
502 (des_ecb_key_schedule *)sav->sched, DES_DECRYPT);
503 }
504
505 static int
506 esp_des_blockencrypt(
507 __unused const struct esp_algorithm *algo,
508 struct secasvar *sav,
509 u_int8_t *s,
510 u_int8_t *d)
511 {
512 /* assumption: d has a good alignment */
513 bcopy(s, d, sizeof(DES_LONG) * 2);
514 return des_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
515 (des_ecb_key_schedule *)sav->sched, DES_ENCRYPT);
516 }
517
518 static int
519 esp_cbc_mature(struct secasvar *sav)
520 {
521 int keylen;
522 const struct esp_algorithm *algo;
523
524 if (sav->flags & SADB_X_EXT_OLD) {
525 ipseclog((LOG_ERR,
526 "esp_cbc_mature: algorithm incompatible with esp-old\n"));
527 return 1;
528 }
529 if (sav->flags & SADB_X_EXT_DERIV) {
530 ipseclog((LOG_ERR,
531 "esp_cbc_mature: algorithm incompatible with derived\n"));
532 return 1;
533 }
534
535 if (!sav->key_enc) {
536 ipseclog((LOG_ERR, "esp_cbc_mature: no key is given.\n"));
537 return 1;
538 }
539
540 algo = esp_algorithm_lookup(sav->alg_enc);
541 if (!algo) {
542 ipseclog((LOG_ERR,
543 "esp_cbc_mature: unsupported algorithm.\n"));
544 return 1;
545 }
546
547 keylen = sav->key_enc->sadb_key_bits;
548 if (keylen < algo->keymin || algo->keymax < keylen) {
549 ipseclog((LOG_ERR,
550 "esp_cbc_mature %s: invalid key length %d.\n",
551 algo->name, sav->key_enc->sadb_key_bits));
552 return 1;
553 }
554 switch (sav->alg_enc) {
555 case SADB_EALG_3DESCBC:
556 /* weak key check */
557 if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc)) ||
558 des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 8)) ||
559 des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 16))) {
560 ipseclog((LOG_ERR,
561 "esp_cbc_mature %s: weak key was passed.\n",
562 algo->name));
563 return 1;
564 }
565 break;
566 case SADB_X_EALG_RIJNDAELCBC:
567 /* allows specific key sizes only */
568 if (!(keylen == 128 || keylen == 192 || keylen == 256)) {
569 ipseclog((LOG_ERR,
570 "esp_cbc_mature %s: invalid key length %d.\n",
571 algo->name, keylen));
572 return 1;
573 }
574 break;
575 }
576
577 return 0;
578 }
579
580 static int
581 esp_gcm_mature(struct secasvar *sav)
582 {
583 int keylen;
584 const struct esp_algorithm *algo;
585
586 if (sav->flags & SADB_X_EXT_OLD) {
587 ipseclog((LOG_ERR,
588 "esp_gcm_mature: algorithm incompatible with esp-old\n"));
589 return 1;
590 }
591 if (sav->flags & SADB_X_EXT_DERIV) {
592 ipseclog((LOG_ERR,
593 "esp_gcm_mature: algorithm incompatible with derived\n"));
594 return 1;
595 }
596 if (sav->flags & SADB_X_EXT_IIV) {
597 ipseclog((LOG_ERR,
598 "esp_gcm_mature: implicit IV not currently implemented\n"));
599 return 1;
600 }
601
602 if (!sav->key_enc) {
603 ipseclog((LOG_ERR, "esp_gcm_mature: no key is given.\n"));
604 return 1;
605 }
606
607 algo = esp_algorithm_lookup(sav->alg_enc);
608 if (!algo) {
609 ipseclog((LOG_ERR,
610 "esp_gcm_mature: unsupported algorithm.\n"));
611 return 1;
612 }
613
614 keylen = sav->key_enc->sadb_key_bits;
615 if (keylen < algo->keymin || algo->keymax < keylen) {
616 ipseclog((LOG_ERR,
617 "esp_gcm_mature %s: invalid key length %d.\n",
618 algo->name, sav->key_enc->sadb_key_bits));
619 return 1;
620 }
621 switch (sav->alg_enc) {
622 case SADB_X_EALG_AES_GCM:
623 /* allows specific key sizes only */
624 if (!(keylen == ESP_AESGCM_KEYLEN128 || keylen == ESP_AESGCM_KEYLEN192 || keylen == ESP_AESGCM_KEYLEN256)) {
625 ipseclog((LOG_ERR,
626 "esp_gcm_mature %s: invalid key length %d.\n",
627 algo->name, keylen));
628 return 1;
629 }
630 break;
631 default:
632 ipseclog((LOG_ERR,
633 "esp_gcm_mature %s: invalid algo %d.\n", sav->alg_enc));
634 return 1;
635 }
636
637 return 0;
638 }
639
640 static int
641 esp_3des_schedlen(
642 __unused const struct esp_algorithm *algo)
643 {
644 return sizeof(des3_ecb_key_schedule);
645 }
646
647 static int
648 esp_3des_schedule(
649 __unused const struct esp_algorithm *algo,
650 struct secasvar *sav)
651 {
652 LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
653
654 if (des3_ecb_key_sched((des_cblock *)_KEYBUF(sav->key_enc),
655 (des3_ecb_key_schedule *)sav->sched)) {
656 return EINVAL;
657 } else {
658 return 0;
659 }
660 }
661
662 static int
663 esp_3des_blockdecrypt(
664 __unused const struct esp_algorithm *algo,
665 struct secasvar *sav,
666 u_int8_t *s,
667 u_int8_t *d)
668 {
669 /* assumption: d has a good alignment */
670 bcopy(s, d, sizeof(DES_LONG) * 2);
671 return des3_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
672 (des3_ecb_key_schedule *)sav->sched, DES_DECRYPT);
673 }
674
675 static int
676 esp_3des_blockencrypt(
677 __unused const struct esp_algorithm *algo,
678 struct secasvar *sav,
679 u_int8_t *s,
680 u_int8_t *d)
681 {
682 /* assumption: d has a good alignment */
683 bcopy(s, d, sizeof(DES_LONG) * 2);
684 return des3_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
685 (des3_ecb_key_schedule *)sav->sched, DES_ENCRYPT);
686 }
687
688 static int
689 esp_common_ivlen(
690 const struct esp_algorithm *algo,
691 __unused struct secasvar *sav)
692 {
693 if (!algo) {
694 panic("esp_common_ivlen: unknown algorithm");
695 }
696 return algo->ivlenval;
697 }
698
699 static int
700 esp_cbc_decrypt(struct mbuf *m, size_t off, struct secasvar *sav,
701 const struct esp_algorithm *algo, int ivlen)
702 {
703 struct mbuf *s;
704 struct mbuf *d, *d0, *dp;
705 int soff, doff; /* offset from the head of chain, to head of this mbuf */
706 int sn, dn; /* offset from the head of the mbuf, to meat */
707 size_t ivoff, bodyoff;
708 u_int8_t iv[MAXIVLEN] __attribute__((aligned(4))), *ivp;
709 u_int8_t *sbuf = NULL, *sp, *sp_unaligned;
710 u_int8_t *p, *q;
711 struct mbuf *scut;
712 int scutoff;
713 int i, result = 0;
714 int blocklen;
715 int derived;
716
717 if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
718 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
719 "unsupported ivlen %d\n", algo->name, ivlen));
720 m_freem(m);
721 return EINVAL;
722 }
723
724 /* assumes blocklen == padbound */
725 blocklen = algo->padbound;
726
727 #if DIAGNOSTIC
728 if (blocklen > sizeof(iv)) {
729 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
730 "unsupported blocklen %d\n", algo->name, blocklen));
731 m_freem(m);
732 return EINVAL;
733 }
734 #endif
735
736 if (sav->flags & SADB_X_EXT_OLD) {
737 /* RFC 1827 */
738 ivoff = off + sizeof(struct esp);
739 bodyoff = off + sizeof(struct esp) + ivlen;
740 derived = 0;
741 } else {
742 /* RFC 2406 */
743 if (sav->flags & SADB_X_EXT_DERIV) {
744 /*
745 * draft-ietf-ipsec-ciph-des-derived-00.txt
746 * uses sequence number field as IV field.
747 */
748 ivoff = off + sizeof(struct esp);
749 bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
750 ivlen = sizeof(u_int32_t);
751 derived = 1;
752 } else {
753 ivoff = off + sizeof(struct newesp);
754 bodyoff = off + sizeof(struct newesp) + ivlen;
755 derived = 0;
756 }
757 }
758
759 /* grab iv */
760 m_copydata(m, ivoff, ivlen, (caddr_t) iv);
761
762 /* extend iv */
763 if (ivlen == blocklen) {
764 ;
765 } else if (ivlen == 4 && blocklen == 8) {
766 bcopy(&iv[0], &iv[4], 4);
767 iv[4] ^= 0xff;
768 iv[5] ^= 0xff;
769 iv[6] ^= 0xff;
770 iv[7] ^= 0xff;
771 } else {
772 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
773 "unsupported ivlen/blocklen: %d %d\n",
774 algo->name, ivlen, blocklen));
775 m_freem(m);
776 return EINVAL;
777 }
778
779 if (m->m_pkthdr.len < bodyoff) {
780 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: bad len %d/%lu\n",
781 algo->name, m->m_pkthdr.len, (u_int32_t)bodyoff));
782 m_freem(m);
783 return EINVAL;
784 }
785 if ((m->m_pkthdr.len - bodyoff) % blocklen) {
786 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
787 "payload length must be multiple of %d\n",
788 algo->name, blocklen));
789 m_freem(m);
790 return EINVAL;
791 }
792
793 s = m;
794 d = d0 = dp = NULL;
795 soff = doff = sn = dn = 0;
796 ivp = sp = NULL;
797
798 /* skip bodyoff */
799 while (soff < bodyoff) {
800 if (soff + s->m_len > bodyoff) {
801 sn = bodyoff - soff;
802 break;
803 }
804
805 soff += s->m_len;
806 s = s->m_next;
807 }
808 scut = s;
809 scutoff = sn;
810
811 /* skip over empty mbuf */
812 while (s && s->m_len == 0) {
813 s = s->m_next;
814 }
815
816 // Allocate blocksized buffer for unaligned or non-contiguous access
817 sbuf = (u_int8_t *)_MALLOC(blocklen, M_SECA, M_DONTWAIT);
818 if (sbuf == NULL) {
819 return ENOBUFS;
820 }
821 while (soff < m->m_pkthdr.len) {
822 /* source */
823 if (sn + blocklen <= s->m_len) {
824 /* body is continuous */
825 sp = mtod(s, u_int8_t *) + sn;
826 } else {
827 /* body is non-continuous */
828 m_copydata(s, sn, blocklen, (caddr_t) sbuf);
829 sp = sbuf;
830 }
831
832 /* destination */
833 if (!d || dn + blocklen > d->m_len) {
834 if (d) {
835 dp = d;
836 }
837 MGET(d, M_DONTWAIT, MT_DATA);
838 i = m->m_pkthdr.len - (soff + sn);
839 if (d && i > MLEN) {
840 MCLGET(d, M_DONTWAIT);
841 if ((d->m_flags & M_EXT) == 0) {
842 m_free(d);
843 d = NULL;
844 }
845 }
846 if (!d) {
847 m_freem(m);
848 if (d0) {
849 m_freem(d0);
850 }
851 result = ENOBUFS;
852 goto end;
853 }
854 if (!d0) {
855 d0 = d;
856 }
857 if (dp) {
858 dp->m_next = d;
859 }
860
861 // try to make mbuf data aligned
862 if (!IPSEC_IS_P2ALIGNED(d->m_data)) {
863 m_adj(d, IPSEC_GET_P2UNALIGNED_OFS(d->m_data));
864 }
865
866 d->m_len = 0;
867 d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
868 if (d->m_len > i) {
869 d->m_len = i;
870 }
871 dn = 0;
872 }
873
874 /* decrypt */
875 // check input pointer alignment and use a separate aligned buffer (if sp is unaligned on 4-byte boundary).
876 if (IPSEC_IS_P2ALIGNED(sp)) {
877 sp_unaligned = NULL;
878 } else {
879 sp_unaligned = sp;
880 sp = sbuf;
881 memcpy(sp, sp_unaligned, blocklen);
882 }
883 // no need to check output pointer alignment
884 (*algo->blockdecrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
885
886 // update unaligned pointers
887 if (!IPSEC_IS_P2ALIGNED(sp_unaligned)) {
888 sp = sp_unaligned;
889 }
890
891 /* xor */
892 p = ivp ? ivp : iv;
893 q = mtod(d, u_int8_t *) + dn;
894 for (i = 0; i < blocklen; i++) {
895 q[i] ^= p[i];
896 }
897
898 /* next iv */
899 if (sp == sbuf) {
900 bcopy(sbuf, iv, blocklen);
901 ivp = NULL;
902 } else {
903 ivp = sp;
904 }
905
906 sn += blocklen;
907 dn += blocklen;
908
909 /* find the next source block */
910 while (s && sn >= s->m_len) {
911 sn -= s->m_len;
912 soff += s->m_len;
913 s = s->m_next;
914 }
915 }
916
917 m_freem(scut->m_next);
918 scut->m_len = scutoff;
919 scut->m_next = d0;
920
921 /* just in case */
922 bzero(iv, sizeof(iv));
923 bzero(sbuf, blocklen);
924 end:
925 if (sbuf != NULL) {
926 FREE(sbuf, M_SECA);
927 }
928 return result;
929 }
930
931 static int
932 esp_cbc_encrypt(
933 struct mbuf *m,
934 size_t off,
935 __unused size_t plen,
936 struct secasvar *sav,
937 const struct esp_algorithm *algo,
938 int ivlen)
939 {
940 struct mbuf *s;
941 struct mbuf *d, *d0, *dp;
942 int soff, doff; /* offset from the head of chain, to head of this mbuf */
943 int sn, dn; /* offset from the head of the mbuf, to meat */
944 size_t ivoff, bodyoff;
945 u_int8_t iv[MAXIVLEN] __attribute__((aligned(4))), *ivp;
946 u_int8_t *sbuf = NULL, *sp, *sp_unaligned;
947 u_int8_t *p, *q;
948 struct mbuf *scut;
949 int scutoff;
950 int i, result = 0;
951 int blocklen;
952 int derived;
953
954 if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
955 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
956 "unsupported ivlen %d\n", algo->name, ivlen));
957 m_freem(m);
958 return EINVAL;
959 }
960
961 /* assumes blocklen == padbound */
962 blocklen = algo->padbound;
963
964 #if DIAGNOSTIC
965 if (blocklen > sizeof(iv)) {
966 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
967 "unsupported blocklen %d\n", algo->name, blocklen));
968 m_freem(m);
969 return EINVAL;
970 }
971 #endif
972
973 if (sav->flags & SADB_X_EXT_OLD) {
974 /* RFC 1827 */
975 ivoff = off + sizeof(struct esp);
976 bodyoff = off + sizeof(struct esp) + ivlen;
977 derived = 0;
978 } else {
979 /* RFC 2406 */
980 if (sav->flags & SADB_X_EXT_DERIV) {
981 /*
982 * draft-ietf-ipsec-ciph-des-derived-00.txt
983 * uses sequence number field as IV field.
984 */
985 ivoff = off + sizeof(struct esp);
986 bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
987 ivlen = sizeof(u_int32_t);
988 derived = 1;
989 } else {
990 ivoff = off + sizeof(struct newesp);
991 bodyoff = off + sizeof(struct newesp) + ivlen;
992 derived = 0;
993 }
994 }
995
996 /* put iv into the packet. if we are in derived mode, use seqno. */
997 if (derived) {
998 m_copydata(m, ivoff, ivlen, (caddr_t) iv);
999 } else {
1000 bcopy(sav->iv, iv, ivlen);
1001 /* maybe it is better to overwrite dest, not source */
1002 m_copyback(m, ivoff, ivlen, (caddr_t) iv);
1003 }
1004
1005 /* extend iv */
1006 if (ivlen == blocklen) {
1007 ;
1008 } else if (ivlen == 4 && blocklen == 8) {
1009 bcopy(&iv[0], &iv[4], 4);
1010 iv[4] ^= 0xff;
1011 iv[5] ^= 0xff;
1012 iv[6] ^= 0xff;
1013 iv[7] ^= 0xff;
1014 } else {
1015 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
1016 "unsupported ivlen/blocklen: %d %d\n",
1017 algo->name, ivlen, blocklen));
1018 m_freem(m);
1019 return EINVAL;
1020 }
1021
1022 if (m->m_pkthdr.len < bodyoff) {
1023 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: bad len %d/%lu\n",
1024 algo->name, m->m_pkthdr.len, (u_int32_t)bodyoff));
1025 m_freem(m);
1026 return EINVAL;
1027 }
1028 if ((m->m_pkthdr.len - bodyoff) % blocklen) {
1029 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
1030 "payload length must be multiple of %lu\n",
1031 algo->name, (u_int32_t)algo->padbound));
1032 m_freem(m);
1033 return EINVAL;
1034 }
1035
1036 s = m;
1037 d = d0 = dp = NULL;
1038 soff = doff = sn = dn = 0;
1039 ivp = sp = NULL;
1040
1041 /* skip bodyoff */
1042 while (soff < bodyoff) {
1043 if (soff + s->m_len > bodyoff) {
1044 sn = bodyoff - soff;
1045 break;
1046 }
1047
1048 soff += s->m_len;
1049 s = s->m_next;
1050 }
1051 scut = s;
1052 scutoff = sn;
1053
1054 /* skip over empty mbuf */
1055 while (s && s->m_len == 0) {
1056 s = s->m_next;
1057 }
1058
1059 // Allocate blocksized buffer for unaligned or non-contiguous access
1060 sbuf = (u_int8_t *)_MALLOC(blocklen, M_SECA, M_DONTWAIT);
1061 if (sbuf == NULL) {
1062 return ENOBUFS;
1063 }
1064 while (soff < m->m_pkthdr.len) {
1065 /* source */
1066 if (sn + blocklen <= s->m_len) {
1067 /* body is continuous */
1068 sp = mtod(s, u_int8_t *) + sn;
1069 } else {
1070 /* body is non-continuous */
1071 m_copydata(s, sn, blocklen, (caddr_t) sbuf);
1072 sp = sbuf;
1073 }
1074
1075 /* destination */
1076 if (!d || dn + blocklen > d->m_len) {
1077 if (d) {
1078 dp = d;
1079 }
1080 MGET(d, M_DONTWAIT, MT_DATA);
1081 i = m->m_pkthdr.len - (soff + sn);
1082 if (d && i > MLEN) {
1083 MCLGET(d, M_DONTWAIT);
1084 if ((d->m_flags & M_EXT) == 0) {
1085 m_free(d);
1086 d = NULL;
1087 }
1088 }
1089 if (!d) {
1090 m_freem(m);
1091 if (d0) {
1092 m_freem(d0);
1093 }
1094 result = ENOBUFS;
1095 goto end;
1096 }
1097 if (!d0) {
1098 d0 = d;
1099 }
1100 if (dp) {
1101 dp->m_next = d;
1102 }
1103
1104 // try to make mbuf data aligned
1105 if (!IPSEC_IS_P2ALIGNED(d->m_data)) {
1106 m_adj(d, IPSEC_GET_P2UNALIGNED_OFS(d->m_data));
1107 }
1108
1109 d->m_len = 0;
1110 d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
1111 if (d->m_len > i) {
1112 d->m_len = i;
1113 }
1114 dn = 0;
1115 }
1116
1117 /* xor */
1118 p = ivp ? ivp : iv;
1119 q = sp;
1120 for (i = 0; i < blocklen; i++) {
1121 q[i] ^= p[i];
1122 }
1123
1124 /* encrypt */
1125 // check input pointer alignment and use a separate aligned buffer (if sp is not aligned on 4-byte boundary).
1126 if (IPSEC_IS_P2ALIGNED(sp)) {
1127 sp_unaligned = NULL;
1128 } else {
1129 sp_unaligned = sp;
1130 sp = sbuf;
1131 memcpy(sp, sp_unaligned, blocklen);
1132 }
1133 // no need to check output pointer alignment
1134 (*algo->blockencrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
1135
1136 // update unaligned pointers
1137 if (!IPSEC_IS_P2ALIGNED(sp_unaligned)) {
1138 sp = sp_unaligned;
1139 }
1140
1141 /* next iv */
1142 ivp = mtod(d, u_int8_t *) + dn;
1143
1144 sn += blocklen;
1145 dn += blocklen;
1146
1147 /* find the next source block */
1148 while (s && sn >= s->m_len) {
1149 sn -= s->m_len;
1150 soff += s->m_len;
1151 s = s->m_next;
1152 }
1153 }
1154
1155 m_freem(scut->m_next);
1156 scut->m_len = scutoff;
1157 scut->m_next = d0;
1158
1159 /* just in case */
1160 bzero(iv, sizeof(iv));
1161 bzero(sbuf, blocklen);
1162
1163 key_sa_stir_iv(sav);
1164 end:
1165 if (sbuf != NULL) {
1166 FREE(sbuf, M_SECA);
1167 }
1168 return result;
1169 }
1170
1171 /*------------------------------------------------------------*/
1172
1173 /* does not free m0 on error */
1174 int
1175 esp_auth(
1176 struct mbuf *m0,
1177 size_t skip, /* offset to ESP header */
1178 size_t length, /* payload length */
1179 struct secasvar *sav,
1180 u_char *sum)
1181 {
1182 struct mbuf *m;
1183 size_t off;
1184 struct ah_algorithm_state s;
1185 u_char sumbuf[AH_MAXSUMSIZE] __attribute__((aligned(4)));
1186 const struct ah_algorithm *algo;
1187 size_t siz;
1188 int error;
1189
1190 /* sanity checks */
1191 if (m0->m_pkthdr.len < skip) {
1192 ipseclog((LOG_DEBUG, "esp_auth: mbuf length < skip\n"));
1193 return EINVAL;
1194 }
1195 if (m0->m_pkthdr.len < skip + length) {
1196 ipseclog((LOG_DEBUG,
1197 "esp_auth: mbuf length < skip + length\n"));
1198 return EINVAL;
1199 }
1200
1201 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_START, skip, length, 0, 0, 0);
1202 /*
1203 * length of esp part (excluding authentication data) must be 4n,
1204 * since nexthdr must be at offset 4n+3.
1205 */
1206 if (length % 4) {
1207 ipseclog((LOG_ERR, "esp_auth: length is not multiple of 4\n"));
1208 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 1, 0, 0, 0, 0);
1209 return EINVAL;
1210 }
1211 if (!sav) {
1212 ipseclog((LOG_DEBUG, "esp_auth: NULL SA passed\n"));
1213 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 2, 0, 0, 0, 0);
1214 return EINVAL;
1215 }
1216 algo = ah_algorithm_lookup(sav->alg_auth);
1217 if (!algo) {
1218 ipseclog((LOG_ERR,
1219 "esp_auth: bad ESP auth algorithm passed: %d\n",
1220 sav->alg_auth));
1221 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 3, 0, 0, 0, 0);
1222 return EINVAL;
1223 }
1224
1225 m = m0;
1226 off = 0;
1227
1228 siz = (((*algo->sumsiz)(sav) + 3) & ~(4 - 1));
1229 if (sizeof(sumbuf) < siz) {
1230 ipseclog((LOG_DEBUG,
1231 "esp_auth: AH_MAXSUMSIZE is too small: siz=%lu\n",
1232 (u_int32_t)siz));
1233 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 4, 0, 0, 0, 0);
1234 return EINVAL;
1235 }
1236
1237 /* skip the header */
1238 while (skip) {
1239 if (!m) {
1240 panic("mbuf chain?");
1241 }
1242 if (m->m_len <= skip) {
1243 skip -= m->m_len;
1244 m = m->m_next;
1245 off = 0;
1246 } else {
1247 off = skip;
1248 skip = 0;
1249 }
1250 }
1251
1252 error = (*algo->init)(&s, sav);
1253 if (error) {
1254 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 5, 0, 0, 0, 0);
1255 return error;
1256 }
1257 while (0 < length) {
1258 if (!m) {
1259 panic("mbuf chain?");
1260 }
1261
1262 if (m->m_len - off < length) {
1263 (*algo->update)(&s, (caddr_t)(mtod(m, u_char *) + off),
1264 m->m_len - off);
1265 length -= m->m_len - off;
1266 m = m->m_next;
1267 off = 0;
1268 } else {
1269 (*algo->update)(&s, (caddr_t)(mtod(m, u_char *) + off), length);
1270 break;
1271 }
1272 }
1273 (*algo->result)(&s, (caddr_t) sumbuf, sizeof(sumbuf));
1274 bcopy(sumbuf, sum, siz); /*XXX*/
1275 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 6, 0, 0, 0, 0);
1276 return 0;
1277 }
1278
1279 void
1280 esp_init(void)
1281 {
1282 static int esp_initialized = 0;
1283
1284 if (esp_initialized) {
1285 return;
1286 }
1287
1288 esp_initialized = 1;
1289
1290 esp_mpkl_log_object = MPKL_CREATE_LOGOBJECT("com.apple.xnu.esp");
1291 if (esp_mpkl_log_object == NULL) {
1292 panic("MPKL_CREATE_LOGOBJECT for ESP failed");
1293 }
1294
1295 return;
1296 }