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