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