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