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