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