Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / 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 #include "opt_inet.h"
34 #include "opt_inet6.h"
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
39 #include <sys/mbuf.h>
40 #include <sys/domain.h>
41 #include <sys/protosw.h>
42 #include <sys/socket.h>
43 #include <sys/errno.h>
44 #include <sys/time.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 #ifdef 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 #ifdef INET6
60 #include <netinet6/ipsec6.h>
61 #endif
62 #include <netinet6/ah.h>
63 #ifdef INET6
64 #include <netinet6/ah6.h>
65 #endif
66 #include <netinet6/esp.h>
67 #ifdef 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_decrypt() 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_decrypt(t, (BF_KEY *)sav->sched);
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);
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_ecb3_encrypt((des_cblock *)d, (des_cblock *)d, 
596                          p[0], p[1], p[2], DES_DECRYPT);
597         return 0;
598 }
599
600 static int
601 esp_3des_blockencrypt(algo, sav, s, d)
602         const struct esp_algorithm *algo;
603         struct secasvar *sav;
604         u_int8_t *s;
605         u_int8_t *d;
606 {
607         des_key_schedule *p;
608
609         /* assumption: d has a good alignment */
610         p = (des_key_schedule *)sav->sched;
611         bcopy(s, d, sizeof(DES_LONG) * 2);
612         des_ecb3_encrypt((des_cblock *)d, (des_cblock *)d, 
613                          p[0], p[1], p[2], DES_ENCRYPT);
614         return 0;
615 }
616
617 static int
618 esp_common_ivlen(algo, sav)
619         const struct esp_algorithm *algo;
620         struct secasvar *sav;
621 {
622
623         if (!algo)
624                 panic("esp_common_ivlen: unknown algorithm");
625         return algo->ivlenval;
626 }
627
628 static int
629 esp_cbc_decrypt(m, off, sav, algo, ivlen)
630         struct mbuf *m;
631         size_t off;
632         struct secasvar *sav;
633         const struct esp_algorithm *algo;
634         int ivlen;
635 {
636         struct mbuf *s;
637         struct mbuf *d, *d0, *dp;
638         int soff, doff; /* offset from the head of chain, to head of this mbuf */
639         int sn, dn;     /* offset from the head of the mbuf, to meat */
640         size_t ivoff, bodyoff;
641         u_int8_t iv[MAXIVLEN], *ivp;
642         u_int8_t sbuf[MAXIVLEN], *sp;
643         u_int8_t *p, *q;
644         struct mbuf *scut;
645         int scutoff;
646         int i;
647         int blocklen;
648         int derived;
649
650         if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
651                 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
652                     "unsupported ivlen %d\n", algo->name, ivlen));
653                 m_freem(m);
654                 return EINVAL;
655         }
656
657         /* assumes blocklen == padbound */
658         blocklen = algo->padbound;
659
660 #ifdef DIAGNOSTIC
661         if (blocklen > sizeof(iv)) {
662                 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
663                     "unsupported blocklen %d\n", algo->name, blocklen));
664                 m_freem(m);
665                 return EINVAL;
666         }
667 #endif
668
669         if (sav->flags & SADB_X_EXT_OLD) {
670                 /* RFC 1827 */
671                 ivoff = off + sizeof(struct esp);
672                 bodyoff = off + sizeof(struct esp) + ivlen;
673                 derived = 0;
674         } else {
675                 /* RFC 2406 */
676                 if (sav->flags & SADB_X_EXT_DERIV) {
677                         /*
678                          * draft-ietf-ipsec-ciph-des-derived-00.txt
679                          * uses sequence number field as IV field.
680                          */
681                         ivoff = off + sizeof(struct esp);
682                         bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
683                         ivlen = sizeof(u_int32_t);
684                         derived = 1;
685                 } else {
686                         ivoff = off + sizeof(struct newesp);
687                         bodyoff = off + sizeof(struct newesp) + ivlen;
688                         derived = 0;
689                 }
690         }
691
692         /* grab iv */
693         m_copydata(m, ivoff, ivlen, iv);
694
695         /* extend iv */
696         if (ivlen == blocklen)
697                 ;
698         else if (ivlen == 4 && blocklen == 8) {
699                 bcopy(&iv[0], &iv[4], 4);
700                 iv[4] ^= 0xff;
701                 iv[5] ^= 0xff;
702                 iv[6] ^= 0xff;
703                 iv[7] ^= 0xff;
704         } else {
705                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
706                     "unsupported ivlen/blocklen: %d %d\n",
707                     algo->name, ivlen, blocklen));
708                 m_freem(m);
709                 return EINVAL;
710         }
711
712         if (m->m_pkthdr.len < bodyoff) {
713                 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: bad len %d/%lu\n",
714                     algo->name, m->m_pkthdr.len, (unsigned long)bodyoff));
715                 m_freem(m);
716                 return EINVAL;
717         }
718         if ((m->m_pkthdr.len - bodyoff) % blocklen) {
719                 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
720                     "payload length must be multiple of %d\n",
721                     algo->name, blocklen));
722                 m_freem(m);
723                 return EINVAL;
724         }
725
726         s = m;
727         d = d0 = dp = NULL;
728         soff = doff = sn = dn = 0;
729         ivp = sp = NULL;
730
731         /* skip bodyoff */
732         while (soff < bodyoff) {
733                 if (soff + s->m_len > bodyoff) {
734                         sn = bodyoff - soff;
735                         break;
736                 }
737
738                 soff += s->m_len;
739                 s = s->m_next;
740         }
741         scut = s;
742         scutoff = sn;
743
744         /* skip over empty mbuf */
745         while (s && s->m_len == 0)
746                 s = s->m_next;
747
748         while (soff < m->m_pkthdr.len) {
749                 /* source */
750                 if (sn + blocklen <= s->m_len) {
751                         /* body is continuous */
752                         sp = mtod(s, u_int8_t *) + sn;
753                 } else {
754                         /* body is non-continuous */
755                         m_copydata(s, sn, blocklen, sbuf);
756                         sp = sbuf;
757                 }
758
759                 /* destination */
760                 if (!d || dn + blocklen > d->m_len) {
761                         if (d)
762                                 dp = d;
763                         MGET(d, M_DONTWAIT, MT_DATA);
764                         i = m->m_pkthdr.len - (soff + sn);
765                         if (d && i > MLEN) {
766                                 MCLGET(d, M_DONTWAIT);
767                                 if ((d->m_flags & M_EXT) == 0) {
768                                         m_free(d);
769                                         d = NULL;
770                                 }
771                         }
772                         if (!d) {
773                                 m_freem(m);
774                                 if (d0)
775                                         m_freem(d0);
776                                 return ENOBUFS;
777                         }
778                         if (!d0)
779                                 d0 = d;
780                         if (dp)
781                                 dp->m_next = d;
782                         d->m_len = 0;
783                         d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
784                         if (d->m_len > i)
785                                 d->m_len = i;
786                         dn = 0;
787                 }
788
789                 /* decrypt */
790                 (*algo->blockdecrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
791
792                 /* xor */
793                 p = ivp ? ivp : iv;
794                 q = mtod(d, u_int8_t *) + dn;
795                 for (i = 0; i < blocklen; i++)
796                         q[i] ^= p[i];
797
798                 /* next iv */
799                 if (sp == sbuf) {
800                         bcopy(sbuf, iv, blocklen);
801                         ivp = NULL;
802                 } else
803                         ivp = sp;
804
805                 sn += blocklen;
806                 dn += blocklen;
807
808                 /* find the next source block */
809                 while (s && sn >= s->m_len) {
810                         sn -= s->m_len;
811                         soff += s->m_len;
812                         s = s->m_next;
813                 }
814
815                 /* skip over empty mbuf */
816                 while (s && s->m_len == 0)
817                         s = s->m_next;
818         }
819
820         m_freem(scut->m_next);
821         scut->m_len = scutoff;
822         scut->m_next = d0;
823
824         /* just in case */
825         bzero(iv, sizeof(iv));
826         bzero(sbuf, sizeof(sbuf));
827
828         return 0;
829 }
830
831 static int
832 esp_cbc_encrypt(m, off, plen, sav, algo, ivlen)
833         struct mbuf *m;
834         size_t off;
835         size_t plen;
836         struct secasvar *sav;
837         const struct esp_algorithm *algo;
838         int ivlen;
839 {
840         struct mbuf *s;
841         struct mbuf *d, *d0, *dp;
842         int soff, doff; /* offset from the head of chain, to head of this mbuf */
843         int sn, dn;     /* offset from the head of the mbuf, to meat */
844         size_t ivoff, bodyoff;
845         u_int8_t iv[MAXIVLEN], *ivp;
846         u_int8_t sbuf[MAXIVLEN], *sp;
847         u_int8_t *p, *q;
848         struct mbuf *scut;
849         int scutoff;
850         int i;
851         int blocklen;
852         int derived;
853
854         if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
855                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
856                     "unsupported ivlen %d\n", algo->name, ivlen));
857                 m_freem(m);
858                 return EINVAL;
859         }
860
861         /* assumes blocklen == padbound */
862         blocklen = algo->padbound;
863
864 #ifdef DIAGNOSTIC
865         if (blocklen > sizeof(iv)) {
866                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
867                     "unsupported blocklen %d\n", algo->name, blocklen));
868                 m_freem(m);
869                 return EINVAL;
870         }
871 #endif
872
873         if (sav->flags & SADB_X_EXT_OLD) {
874                 /* RFC 1827 */
875                 ivoff = off + sizeof(struct esp);
876                 bodyoff = off + sizeof(struct esp) + ivlen;
877                 derived = 0;
878         } else {
879                 /* RFC 2406 */
880                 if (sav->flags & SADB_X_EXT_DERIV) {
881                         /*
882                          * draft-ietf-ipsec-ciph-des-derived-00.txt
883                          * uses sequence number field as IV field.
884                          */
885                         ivoff = off + sizeof(struct esp);
886                         bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
887                         ivlen = sizeof(u_int32_t);
888                         derived = 1;
889                 } else {
890                         ivoff = off + sizeof(struct newesp);
891                         bodyoff = off + sizeof(struct newesp) + ivlen;
892                         derived = 0;
893                 }
894         }
895
896         /* put iv into the packet.  if we are in derived mode, use seqno. */
897         if (derived)
898                 m_copydata(m, ivoff, ivlen, iv);
899         else {
900                 bcopy(sav->iv, iv, ivlen);
901                 /* maybe it is better to overwrite dest, not source */
902                 m_copyback(m, ivoff, ivlen, iv);
903         }
904
905         /* extend iv */
906         if (ivlen == blocklen)
907                 ;
908         else if (ivlen == 4 && blocklen == 8) {
909                 bcopy(&iv[0], &iv[4], 4);
910                 iv[4] ^= 0xff;
911                 iv[5] ^= 0xff;
912                 iv[6] ^= 0xff;
913                 iv[7] ^= 0xff;
914         } else {
915                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
916                     "unsupported ivlen/blocklen: %d %d\n",
917                     algo->name, ivlen, blocklen));
918                 m_freem(m);
919                 return EINVAL;
920         }
921
922         if (m->m_pkthdr.len < bodyoff) {
923                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: bad len %d/%lu\n",
924                     algo->name, m->m_pkthdr.len, (unsigned long)bodyoff));
925                 m_freem(m);
926                 return EINVAL;
927         }
928         if ((m->m_pkthdr.len - bodyoff) % blocklen) {
929                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
930                     "payload length must be multiple of %lu\n",
931                     algo->name, (unsigned long)algo->padbound));
932                 m_freem(m);
933                 return EINVAL;
934         }
935
936         s = m;
937         d = d0 = dp = NULL;
938         soff = doff = sn = dn = 0;
939         ivp = sp = NULL;
940
941         /* skip bodyoff */
942         while (soff < bodyoff) {
943                 if (soff + s->m_len > bodyoff) {
944                         sn = bodyoff - soff;
945                         break;
946                 }
947
948                 soff += s->m_len;
949                 s = s->m_next;
950         }
951         scut = s;
952         scutoff = sn;
953
954         /* skip over empty mbuf */
955         while (s && s->m_len == 0)
956                 s = s->m_next;
957
958         while (soff < m->m_pkthdr.len) {
959                 /* source */
960                 if (sn + blocklen <= s->m_len) {
961                         /* body is continuous */
962                         sp = mtod(s, u_int8_t *) + sn;
963                 } else {
964                         /* body is non-continuous */
965                         m_copydata(s, sn, blocklen, sbuf);
966                         sp = sbuf;
967                 }
968
969                 /* destination */
970                 if (!d || dn + blocklen > d->m_len) {
971                         if (d)
972                                 dp = d;
973                         MGET(d, M_DONTWAIT, MT_DATA);
974                         i = m->m_pkthdr.len - (soff + sn);
975                         if (d && i > MLEN) {
976                                 MCLGET(d, M_DONTWAIT);
977                                 if ((d->m_flags & M_EXT) == 0) {
978                                         m_free(d);
979                                         d = NULL;
980                                 }
981                         }
982                         if (!d) {
983                                 m_freem(m);
984                                 if (d0)
985                                         m_freem(d0);
986                                 return ENOBUFS;
987                         }
988                         if (!d0)
989                                 d0 = d;
990                         if (dp)
991                                 dp->m_next = d;
992                         d->m_len = 0;
993                         d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
994                         if (d->m_len > i)
995                                 d->m_len = i;
996                         dn = 0;
997                 }
998
999                 /* xor */
1000                 p = ivp ? ivp : iv;
1001                 q = sp;
1002                 for (i = 0; i < blocklen; i++)
1003                         q[i] ^= p[i];
1004
1005                 /* encrypt */
1006                 (*algo->blockencrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
1007
1008                 /* next iv */
1009                 ivp = mtod(d, u_int8_t *) + dn;
1010
1011                 sn += blocklen;
1012                 dn += blocklen;
1013
1014                 /* find the next source block */
1015                 while (s && sn >= s->m_len) {
1016                         sn -= s->m_len;
1017                         soff += s->m_len;
1018                         s = s->m_next;
1019                 }
1020
1021                 /* skip over empty mbuf */
1022                 while (s && s->m_len == 0)
1023                         s = s->m_next;
1024         }
1025
1026         m_freem(scut->m_next);
1027         scut->m_len = scutoff;
1028         scut->m_next = d0;
1029
1030         /* just in case */
1031         bzero(iv, sizeof(iv));
1032         bzero(sbuf, sizeof(sbuf));
1033
1034         key_sa_stir_iv(sav);
1035
1036         return 0;
1037 }
1038
1039 /*------------------------------------------------------------*/
1040
1041 /* does not free m0 on error */
1042 int
1043 esp_auth(m0, skip, length, sav, sum)
1044         struct mbuf *m0;
1045         size_t skip;    /* offset to ESP header */
1046         size_t length;  /* payload length */
1047         struct secasvar *sav;
1048         u_char *sum;
1049 {
1050         struct mbuf *m;
1051         size_t off;
1052         struct ah_algorithm_state s;
1053         u_char sumbuf[AH_MAXSUMSIZE];
1054         const struct ah_algorithm *algo;
1055         size_t siz;
1056         int error;
1057
1058         /* sanity checks */
1059         if (m0->m_pkthdr.len < skip) {
1060                 ipseclog((LOG_DEBUG, "esp_auth: mbuf length < skip\n"));
1061                 return EINVAL;
1062         }
1063         if (m0->m_pkthdr.len < skip + length) {
1064                 ipseclog((LOG_DEBUG,
1065                     "esp_auth: mbuf length < skip + length\n"));
1066                 return EINVAL;
1067         }
1068         /*
1069          * length of esp part (excluding authentication data) must be 4n,
1070          * since nexthdr must be at offset 4n+3.
1071          */
1072         if (length % 4) {
1073                 ipseclog((LOG_ERR, "esp_auth: length is not multiple of 4\n"));
1074                 return EINVAL;
1075         }
1076         if (!sav) {
1077                 ipseclog((LOG_DEBUG, "esp_auth: NULL SA passed\n"));
1078                 return EINVAL;
1079         }
1080         algo = ah_algorithm_lookup(sav->alg_auth);
1081         if (!algo) {
1082                 ipseclog((LOG_ERR,
1083                     "esp_auth: bad ESP auth algorithm passed: %d\n",
1084                     sav->alg_auth));
1085                 return EINVAL;
1086         }
1087
1088         m = m0;
1089         off = 0;
1090
1091         siz = (((*algo->sumsiz)(sav) + 3) & ~(4 - 1));
1092         if (sizeof(sumbuf) < siz) {
1093                 ipseclog((LOG_DEBUG,
1094                     "esp_auth: AH_MAXSUMSIZE is too small: siz=%lu\n",
1095                     (u_long)siz));
1096                 return EINVAL;
1097         }
1098
1099         /* skip the header */
1100         while (skip) {
1101                 if (!m)
1102                         panic("mbuf chain?");
1103                 if (m->m_len <= skip) {
1104                         skip -= m->m_len;
1105                         m = m->m_next;
1106                         off = 0;
1107                 } else {
1108                         off = skip;
1109                         skip = 0;
1110                 }
1111         }
1112
1113         error = (*algo->init)(&s, sav);
1114         if (error)
1115                 return error;
1116
1117         while (0 < length) {
1118                 if (!m)
1119                         panic("mbuf chain?");
1120
1121                 if (m->m_len - off < length) {
1122                         (*algo->update)(&s, mtod(m, u_char *) + off,
1123                                 m->m_len - off);
1124                         length -= m->m_len - off;
1125                         m = m->m_next;
1126                         off = 0;
1127                 } else {
1128                         (*algo->update)(&s, mtod(m, u_char *) + off, length);
1129                         break;
1130                 }
1131         }
1132         (*algo->result)(&s, sumbuf);
1133         bcopy(sumbuf, sum, siz);        /* XXX */
1134         
1135         return 0;
1136 }