]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/esp_core.c
xnu-4903.221.2.tar.gz
[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 return ivlen;
240 }
241
242 int
243 esp_schedule(const struct esp_algorithm *algo, struct secasvar *sav)
244 {
245 int error;
246
247 /* check for key length */
248 if (_KEYBITS(sav->key_enc) < algo->keymin ||
249 _KEYBITS(sav->key_enc) > algo->keymax) {
250 ipseclog((LOG_ERR,
251 "esp_schedule %s: unsupported key length %d: "
252 "needs %d to %d bits\n", algo->name, _KEYBITS(sav->key_enc),
253 algo->keymin, algo->keymax));
254 return EINVAL;
255 }
256
257 lck_mtx_lock(sadb_mutex);
258 /* already allocated */
259 if (sav->sched && sav->schedlen != 0) {
260 lck_mtx_unlock(sadb_mutex);
261 return 0;
262 }
263
264 /* prevent disallowed implicit IV */
265 if (((sav->flags & SADB_X_EXT_IIV) != 0) &&
266 (sav->alg_enc != SADB_X_EALG_AES_GCM) &&
267 (sav->alg_enc != SADB_X_EALG_CHACHA20POLY1305)) {
268 ipseclog((LOG_ERR,
269 "esp_schedule %s: implicit IV not allowed\n",
270 algo->name));
271 lck_mtx_unlock(sadb_mutex);
272 return EINVAL;
273 }
274
275 /* no schedule necessary */
276 if (!algo->schedule || !algo->schedlen) {
277 lck_mtx_unlock(sadb_mutex);
278 return 0;
279 }
280
281 sav->schedlen = (*algo->schedlen)(algo);
282 if ((signed) sav->schedlen < 0) {
283 lck_mtx_unlock(sadb_mutex);
284 return EINVAL;
285 }
286
287 //#### that malloc should be replaced by a saved buffer...
288 sav->sched = _MALLOC(sav->schedlen, M_SECA, M_DONTWAIT);
289 if (!sav->sched) {
290 sav->schedlen = 0;
291 lck_mtx_unlock(sadb_mutex);
292 return ENOBUFS;
293 }
294
295 error = (*algo->schedule)(algo, sav);
296 if (error) {
297 ipseclog((LOG_ERR, "esp_schedule %s: error %d\n",
298 algo->name, error));
299 bzero(sav->sched, sav->schedlen);
300 FREE(sav->sched, M_SECA);
301 sav->sched = NULL;
302 sav->schedlen = 0;
303 }
304 lck_mtx_unlock(sadb_mutex);
305 return error;
306 }
307
308 static int
309 esp_null_mature(
310 __unused struct secasvar *sav)
311 {
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
326 return 0; /* do nothing */
327 }
328
329 static int
330 esp_null_encrypt(
331 __unused struct mbuf *m,
332 __unused size_t off, /* offset to ESP header */
333 __unused size_t plen, /* payload length (to be encrypted) */
334 __unused struct secasvar *sav,
335 __unused const struct esp_algorithm *algo,
336 __unused int ivlen)
337 {
338
339 return 0; /* do nothing */
340 }
341
342 static int
343 esp_descbc_mature(struct secasvar *sav)
344 {
345 const struct esp_algorithm *algo;
346
347 if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B)) {
348 ipseclog((LOG_ERR, "esp_cbc_mature: "
349 "algorithm incompatible with 4 octets IV length\n"));
350 return 1;
351 }
352
353 if (!sav->key_enc) {
354 ipseclog((LOG_ERR, "esp_descbc_mature: no key is given.\n"));
355 return 1;
356 }
357
358 algo = esp_algorithm_lookup(sav->alg_enc);
359 if (!algo) {
360 ipseclog((LOG_ERR,
361 "esp_descbc_mature: unsupported algorithm.\n"));
362 return 1;
363 }
364
365 if (_KEYBITS(sav->key_enc) < algo->keymin ||
366 _KEYBITS(sav->key_enc) > algo->keymax) {
367 ipseclog((LOG_ERR,
368 "esp_descbc_mature: invalid key length %d.\n",
369 _KEYBITS(sav->key_enc)));
370 return 1;
371 }
372
373 /* weak key check */
374 if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc))) {
375 ipseclog((LOG_ERR,
376 "esp_descbc_mature: weak key was passed.\n"));
377 return 1;
378 }
379
380 return 0;
381 }
382
383 static int
384 esp_descbc_ivlen(
385 __unused const struct esp_algorithm *algo,
386 struct secasvar *sav)
387 {
388
389 if (!sav)
390 return 8;
391 if ((sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B))
392 return 4;
393 if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_DERIV))
394 return 4;
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
411 LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
412 if (des_ecb_key_sched((des_cblock *)_KEYBUF(sav->key_enc),
413 (des_ecb_key_schedule *)sav->sched))
414 return EINVAL;
415 else
416 return 0;
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
574 return sizeof(des3_ecb_key_schedule);
575 }
576
577 static int
578 esp_3des_schedule(
579 __unused const struct esp_algorithm *algo,
580 struct secasvar *sav)
581 {
582 LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
583
584 if (des3_ecb_key_sched((des_cblock *)_KEYBUF(sav->key_enc),
585 (des3_ecb_key_schedule *)sav->sched))
586 return EINVAL;
587 else
588 return 0;
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
625 if (!algo)
626 panic("esp_common_ivlen: unknown algorithm");
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 // Allocate blocksized buffer for unaligned or non-contiguous access
747 sbuf = (u_int8_t *)_MALLOC(blocklen, M_SECA, M_DONTWAIT);
748 if (sbuf == NULL)
749 return ENOBUFS;
750 while (soff < m->m_pkthdr.len) {
751 /* source */
752 if (sn + blocklen <= s->m_len) {
753 /* body is continuous */
754 sp = mtod(s, u_int8_t *) + sn;
755 } else {
756 /* body is non-continuous */
757 m_copydata(s, sn, blocklen, (caddr_t) sbuf);
758 sp = sbuf;
759 }
760
761 /* destination */
762 if (!d || dn + blocklen > d->m_len) {
763 if (d)
764 dp = d;
765 MGET(d, M_DONTWAIT, MT_DATA);
766 i = m->m_pkthdr.len - (soff + sn);
767 if (d && i > MLEN) {
768 MCLGET(d, M_DONTWAIT);
769 if ((d->m_flags & M_EXT) == 0) {
770 m_free(d);
771 d = NULL;
772 }
773 }
774 if (!d) {
775 m_freem(m);
776 if (d0)
777 m_freem(d0);
778 result = ENOBUFS;
779 goto end;
780 }
781 if (!d0)
782 d0 = d;
783 if (dp)
784 dp->m_next = d;
785
786 // try to make mbuf data aligned
787 if (!IPSEC_IS_P2ALIGNED(d->m_data)) {
788 m_adj(d, IPSEC_GET_P2UNALIGNED_OFS(d->m_data));
789 }
790
791 d->m_len = 0;
792 d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
793 if (d->m_len > i)
794 d->m_len = i;
795 dn = 0;
796 }
797
798 /* decrypt */
799 // check input pointer alignment and use a separate aligned buffer (if sp is unaligned on 4-byte boundary).
800 if (IPSEC_IS_P2ALIGNED(sp)) {
801 sp_unaligned = NULL;
802 } else {
803 sp_unaligned = sp;
804 sp = sbuf;
805 memcpy(sp, sp_unaligned, blocklen);
806 }
807 // no need to check output pointer alignment
808 (*algo->blockdecrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
809
810 // update unaligned pointers
811 if (!IPSEC_IS_P2ALIGNED(sp_unaligned)) {
812 sp = sp_unaligned;
813 }
814
815 /* xor */
816 p = ivp ? ivp : iv;
817 q = mtod(d, u_int8_t *) + dn;
818 for (i = 0; i < blocklen; i++)
819 q[i] ^= p[i];
820
821 /* next iv */
822 if (sp == sbuf) {
823 bcopy(sbuf, iv, blocklen);
824 ivp = NULL;
825 } else
826 ivp = sp;
827
828 sn += blocklen;
829 dn += blocklen;
830
831 /* find the next source block */
832 while (s && sn >= s->m_len) {
833 sn -= s->m_len;
834 soff += s->m_len;
835 s = s->m_next;
836 }
837 }
838
839 m_freem(scut->m_next);
840 scut->m_len = scutoff;
841 scut->m_next = d0;
842
843 /* just in case */
844 bzero(iv, sizeof(iv));
845 bzero(sbuf, blocklen);
846 end:
847 if (sbuf != NULL)
848 FREE(sbuf, M_SECA);
849 return result;
850 }
851
852 static int
853 esp_cbc_encrypt(
854 struct mbuf *m,
855 size_t off,
856 __unused size_t plen,
857 struct secasvar *sav,
858 const struct esp_algorithm *algo,
859 int ivlen)
860 {
861 struct mbuf *s;
862 struct mbuf *d, *d0, *dp;
863 int soff, doff; /* offset from the head of chain, to head of this mbuf */
864 int sn, dn; /* offset from the head of the mbuf, to meat */
865 size_t ivoff, bodyoff;
866 u_int8_t iv[MAXIVLEN] __attribute__((aligned(4))), *ivp;
867 u_int8_t *sbuf = NULL, *sp, *sp_unaligned;
868 u_int8_t *p, *q;
869 struct mbuf *scut;
870 int scutoff;
871 int i, result = 0;
872 int blocklen;
873 int derived;
874
875 if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
876 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
877 "unsupported ivlen %d\n", algo->name, ivlen));
878 m_freem(m);
879 return EINVAL;
880 }
881
882 /* assumes blocklen == padbound */
883 blocklen = algo->padbound;
884
885 #if DIAGNOSTIC
886 if (blocklen > sizeof(iv)) {
887 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
888 "unsupported blocklen %d\n", algo->name, blocklen));
889 m_freem(m);
890 return EINVAL;
891 }
892 #endif
893
894 if (sav->flags & SADB_X_EXT_OLD) {
895 /* RFC 1827 */
896 ivoff = off + sizeof(struct esp);
897 bodyoff = off + sizeof(struct esp) + ivlen;
898 derived = 0;
899 } else {
900 /* RFC 2406 */
901 if (sav->flags & SADB_X_EXT_DERIV) {
902 /*
903 * draft-ietf-ipsec-ciph-des-derived-00.txt
904 * uses sequence number field as IV field.
905 */
906 ivoff = off + sizeof(struct esp);
907 bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
908 ivlen = sizeof(u_int32_t);
909 derived = 1;
910 } else {
911 ivoff = off + sizeof(struct newesp);
912 bodyoff = off + sizeof(struct newesp) + ivlen;
913 derived = 0;
914 }
915 }
916
917 /* put iv into the packet. if we are in derived mode, use seqno. */
918 if (derived)
919 m_copydata(m, ivoff, ivlen, (caddr_t) iv);
920 else {
921 bcopy(sav->iv, iv, ivlen);
922 /* maybe it is better to overwrite dest, not source */
923 m_copyback(m, ivoff, ivlen, (caddr_t) iv);
924 }
925
926 /* extend iv */
927 if (ivlen == blocklen)
928 ;
929 else if (ivlen == 4 && blocklen == 8) {
930 bcopy(&iv[0], &iv[4], 4);
931 iv[4] ^= 0xff;
932 iv[5] ^= 0xff;
933 iv[6] ^= 0xff;
934 iv[7] ^= 0xff;
935 } else {
936 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
937 "unsupported ivlen/blocklen: %d %d\n",
938 algo->name, ivlen, blocklen));
939 m_freem(m);
940 return EINVAL;
941 }
942
943 if (m->m_pkthdr.len < bodyoff) {
944 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: bad len %d/%lu\n",
945 algo->name, m->m_pkthdr.len, (u_int32_t)bodyoff));
946 m_freem(m);
947 return EINVAL;
948 }
949 if ((m->m_pkthdr.len - bodyoff) % blocklen) {
950 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
951 "payload length must be multiple of %lu\n",
952 algo->name, (u_int32_t)algo->padbound));
953 m_freem(m);
954 return EINVAL;
955 }
956
957 s = m;
958 d = d0 = dp = NULL;
959 soff = doff = sn = dn = 0;
960 ivp = sp = NULL;
961
962 /* skip bodyoff */
963 while (soff < bodyoff) {
964 if (soff + s->m_len > bodyoff) {
965 sn = bodyoff - soff;
966 break;
967 }
968
969 soff += s->m_len;
970 s = s->m_next;
971 }
972 scut = s;
973 scutoff = sn;
974
975 /* skip over empty mbuf */
976 while (s && s->m_len == 0)
977 s = s->m_next;
978
979 // Allocate blocksized buffer for unaligned or non-contiguous access
980 sbuf = (u_int8_t *)_MALLOC(blocklen, M_SECA, M_DONTWAIT);
981 if (sbuf == NULL)
982 return ENOBUFS;
983 while (soff < m->m_pkthdr.len) {
984 /* source */
985 if (sn + blocklen <= s->m_len) {
986 /* body is continuous */
987 sp = mtod(s, u_int8_t *) + sn;
988 } else {
989 /* body is non-continuous */
990 m_copydata(s, sn, blocklen, (caddr_t) sbuf);
991 sp = sbuf;
992 }
993
994 /* destination */
995 if (!d || dn + blocklen > d->m_len) {
996 if (d)
997 dp = d;
998 MGET(d, M_DONTWAIT, MT_DATA);
999 i = m->m_pkthdr.len - (soff + sn);
1000 if (d && i > MLEN) {
1001 MCLGET(d, M_DONTWAIT);
1002 if ((d->m_flags & M_EXT) == 0) {
1003 m_free(d);
1004 d = NULL;
1005 }
1006 }
1007 if (!d) {
1008 m_freem(m);
1009 if (d0)
1010 m_freem(d0);
1011 result = ENOBUFS;
1012 goto end;
1013 }
1014 if (!d0)
1015 d0 = d;
1016 if (dp)
1017 dp->m_next = d;
1018
1019 // try to make mbuf data aligned
1020 if (!IPSEC_IS_P2ALIGNED(d->m_data)) {
1021 m_adj(d, IPSEC_GET_P2UNALIGNED_OFS(d->m_data));
1022 }
1023
1024 d->m_len = 0;
1025 d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
1026 if (d->m_len > i)
1027 d->m_len = i;
1028 dn = 0;
1029 }
1030
1031 /* xor */
1032 p = ivp ? ivp : iv;
1033 q = sp;
1034 for (i = 0; i < blocklen; i++)
1035 q[i] ^= p[i];
1036
1037 /* encrypt */
1038 // check input pointer alignment and use a separate aligned buffer (if sp is not aligned on 4-byte boundary).
1039 if (IPSEC_IS_P2ALIGNED(sp)) {
1040 sp_unaligned = NULL;
1041 } else {
1042 sp_unaligned = sp;
1043 sp = sbuf;
1044 memcpy(sp, sp_unaligned, blocklen);
1045 }
1046 // no need to check output pointer alignment
1047 (*algo->blockencrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
1048
1049 // update unaligned pointers
1050 if (!IPSEC_IS_P2ALIGNED(sp_unaligned)) {
1051 sp = sp_unaligned;
1052 }
1053
1054 /* next iv */
1055 ivp = mtod(d, u_int8_t *) + dn;
1056
1057 sn += blocklen;
1058 dn += blocklen;
1059
1060 /* find the next source block */
1061 while (s && sn >= s->m_len) {
1062 sn -= s->m_len;
1063 soff += s->m_len;
1064 s = s->m_next;
1065 }
1066 }
1067
1068 m_freem(scut->m_next);
1069 scut->m_len = scutoff;
1070 scut->m_next = d0;
1071
1072 /* just in case */
1073 bzero(iv, sizeof(iv));
1074 bzero(sbuf, blocklen);
1075
1076 key_sa_stir_iv(sav);
1077 end:
1078 if (sbuf != NULL)
1079 FREE(sbuf, M_SECA);
1080 return result;
1081 }
1082
1083 /*------------------------------------------------------------*/
1084
1085 /* does not free m0 on error */
1086 int
1087 esp_auth(
1088 struct mbuf *m0,
1089 size_t skip, /* offset to ESP header */
1090 size_t length, /* payload length */
1091 struct secasvar *sav,
1092 u_char *sum)
1093 {
1094 struct mbuf *m;
1095 size_t off;
1096 struct ah_algorithm_state s;
1097 u_char sumbuf[AH_MAXSUMSIZE] __attribute__((aligned(4)));
1098 const struct ah_algorithm *algo;
1099 size_t siz;
1100 int error;
1101
1102 /* sanity checks */
1103 if (m0->m_pkthdr.len < skip) {
1104 ipseclog((LOG_DEBUG, "esp_auth: mbuf length < skip\n"));
1105 return EINVAL;
1106 }
1107 if (m0->m_pkthdr.len < skip + length) {
1108 ipseclog((LOG_DEBUG,
1109 "esp_auth: mbuf length < skip + length\n"));
1110 return EINVAL;
1111 }
1112
1113 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_START, skip,length,0,0,0);
1114 /*
1115 * length of esp part (excluding authentication data) must be 4n,
1116 * since nexthdr must be at offset 4n+3.
1117 */
1118 if (length % 4) {
1119 ipseclog((LOG_ERR, "esp_auth: length is not multiple of 4\n"));
1120 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 1,0,0,0,0);
1121 return EINVAL;
1122 }
1123 if (!sav) {
1124 ipseclog((LOG_DEBUG, "esp_auth: NULL SA passed\n"));
1125 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 2,0,0,0,0);
1126 return EINVAL;
1127 }
1128 algo = ah_algorithm_lookup(sav->alg_auth);
1129 if (!algo) {
1130 ipseclog((LOG_ERR,
1131 "esp_auth: bad ESP auth algorithm passed: %d\n",
1132 sav->alg_auth));
1133 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 3,0,0,0,0);
1134 return EINVAL;
1135 }
1136
1137 m = m0;
1138 off = 0;
1139
1140 siz = (((*algo->sumsiz)(sav) + 3) & ~(4 - 1));
1141 if (sizeof(sumbuf) < siz) {
1142 ipseclog((LOG_DEBUG,
1143 "esp_auth: AH_MAXSUMSIZE is too small: siz=%lu\n",
1144 (u_int32_t)siz));
1145 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 4,0,0,0,0);
1146 return EINVAL;
1147 }
1148
1149 /* skip the header */
1150 while (skip) {
1151 if (!m)
1152 panic("mbuf chain?");
1153 if (m->m_len <= skip) {
1154 skip -= m->m_len;
1155 m = m->m_next;
1156 off = 0;
1157 } else {
1158 off = skip;
1159 skip = 0;
1160 }
1161 }
1162
1163 error = (*algo->init)(&s, sav);
1164 if (error) {
1165 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 5,0,0,0,0);
1166 return error;
1167 }
1168 while (0 < length) {
1169 if (!m)
1170 panic("mbuf chain?");
1171
1172 if (m->m_len - off < length) {
1173 (*algo->update)(&s, (caddr_t)(mtod(m, u_char *) + off),
1174 m->m_len - off);
1175 length -= m->m_len - off;
1176 m = m->m_next;
1177 off = 0;
1178 } else {
1179 (*algo->update)(&s, (caddr_t)(mtod(m, u_char *) + off), length);
1180 break;
1181 }
1182 }
1183 (*algo->result)(&s, (caddr_t) sumbuf, sizeof(sumbuf));
1184 bcopy(sumbuf, sum, siz); /*XXX*/
1185 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 6,0,0,0,0);
1186 return 0;
1187 }