No empty .Rs/.Re
[netbsd-mini2440.git] / sys / netinet6 / esp_core.c
blobd283b7dc829ed7211857b67c0e744aae99cf1486
1 /* $NetBSD: esp_core.c,v 1.44 2009/03/18 17:06:52 cegger Exp $ */
2 /* $KAME: esp_core.c,v 1.53 2001/11/27 09:47:30 sakane Exp $ */
4 /*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
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.
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.
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: esp_core.c,v 1.44 2009/03/18 17:06:52 cegger Exp $");
36 #include "opt_inet.h"
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/malloc.h>
41 #include <sys/mbuf.h>
42 #include <sys/domain.h>
43 #include <sys/protosw.h>
44 #include <sys/socket.h>
45 #include <sys/errno.h>
46 #include <sys/time.h>
47 #include <sys/kernel.h>
48 #include <sys/syslog.h>
50 #include <net/if.h>
51 #include <net/route.h>
53 #include <netinet/in.h>
55 #include <netinet6/ipsec.h>
56 #include <netinet6/ah.h>
57 #include <netinet6/esp.h>
58 #include <netinet6/esp_rijndael.h>
59 #include <netinet6/esp_aesctr.h>
60 #include <net/pfkeyv2.h>
61 #include <netkey/key.h>
63 #include <crypto/des/des.h>
64 #include <crypto/blowfish/blowfish.h>
65 #include <crypto/cast128/cast128.h>
67 #include <net/net_osdep.h>
69 static int esp_null_mature(struct secasvar *);
70 static int esp_null_decrypt(struct mbuf *, size_t,
71 struct secasvar *, const struct esp_algorithm *, int);
72 static int esp_null_encrypt(struct mbuf *, size_t, size_t,
73 struct secasvar *, const struct esp_algorithm *, int);
74 static int esp_descbc_mature(struct secasvar *);
75 static int esp_descbc_ivlen(const struct esp_algorithm *,
76 struct secasvar *);
77 static int esp_des_schedule(const struct esp_algorithm *,
78 struct secasvar *);
79 static size_t esp_des_schedlen(const struct esp_algorithm *);
80 static int esp_des_blockdecrypt(const struct esp_algorithm *,
81 struct secasvar *, u_int8_t *, u_int8_t *);
82 static int esp_des_blockencrypt(const struct esp_algorithm *,
83 struct secasvar *, u_int8_t *, u_int8_t *);
84 static int esp_cbc_mature(struct secasvar *);
85 static int esp_blowfish_schedule(const struct esp_algorithm *,
86 struct secasvar *);
87 static size_t esp_blowfish_schedlen(const struct esp_algorithm *);
88 static int esp_blowfish_blockdecrypt(const struct esp_algorithm *,
89 struct secasvar *, u_int8_t *, u_int8_t *);
90 static int esp_blowfish_blockencrypt(const struct esp_algorithm *,
91 struct secasvar *, u_int8_t *, u_int8_t *);
92 static int esp_cast128_schedule(const struct esp_algorithm *,
93 struct secasvar *);
94 static size_t esp_cast128_schedlen(const struct esp_algorithm *);
95 static int esp_cast128_blockdecrypt(const struct esp_algorithm *,
96 struct secasvar *, u_int8_t *, u_int8_t *);
97 static int esp_cast128_blockencrypt(const struct esp_algorithm *,
98 struct secasvar *, u_int8_t *, u_int8_t *);
99 static int esp_3des_schedule(const struct esp_algorithm *,
100 struct secasvar *);
101 static size_t esp_3des_schedlen(const struct esp_algorithm *);
102 static int esp_3des_blockdecrypt(const struct esp_algorithm *,
103 struct secasvar *, u_int8_t *, u_int8_t *);
104 static int esp_3des_blockencrypt(const struct esp_algorithm *,
105 struct secasvar *, u_int8_t *, u_int8_t *);
106 static int esp_common_ivlen(const struct esp_algorithm *,
107 struct secasvar *);
108 static int esp_cbc_decrypt(struct mbuf *, size_t,
109 struct secasvar *, const struct esp_algorithm *, int);
110 static int esp_cbc_encrypt(struct mbuf *, size_t, size_t,
111 struct secasvar *, const struct esp_algorithm *, int);
113 #define MAXIVLEN 16
115 static const struct esp_algorithm esp_algorithms[] = {
116 { 8, -1, esp_descbc_mature, 64, 64, esp_des_schedlen,
117 "des-cbc",
118 esp_descbc_ivlen, esp_cbc_decrypt,
119 esp_cbc_encrypt, esp_des_schedule,
120 esp_des_blockdecrypt, esp_des_blockencrypt, },
121 { 8, 8, esp_cbc_mature, 192, 192, esp_3des_schedlen,
122 "3des-cbc",
123 esp_common_ivlen, esp_cbc_decrypt,
124 esp_cbc_encrypt, esp_3des_schedule,
125 esp_3des_blockdecrypt, esp_3des_blockencrypt, },
126 { 1, 0, esp_null_mature, 0, 2048, NULL,
127 "null",
128 esp_common_ivlen, esp_null_decrypt,
129 esp_null_encrypt, NULL,
130 NULL, NULL },
131 { 8, 8, esp_cbc_mature, 40, 448, esp_blowfish_schedlen, "blowfish-cbc",
132 esp_common_ivlen, esp_cbc_decrypt,
133 esp_cbc_encrypt, esp_blowfish_schedule,
134 esp_blowfish_blockdecrypt, esp_blowfish_blockencrypt, },
135 { 8, 8, esp_cbc_mature, 40, 128, esp_cast128_schedlen,
136 "cast128-cbc",
137 esp_common_ivlen, esp_cbc_decrypt,
138 esp_cbc_encrypt, esp_cast128_schedule,
139 esp_cast128_blockdecrypt, esp_cast128_blockencrypt, },
140 { 16, 16, esp_cbc_mature, 128, 256, esp_rijndael_schedlen,
141 "rijndael-cbc",
142 esp_common_ivlen, esp_cbc_decrypt,
143 esp_cbc_encrypt, esp_rijndael_schedule,
144 esp_rijndael_blockdecrypt, esp_rijndael_blockencrypt },
145 { 16, 8, esp_aesctr_mature, 160, 288, esp_aesctr_schedlen,
146 "aes-ctr",
147 esp_common_ivlen, esp_aesctr_decrypt,
148 esp_aesctr_encrypt, esp_aesctr_schedule,
149 NULL, NULL },
152 const struct esp_algorithm *
153 esp_algorithm_lookup(int idx)
156 switch (idx) {
157 case SADB_EALG_DESCBC:
158 return &esp_algorithms[0];
159 case SADB_EALG_3DESCBC:
160 return &esp_algorithms[1];
161 case SADB_EALG_NULL:
162 return &esp_algorithms[2];
163 case SADB_X_EALG_BLOWFISHCBC:
164 return &esp_algorithms[3];
165 case SADB_X_EALG_CAST128CBC:
166 return &esp_algorithms[4];
167 case SADB_X_EALG_RIJNDAELCBC:
168 return &esp_algorithms[5];
169 case SADB_X_EALG_AESCTR:
170 return &esp_algorithms[6];
171 default:
172 return NULL;
177 esp_max_padbound(void)
179 int idx;
180 static int padbound = 0;
182 if (padbound)
183 return padbound;
185 for (idx = 0; idx < sizeof(esp_algorithms)/sizeof(esp_algorithms[0]);
186 idx++) {
187 if (esp_algorithms[idx].padbound > padbound)
188 padbound = esp_algorithms[idx].padbound;
190 return padbound;
194 esp_max_ivlen(void)
196 int idx;
197 static int ivlen = 0;
199 if (ivlen)
200 return ivlen;
202 for (idx = 0; idx < sizeof(esp_algorithms)/sizeof(esp_algorithms[0]);
203 idx++) {
204 if (esp_algorithms[idx].ivlenval > ivlen)
205 ivlen = esp_algorithms[idx].ivlenval;
207 return ivlen;
211 esp_schedule(const struct esp_algorithm *algo, struct secasvar *sav)
213 int error;
215 /* check for key length */
216 if (_KEYBITS(sav->key_enc) < algo->keymin ||
217 _KEYBITS(sav->key_enc) > algo->keymax) {
218 ipseclog((LOG_ERR,
219 "esp_schedule %s: unsupported key length %d: "
220 "needs %d to %d bits\n", algo->name, _KEYBITS(sav->key_enc),
221 algo->keymin, algo->keymax));
222 return EINVAL;
225 /* already allocated */
226 if (sav->sched && sav->schedlen != 0)
227 return 0;
228 /* no schedule necessary */
229 if (!algo->schedule || !algo->schedlen)
230 return 0;
232 sav->schedlen = (*algo->schedlen)(algo);
233 sav->sched = malloc(sav->schedlen, M_SECA, M_DONTWAIT);
234 if (!sav->sched) {
235 sav->schedlen = 0;
236 return ENOBUFS;
239 error = (*algo->schedule)(algo, sav);
240 if (error) {
241 ipseclog((LOG_ERR, "esp_schedule %s: error %d\n",
242 algo->name, error));
243 memset(sav->sched, 0, sav->schedlen);
244 free(sav->sched, M_SECA);
245 sav->sched = NULL;
246 sav->schedlen = 0;
248 return error;
251 static int
252 esp_null_mature(struct secasvar *sav)
255 /* anything is okay */
256 return 0;
259 static int
260 esp_null_decrypt(
261 struct mbuf *m,
262 size_t off, /* offset to ESP header */
263 struct secasvar *sav,
264 const struct esp_algorithm *algo,
265 int ivlen
269 return 0; /* do nothing */
272 static int
273 esp_null_encrypt(
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
283 return 0; /* do nothing */
286 static int
287 esp_descbc_mature(struct secasvar *sav)
289 const struct esp_algorithm *algo;
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;
297 if (!sav->key_enc) {
298 ipseclog((LOG_ERR, "esp_descbc_mature: no key is given.\n"));
299 return 1;
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;
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;
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;
324 return 0;
327 static int
328 esp_descbc_ivlen(const struct esp_algorithm *algo,
329 struct secasvar *sav)
332 if (!sav)
333 return 8;
334 if ((sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B))
335 return 4;
336 if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_DERIV))
337 return 4;
338 return 8;
341 static size_t
342 esp_des_schedlen(const struct esp_algorithm *algo)
345 return sizeof(des_key_schedule);
348 static int
349 esp_des_schedule(const struct esp_algorithm *algo,
350 struct secasvar *sav)
353 if (des_key_sched((des_cblock *)_KEYBUF(sav->key_enc),
354 *(des_key_schedule *)sav->sched))
355 return EINVAL;
356 else
357 return 0;
360 static int
361 esp_des_blockdecrypt( const struct esp_algorithm *algo,
362 struct secasvar *sav, u_int8_t *s, u_int8_t *d)
365 /* assumption: d has a good alignment */
366 memcpy(d, s, sizeof(DES_LONG) * 2);
367 des_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
368 *(des_key_schedule *)sav->sched, DES_DECRYPT);
369 return 0;
372 static int
373 esp_des_blockencrypt(const struct esp_algorithm *algo,
374 struct secasvar *sav, u_int8_t *s, u_int8_t *d)
377 /* assumption: d has a good alignment */
378 memcpy(d, s, sizeof(DES_LONG) * 2);
379 des_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
380 *(des_key_schedule *)sav->sched, DES_ENCRYPT);
381 return 0;
384 static int
385 esp_cbc_mature(struct secasvar *sav)
387 int keylen;
388 const struct esp_algorithm *algo;
390 if (sav->flags & SADB_X_EXT_OLD) {
391 ipseclog((LOG_ERR,
392 "esp_cbc_mature: algorithm incompatible with esp-old\n"));
393 return 1;
395 if (sav->flags & SADB_X_EXT_DERIV) {
396 ipseclog((LOG_ERR,
397 "esp_cbc_mature: algorithm incompatible with derived\n"));
398 return 1;
401 if (!sav->key_enc) {
402 ipseclog((LOG_ERR, "esp_cbc_mature: no key is given.\n"));
403 return 1;
406 algo = esp_algorithm_lookup(sav->alg_enc);
407 if (!algo) {
408 ipseclog((LOG_ERR,
409 "esp_cbc_mature %s: unsupported algorithm.\n", algo->name));
410 return 1;
413 keylen = sav->key_enc->sadb_key_bits;
414 if (keylen < algo->keymin || algo->keymax < keylen) {
415 ipseclog((LOG_ERR,
416 "esp_cbc_mature %s: invalid key length %d.\n",
417 algo->name, sav->key_enc->sadb_key_bits));
418 return 1;
420 switch (sav->alg_enc) {
421 case SADB_EALG_3DESCBC:
422 /* weak key check */
423 if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc)) ||
424 des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 8)) ||
425 des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 16))) {
426 ipseclog((LOG_ERR,
427 "esp_cbc_mature %s: weak key was passed.\n",
428 algo->name));
429 return 1;
431 break;
432 case SADB_X_EALG_BLOWFISHCBC:
433 case SADB_X_EALG_CAST128CBC:
434 break;
435 case SADB_X_EALG_RIJNDAELCBC:
436 /* allows specific key sizes only */
437 if (!(keylen == 128 || keylen == 192 || keylen == 256)) {
438 ipseclog((LOG_ERR,
439 "esp_cbc_mature %s: invalid key length %d.\n",
440 algo->name, keylen));
441 return 1;
443 break;
446 return 0;
449 static size_t
450 esp_blowfish_schedlen(const struct esp_algorithm *algo)
453 return sizeof(BF_KEY);
456 static int
457 esp_blowfish_schedule(const struct esp_algorithm *algo,
458 struct secasvar *sav)
461 BF_set_key((BF_KEY *)sav->sched, _KEYLEN(sav->key_enc),
462 _KEYBUF(sav->key_enc));
463 return 0;
466 static int
467 esp_blowfish_blockdecrypt(const struct esp_algorithm *algo,
468 struct secasvar *sav, u_int8_t *s, u_int8_t *d)
471 BF_ecb_encrypt(s, d, (BF_KEY *)sav->sched, 0);
472 return 0;
475 static int
476 esp_blowfish_blockencrypt(const struct esp_algorithm *algo,
477 struct secasvar *sav, u_int8_t *s, u_int8_t *d)
480 BF_ecb_encrypt(s, d, (BF_KEY *)sav->sched, 1);
481 return 0;
484 static size_t
485 esp_cast128_schedlen(const struct esp_algorithm *algo)
488 return sizeof(cast128_key);
491 static int
492 esp_cast128_schedule(const struct esp_algorithm *algo,
493 struct secasvar *sav)
496 cast128_setkey((cast128_key *)sav->sched, _KEYBUF(sav->key_enc),
497 _KEYLEN(sav->key_enc));
498 return 0;
501 static int
502 esp_cast128_blockdecrypt(const struct esp_algorithm *algo,
503 struct secasvar *sav, u_int8_t *s, u_int8_t *d)
506 cast128_decrypt((cast128_key *)sav->sched, s, d);
507 return 0;
510 static int
511 esp_cast128_blockencrypt(const struct esp_algorithm *algo,
512 struct secasvar *sav, u_int8_t *s, u_int8_t *d)
515 cast128_encrypt((cast128_key *)sav->sched, s, d);
516 return 0;
519 static size_t
520 esp_3des_schedlen(const struct esp_algorithm *algo)
523 return sizeof(des_key_schedule) * 3;
526 static int
527 esp_3des_schedule(const struct esp_algorithm *algo,
528 struct secasvar *sav)
530 int error;
531 des_key_schedule *p;
532 int i;
533 u_int8_t *k;
535 p = (des_key_schedule *)sav->sched;
536 k = _KEYBUF(sav->key_enc);
537 for (i = 0; i < 3; i++) {
538 error = des_key_sched((des_cblock *)(k + 8 * i), p[i]);
539 if (error)
540 return EINVAL;
542 return 0;
545 static int
546 esp_3des_blockdecrypt(const struct esp_algorithm *algo,
547 struct secasvar *sav, u_int8_t *s, u_int8_t *d)
549 des_key_schedule *p;
551 /* assumption: d has a good alignment */
552 p = (des_key_schedule *)sav->sched;
553 memcpy(d, s, sizeof(DES_LONG) * 2);
554 des_ecb3_encrypt((des_cblock *)d, (des_cblock *)d,
555 p[0], p[1], p[2], DES_DECRYPT);
556 return 0;
559 static int
560 esp_3des_blockencrypt(const struct esp_algorithm *algo,
561 struct secasvar *sav, u_int8_t *s, u_int8_t *d)
563 des_key_schedule *p;
565 /* assumption: d has a good alignment */
566 p = (des_key_schedule *)sav->sched;
567 memcpy(d, s, sizeof(DES_LONG) * 2);
568 des_ecb3_encrypt((des_cblock *)d, (des_cblock *)d,
569 p[0], p[1], p[2], DES_ENCRYPT);
570 return 0;
573 static int
574 esp_common_ivlen(const struct esp_algorithm *algo,
575 struct secasvar *sav)
578 if (!algo)
579 panic("esp_common_ivlen: unknown algorithm");
580 return algo->ivlenval;
583 static int
584 esp_cbc_decrypt(struct mbuf *m, size_t off, struct secasvar *sav,
585 const struct esp_algorithm *algo, int ivlen)
587 struct mbuf *s;
588 struct mbuf *d, *d0, *dp;
589 int soff, doff; /* offset from the head of chain, to head of this mbuf */
590 int sn, dn; /* offset from the head of the mbuf, to meat */
591 size_t ivoff, bodyoff;
592 u_int8_t iv[MAXIVLEN], *ivp;
593 u_int8_t sbuf[MAXIVLEN], *sp;
594 u_int8_t *p, *q;
595 struct mbuf *scut;
596 int scutoff;
597 int i;
598 int blocklen;
600 if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
601 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
602 "unsupported ivlen %d\n", algo->name, ivlen));
603 m_freem(m);
604 return EINVAL;
607 /* assumes blocklen == padbound */
608 blocklen = algo->padbound;
610 #ifdef DIAGNOSTIC
611 if (blocklen > sizeof(iv)) {
612 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
613 "unsupported blocklen %d\n", algo->name, blocklen));
614 m_freem(m);
615 return EINVAL;
617 #endif
619 if (sav->flags & SADB_X_EXT_OLD) {
620 /* RFC 1827 */
621 ivoff = off + sizeof(struct esp);
622 bodyoff = off + sizeof(struct esp) + ivlen;
623 } else {
624 /* RFC 2406 */
625 if (sav->flags & SADB_X_EXT_DERIV) {
627 * draft-ietf-ipsec-ciph-des-derived-00.txt
628 * uses sequence number field as IV field.
630 ivoff = off + sizeof(struct esp);
631 bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
632 ivlen = sizeof(u_int32_t);
633 } else {
634 ivoff = off + sizeof(struct newesp);
635 bodyoff = off + sizeof(struct newesp) + ivlen;
639 /* grab iv */
640 m_copydata(m, ivoff, ivlen, (void *)iv);
642 /* extend iv */
643 if (ivlen == blocklen)
645 else if (ivlen == 4 && blocklen == 8) {
646 memcpy(&iv[4], &iv[0], 4);
647 iv[4] ^= 0xff;
648 iv[5] ^= 0xff;
649 iv[6] ^= 0xff;
650 iv[7] ^= 0xff;
651 } else {
652 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
653 "unsupported ivlen/blocklen: %d %d\n",
654 algo->name, ivlen, blocklen));
655 m_freem(m);
656 return EINVAL;
659 if (m->m_pkthdr.len < bodyoff) {
660 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: bad len %d/%lu\n",
661 algo->name, m->m_pkthdr.len, (unsigned long)bodyoff));
662 m_freem(m);
663 return EINVAL;
665 if ((m->m_pkthdr.len - bodyoff) % blocklen) {
666 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
667 "payload length must be multiple of %d\n",
668 algo->name, blocklen));
669 m_freem(m);
670 return EINVAL;
673 s = m;
674 d = d0 = dp = NULL;
675 soff = doff = sn = dn = 0;
676 ivp = sp = NULL;
678 /* skip bodyoff */
679 while (soff < bodyoff) {
680 if (soff + s->m_len > bodyoff) {
681 sn = bodyoff - soff;
682 break;
685 soff += s->m_len;
686 s = s->m_next;
688 scut = s;
689 scutoff = sn;
691 /* skip over empty mbuf */
692 while (s && s->m_len == 0)
693 s = s->m_next;
695 while (soff < m->m_pkthdr.len) {
696 /* source */
697 if (sn + blocklen <= s->m_len) {
698 /* body is continuous */
699 sp = mtod(s, u_int8_t *) + sn;
700 } else {
701 /* body is non-continuous */
702 m_copydata(s, sn, blocklen, (void *)sbuf);
703 sp = sbuf;
706 /* destination */
707 if (!d || dn + blocklen > d->m_len) {
708 if (d)
709 dp = d;
710 MGET(d, M_DONTWAIT, MT_DATA);
711 i = m->m_pkthdr.len - (soff + sn);
712 if (d && i > MLEN) {
713 MCLGET(d, M_DONTWAIT);
714 if ((d->m_flags & M_EXT) == 0) {
715 m_free(d);
716 d = NULL;
719 if (!d) {
720 m_freem(m);
721 if (d0)
722 m_freem(d0);
723 return ENOBUFS;
725 if (!d0)
726 d0 = d;
727 if (dp)
728 dp->m_next = d;
729 d->m_len = 0;
730 d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
731 if (d->m_len > i)
732 d->m_len = i;
733 dn = 0;
736 /* decrypt */
737 (*algo->blockdecrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
739 /* xor */
740 p = ivp ? ivp : iv;
741 q = mtod(d, u_int8_t *) + dn;
742 for (i = 0; i < blocklen; i++)
743 q[i] ^= p[i];
745 /* next iv */
746 if (sp == sbuf) {
747 memcpy(iv, sbuf, blocklen);
748 ivp = NULL;
749 } else
750 ivp = sp;
752 sn += blocklen;
753 dn += blocklen;
755 /* find the next source block */
756 while (s && sn >= s->m_len) {
757 sn -= s->m_len;
758 soff += s->m_len;
759 s = s->m_next;
762 /* skip over empty mbuf */
763 while (s && s->m_len == 0)
764 s = s->m_next;
767 m_freem(scut->m_next);
768 scut->m_len = scutoff;
769 scut->m_next = d0;
771 /* just in case */
772 memset(iv, 0, sizeof(iv));
773 memset(sbuf, 0, sizeof(sbuf));
775 return 0;
778 static int
779 esp_cbc_encrypt(
780 struct mbuf *m,
781 size_t off,
782 size_t plen,
783 struct secasvar *sav,
784 const struct esp_algorithm *algo,
785 int ivlen
788 struct mbuf *s;
789 struct mbuf *d, *d0, *dp;
790 int soff, doff; /* offset from the head of chain, to head of this mbuf */
791 int sn, dn; /* offset from the head of the mbuf, to meat */
792 size_t ivoff, bodyoff;
793 u_int8_t iv[MAXIVLEN], *ivp;
794 u_int8_t sbuf[MAXIVLEN], *sp;
795 u_int8_t *p, *q;
796 struct mbuf *scut;
797 int scutoff;
798 int i;
799 int blocklen;
800 int derived;
802 if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
803 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
804 "unsupported ivlen %d\n", algo->name, ivlen));
805 m_freem(m);
806 return EINVAL;
809 /* assumes blocklen == padbound */
810 blocklen = algo->padbound;
812 #ifdef DIAGNOSTIC
813 if (blocklen > sizeof(iv)) {
814 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
815 "unsupported blocklen %d\n", algo->name, blocklen));
816 m_freem(m);
817 return EINVAL;
819 #endif
821 if (sav->flags & SADB_X_EXT_OLD) {
822 /* RFC 1827 */
823 ivoff = off + sizeof(struct esp);
824 bodyoff = off + sizeof(struct esp) + ivlen;
825 derived = 0;
826 } else {
827 /* RFC 2406 */
828 if (sav->flags & SADB_X_EXT_DERIV) {
830 * draft-ietf-ipsec-ciph-des-derived-00.txt
831 * uses sequence number field as IV field.
833 ivoff = off + sizeof(struct esp);
834 bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
835 ivlen = sizeof(u_int32_t);
836 derived = 1;
837 } else {
838 ivoff = off + sizeof(struct newesp);
839 bodyoff = off + sizeof(struct newesp) + ivlen;
840 derived = 0;
844 /* put iv into the packet. if we are in derived mode, use seqno. */
845 if (derived)
846 m_copydata(m, ivoff, ivlen, (void *)iv);
847 else {
848 memcpy(iv, sav->iv, ivlen);
849 /* maybe it is better to overwrite dest, not source */
850 m_copyback(m, ivoff, ivlen, (void *)iv);
853 /* extend iv */
854 if (ivlen == blocklen)
856 else if (ivlen == 4 && blocklen == 8) {
857 memcpy(&iv[4], &iv[0], 4);
858 iv[4] ^= 0xff;
859 iv[5] ^= 0xff;
860 iv[6] ^= 0xff;
861 iv[7] ^= 0xff;
862 } else {
863 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
864 "unsupported ivlen/blocklen: %d %d\n",
865 algo->name, ivlen, blocklen));
866 m_freem(m);
867 return EINVAL;
870 if (m->m_pkthdr.len < bodyoff) {
871 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: bad len %d/%lu\n",
872 algo->name, m->m_pkthdr.len, (unsigned long)bodyoff));
873 m_freem(m);
874 return EINVAL;
876 if ((m->m_pkthdr.len - bodyoff) % blocklen) {
877 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
878 "payload length must be multiple of %lu\n",
879 algo->name, (unsigned long)algo->padbound));
880 m_freem(m);
881 return EINVAL;
884 s = m;
885 d = d0 = dp = NULL;
886 soff = doff = sn = dn = 0;
887 ivp = sp = NULL;
889 /* skip bodyoff */
890 while (soff < bodyoff) {
891 if (soff + s->m_len > bodyoff) {
892 sn = bodyoff - soff;
893 break;
896 soff += s->m_len;
897 s = s->m_next;
899 scut = s;
900 scutoff = sn;
902 /* skip over empty mbuf */
903 while (s && s->m_len == 0)
904 s = s->m_next;
906 while (soff < m->m_pkthdr.len) {
907 /* source */
908 if (sn + blocklen <= s->m_len) {
909 /* body is continuous */
910 sp = mtod(s, u_int8_t *) + sn;
911 } else {
912 /* body is non-continuous */
913 m_copydata(s, sn, blocklen, (void *)sbuf);
914 sp = sbuf;
917 /* destination */
918 if (!d || dn + blocklen > d->m_len) {
919 if (d)
920 dp = d;
921 MGET(d, M_DONTWAIT, MT_DATA);
922 i = m->m_pkthdr.len - (soff + sn);
923 if (d && i > MLEN) {
924 MCLGET(d, M_DONTWAIT);
925 if ((d->m_flags & M_EXT) == 0) {
926 m_free(d);
927 d = NULL;
930 if (!d) {
931 m_freem(m);
932 if (d0)
933 m_freem(d0);
934 return ENOBUFS;
936 if (!d0)
937 d0 = d;
938 if (dp)
939 dp->m_next = d;
940 d->m_len = 0;
941 d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
942 if (d->m_len > i)
943 d->m_len = i;
944 dn = 0;
947 /* xor */
948 p = ivp ? ivp : iv;
949 q = sp;
950 for (i = 0; i < blocklen; i++)
951 q[i] ^= p[i];
953 /* encrypt */
954 (*algo->blockencrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
956 /* next iv */
957 ivp = mtod(d, u_int8_t *) + dn;
959 sn += blocklen;
960 dn += blocklen;
962 /* find the next source block */
963 while (s && sn >= s->m_len) {
964 sn -= s->m_len;
965 soff += s->m_len;
966 s = s->m_next;
969 /* skip over empty mbuf */
970 while (s && s->m_len == 0)
971 s = s->m_next;
974 m_freem(scut->m_next);
975 scut->m_len = scutoff;
976 scut->m_next = d0;
978 /* just in case */
979 memset(iv, 0, sizeof(iv));
980 memset(sbuf, 0, sizeof(sbuf));
982 key_sa_stir_iv(sav);
984 return 0;
987 /*------------------------------------------------------------*/
989 /* does not free m0 on error
991 * skip - offset to ESP header
992 * length - payloadd length
995 esp_auth(struct mbuf *m0, size_t skip, size_t length,
996 struct secasvar *sav, u_char *sum)
998 struct mbuf *m;
999 size_t off;
1000 struct ah_algorithm_state s;
1001 u_char sumbuf[AH_MAXSUMSIZE];
1002 const struct ah_algorithm *algo;
1003 size_t siz;
1004 int error;
1006 /* sanity checks */
1007 if (m0->m_pkthdr.len < skip) {
1008 ipseclog((LOG_DEBUG, "esp_auth: mbuf length < skip\n"));
1009 return EINVAL;
1011 if (m0->m_pkthdr.len < skip + length) {
1012 ipseclog((LOG_DEBUG,
1013 "esp_auth: mbuf length < skip + length\n"));
1014 return EINVAL;
1017 * length of esp part (excluding authentication data) must be 4n,
1018 * since nexthdr must be at offset 4n+3.
1020 if (length % 4) {
1021 ipseclog((LOG_ERR, "esp_auth: length is not multiple of 4\n"));
1022 return EINVAL;
1024 if (!sav) {
1025 ipseclog((LOG_DEBUG, "esp_auth: NULL SA passed\n"));
1026 return EINVAL;
1028 algo = ah_algorithm_lookup(sav->alg_auth);
1029 if (!algo) {
1030 ipseclog((LOG_ERR,
1031 "esp_auth: bad ESP auth algorithm passed: %d\n",
1032 sav->alg_auth));
1033 return EINVAL;
1036 m = m0;
1037 off = 0;
1039 siz = (((*algo->sumsiz)(sav) + 3) & ~(4 - 1));
1040 if (sizeof(sumbuf) < siz) {
1041 ipseclog((LOG_DEBUG,
1042 "esp_auth: AH_MAXSUMSIZE is too small: siz=%lu\n",
1043 (u_long)siz));
1044 return EINVAL;
1047 /* skip the header */
1048 while (skip) {
1049 if (!m)
1050 panic("mbuf chain?");
1051 if (m->m_len <= skip) {
1052 skip -= m->m_len;
1053 m = m->m_next;
1054 off = 0;
1055 } else {
1056 off = skip;
1057 skip = 0;
1061 error = (*algo->init)(&s, sav);
1062 if (error)
1063 return error;
1065 while (0 < length) {
1066 if (!m)
1067 panic("mbuf chain?");
1069 if (m->m_len - off < length) {
1070 (*algo->update)(&s, mtod(m, u_char *) + off,
1071 m->m_len - off);
1072 length -= m->m_len - off;
1073 m = m->m_next;
1074 off = 0;
1075 } else {
1076 (*algo->update)(&s, mtod(m, u_char *) + off, length);
1077 break;
1080 (*algo->result)(&s, sumbuf, sizeof(sumbuf));
1081 memcpy(sum, sumbuf, siz); /* XXX */
1083 return 0;