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