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