a26eb50d70ee3e9aa1f6de2ab0bff9b442640c51
[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 %s: unsupported algorithm.\n", algo->name));
407                 return 1;
408         }
409
410         keylen = sav->key_enc->sadb_key_bits;
411         if (keylen < algo->keymin || algo->keymax < keylen) {
412                 ipseclog((LOG_ERR,
413                     "esp_cbc_mature %s: invalid key length %d.\n",
414                     algo->name, sav->key_enc->sadb_key_bits));
415                 return 1;
416         }
417         switch (sav->alg_enc) {
418         case SADB_EALG_3DESCBC:
419                 /* weak key check */
420                 if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc)) ||
421                     des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 8)) ||
422                     des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 16))) {
423                         ipseclog((LOG_ERR,
424                             "esp_cbc_mature %s: weak key was passed.\n",
425                             algo->name));
426                         return 1;
427                 }
428                 break;
429         case SADB_X_EALG_BLOWFISHCBC:
430         case SADB_X_EALG_CAST128CBC:
431                 break;
432         case SADB_X_EALG_RIJNDAELCBC:
433         case SADB_X_EALG_CAMELLIACBC:
434                 /* allows specific key sizes only */
435                 if (!(keylen == 128 || keylen == 192 || keylen == 256)) {
436                         ipseclog((LOG_ERR,
437                             "esp_cbc_mature %s: invalid key length %d.\n",
438                             algo->name, keylen));
439                         return 1;
440                 }
441                 break;
442         }
443
444         return 0;
445 }
446
447 static size_t
448 esp_blowfish_schedlen(const struct esp_algorithm *algo)
449 {
450
451         return sizeof(BF_KEY);
452 }
453
454 static int
455 esp_blowfish_schedule(const struct esp_algorithm *algo, struct secasvar *sav)
456 {
457
458         BF_set_key((BF_KEY *)sav->sched, _KEYLEN(sav->key_enc),
459             _KEYBUF(sav->key_enc));
460         return 0;
461 }
462
463 static int
464 esp_blowfish_blockdecrypt(const struct esp_algorithm *algo,
465                           struct secasvar *sav, u_int8_t *s, u_int8_t *d)
466 {
467
468         BF_ecb_encrypt(s, d, (BF_KEY *)sav->sched, 0);
469         return 0;
470 }
471
472 static int
473 esp_blowfish_blockencrypt(const struct esp_algorithm *algo,
474                           struct secasvar *sav, u_int8_t *s, u_int8_t *d)
475 {
476
477         BF_ecb_encrypt(s, d, (BF_KEY *)sav->sched, 1);
478         return 0;
479 }
480
481 static size_t
482 esp_cast128_schedlen(const struct esp_algorithm *algo)
483 {
484
485         return sizeof(cast128_key);
486 }
487
488 static int
489 esp_cast128_schedule(const struct esp_algorithm *algo, struct secasvar *sav)
490 {
491
492         cast128_setkey((cast128_key *)sav->sched, _KEYBUF(sav->key_enc),
493             _KEYLEN(sav->key_enc));
494         return 0;
495 }
496
497 static int
498 esp_cast128_blockdecrypt(const struct esp_algorithm *algo,
499                          struct secasvar *sav, u_int8_t *s, u_int8_t *d)
500 {
501
502         cast128_decrypt((cast128_key *)sav->sched, s, d);
503         return 0;
504 }
505
506 static int
507 esp_cast128_blockencrypt(const struct esp_algorithm *algo, struct secasvar *sav,
508                          u_int8_t *s, u_int8_t *d)
509 {
510
511         cast128_encrypt((cast128_key *)sav->sched, s, d);
512         return 0;
513 }
514
515 static size_t
516 esp_3des_schedlen(const struct esp_algorithm *algo)
517 {
518
519         return sizeof(des_key_schedule) * 3;
520 }
521
522 static int
523 esp_3des_schedule(const struct esp_algorithm *algo, struct secasvar *sav)
524 {
525         int error;
526         des_key_schedule *p;
527         int i;
528         u_int8_t *k;
529
530         p = (des_key_schedule *)sav->sched;
531         k = _KEYBUF(sav->key_enc);
532         for (i = 0; i < 3; i++) {
533                 error = des_key_sched((des_cblock *)(k + 8 * i), p[i]);
534                 if (error)
535                         return EINVAL;
536         }
537         return 0;
538 }
539
540 static int
541 esp_3des_blockdecrypt(const struct esp_algorithm *algo, struct secasvar *sav,
542                       u_int8_t *s, u_int8_t *d)
543 {
544         des_key_schedule *p;
545
546         /* assumption: d has a good alignment */
547         p = (des_key_schedule *)sav->sched;
548         bcopy(s, d, sizeof(DES_LONG) * 2);
549         des_ecb3_encrypt((des_cblock *)d, (des_cblock *)d,
550                          p[0], p[1], p[2], DES_DECRYPT);
551         return 0;
552 }
553
554 static int
555 esp_3des_blockencrypt(const struct esp_algorithm *algo, struct secasvar *sav,
556                       u_int8_t *s, u_int8_t *d)
557 {
558         des_key_schedule *p;
559
560         /* assumption: d has a good alignment */
561         p = (des_key_schedule *)sav->sched;
562         bcopy(s, d, sizeof(DES_LONG) * 2);
563         des_ecb3_encrypt((des_cblock *)d, (des_cblock *)d,
564                          p[0], p[1], p[2], DES_ENCRYPT);
565         return 0;
566 }
567
568 static int
569 esp_common_ivlen(const struct esp_algorithm *algo, struct secasvar *sav)
570 {
571
572         if (!algo)
573                 panic("esp_common_ivlen: unknown algorithm");
574         return algo->ivlenval;
575 }
576
577 static int
578 esp_cbc_decrypt(struct mbuf *m, size_t off, struct secasvar *sav,
579                 const struct esp_algorithm *algo, int ivlen)
580 {
581         struct mbuf *s;
582         struct mbuf *d, *d0, *dp;
583         int soff, doff; /* offset from the head of chain, to head of this mbuf */
584         int sn, dn;     /* offset from the head of the mbuf, to meat */
585         size_t ivoff, bodyoff;
586         u_int8_t iv[MAXIVLEN], *ivp;
587         u_int8_t sbuf[MAXIVLEN], *sp;
588         u_int8_t *p, *q;
589         struct mbuf *scut;
590         int scutoff;
591         int i;
592         int blocklen;
593         int derived;
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                 derived = 0;
619         } else {
620                 /* RFC 2406 */
621                 if (sav->flags & SADB_X_EXT_DERIV) {
622                         /*
623                          * draft-ietf-ipsec-ciph-des-derived-00.txt
624                          * uses sequence number field as IV field.
625                          */
626                         ivoff = off + sizeof(struct esp);
627                         bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
628                         ivlen = sizeof(u_int32_t);
629                         derived = 1;
630                 } else {
631                         ivoff = off + sizeof(struct newesp);
632                         bodyoff = off + sizeof(struct newesp) + ivlen;
633                         derived = 0;
634                 }
635         }
636
637         /* grab iv */
638         m_copydata(m, ivoff, ivlen, (caddr_t)iv);
639
640         /* extend iv */
641         if (ivlen == blocklen)
642                 ;
643         else if (ivlen == 4 && blocklen == 8) {
644                 bcopy(&iv[0], &iv[4], 4);
645                 iv[4] ^= 0xff;
646                 iv[5] ^= 0xff;
647                 iv[6] ^= 0xff;
648                 iv[7] ^= 0xff;
649         } else {
650                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
651                     "unsupported ivlen/blocklen: %d %d\n",
652                     algo->name, ivlen, blocklen));
653                 m_freem(m);
654                 return EINVAL;
655         }
656
657         if (m->m_pkthdr.len < bodyoff) {
658                 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: bad len %d/%lu\n",
659                     algo->name, m->m_pkthdr.len, (unsigned long)bodyoff));
660                 m_freem(m);
661                 return EINVAL;
662         }
663         if ((m->m_pkthdr.len - bodyoff) % blocklen) {
664                 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
665                     "payload length must be multiple of %d\n",
666                     algo->name, blocklen));
667                 m_freem(m);
668                 return EINVAL;
669         }
670
671         s = m;
672         d = d0 = dp = NULL;
673         soff = doff = sn = dn = 0;
674         ivp = sp = NULL;
675
676         /* skip bodyoff */
677         while (soff < bodyoff) {
678                 if (soff + s->m_len >= bodyoff) {
679                         sn = bodyoff - soff;
680                         break;
681                 }
682
683                 soff += s->m_len;
684                 s = s->m_next;
685         }
686         scut = s;
687         scutoff = sn;
688
689         /* skip over empty mbuf */
690         while (s && s->m_len == 0)
691                 s = s->m_next;
692
693         while (soff < m->m_pkthdr.len) {
694                 /* source */
695                 if (sn + blocklen <= s->m_len) {
696                         /* body is continuous */
697                         sp = mtod(s, u_int8_t *) + sn;
698                 } else {
699                         /* body is non-continuous */
700                         m_copydata(s, sn, blocklen, sbuf);
701                         sp = sbuf;
702                 }
703
704                 /* destination */
705                 if (!d || dn + blocklen > d->m_len) {
706                         if (d)
707                                 dp = d;
708                         i = m->m_pkthdr.len - (soff + sn);
709                         d = m_getb(i, MB_DONTWAIT, MT_DATA, 0);
710                         if (!d) {
711                                 m_freem(m);
712                                 if (d0)
713                                         m_freem(d0);
714                                 return ENOBUFS;
715                         }
716                         if (!d0)
717                                 d0 = d;
718                         if (dp)
719                                 dp->m_next = d;
720                         d->m_len = 0;
721                         d->m_len = rounddown(M_TRAILINGSPACE(d), blocklen);
722                         if (d->m_len > i)
723                                 d->m_len = i;
724                         dn = 0;
725                 }
726
727                 /* decrypt */
728                 (*algo->blockdecrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
729
730                 /* xor */
731                 p = ivp ? ivp : iv;
732                 q = mtod(d, u_int8_t *) + dn;
733                 for (i = 0; i < blocklen; i++)
734                         q[i] ^= p[i];
735
736                 /* next iv */
737                 if (sp == sbuf) {
738                         bcopy(sbuf, iv, blocklen);
739                         ivp = NULL;
740                 } else
741                         ivp = sp;
742
743                 sn += blocklen;
744                 dn += blocklen;
745
746                 /* find the next source block */
747                 while (s && sn >= s->m_len) {
748                         sn -= s->m_len;
749                         soff += s->m_len;
750                         s = s->m_next;
751                 }
752
753                 /* skip over empty mbuf */
754                 while (s && s->m_len == 0)
755                         s = s->m_next;
756         }
757
758         m_freem(scut->m_next);
759         scut->m_len = scutoff;
760         scut->m_next = d0;
761
762         /* just in case */
763         bzero(iv, sizeof(iv));
764         bzero(sbuf, sizeof(sbuf));
765
766         return 0;
767 }
768
769 static int
770 esp_cbc_encrypt(struct mbuf *m, size_t off, size_t plen, struct secasvar *sav,
771                 const struct esp_algorithm *algo, int ivlen)
772 {
773         struct mbuf *s;
774         struct mbuf *d, *d0, *dp;
775         int soff, doff; /* offset from the head of chain, to head of this mbuf */
776         int sn, dn;     /* offset from the head of the mbuf, to meat */
777         size_t ivoff, bodyoff;
778         u_int8_t iv[MAXIVLEN], *ivp;
779         u_int8_t sbuf[MAXIVLEN], *sp;
780         u_int8_t *p, *q;
781         struct mbuf *scut;
782         int scutoff;
783         int i;
784         int blocklen;
785         int derived;
786
787         if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
788                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
789                     "unsupported ivlen %d\n", algo->name, ivlen));
790                 m_freem(m);
791                 return EINVAL;
792         }
793
794         /* assumes blocklen == padbound */
795         blocklen = algo->padbound;
796
797 #ifdef DIAGNOSTIC
798         if (blocklen > sizeof(iv)) {
799                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
800                     "unsupported blocklen %d\n", algo->name, blocklen));
801                 m_freem(m);
802                 return EINVAL;
803         }
804 #endif
805
806         if (sav->flags & SADB_X_EXT_OLD) {
807                 /* RFC 1827 */
808                 ivoff = off + sizeof(struct esp);
809                 bodyoff = off + sizeof(struct esp) + ivlen;
810                 derived = 0;
811         } else {
812                 /* RFC 2406 */
813                 if (sav->flags & SADB_X_EXT_DERIV) {
814                         /*
815                          * draft-ietf-ipsec-ciph-des-derived-00.txt
816                          * uses sequence number field as IV field.
817                          */
818                         ivoff = off + sizeof(struct esp);
819                         bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
820                         ivlen = sizeof(u_int32_t);
821                         derived = 1;
822                 } else {
823                         ivoff = off + sizeof(struct newesp);
824                         bodyoff = off + sizeof(struct newesp) + ivlen;
825                         derived = 0;
826                 }
827         }
828
829         /* put iv into the packet.  if we are in derived mode, use seqno. */
830         if (derived)
831                 m_copydata(m, ivoff, ivlen, (caddr_t)iv);
832         else {
833                 bcopy(sav->iv, iv, ivlen);
834                 /* maybe it is better to overwrite dest, not source */
835                 m_copyback(m, ivoff, ivlen, (caddr_t)iv);
836         }
837
838         /* extend iv */
839         if (ivlen == blocklen)
840                 ;
841         else if (ivlen == 4 && blocklen == 8) {
842                 bcopy(&iv[0], &iv[4], 4);
843                 iv[4] ^= 0xff;
844                 iv[5] ^= 0xff;
845                 iv[6] ^= 0xff;
846                 iv[7] ^= 0xff;
847         } else {
848                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
849                     "unsupported ivlen/blocklen: %d %d\n",
850                     algo->name, ivlen, blocklen));
851                 m_freem(m);
852                 return EINVAL;
853         }
854
855         if (m->m_pkthdr.len < bodyoff) {
856                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: bad len %d/%lu\n",
857                     algo->name, m->m_pkthdr.len, (unsigned long)bodyoff));
858                 m_freem(m);
859                 return EINVAL;
860         }
861         if ((m->m_pkthdr.len - bodyoff) % blocklen) {
862                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
863                     "payload length must be multiple of %lu\n",
864                     algo->name, (unsigned long)algo->padbound));
865                 m_freem(m);
866                 return EINVAL;
867         }
868
869         s = m;
870         d = d0 = dp = NULL;
871         soff = doff = sn = dn = 0;
872         ivp = sp = NULL;
873
874         /* skip bodyoff */
875         while (soff < bodyoff) {
876                 if (soff + s->m_len >= bodyoff) {
877                         sn = bodyoff - soff;
878                         break;
879                 }
880
881                 soff += s->m_len;
882                 s = s->m_next;
883         }
884         scut = s;
885         scutoff = sn;
886
887         /* skip over empty mbuf */
888         while (s && s->m_len == 0)
889                 s = s->m_next;
890
891         while (soff < m->m_pkthdr.len) {
892                 /* source */
893                 if (sn + blocklen <= s->m_len) {
894                         /* body is continuous */
895                         sp = mtod(s, u_int8_t *) + sn;
896                 } else {
897                         /* body is non-continuous */
898                         m_copydata(s, sn, blocklen, (caddr_t)sbuf);
899                         sp = sbuf;
900                 }
901
902                 /* destination */
903                 if (!d || dn + blocklen > d->m_len) {
904                         if (d)
905                                 dp = d;
906                         i = m->m_pkthdr.len - (soff + sn);
907                         d = m_getb(i, MB_DONTWAIT, MT_DATA, 0);
908                         if (!d) {
909                                 m_freem(m);
910                                 if (d0)
911                                         m_freem(d0);
912                                 return ENOBUFS;
913                         }
914                         if (!d0)
915                                 d0 = d;
916                         if (dp)
917                                 dp->m_next = d;
918                         d->m_len = 0;
919                         d->m_len = rounddown(M_TRAILINGSPACE(d), blocklen);
920                         if (d->m_len > i)
921                                 d->m_len = i;
922                         dn = 0;
923                 }
924
925                 /* xor */
926                 p = ivp ? ivp : iv;
927                 q = sp;
928                 for (i = 0; i < blocklen; i++)
929                         q[i] ^= p[i];
930
931                 /* encrypt */
932                 (*algo->blockencrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
933
934                 /* next iv */
935                 ivp = mtod(d, u_int8_t *) + dn;
936
937                 sn += blocklen;
938                 dn += blocklen;
939
940                 /* find the next source block */
941                 while (s && sn >= s->m_len) {
942                         sn -= s->m_len;
943                         soff += s->m_len;
944                         s = s->m_next;
945                 }
946
947                 /* skip over empty mbuf */
948                 while (s && s->m_len == 0)
949                         s = s->m_next;
950         }
951
952         m_freem(scut->m_next);
953         scut->m_len = scutoff;
954         scut->m_next = d0;
955
956         /* just in case */
957         bzero(iv, sizeof(iv));
958         bzero(sbuf, sizeof(sbuf));
959
960         key_sa_stir_iv(sav);
961
962         return 0;
963 }
964
965 /*------------------------------------------------------------*/
966
967 /* does not free m0 on error */
968 int
969 esp_auth(struct mbuf *m0,
970          size_t skip,   /* offset to ESP header */
971          size_t length, /* payload length */
972          struct secasvar *sav, u_char *sum)
973 {
974         struct mbuf *m;
975         size_t off;
976         struct ah_algorithm_state s;
977         u_char sumbuf[AH_MAXSUMSIZE];
978         const struct ah_algorithm *algo;
979         size_t siz;
980         int error;
981
982         /* sanity checks */
983         if (m0->m_pkthdr.len < skip) {
984                 ipseclog((LOG_DEBUG, "esp_auth: mbuf length < skip\n"));
985                 return EINVAL;
986         }
987         if (m0->m_pkthdr.len < skip + length) {
988                 ipseclog((LOG_DEBUG,
989                     "esp_auth: mbuf length < skip + length\n"));
990                 return EINVAL;
991         }
992         /*
993          * length of esp part (excluding authentication data) must be 4n,
994          * since nexthdr must be at offset 4n+3.
995          */
996         if (length % 4) {
997                 ipseclog((LOG_ERR, "esp_auth: length is not multiple of 4\n"));
998                 return EINVAL;
999         }
1000         if (!sav) {
1001                 ipseclog((LOG_DEBUG, "esp_auth: NULL SA passed\n"));
1002                 return EINVAL;
1003         }
1004         algo = ah_algorithm_lookup(sav->alg_auth);
1005         if (!algo) {
1006                 ipseclog((LOG_ERR,
1007                     "esp_auth: bad ESP auth algorithm passed: %d\n",
1008                     sav->alg_auth));
1009                 return EINVAL;
1010         }
1011
1012         m = m0;
1013         off = 0;
1014
1015         siz = (((*algo->sumsiz)(sav) + 3) & ~(4 - 1));
1016         if (sizeof(sumbuf) < siz) {
1017                 ipseclog((LOG_DEBUG,
1018                     "esp_auth: AH_MAXSUMSIZE is too small: siz=%lu\n",
1019                     (u_long)siz));
1020                 return EINVAL;
1021         }
1022
1023         /* skip the header */
1024         while (skip) {
1025                 if (!m)
1026                         panic("mbuf chain?");
1027                 if (m->m_len <= skip) {
1028                         skip -= m->m_len;
1029                         m = m->m_next;
1030                         off = 0;
1031                 } else {
1032                         off = skip;
1033                         skip = 0;
1034                 }
1035         }
1036
1037         error = (*algo->init)(&s, sav);
1038         if (error)
1039                 return error;
1040
1041         while (0 < length) {
1042                 if (!m)
1043                         panic("mbuf chain?");
1044
1045                 if (m->m_len - off < length) {
1046                         (*algo->update)(&s, mtod(m, u_char *) + off,
1047                                 m->m_len - off);
1048                         length -= m->m_len - off;
1049                         m = m->m_next;
1050                         off = 0;
1051                 } else {
1052                         (*algo->update)(&s, mtod(m, u_char *) + off, length);
1053                         break;
1054                 }
1055         }
1056         (*algo->result)(&s, sumbuf);
1057         bcopy(sumbuf, sum, siz);        /* XXX */
1058
1059         return 0;
1060 }