Add threads to the process-retrieval sysctls so they show up in top, ps, etc.
[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 /*      $DragonFly: src/sys/netinet6/esp_core.c,v 1.2 2003/06/17 04:28:51 dillon Exp $  */
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>
73 #include <netkey/keydb.h>
74 #include <netkey/key.h>
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
81 static int esp_null_mature __P((struct secasvar *));
82 static int esp_null_decrypt __P((struct mbuf *, size_t,
83         struct secasvar *, const struct esp_algorithm *, int));
84 static int esp_null_encrypt __P((struct mbuf *, size_t, size_t,
85         struct secasvar *, const struct esp_algorithm *, int));
86 static int esp_descbc_mature __P((struct secasvar *));
87 static int esp_descbc_ivlen __P((const struct esp_algorithm *,
88         struct secasvar *));
89 static int esp_des_schedule __P((const struct esp_algorithm *,
90         struct secasvar *));
91 static int esp_des_schedlen __P((const struct esp_algorithm *));
92 static int esp_des_blockdecrypt __P((const struct esp_algorithm *,
93         struct secasvar *, u_int8_t *, u_int8_t *));
94 static int esp_des_blockencrypt __P((const struct esp_algorithm *,
95         struct secasvar *, u_int8_t *, u_int8_t *));
96 static int esp_cbc_mature __P((struct secasvar *));
97 static int esp_blowfish_schedule __P((const struct esp_algorithm *,
98         struct secasvar *));
99 static int esp_blowfish_schedlen __P((const struct esp_algorithm *));
100 static int esp_blowfish_blockdecrypt __P((const struct esp_algorithm *,
101         struct secasvar *, u_int8_t *, u_int8_t *));
102 static int esp_blowfish_blockencrypt __P((const struct esp_algorithm *,
103         struct secasvar *, u_int8_t *, u_int8_t *));
104 static int esp_cast128_schedule __P((const struct esp_algorithm *,
105         struct secasvar *));
106 static int esp_cast128_schedlen __P((const struct esp_algorithm *));
107 static int esp_cast128_blockdecrypt __P((const struct esp_algorithm *,
108         struct secasvar *, u_int8_t *, u_int8_t *));
109 static int esp_cast128_blockencrypt __P((const struct esp_algorithm *,
110         struct secasvar *, u_int8_t *, u_int8_t *));
111 static int esp_3des_schedule __P((const struct esp_algorithm *,
112         struct secasvar *));
113 static int esp_3des_schedlen __P((const struct esp_algorithm *));
114 static int esp_3des_blockdecrypt __P((const struct esp_algorithm *,
115         struct secasvar *, u_int8_t *, u_int8_t *));
116 static int esp_3des_blockencrypt __P((const struct esp_algorithm *,
117         struct secasvar *, u_int8_t *, u_int8_t *));
118 static int esp_common_ivlen __P((const struct esp_algorithm *,
119         struct secasvar *));
120 static int esp_cbc_decrypt __P((struct mbuf *, size_t,
121         struct secasvar *, const struct esp_algorithm *, int));
122 static 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
127 static 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
157 const struct esp_algorithm *
158 esp_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
180 int
181 esp_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
196 int
197 esp_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;
223         sav->sched = malloc(sav->schedlen, M_SECA, M_DONTWAIT);
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
240 static int
241 esp_null_mature(sav)
242         struct secasvar *sav;
243 {
244
245         /* anything is okay */
246         return 0;
247 }
248
249 static int
250 esp_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
261 static int
262 esp_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
274 static int
275 esp_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
316 static int
317 esp_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
331 static int
332 esp_des_schedlen(algo)
333         const struct esp_algorithm *algo;
334 {
335
336         return sizeof(des_key_schedule);
337 }
338
339 static int
340 esp_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
352 static int
353 esp_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
367 static int
368 esp_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
382 static int
383 esp_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
448 static int
449 esp_blowfish_schedlen(algo)
450         const struct esp_algorithm *algo;
451 {
452
453         return sizeof(BF_KEY);
454 }
455
456 static int
457 esp_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
467 static int
468 esp_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
487 static int
488 esp_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
507 static int
508 esp_cast128_schedlen(algo)
509         const struct esp_algorithm *algo;
510 {
511
512         return sizeof(u_int32_t) * 32;
513 }
514
515 static int
516 esp_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
526 static int
527 esp_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
541 static int
542 esp_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
556 static int
557 esp_3des_schedlen(algo)
558         const struct esp_algorithm *algo;
559 {
560
561         return sizeof(des_key_schedule) * 3;
562 }
563
564 static int
565 esp_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
584 static int
585 esp_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
601 static int
602 esp_3des_blockencrypt(algo, sav, s, d)
603         const struct esp_algorithm *algo;
604         struct secasvar *sav;
605         u_int8_t *s;
606         u_int8_t *d;
607 {
608         des_key_schedule *p;
609
610         /* assumption: d has a good alignment */
611         p = (des_key_schedule *)sav->sched;
612         bcopy(s, d, sizeof(DES_LONG) * 2);
613         des_ecb3_encrypt((des_cblock *)d, (des_cblock *)d, 
614                          p[0], p[1], p[2], DES_ENCRYPT);
615         return 0;
616 }
617
618 static int
619 esp_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
629 static int
630 esp_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
832 static int
833 esp_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 */
1043 int
1044 esp_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 }