]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/esp_core.c
xnu-792.24.17.tar.gz
[apple/xnu.git] / bsd / netinet6 / esp_core.c
1 /* $FreeBSD: src/sys/netinet6/esp_core.c,v 1.1.2.4 2002/03/26 10:12:29 ume Exp $ */
2 /* $KAME: esp_core.c,v 1.50 2000/11/02 12:27:38 itojun Exp $ */
3
4 /*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #define _IP_VHL
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/malloc.h>
38 #include <sys/mbuf.h>
39 #include <sys/domain.h>
40 #include <sys/protosw.h>
41 #include <sys/socket.h>
42 #include <sys/errno.h>
43 #include <sys/time.h>
44 #include <sys/kernel.h>
45 #include <sys/syslog.h>
46
47 #include <kern/locks.h>
48
49 #include <net/if.h>
50 #include <net/route.h>
51
52 #include <netinet/in.h>
53 #include <netinet/in_var.h>
54 #if INET6
55 #include <netinet/ip6.h>
56 #include <netinet6/ip6_var.h>
57 #include <netinet/icmp6.h>
58 #endif
59
60 #include <netinet6/ipsec.h>
61 #if INET6
62 #include <netinet6/ipsec6.h>
63 #endif
64 #include <netinet6/ah.h>
65 #if INET6
66 #include <netinet6/ah6.h>
67 #endif
68 #include <netinet6/esp.h>
69 #if INET6
70 #include <netinet6/esp6.h>
71 #endif
72 #include <netinet6/esp_rijndael.h>
73 #include <net/pfkeyv2.h>
74 #include <netkey/keydb.h>
75 #include <netkey/key.h>
76 #include <crypto/des/des.h>
77 #include <crypto/blowfish/blowfish.h>
78 #include <crypto/cast128/cast128.h>
79
80 #include <net/net_osdep.h>
81
82 #include <sys/kdebug.h>
83 #define DBG_LAYER_BEG NETDBG_CODE(DBG_NETIPSEC, 1)
84 #define DBG_LAYER_END NETDBG_CODE(DBG_NETIPSEC, 3)
85 #define DBG_FNC_ESPAUTH NETDBG_CODE(DBG_NETIPSEC, (8 << 8))
86
87 extern lck_mtx_t *sadb_mutex;
88
89 static int esp_null_mature(struct secasvar *);
90 static int esp_null_decrypt(struct mbuf *, size_t,
91 struct secasvar *, const struct esp_algorithm *, int);
92 static int esp_null_encrypt(struct mbuf *, size_t, size_t,
93 struct secasvar *, const struct esp_algorithm *, int);
94 static int esp_descbc_mature(struct secasvar *);
95 static int esp_descbc_ivlen(const struct esp_algorithm *,
96 struct secasvar *);
97 static int esp_des_schedule(const struct esp_algorithm *,
98 struct secasvar *);
99 static int esp_des_schedlen(const struct esp_algorithm *);
100 static int esp_des_blockdecrypt(const struct esp_algorithm *,
101 struct secasvar *, u_int8_t *, u_int8_t *);
102 static int esp_des_blockencrypt(const struct esp_algorithm *,
103 struct secasvar *, u_int8_t *, u_int8_t *);
104 static int esp_cbc_mature(struct secasvar *);
105 static int esp_blowfish_schedule(const struct esp_algorithm *,
106 struct secasvar *);
107 static int esp_blowfish_schedlen(const struct esp_algorithm *);
108 static int esp_blowfish_blockdecrypt(const struct esp_algorithm *,
109 struct secasvar *, u_int8_t *, u_int8_t *);
110 static int esp_blowfish_blockencrypt(const struct esp_algorithm *,
111 struct secasvar *, u_int8_t *, u_int8_t *);
112 static int esp_cast128_schedule(const struct esp_algorithm *,
113 struct secasvar *);
114 static int esp_cast128_schedlen(const struct esp_algorithm *);
115 static int esp_cast128_blockdecrypt(const struct esp_algorithm *,
116 struct secasvar *, u_int8_t *, u_int8_t *);
117 static int esp_cast128_blockencrypt(const struct esp_algorithm *,
118 struct secasvar *, u_int8_t *, u_int8_t *);
119 static int esp_3des_schedule(const struct esp_algorithm *,
120 struct secasvar *);
121 static int esp_3des_schedlen(const struct esp_algorithm *);
122 static int esp_3des_blockdecrypt(const struct esp_algorithm *,
123 struct secasvar *, u_int8_t *, u_int8_t *);
124 static int esp_3des_blockencrypt(const struct esp_algorithm *,
125 struct secasvar *, u_int8_t *, u_int8_t *);
126 static int esp_common_ivlen(const struct esp_algorithm *,
127 struct secasvar *);
128 static int esp_cbc_decrypt(struct mbuf *, size_t,
129 struct secasvar *, const struct esp_algorithm *, int);
130 static int esp_cbc_encrypt(struct mbuf *, size_t, size_t,
131 struct secasvar *, const struct esp_algorithm *, int);
132
133 #define MAXIVLEN 16
134
135 static const struct esp_algorithm esp_algorithms[] = {
136 { 8, -1, esp_descbc_mature, 64, 64, esp_des_schedlen,
137 "des-cbc",
138 esp_descbc_ivlen, esp_cbc_decrypt,
139 esp_cbc_encrypt, esp_des_schedule,
140 esp_des_blockdecrypt, esp_des_blockencrypt, },
141 { 8, 8, esp_cbc_mature, 192, 192, esp_3des_schedlen,
142 "3des-cbc",
143 esp_common_ivlen, esp_cbc_decrypt,
144 esp_cbc_encrypt, esp_3des_schedule,
145 esp_3des_blockdecrypt, esp_3des_blockencrypt, },
146 { 1, 0, esp_null_mature, 0, 2048, 0, "null",
147 esp_common_ivlen, esp_null_decrypt,
148 esp_null_encrypt, NULL, },
149 { 8, 8, esp_cbc_mature, 40, 448, esp_blowfish_schedlen, "blowfish-cbc",
150 esp_common_ivlen, esp_cbc_decrypt,
151 esp_cbc_encrypt, esp_blowfish_schedule,
152 esp_blowfish_blockdecrypt, esp_blowfish_blockencrypt, },
153 { 8, 8, esp_cbc_mature, 40, 128, esp_cast128_schedlen,
154 "cast128-cbc",
155 esp_common_ivlen, esp_cbc_decrypt,
156 esp_cbc_encrypt, esp_cast128_schedule,
157 esp_cast128_blockdecrypt, esp_cast128_blockencrypt, },
158 { 16, 16, esp_cbc_mature, 128, 256, esp_aes_schedlen,
159 "aes-cbc",
160 esp_common_ivlen, esp_cbc_decrypt_aes,
161 esp_cbc_encrypt_aes, esp_aes_schedule,
162 0, 0 },
163 };
164
165 const struct esp_algorithm *
166 esp_algorithm_lookup(idx)
167 int idx;
168 {
169
170 switch (idx) {
171 case SADB_EALG_DESCBC:
172 return &esp_algorithms[0];
173 case SADB_EALG_3DESCBC:
174 return &esp_algorithms[1];
175 case SADB_EALG_NULL:
176 return &esp_algorithms[2];
177 case SADB_X_EALG_BLOWFISHCBC:
178 return &esp_algorithms[3];
179 case SADB_X_EALG_CAST128CBC:
180 return &esp_algorithms[4];
181 case SADB_X_EALG_RIJNDAELCBC:
182 return &esp_algorithms[5];
183 default:
184 return NULL;
185 }
186 }
187
188 int
189 esp_max_ivlen()
190 {
191 int idx;
192 int ivlen;
193
194 ivlen = 0;
195 for (idx = 0; idx < sizeof(esp_algorithms)/sizeof(esp_algorithms[0]);
196 idx++) {
197 if (esp_algorithms[idx].ivlenval > ivlen)
198 ivlen = esp_algorithms[idx].ivlenval;
199 }
200
201 return ivlen;
202 }
203
204 int
205 esp_schedule(algo, sav)
206 const struct esp_algorithm *algo;
207 struct secasvar *sav;
208 {
209 int error;
210
211 /* check for key length */
212 if (_KEYBITS(sav->key_enc) < algo->keymin ||
213 _KEYBITS(sav->key_enc) > algo->keymax) {
214 ipseclog((LOG_ERR,
215 "esp_schedule %s: unsupported key length %d: "
216 "needs %d to %d bits\n", algo->name, _KEYBITS(sav->key_enc),
217 algo->keymin, algo->keymax));
218 return EINVAL;
219 }
220
221 /* already allocated */
222 if (sav->sched && sav->schedlen != 0)
223 return 0;
224 /* no schedule necessary */
225 if (!algo->schedule || !algo->schedlen)
226 return 0;
227
228 sav->schedlen = (*algo->schedlen)(algo);
229 if (sav->schedlen < 0)
230 return EINVAL;
231
232 //#### that malloc should be replaced by a saved buffer...
233 sav->sched = _MALLOC(sav->schedlen, M_SECA, M_DONTWAIT);
234 if (!sav->sched) {
235 sav->schedlen = 0;
236 return ENOBUFS;
237 }
238
239 error = (*algo->schedule)(algo, sav);
240 if (error) {
241 ipseclog((LOG_ERR, "esp_schedule %s: error %d\n",
242 algo->name, error));
243 bzero(sav->sched, sav->schedlen);
244 FREE(sav->sched, M_SECA);
245 sav->sched = NULL;
246 sav->schedlen = 0;
247 }
248 return error;
249 }
250
251 static int
252 esp_null_mature(sav)
253 struct secasvar *sav;
254 {
255
256 /* anything is okay */
257 return 0;
258 }
259
260 static int
261 esp_null_decrypt(m, off, sav, algo, ivlen)
262 struct mbuf *m;
263 size_t off; /* offset to ESP header */
264 struct secasvar *sav;
265 const struct esp_algorithm *algo;
266 int ivlen;
267 {
268
269 return 0; /* do nothing */
270 }
271
272 static int
273 esp_null_encrypt(m, off, plen, sav, algo, ivlen)
274 struct mbuf *m;
275 size_t off; /* offset to ESP header */
276 size_t plen; /* payload length (to be encrypted) */
277 struct secasvar *sav;
278 const struct esp_algorithm *algo;
279 int ivlen;
280 {
281
282 return 0; /* do nothing */
283 }
284
285 static int
286 esp_descbc_mature(sav)
287 struct secasvar *sav;
288 {
289 const struct esp_algorithm *algo;
290
291 if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B)) {
292 ipseclog((LOG_ERR, "esp_cbc_mature: "
293 "algorithm incompatible with 4 octets IV length\n"));
294 return 1;
295 }
296
297 if (!sav->key_enc) {
298 ipseclog((LOG_ERR, "esp_descbc_mature: no key is given.\n"));
299 return 1;
300 }
301
302 algo = esp_algorithm_lookup(sav->alg_enc);
303 if (!algo) {
304 ipseclog((LOG_ERR,
305 "esp_descbc_mature: unsupported algorithm.\n"));
306 return 1;
307 }
308
309 if (_KEYBITS(sav->key_enc) < algo->keymin ||
310 _KEYBITS(sav->key_enc) > algo->keymax) {
311 ipseclog((LOG_ERR,
312 "esp_descbc_mature: invalid key length %d.\n",
313 _KEYBITS(sav->key_enc)));
314 return 1;
315 }
316
317 /* weak key check */
318 if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc))) {
319 ipseclog((LOG_ERR,
320 "esp_descbc_mature: weak key was passed.\n"));
321 return 1;
322 }
323
324 return 0;
325 }
326
327 static int
328 esp_descbc_ivlen(algo, sav)
329 const struct esp_algorithm *algo;
330 struct secasvar *sav;
331 {
332
333 if (!sav)
334 return 8;
335 if ((sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B))
336 return 4;
337 if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_DERIV))
338 return 4;
339 return 8;
340 }
341
342 static int
343 esp_des_schedlen(algo)
344 const struct esp_algorithm *algo;
345 {
346
347 return sizeof(des_key_schedule);
348 }
349
350 static int
351 esp_des_schedule(algo, sav)
352 const struct esp_algorithm *algo;
353 struct secasvar *sav;
354 {
355
356 if (des_key_sched((des_cblock *)_KEYBUF(sav->key_enc),
357 *(des_key_schedule *)sav->sched))
358 return EINVAL;
359 else
360 return 0;
361 }
362
363 static int
364 esp_des_blockdecrypt(algo, sav, s, d)
365 const struct esp_algorithm *algo;
366 struct secasvar *sav;
367 u_int8_t *s;
368 u_int8_t *d;
369 {
370
371 /* assumption: d has a good alignment */
372 bcopy(s, d, sizeof(DES_LONG) * 2);
373 des_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
374 *(des_key_schedule *)sav->sched, DES_DECRYPT);
375 return 0;
376 }
377
378 static int
379 esp_des_blockencrypt(algo, sav, s, d)
380 const struct esp_algorithm *algo;
381 struct secasvar *sav;
382 u_int8_t *s;
383 u_int8_t *d;
384 {
385
386 /* assumption: d has a good alignment */
387 bcopy(s, d, sizeof(DES_LONG) * 2);
388 des_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
389 *(des_key_schedule *)sav->sched, DES_ENCRYPT);
390 return 0;
391 }
392
393 static int
394 esp_cbc_mature(sav)
395 struct secasvar *sav;
396 {
397 int keylen;
398 const struct esp_algorithm *algo;
399
400 if (sav->flags & SADB_X_EXT_OLD) {
401 ipseclog((LOG_ERR,
402 "esp_cbc_mature: algorithm incompatible with esp-old\n"));
403 return 1;
404 }
405 if (sav->flags & SADB_X_EXT_DERIV) {
406 ipseclog((LOG_ERR,
407 "esp_cbc_mature: algorithm incompatible with derived\n"));
408 return 1;
409 }
410
411 if (!sav->key_enc) {
412 ipseclog((LOG_ERR, "esp_cbc_mature: no key is given.\n"));
413 return 1;
414 }
415
416 algo = esp_algorithm_lookup(sav->alg_enc);
417 if (!algo) {
418 ipseclog((LOG_ERR,
419 "esp_cbc_mature %s: unsupported algorithm.\n", algo->name));
420 return 1;
421 }
422
423 keylen = sav->key_enc->sadb_key_bits;
424 if (keylen < algo->keymin || algo->keymax < keylen) {
425 ipseclog((LOG_ERR,
426 "esp_cbc_mature %s: invalid key length %d.\n",
427 algo->name, sav->key_enc->sadb_key_bits));
428 return 1;
429 }
430 switch (sav->alg_enc) {
431 case SADB_EALG_3DESCBC:
432 /* weak key check */
433 if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc)) ||
434 des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 8)) ||
435 des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 16))) {
436 ipseclog((LOG_ERR,
437 "esp_cbc_mature %s: weak key was passed.\n",
438 algo->name));
439 return 1;
440 }
441 break;
442 case SADB_X_EALG_BLOWFISHCBC:
443 case SADB_X_EALG_CAST128CBC:
444 break;
445 case SADB_X_EALG_RIJNDAELCBC:
446 /* allows specific key sizes only */
447 if (!(keylen == 128 || keylen == 192 || keylen == 256)) {
448 ipseclog((LOG_ERR,
449 "esp_cbc_mature %s: invalid key length %d.\n",
450 algo->name, keylen));
451 return 1;
452 }
453 break;
454 }
455
456 return 0;
457 }
458
459 static int
460 esp_blowfish_schedlen(algo)
461 const struct esp_algorithm *algo;
462 {
463
464 return sizeof(BF_KEY);
465 }
466
467 static int
468 esp_blowfish_schedule(algo, sav)
469 const struct esp_algorithm *algo;
470 struct secasvar *sav;
471 {
472
473 BF_set_key((BF_KEY *)sav->sched, _KEYLEN(sav->key_enc),
474 _KEYBUF(sav->key_enc));
475 return 0;
476 }
477
478 static int
479 esp_blowfish_blockdecrypt(algo, sav, s, d)
480 const struct esp_algorithm *algo;
481 struct secasvar *sav;
482 u_int8_t *s;
483 u_int8_t *d;
484 {
485 /* HOLY COW! BF_decrypt() takes values in host byteorder */
486 BF_LONG t[2];
487
488 bcopy(s, t, sizeof(t));
489 t[0] = ntohl(t[0]);
490 t[1] = ntohl(t[1]);
491 BF_decrypt(t, (BF_KEY *)sav->sched);
492 t[0] = htonl(t[0]);
493 t[1] = htonl(t[1]);
494 bcopy(t, d, sizeof(t));
495 return 0;
496 }
497
498 static int
499 esp_blowfish_blockencrypt(algo, sav, s, d)
500 const struct esp_algorithm *algo;
501 struct secasvar *sav;
502 u_int8_t *s;
503 u_int8_t *d;
504 {
505 /* HOLY COW! BF_encrypt() takes values in host byteorder */
506 BF_LONG t[2];
507
508 bcopy(s, t, sizeof(t));
509 t[0] = ntohl(t[0]);
510 t[1] = ntohl(t[1]);
511 BF_encrypt(t, (BF_KEY *)sav->sched);
512 t[0] = htonl(t[0]);
513 t[1] = htonl(t[1]);
514 bcopy(t, d, sizeof(t));
515 return 0;
516 }
517
518 static int
519 esp_cast128_schedlen(algo)
520 const struct esp_algorithm *algo;
521 {
522
523 return sizeof(u_int32_t) * 32;
524 }
525
526 static int
527 esp_cast128_schedule(algo, sav)
528 const struct esp_algorithm *algo;
529 struct secasvar *sav;
530 {
531
532 set_cast128_subkey((u_int32_t *)sav->sched, _KEYBUF(sav->key_enc),
533 _KEYLEN(sav->key_enc));
534 return 0;
535 }
536
537 static int
538 esp_cast128_blockdecrypt(algo, sav, s, d)
539 const struct esp_algorithm *algo;
540 struct secasvar *sav;
541 u_int8_t *s;
542 u_int8_t *d;
543 {
544
545 if (_KEYLEN(sav->key_enc) <= 80 / 8)
546 cast128_decrypt_round12(d, s, (u_int32_t *)sav->sched);
547 else
548 cast128_decrypt_round16(d, s, (u_int32_t *)sav->sched);
549 return 0;
550 }
551
552 static int
553 esp_cast128_blockencrypt(algo, sav, s, d)
554 const struct esp_algorithm *algo;
555 struct secasvar *sav;
556 u_int8_t *s;
557 u_int8_t *d;
558 {
559
560 if (_KEYLEN(sav->key_enc) <= 80 / 8)
561 cast128_encrypt_round12(d, s, (u_int32_t *)sav->sched);
562 else
563 cast128_encrypt_round16(d, s, (u_int32_t *)sav->sched);
564 return 0;
565 }
566
567 static int
568 esp_3des_schedlen(algo)
569 const struct esp_algorithm *algo;
570 {
571
572 return sizeof(des_key_schedule) * 3;
573 }
574
575 static int
576 esp_3des_schedule(algo, sav)
577 const struct esp_algorithm *algo;
578 struct secasvar *sav;
579 {
580 int error;
581 des_key_schedule *p;
582 int i;
583 char *k;
584
585 p = (des_key_schedule *)sav->sched;
586 k = _KEYBUF(sav->key_enc);
587 for (i = 0; i < 3; i++) {
588 error = des_key_sched((des_cblock *)(k + 8 * i), p[i]);
589 if (error)
590 return EINVAL;
591 }
592 return 0;
593 }
594
595 static int
596 esp_3des_blockdecrypt(algo, sav, s, d)
597 const struct esp_algorithm *algo;
598 struct secasvar *sav;
599 u_int8_t *s;
600 u_int8_t *d;
601 {
602 des_key_schedule *p;
603
604 /* assumption: d has a good alignment */
605 p = (des_key_schedule *)sav->sched;
606 bcopy(s, d, sizeof(DES_LONG) * 2);
607 des_ecb3_encrypt((des_cblock *)d, (des_cblock *)d,
608 p[0], p[1], p[2], DES_DECRYPT);
609 return 0;
610 }
611
612 static int
613 esp_3des_blockencrypt(algo, sav, s, d)
614 const struct esp_algorithm *algo;
615 struct secasvar *sav;
616 u_int8_t *s;
617 u_int8_t *d;
618 {
619 des_key_schedule *p;
620
621 /* assumption: d has a good alignment */
622 p = (des_key_schedule *)sav->sched;
623 bcopy(s, d, sizeof(DES_LONG) * 2);
624 des_ecb3_encrypt((des_cblock *)d, (des_cblock *)d,
625 p[0], p[1], p[2], DES_ENCRYPT);
626 return 0;
627 }
628
629 static int
630 esp_common_ivlen(algo, sav)
631 const struct esp_algorithm *algo;
632 struct secasvar *sav;
633 {
634
635 if (!algo)
636 panic("esp_common_ivlen: unknown algorithm");
637 return algo->ivlenval;
638 }
639
640 static int
641 esp_cbc_decrypt(m, off, sav, algo, ivlen)
642 struct mbuf *m;
643 size_t off;
644 struct secasvar *sav;
645 const struct esp_algorithm *algo;
646 int ivlen;
647 {
648 struct mbuf *s;
649 struct mbuf *d, *d0, *dp;
650 int soff, doff; /* offset from the head of chain, to head of this mbuf */
651 int sn, dn; /* offset from the head of the mbuf, to meat */
652 size_t ivoff, bodyoff;
653 u_int8_t iv[MAXIVLEN], *ivp;
654 u_int8_t sbuf[MAXIVLEN], *sp;
655 u_int8_t *p, *q;
656 struct mbuf *scut;
657 int scutoff;
658 int i;
659 int blocklen;
660 int derived;
661
662 if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
663 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
664 "unsupported ivlen %d\n", algo->name, ivlen));
665 m_freem(m);
666 return EINVAL;
667 }
668
669 /* assumes blocklen == padbound */
670 blocklen = algo->padbound;
671
672 #if DIAGNOSTIC
673 if (blocklen > sizeof(iv)) {
674 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
675 "unsupported blocklen %d\n", algo->name, blocklen));
676 m_freem(m);
677 return EINVAL;
678 }
679 #endif
680
681 if (sav->flags & SADB_X_EXT_OLD) {
682 /* RFC 1827 */
683 ivoff = off + sizeof(struct esp);
684 bodyoff = off + sizeof(struct esp) + ivlen;
685 derived = 0;
686 } else {
687 /* RFC 2406 */
688 if (sav->flags & SADB_X_EXT_DERIV) {
689 /*
690 * draft-ietf-ipsec-ciph-des-derived-00.txt
691 * uses sequence number field as IV field.
692 */
693 ivoff = off + sizeof(struct esp);
694 bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
695 ivlen = sizeof(u_int32_t);
696 derived = 1;
697 } else {
698 ivoff = off + sizeof(struct newesp);
699 bodyoff = off + sizeof(struct newesp) + ivlen;
700 derived = 0;
701 }
702 }
703
704 /* grab iv */
705 m_copydata(m, ivoff, ivlen, iv);
706
707 /* extend iv */
708 if (ivlen == blocklen)
709 ;
710 else if (ivlen == 4 && blocklen == 8) {
711 bcopy(&iv[0], &iv[4], 4);
712 iv[4] ^= 0xff;
713 iv[5] ^= 0xff;
714 iv[6] ^= 0xff;
715 iv[7] ^= 0xff;
716 } else {
717 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
718 "unsupported ivlen/blocklen: %d %d\n",
719 algo->name, ivlen, blocklen));
720 m_freem(m);
721 return EINVAL;
722 }
723
724 if (m->m_pkthdr.len < bodyoff) {
725 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: bad len %d/%lu\n",
726 algo->name, m->m_pkthdr.len, (unsigned long)bodyoff));
727 m_freem(m);
728 return EINVAL;
729 }
730 if ((m->m_pkthdr.len - bodyoff) % blocklen) {
731 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
732 "payload length must be multiple of %d\n",
733 algo->name, blocklen));
734 m_freem(m);
735 return EINVAL;
736 }
737
738 s = m;
739 d = d0 = dp = NULL;
740 soff = doff = sn = dn = 0;
741 ivp = sp = NULL;
742
743 /* skip bodyoff */
744 while (soff < bodyoff) {
745 if (soff + s->m_len > bodyoff) {
746 sn = bodyoff - soff;
747 break;
748 }
749
750 soff += s->m_len;
751 s = s->m_next;
752 }
753 scut = s;
754 scutoff = sn;
755
756 /* skip over empty mbuf */
757 while (s && s->m_len == 0)
758 s = s->m_next;
759
760 while (soff < m->m_pkthdr.len) {
761 /* source */
762 if (sn + blocklen <= s->m_len) {
763 /* body is continuous */
764 sp = mtod(s, u_int8_t *) + sn;
765 } else {
766 /* body is non-continuous */
767 m_copydata(s, sn, blocklen, sbuf);
768 sp = sbuf;
769 }
770
771 /* destination */
772 if (!d || dn + blocklen > d->m_len) {
773 if (d)
774 dp = d;
775 MGET(d, M_DONTWAIT, MT_DATA);
776 i = m->m_pkthdr.len - (soff + sn);
777 if (d && i > MLEN) {
778 MCLGET(d, M_DONTWAIT);
779 if ((d->m_flags & M_EXT) == 0) {
780 m_free(d);
781 d = NULL;
782 }
783 }
784 if (!d) {
785 m_freem(m);
786 if (d0)
787 m_freem(d0);
788 return ENOBUFS;
789 }
790 if (!d0)
791 d0 = d;
792 if (dp)
793 dp->m_next = d;
794 d->m_len = 0;
795 d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
796 if (d->m_len > i)
797 d->m_len = i;
798 dn = 0;
799 }
800
801 /* decrypt */
802 (*algo->blockdecrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
803
804 /* xor */
805 p = ivp ? ivp : iv;
806 q = mtod(d, u_int8_t *) + dn;
807 for (i = 0; i < blocklen; i++)
808 q[i] ^= p[i];
809
810 /* next iv */
811 if (sp == sbuf) {
812 bcopy(sbuf, iv, blocklen);
813 ivp = NULL;
814 } else
815 ivp = sp;
816
817 sn += blocklen;
818 dn += blocklen;
819
820 /* find the next source block */
821 while (s && sn >= s->m_len) {
822 sn -= s->m_len;
823 soff += s->m_len;
824 s = s->m_next;
825 }
826 }
827
828 m_freem(scut->m_next);
829 scut->m_len = scutoff;
830 scut->m_next = d0;
831
832 /* just in case */
833 bzero(iv, sizeof(iv));
834 bzero(sbuf, sizeof(sbuf));
835
836 return 0;
837 }
838
839 static int
840 esp_cbc_encrypt(m, off, plen, sav, algo, ivlen)
841 struct mbuf *m;
842 size_t off;
843 size_t plen;
844 struct secasvar *sav;
845 const struct esp_algorithm *algo;
846 int ivlen;
847 {
848 struct mbuf *s;
849 struct mbuf *d, *d0, *dp;
850 int soff, doff; /* offset from the head of chain, to head of this mbuf */
851 int sn, dn; /* offset from the head of the mbuf, to meat */
852 size_t ivoff, bodyoff;
853 u_int8_t iv[MAXIVLEN], *ivp;
854 u_int8_t sbuf[MAXIVLEN], *sp;
855 u_int8_t *p, *q;
856 struct mbuf *scut;
857 int scutoff;
858 int i;
859 int blocklen;
860 int derived;
861
862 if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
863 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
864 "unsupported ivlen %d\n", algo->name, ivlen));
865 m_freem(m);
866 return EINVAL;
867 }
868
869 /* assumes blocklen == padbound */
870 blocklen = algo->padbound;
871
872 #if DIAGNOSTIC
873 if (blocklen > sizeof(iv)) {
874 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
875 "unsupported blocklen %d\n", algo->name, blocklen));
876 m_freem(m);
877 return EINVAL;
878 }
879 #endif
880
881 if (sav->flags & SADB_X_EXT_OLD) {
882 /* RFC 1827 */
883 ivoff = off + sizeof(struct esp);
884 bodyoff = off + sizeof(struct esp) + ivlen;
885 derived = 0;
886 } else {
887 /* RFC 2406 */
888 if (sav->flags & SADB_X_EXT_DERIV) {
889 /*
890 * draft-ietf-ipsec-ciph-des-derived-00.txt
891 * uses sequence number field as IV field.
892 */
893 ivoff = off + sizeof(struct esp);
894 bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
895 ivlen = sizeof(u_int32_t);
896 derived = 1;
897 } else {
898 ivoff = off + sizeof(struct newesp);
899 bodyoff = off + sizeof(struct newesp) + ivlen;
900 derived = 0;
901 }
902 }
903
904 /* put iv into the packet. if we are in derived mode, use seqno. */
905 if (derived)
906 m_copydata(m, ivoff, ivlen, iv);
907 else {
908 bcopy(sav->iv, iv, ivlen);
909 /* maybe it is better to overwrite dest, not source */
910 m_copyback(m, ivoff, ivlen, iv);
911 }
912
913 /* extend iv */
914 if (ivlen == blocklen)
915 ;
916 else if (ivlen == 4 && blocklen == 8) {
917 bcopy(&iv[0], &iv[4], 4);
918 iv[4] ^= 0xff;
919 iv[5] ^= 0xff;
920 iv[6] ^= 0xff;
921 iv[7] ^= 0xff;
922 } else {
923 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
924 "unsupported ivlen/blocklen: %d %d\n",
925 algo->name, ivlen, blocklen));
926 m_freem(m);
927 return EINVAL;
928 }
929
930 if (m->m_pkthdr.len < bodyoff) {
931 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: bad len %d/%lu\n",
932 algo->name, m->m_pkthdr.len, (unsigned long)bodyoff));
933 m_freem(m);
934 return EINVAL;
935 }
936 if ((m->m_pkthdr.len - bodyoff) % blocklen) {
937 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
938 "payload length must be multiple of %lu\n",
939 algo->name, (unsigned long)algo->padbound));
940 m_freem(m);
941 return EINVAL;
942 }
943
944 s = m;
945 d = d0 = dp = NULL;
946 soff = doff = sn = dn = 0;
947 ivp = sp = NULL;
948
949 /* skip bodyoff */
950 while (soff < bodyoff) {
951 if (soff + s->m_len > bodyoff) {
952 sn = bodyoff - soff;
953 break;
954 }
955
956 soff += s->m_len;
957 s = s->m_next;
958 }
959 scut = s;
960 scutoff = sn;
961
962 /* skip over empty mbuf */
963 while (s && s->m_len == 0)
964 s = s->m_next;
965
966 while (soff < m->m_pkthdr.len) {
967 /* source */
968 if (sn + blocklen <= s->m_len) {
969 /* body is continuous */
970 sp = mtod(s, u_int8_t *) + sn;
971 } else {
972 /* body is non-continuous */
973 m_copydata(s, sn, blocklen, sbuf);
974 sp = sbuf;
975 }
976
977 /* destination */
978 if (!d || dn + blocklen > d->m_len) {
979 if (d)
980 dp = d;
981 MGET(d, M_DONTWAIT, MT_DATA);
982 i = m->m_pkthdr.len - (soff + sn);
983 if (d && i > MLEN) {
984 MCLGET(d, M_DONTWAIT);
985 if ((d->m_flags & M_EXT) == 0) {
986 m_free(d);
987 d = NULL;
988 }
989 }
990 if (!d) {
991 m_freem(m);
992 if (d0)
993 m_freem(d0);
994 return ENOBUFS;
995 }
996 if (!d0)
997 d0 = d;
998 if (dp)
999 dp->m_next = d;
1000 d->m_len = 0;
1001 d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
1002 if (d->m_len > i)
1003 d->m_len = i;
1004 dn = 0;
1005 }
1006
1007 /* xor */
1008 p = ivp ? ivp : iv;
1009 q = sp;
1010 for (i = 0; i < blocklen; i++)
1011 q[i] ^= p[i];
1012
1013 /* encrypt */
1014 (*algo->blockencrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
1015
1016 /* next iv */
1017 ivp = mtod(d, u_int8_t *) + dn;
1018
1019 sn += blocklen;
1020 dn += blocklen;
1021
1022 /* find the next source block */
1023 while (s && sn >= s->m_len) {
1024 sn -= s->m_len;
1025 soff += s->m_len;
1026 s = s->m_next;
1027 }
1028 }
1029
1030 m_freem(scut->m_next);
1031 scut->m_len = scutoff;
1032 scut->m_next = d0;
1033
1034 /* just in case */
1035 bzero(iv, sizeof(iv));
1036 bzero(sbuf, sizeof(sbuf));
1037
1038 key_sa_stir_iv(sav);
1039
1040 return 0;
1041 }
1042
1043 /*------------------------------------------------------------*/
1044
1045 /* does not free m0 on error */
1046 int
1047 esp_auth(m0, skip, length, sav, sum)
1048 struct mbuf *m0;
1049 size_t skip; /* offset to ESP header */
1050 size_t length; /* payload length */
1051 struct secasvar *sav;
1052 u_char *sum;
1053 {
1054 struct mbuf *m;
1055 size_t off;
1056 struct ah_algorithm_state s;
1057 u_char sumbuf[AH_MAXSUMSIZE];
1058 const struct ah_algorithm *algo;
1059 size_t siz;
1060 int error;
1061
1062 /* sanity checks */
1063 if (m0->m_pkthdr.len < skip) {
1064 ipseclog((LOG_DEBUG, "esp_auth: mbuf length < skip\n"));
1065 return EINVAL;
1066 }
1067 if (m0->m_pkthdr.len < skip + length) {
1068 ipseclog((LOG_DEBUG,
1069 "esp_auth: mbuf length < skip + length\n"));
1070 return EINVAL;
1071 }
1072
1073 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_START, skip,length,0,0,0);
1074 /*
1075 * length of esp part (excluding authentication data) must be 4n,
1076 * since nexthdr must be at offset 4n+3.
1077 */
1078 if (length % 4) {
1079 ipseclog((LOG_ERR, "esp_auth: length is not multiple of 4\n"));
1080 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 1,0,0,0,0);
1081 return EINVAL;
1082 }
1083 if (!sav) {
1084 ipseclog((LOG_DEBUG, "esp_auth: NULL SA passed\n"));
1085 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 2,0,0,0,0);
1086 return EINVAL;
1087 }
1088 algo = ah_algorithm_lookup(sav->alg_auth);
1089 if (!algo) {
1090 ipseclog((LOG_ERR,
1091 "esp_auth: bad ESP auth algorithm passed: %d\n",
1092 sav->alg_auth));
1093 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 3,0,0,0,0);
1094 return EINVAL;
1095 }
1096
1097 m = m0;
1098 off = 0;
1099
1100 siz = (((*algo->sumsiz)(sav) + 3) & ~(4 - 1));
1101 if (sizeof(sumbuf) < siz) {
1102 ipseclog((LOG_DEBUG,
1103 "esp_auth: AH_MAXSUMSIZE is too small: siz=%lu\n",
1104 (u_long)siz));
1105 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 4,0,0,0,0);
1106 return EINVAL;
1107 }
1108
1109 /* skip the header */
1110 while (skip) {
1111 if (!m)
1112 panic("mbuf chain?");
1113 if (m->m_len <= skip) {
1114 skip -= m->m_len;
1115 m = m->m_next;
1116 off = 0;
1117 } else {
1118 off = skip;
1119 skip = 0;
1120 }
1121 }
1122
1123 error = (*algo->init)(&s, sav);
1124 if (error) {
1125 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 5,0,0,0,0);
1126 return error;
1127 }
1128 lck_mtx_unlock(sadb_mutex);
1129 while (0 < length) {
1130 if (!m)
1131 panic("mbuf chain?");
1132
1133 if (m->m_len - off < length) {
1134 (*algo->update)(&s, mtod(m, u_char *) + off,
1135 m->m_len - off);
1136 length -= m->m_len - off;
1137 m = m->m_next;
1138 off = 0;
1139 } else {
1140 (*algo->update)(&s, mtod(m, u_char *) + off, length);
1141 break;
1142 }
1143 }
1144 (*algo->result)(&s, sumbuf);
1145 bcopy(sumbuf, sum, siz); /*XXX*/
1146 lck_mtx_lock(sadb_mutex);
1147 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 6,0,0,0,0);
1148 return 0;
1149 }