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