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