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
115extern lck_mtx_t *sadb_mutex;
116
117static int esp_null_mature(struct secasvar *);
118static int esp_null_decrypt(struct mbuf *, size_t,
119 struct secasvar *, const struct esp_algorithm *, int);
120static int esp_null_encrypt(struct mbuf *, size_t, size_t,
121 struct secasvar *, const struct esp_algorithm *, int);
122static int esp_descbc_mature(struct secasvar *);
123static int esp_descbc_ivlen(const struct esp_algorithm *,
124 struct secasvar *);
125static int esp_des_schedule(const struct esp_algorithm *,
126 struct secasvar *);
127static int esp_des_schedlen(const struct esp_algorithm *);
128static int esp_des_blockdecrypt(const struct esp_algorithm *,
129 struct secasvar *, u_int8_t *, u_int8_t *);
130static int esp_des_blockencrypt(const struct esp_algorithm *,
131 struct secasvar *, u_int8_t *, u_int8_t *);
132static int esp_cbc_mature(struct secasvar *);
133static int esp_3des_schedule(const struct esp_algorithm *,
134 struct secasvar *);
135static int esp_3des_schedlen(const struct esp_algorithm *);
136static int esp_3des_blockdecrypt(const struct esp_algorithm *,
137 struct secasvar *, u_int8_t *, u_int8_t *);
138static int esp_3des_blockencrypt(const struct esp_algorithm *,
139 struct secasvar *, u_int8_t *, u_int8_t *);
140static int esp_common_ivlen(const struct esp_algorithm *,
141 struct secasvar *);
142static int esp_cbc_decrypt(struct mbuf *, size_t,
143 struct secasvar *, const struct esp_algorithm *, int);
144static int esp_cbc_encrypt(struct mbuf *, size_t, size_t,
145 struct secasvar *, const struct esp_algorithm *, int);
146static 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
154static 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 };
161static 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 };
168static 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 };
173static 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 };
180static 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};
187static 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
196static 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
205const struct esp_algorithm *
206esp_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
226int
227esp_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
242int
243esp_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
308static int
309esp_null_mature(
310 __unused struct secasvar *sav)
311{
312
313 /* anything is okay */
314 return 0;
315}
316
317static int
318esp_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
329static int
330esp_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
342static int
343esp_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
383static int
384esp_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
398static int
399esp_des_schedlen(
400 __unused const struct esp_algorithm *algo)
401{
402 return sizeof(des_ecb_key_schedule);
403}
404
405static int
406esp_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
419static int
420esp_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
433static int
434esp_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
447static int
448esp_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
509static int
510esp_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
569static int
570esp_3des_schedlen(
571 __unused const struct esp_algorithm *algo)
572{
573
574 return sizeof(des3_ecb_key_schedule);
575}
576
577static int
578esp_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
591static int
592esp_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
605static int
606esp_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
619static int
620esp_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
630static int
631esp_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);
846end:
847 if (sbuf != NULL)
848 FREE(sbuf, M_SECA);
849 return result;
850}
851
852static int
853esp_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);
1077end:
1078 if (sbuf != NULL)
1079 FREE(sbuf, M_SECA);
1080 return result;
1081}
1082
1083/*------------------------------------------------------------*/
1084
1085/* does not free m0 on error */
1086int
1087esp_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}
1188