]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet6/esp_core.c
xnu-201.42.3.tar.gz
[apple/xnu.git] / bsd / netinet6 / esp_core.c
CommitLineData
1c79356b
A
1/* $KAME: esp_core.c,v 1.11 2000/02/22 14:04:15 itojun Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#define _IP_VHL
33#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
34#include "opt_inet.h"
35#endif
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/malloc.h>
40#include <sys/mbuf.h>
41#include <sys/domain.h>
42#include <sys/protosw.h>
43#include <sys/socket.h>
44#include <sys/errno.h>
45#include <sys/time.h>
46#include <sys/kernel.h>
47#include <sys/syslog.h>
48
49#include <net/if.h>
50#include <net/route.h>
51
52#include <netinet/in.h>
53#include <netinet/in_var.h>
54#if INET6
55#include <netinet/ip6.h>
56#include <netinet6/ip6_var.h>
57#include <netinet/icmp6.h>
58#endif
59
60#include <netinet6/ipsec.h>
61#include <netinet6/ah.h>
62#include <netinet6/esp.h>
63#include <net/pfkeyv2.h>
64#include <netkey/keydb.h>
65#include <crypto/des/des.h>
66#include <crypto/blowfish/blowfish.h>
67#include <crypto/cast128/cast128.h>
68#include <crypto/rc5/rc5.h>
69
70#include <net/net_osdep.h>
71
72static int esp_null_mature __P((struct secasvar *));
73static int esp_null_ivlen __P((struct secasvar *));
74static int esp_null_decrypt __P((struct mbuf *, size_t,
75 struct secasvar *, struct esp_algorithm *, int));
76static int esp_null_encrypt __P((struct mbuf *, size_t, size_t,
77 struct secasvar *, struct esp_algorithm *, int));
78static int esp_descbc_mature __P((struct secasvar *));
79static int esp_descbc_ivlen __P((struct secasvar *));
80static int esp_descbc_decrypt __P((struct mbuf *, size_t,
81 struct secasvar *, struct esp_algorithm *, int));
82static int esp_descbc_encrypt __P((struct mbuf *, size_t, size_t,
83 struct secasvar *, struct esp_algorithm *, int));
84static int esp_cbc_mature __P((struct secasvar *));
85static int esp_blowfish_cbc_decrypt __P((struct mbuf *, size_t,
86 struct secasvar *, struct esp_algorithm *, int));
87static int esp_blowfish_cbc_encrypt __P((struct mbuf *, size_t,
88 size_t, struct secasvar *, struct esp_algorithm *, int));
89static int esp_blowfish_cbc_ivlen __P((struct secasvar *));
90static int esp_cast128cbc_ivlen __P((struct secasvar *));
91static int esp_cast128cbc_decrypt __P((struct mbuf *, size_t,
92 struct secasvar *, struct esp_algorithm *, int));
93static int esp_cast128cbc_encrypt __P((struct mbuf *, size_t, size_t,
94 struct secasvar *, struct esp_algorithm *, int));
95static int esp_3descbc_ivlen __P((struct secasvar *));
96static int esp_3descbc_decrypt __P((struct mbuf *, size_t,
97 struct secasvar *, struct esp_algorithm *, int));
98static int esp_3descbc_encrypt __P((struct mbuf *, size_t, size_t,
99 struct secasvar *, struct esp_algorithm *, int));
100static int esp_rc5cbc_ivlen __P((struct secasvar *));
101static int esp_rc5cbc_decrypt __P((struct mbuf *, size_t,
102 struct secasvar *, struct esp_algorithm *, int));
103static int esp_rc5cbc_encrypt __P((struct mbuf *, size_t, size_t,
104 struct secasvar *, struct esp_algorithm *, int));
105static void esp_increment_iv __P((struct secasvar *));
106static caddr_t mbuf_find_offset __P((struct mbuf *, size_t, size_t));
107
108/* NOTE: The order depends on SADB_EALG_x in netkey/keyv2.h */
109struct esp_algorithm esp_algorithms[] = {
110 { 0, 0, 0, 0, 0, 0, 0, },
111 { 8, esp_descbc_mature, 64, 64,
112 esp_descbc_ivlen, esp_descbc_decrypt, esp_descbc_encrypt, },
113 { 8, esp_cbc_mature, 192, 192,
114 esp_3descbc_ivlen, esp_3descbc_decrypt, esp_3descbc_encrypt, },
115 { 1, esp_null_mature, 0, 2048,
116 esp_null_ivlen, esp_null_decrypt, esp_null_encrypt, },
117 { 8, esp_cbc_mature, 40, 448,
118 esp_blowfish_cbc_ivlen, esp_blowfish_cbc_decrypt,
119 esp_blowfish_cbc_encrypt, },
120 { 8, esp_cbc_mature, 40, 128,
121 esp_cast128cbc_ivlen, esp_cast128cbc_decrypt,
122 esp_cast128cbc_encrypt, },
123 { 8, esp_cbc_mature, 40, 2040,
124 esp_rc5cbc_ivlen, esp_rc5cbc_decrypt, esp_rc5cbc_encrypt, },
125};
126
127/*
128 * mbuf assumption: foo_encrypt() assumes that IV part is placed in a single
129 * mbuf, not across multiple mbufs.
130 */
131
132static int
133esp_null_mature(sav)
134 struct secasvar *sav;
135{
136 /* anything is okay */
137 return 0;
138}
139
140static int
141esp_null_ivlen(sav)
142 struct secasvar *sav;
143{
144 return 0;
145}
146
147static int
148esp_null_decrypt(m, off, sav, algo, ivlen)
149 struct mbuf *m;
150 size_t off; /* offset to ESP header */
151 struct secasvar *sav;
152 struct esp_algorithm *algo;
153 int ivlen;
154{
155 return 0; /* do nothing */
156}
157
158static int
159esp_null_encrypt(m, off, plen, sav, algo, ivlen)
160 struct mbuf *m;
161 size_t off; /* offset to ESP header */
162 size_t plen; /* payload length (to be encrypted) */
163 struct secasvar *sav;
164 struct esp_algorithm *algo;
165 int ivlen;
166{
167 return 0; /* do nothing */
168}
169
170static int
171esp_descbc_mature(sav)
172 struct secasvar *sav;
173{
174 struct esp_algorithm *algo;
175
176 if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B)) {
177 ipseclog((LOG_ERR, "esp_cbc_mature: "
178 "algorithm incompatible with 4 octets IV length\n"));
179 return 1;
180 }
181
182 if (!sav->key_enc) {
183 ipseclog((LOG_ERR, "esp_descbc_mature: no key is given.\n"));
184 return 1;
185 }
186 algo = &esp_algorithms[sav->alg_enc];
187 if (_KEYBITS(sav->key_enc) < algo->keymin
188 || algo->keymax < _KEYBITS(sav->key_enc)) {
189 ipseclog((LOG_ERR,
190 "esp_descbc_mature: invalid key length %d.\n",
191 _KEYBITS(sav->key_enc)));
192 return 1;
193 }
194
195 /* weak key check */
196 if (des_is_weak_key((C_Block *)_KEYBUF(sav->key_enc))) {
197 ipseclog((LOG_ERR,
198 "esp_descbc_mature: weak key was passed.\n"));
199 return 1;
200 }
201
202 return 0;
203}
204
205static int
206esp_descbc_ivlen(sav)
207 struct secasvar *sav;
208{
209 if (sav && (sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B))
210 return 4;
211
212 if (sav && !(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_DERIV))
213 return 4;
214 else
215 return 8;
216}
217
218static int
219esp_descbc_decrypt(m, off, sav, algo, ivlen)
220 struct mbuf *m;
221 size_t off; /* offset to ESP header */
222 struct secasvar *sav;
223 struct esp_algorithm *algo;
224 int ivlen;
225{
226 size_t ivoff = 0;
227 size_t bodyoff = 0;
228 u_int8_t *iv;
229 size_t plen;
230 u_int8_t tiv[8];
231 int derived;
232
233 derived = 0;
234 /* sanity check */
235 if (ivlen != sav->ivlen) {
236 ipseclog((LOG_ERR, "esp_descbc_decrypt: bad ivlen %d/%d\n",
237 ivlen, sav->ivlen));
238 return EINVAL;
239 }
240 if (_KEYBITS(sav->key_enc) < algo->keymin
241 || algo->keymax < _KEYBITS(sav->key_enc)) {
242 ipseclog((LOG_ERR, "esp_descbc_decrypt: bad keylen %d\n",
243 _KEYBITS(sav->key_enc)));
244 return EINVAL;
245 }
246
247 if (sav->flags & SADB_X_EXT_OLD) {
248 /* RFC 1827 */
249 ivoff = off + sizeof(struct esp);
250 bodyoff = off + sizeof(struct esp) + ivlen;
251 derived = 0;
252 } else {
253 /* RFC 2406 */
254 if (sav->flags & SADB_X_EXT_DERIV) {
255 /*
256 * draft-ietf-ipsec-ciph-des-derived-00.txt
257 * uses sequence number field as IV field.
258 * This draft has been deleted, but you can get from
259 * ftp://ftp.kame.net/pub/internet-drafts/.
260 */
261 ivoff = off + sizeof(struct esp);
262 bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
263 ivlen = sizeof(u_int32_t);
264 derived = 1;
265 } else {
266 ivoff = off + sizeof(struct newesp);
267 bodyoff = off + sizeof(struct newesp) + ivlen;
268 derived = 0;
269 }
270 }
271 if (ivlen == 4) {
272 iv = &tiv[0];
273 m_copydata(m, ivoff, 4, &tiv[0]);
274 m_copydata(m, ivoff, 4, &tiv[4]);
275 tiv[4] ^= 0xff;
276 tiv[5] ^= 0xff;
277 tiv[6] ^= 0xff;
278 tiv[7] ^= 0xff;
279 } else if (ivlen == 8) {
280 iv = &tiv[0];
281 m_copydata(m, ivoff, 8, &tiv[0]);
282 } else {
283 ipseclog((LOG_ERR, "esp_descbc_decrypt: unsupported ivlen %d\n",
284 ivlen));
285 return EINVAL;
286 }
287
288 plen = m->m_pkthdr.len;
289 if (plen < bodyoff)
290 panic("esp_descbc_decrypt: too short packet: len=%lu",
291 (u_long)plen);
292 plen -= bodyoff;
293
294 if (plen % 8) {
295 ipseclog((LOG_ERR, "esp_descbc_decrypt: "
296 "payload length must be multiple of 8\n"));
297 return EINVAL;
298 }
299
300 {
301 int deserr;
302 des_key_schedule ks;
303
304 deserr = des_key_sched((C_Block *)_KEYBUF(sav->key_enc), ks);
305 if (deserr != 0) {
306 ipseclog((LOG_ERR,
307 "esp_descbc_decrypt: key error %d\n", deserr));
308 return EINVAL;
309 }
310
311 des_cbc_encrypt(m, bodyoff, plen, ks, (C_Block *)iv, DES_DECRYPT);
312
313 /* for safety */
314 bzero(&ks, sizeof(des_key_schedule));
315 }
316
317 /* for safety */
318 bzero(&tiv[0], sizeof(tiv));
319
320 return 0;
321}
322
323static int
324esp_descbc_encrypt(m, off, plen, sav, algo, ivlen)
325 struct mbuf *m;
326 size_t off; /* offset to ESP header */
327 size_t plen; /* payload length (to be decrypted) */
328 struct secasvar *sav;
329 struct esp_algorithm *algo;
330 int ivlen;
331{
332 size_t ivoff = 0;
333 size_t bodyoff = 0;
334 u_int8_t *iv;
335 u_int8_t tiv[8];
336 int derived;
337
338 derived = 0;
339
340 /* sanity check */
341 if (plen % 8) {
342 ipseclog((LOG_ERR, "esp_descbc_encrypt: "
343 "payload length must be multiple of 8\n"));
344 return EINVAL;
345 }
346 if (sav->ivlen != ivlen) {
347 ipseclog((LOG_ERR, "esp_descbc_encrypt: bad ivlen %d/%d\n",
348 ivlen, sav->ivlen));
349 return EINVAL;
350 }
351 if (_KEYBITS(sav->key_enc) < algo->keymin
352 || algo->keymax < _KEYBITS(sav->key_enc)) {
353 ipseclog((LOG_ERR, "esp_descbc_encrypt: bad keylen %d\n",
354 _KEYBITS(sav->key_enc)));
355 return EINVAL;
356 }
357
358 if (sav->flags & SADB_X_EXT_OLD) {
359 /* RFC 1827 */
360 /*
361 * draft-ietf-ipsec-ciph-des-derived-00.txt
362 * uses sequence number field as IV field.
363 * This draft has been deleted, see above.
364 */
365 ivoff = off + sizeof(struct esp);
366 bodyoff = off + sizeof(struct esp) + ivlen;
367 derived = 0;
368 } else {
369 /* RFC 2406 */
370 if (sav->flags & SADB_X_EXT_DERIV) {
371 /*
372 * draft-ietf-ipsec-ciph-des-derived-00.txt
373 * uses sequence number field as IV field.
374 * This draft has been deleted, see above.
375 */
376 ivoff = off + sizeof(struct esp);
377 bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
378 ivlen = sizeof(u_int32_t);
379 derived = 1;
380 } else {
381 ivoff = off + sizeof(struct newesp);
382 bodyoff = off + sizeof(struct newesp) + ivlen;
383 derived = 0;
384 }
385 }
386
387 if (m->m_pkthdr.len < bodyoff)
388 panic("assumption failed: mbuf too short");
389 iv = mbuf_find_offset(m, ivoff, ivlen);
390 if (!iv)
391 panic("assumption failed: bad mbuf chain");
392 if (ivlen == 4) {
393 if (!derived) {
394 bcopy(sav->iv, &tiv[0], 4);
395 bcopy(sav->iv, &tiv[4], 4);
396 tiv[4] ^= 0xff;
397 tiv[5] ^= 0xff;
398 tiv[6] ^= 0xff;
399 tiv[7] ^= 0xff;
400 bcopy(&tiv[0], iv, 4);
401 iv = &tiv[0];
402 } else {
403 bcopy(iv, &tiv[0], 4);
404 bcopy(iv, &tiv[4], 4);
405 tiv[4] ^= 0xff;
406 tiv[5] ^= 0xff;
407 tiv[6] ^= 0xff;
408 tiv[7] ^= 0xff;
409 iv = &tiv[0];
410 }
411 } else if (ivlen == 8)
412 bcopy((caddr_t)sav->iv, (caddr_t)iv, ivlen);
413 else {
414 ipseclog((LOG_ERR,
415 "esp_descbc_encrypt: unsupported ivlen %d\n", ivlen));
416 return EINVAL;
417 }
418
419 {
420 int deserr;
421 des_key_schedule ks;
422
423 deserr = des_key_sched((C_Block *)_KEYBUF(sav->key_enc), ks);
424 if (deserr != 0) {
425 ipseclog((LOG_ERR,
426 "esp_descbc_encrypt: key error %d\n", deserr));
427 return EINVAL;
428 }
429
430 des_cbc_encrypt(m, bodyoff, plen, ks, (C_Block *)iv, DES_ENCRYPT);
431
432 /* for safety */
433 bzero(&ks, sizeof(des_key_schedule));
434 }
435
436 esp_increment_iv(sav);
437
438 /* for safety */
439 bzero(&tiv[0], sizeof(tiv));
440
441 return 0;
442}
443
444static int
445esp_cbc_mature(sav)
446 struct secasvar *sav;
447{
448 int keylen;
449 struct esp_algorithm *algo;
450
451 if (sav->flags & SADB_X_EXT_OLD) {
452 ipseclog((LOG_ERR,
453 "esp_cbc_mature: algorithm incompatible with esp-old\n"));
454 return 1;
455 }
456 if (sav->flags & SADB_X_EXT_DERIV) {
457 ipseclog((LOG_ERR,
458 "esp_cbc_mature: algorithm incompatible with derived\n"));
459 return 1;
460 }
461
462 if (!sav->key_enc) {
463 ipseclog((LOG_ERR,
464 "esp_cbc_mature: no key is given.\n"));
465 return 1;
466 }
467 algo = &esp_algorithms[sav->alg_enc];
468 keylen = sav->key_enc->sadb_key_bits;
469 if (keylen < algo->keymin || algo->keymax < keylen) {
470 ipseclog((LOG_ERR, "esp_cbc_mature: invalid key length %d.\n",
471 sav->key_enc->sadb_key_bits));
472 return 1;
473 }
474 switch (sav->alg_enc) {
475 case SADB_EALG_3DESCBC:
476 /* weak key check */
477 if (des_is_weak_key((C_Block *)_KEYBUF(sav->key_enc))
478 || des_is_weak_key((C_Block *)(_KEYBUF(sav->key_enc) + 8))
479 || des_is_weak_key((C_Block *)(_KEYBUF(sav->key_enc) + 16))) {
480 ipseclog((LOG_ERR,
481 "esp_cbc_mature: weak key was passed.\n"));
482 return 1;
483 }
484 break;
485 case SADB_EALG_BLOWFISHCBC:
486 case SADB_EALG_CAST128CBC:
487 case SADB_EALG_RC5CBC:
488 break;
489 }
490
491 return 0;
492}
493
494static int
495esp_blowfish_cbc_decrypt(m, off, sav, algo, ivlen)
496 struct mbuf *m;
497 size_t off; /* offset to ESP header */
498 struct secasvar *sav;
499 struct esp_algorithm *algo;
500 int ivlen;
501{
502 size_t ivoff;
503 size_t bodyoff;
504 u_int8_t *iv;
505 u_int8_t tiv[8];
506 size_t plen;
507 static BF_KEY key; /* made static to avoid kernel stack overflow */
508 int s;
509
510 /* sanity check */
511 if (sav->ivlen != ivlen) {
512 ipseclog((LOG_ERR,
513 "esp_blowfish_cbc_decrypt: bad ivlen %d/%d\n",
514 ivlen, sav->ivlen));
515 return EINVAL;
516 }
517 if (_KEYBITS(sav->key_enc) < algo->keymin
518 || algo->keymax < _KEYBITS(sav->key_enc)) {
519 ipseclog((LOG_ERR,
520 "esp_blowfish_cbc_decrypt: unsupported key length %d: "
521 "need %d to %d bits\n", _KEYBITS(sav->key_enc),
522 algo->keymin, algo->keymax));
523 return EINVAL;
524 }
525 if (sav->flags & SADB_X_EXT_OLD) {
526 ipseclog((LOG_ERR,
527 "esp_blowfish_cbc_decrypt: unsupported ESP version\n"));
528 return EINVAL;
529 }
530 if (ivlen != 8) {
531 ipseclog((LOG_ERR,
532 "esp_blowfish_cbc_decrypt: unsupported ivlen %d\n", ivlen));
533 return EINVAL;
534 }
535
536 ivoff = off + sizeof(struct newesp);
537 bodyoff = off + sizeof(struct newesp) + ivlen;
538 iv = &tiv[0];
539 m_copydata(m, ivoff, 8, &tiv[0]);
540
541 plen = m->m_pkthdr.len;
542 if (plen < bodyoff)
543 panic("esp_blowfish_cbc_decrypt: too short packet: len=%lu",
544 (u_long)plen);
545 plen -= bodyoff;
546
547 if (plen % 8) {
548 ipseclog((LOG_ERR, "esp_blowfish_cbc_decrypt: "
549 "payload length must be multiple of 8\n"));
550 return EINVAL;
551 }
552
553#if __NetBSD__
554 s = splsoftnet(); /* XXX correct? */
555#else
556 s = splnet(); /* XXX correct? */
557#endif
558
559 BF_set_key(&key, _KEYBITS(sav->key_enc) / 8, _KEYBUF(sav->key_enc));
560 BF_cbc_encrypt_m(m, bodyoff, plen, &key, iv, BF_DECRYPT);
561
562 /* for safety */
563 bzero(&key, sizeof(BF_KEY));
564
565 splx(s);
566
567 /* for safety */
568 bzero(&tiv[0], sizeof(tiv));
569
570 return 0;
571}
572
573static int
574esp_blowfish_cbc_encrypt(m, off, plen, sav, algo, ivlen)
575 struct mbuf *m;
576 size_t off; /* offset to ESP header */
577 size_t plen; /* payload length (to be decrypted) */
578 struct secasvar *sav;
579 struct esp_algorithm *algo;
580 int ivlen;
581{
582 size_t ivoff;
583 size_t bodyoff;
584 u_int8_t *iv;
585 static BF_KEY key; /* made static to avoid kernel stack overflow */
586 int s;
587
588 /* sanity check */
589 if (plen % 8) {
590 ipseclog((LOG_ERR, "esp_blowfish_cbc_encrypt: "
591 "payload length must be multiple of 8\n"));
592 return EINVAL;
593 }
594 if (sav->ivlen != ivlen) {
595 ipseclog((LOG_ERR,
596 "esp_blowfish_cbc_encrypt: bad ivlen %d/%d\n",
597 ivlen, sav->ivlen));
598 return EINVAL;
599 }
600 if (_KEYBITS(sav->key_enc) < algo->keymin
601 || algo->keymax < _KEYBITS(sav->key_enc)) {
602 ipseclog((LOG_ERR,
603 "esp_blowfish_cbc_encrypt: unsupported key length %d: "
604 "need %d to %d bits\n", _KEYBITS(sav->key_enc),
605 algo->keymin, algo->keymax));
606 return EINVAL;
607 }
608 if (sav->flags & SADB_X_EXT_OLD) {
609 ipseclog((LOG_ERR,
610 "esp_blowfish_cbc_encrypt: unsupported ESP version\n"));
611 return EINVAL;
612 }
613 if (ivlen != 8) {
614 ipseclog((LOG_ERR,
615 "esp_blowfish_cbc_encrypt: unsupported ivlen %d\n", ivlen));
616 return EINVAL;
617 }
618
619 ivoff = off + sizeof(struct newesp);
620 bodyoff = off + sizeof(struct newesp) + ivlen;
621
622 if (m->m_pkthdr.len < bodyoff)
623 panic("assumption failed: mbuf too short");
624 iv = mbuf_find_offset(m, ivoff, ivlen);
625 if (!iv)
626 panic("assumption failed: bad mbuf chain");
627
628 bcopy((caddr_t)sav->iv, (caddr_t)iv, ivlen);
629
630#if __NetBSD__
631 s = splsoftnet(); /* XXX correct? */
632#else
633 s = splnet(); /* XXX correct? */
634#endif
635
636 BF_set_key(&key, _KEYBITS(sav->key_enc) / 8, _KEYBUF(sav->key_enc));
637 BF_cbc_encrypt_m(m, bodyoff, plen, &key, iv, BF_ENCRYPT);
638
639 /* for safety */
640 bzero(&key, sizeof(BF_KEY));
641
642 splx(s);
643
644 esp_increment_iv(sav);
645
646 return 0;
647}
648
649static int
650esp_blowfish_cbc_ivlen(sav)
651 struct secasvar *sav;
652{
653 return 8;
654}
655
656static int
657esp_cast128cbc_ivlen(sav)
658 struct secasvar *sav;
659{
660 return 8;
661}
662
663static int
664esp_cast128cbc_decrypt(m, off, sav, algo, ivlen)
665 struct mbuf *m;
666 size_t off;
667 struct secasvar *sav;
668 struct esp_algorithm *algo;
669 int ivlen;
670{
671 size_t ivoff;
672 size_t bodyoff;
673 u_int8_t iv[8];
674 size_t plen;
675
676 /* sanity check */
677 if (ivlen != sav->ivlen) {
678 ipseclog((LOG_ERR, "esp_cast128cbc_decrypt: bad ivlen %d/%d\n",
679 ivlen, sav->ivlen));
680 return EINVAL;
681 }
682 if (_KEYBITS(sav->key_enc) < algo->keymin
683 || _KEYBITS(sav->key_enc) > algo->keymax) {
684 ipseclog((LOG_ERR,
685 "esp_cast128cbc_decrypt: unsupported key length %d: "
686 "need %d to %d bits\n", _KEYBITS(sav->key_enc),
687 algo->keymin, algo->keymax));
688 return EINVAL;
689 }
690 if (sav->flags & SADB_X_EXT_OLD) {
691 ipseclog((LOG_ERR,
692 "esp_cast128cbc_decrypt: unsupported ESP version\n"));
693 return EINVAL;
694 }
695 if (ivlen != 8) {
696 ipseclog((LOG_ERR,
697 "esp_cast128cbc_decrypt: unsupported ivlen %d\n", ivlen));
698 return EINVAL;
699 }
700
701 ivoff = off + sizeof(struct newesp);
702 bodyoff = off + sizeof(struct newesp) + ivlen;
703
704 /* copy mbuf's IV into iv */
705 m_copydata(m, ivoff, 8, iv);
706
707 plen = m->m_pkthdr.len;
708 if (plen < bodyoff) {
709 panic("esp_cast128cbc_decrypt: too short packet: len=%lu\n",
710 (u_long)plen);
711 }
712 plen -= bodyoff;
713
714 if (plen % 8) {
715 ipseclog((LOG_ERR, "esp_cast128cbc_decrypt: "
716 "payload length must be multiple of 8\n"));
717 return EINVAL;
718 }
719
720 /* decrypt */
721 {
722 u_int8_t key[16];
723 u_int32_t subkey[32];
724
725 bzero(key, sizeof(key));
726 bcopy(_KEYBUF(sav->key_enc), key, _KEYLEN(sav->key_enc));
727
728 set_cast128_subkey(subkey, key);
729 cast128_cbc_process(m, bodyoff, plen, subkey, iv,
730 _KEYBITS(sav->key_enc) / 8, CAST128_DECRYPT);
731
732 /* for safety */
733 bzero(subkey, sizeof(subkey));
734 bzero(key, sizeof(key));
735 }
736
737 return 0;
738}
739
740static int
741esp_cast128cbc_encrypt(m, off, plen, sav, algo, ivlen)
742 struct mbuf *m;
743 size_t off;
744 size_t plen;
745 struct secasvar *sav;
746 struct esp_algorithm *algo;
747 int ivlen;
748{
749 size_t ivoff;
750 size_t bodyoff;
751 u_int8_t *iv;
752
753 /* sanity check */
754 if (plen % 8) {
755 ipseclog((LOG_ERR, "esp_cast128cbc_encrypt: "
756 "payload length must be multiple of 8\n"));
757 return EINVAL;
758 }
759 if (sav->ivlen != ivlen) {
760 ipseclog((LOG_ERR, "esp_cast128cbc_encrypt: bad ivlen %d/%d\n",
761 ivlen, sav->ivlen));
762 return EINVAL;
763 }
764 if (_KEYBITS(sav->key_enc) < algo->keymin
765 || _KEYBITS(sav->key_enc) > algo->keymax) {
766 ipseclog((LOG_ERR,
767 "esp_cast128cbc_encrypt: unsupported key length %d: "
768 "needs %d to %d bits\n", _KEYBITS(sav->key_enc),
769 algo->keymin, algo->keymax));
770 return EINVAL;
771 }
772 if (sav->flags & SADB_X_EXT_OLD) {
773 ipseclog((LOG_ERR,
774 "esp_cast128cbc_encrypt: unsupported ESP version\n"));
775 return EINVAL;
776 }
777 if (ivlen != 8) {
778 ipseclog((LOG_ERR,
779 "esp_cast128cbc_encrypt: unsupported ivlen %d\n", ivlen));
780 return EINVAL;
781 }
782
783 ivoff = off + sizeof(struct newesp);
784 bodyoff = off + sizeof(struct newesp) + ivlen;
785
786 if (m->m_pkthdr.len < bodyoff)
787 panic("assumption failed: mbuf too short");
788 iv = mbuf_find_offset(m, ivoff, ivlen);
789 if (!iv)
790 panic("assumption failed: bad mbuf chain");
791
792 bcopy(sav->iv, iv, ivlen);
793
794 /* encrypt */
795 {
796 u_int8_t key[16];
797 u_int32_t subkey[32];
798
799 bzero(key, sizeof(key));
800 bcopy(_KEYBUF(sav->key_enc), key, _KEYLEN(sav->key_enc));
801
802 set_cast128_subkey(subkey, key);
803 cast128_cbc_process(m, bodyoff, plen, subkey, iv,
804 _KEYBITS(sav->key_enc) / 8, CAST128_ENCRYPT);
805
806 /* for safety */
807 bzero(subkey, sizeof(subkey));
808 bzero(key, sizeof(key));
809 }
810
811 esp_increment_iv(sav);
812
813 return 0;
814}
815
816static int
817esp_3descbc_ivlen(sav)
818 struct secasvar *sav;
819{
820 return 8;
821}
822
823static int
824esp_3descbc_decrypt(m, off, sav, algo, ivlen)
825 struct mbuf *m;
826 size_t off;
827 struct secasvar *sav;
828 struct esp_algorithm *algo;
829 int ivlen;
830{
831 size_t ivoff;
832 size_t bodyoff;
833 u_int8_t *iv;
834 size_t plen;
835 u_int8_t tiv[8];
836
837 /* sanity check */
838 if (ivlen != sav->ivlen) {
839 ipseclog((LOG_ERR, "esp_3descbc_decrypt: bad ivlen %d/%d\n",
840 ivlen, sav->ivlen));
841 return EINVAL;
842 }
843 if (_KEYBITS(sav->key_enc) < algo->keymin
844 || algo->keymax < _KEYBITS(sav->key_enc)) {
845 ipseclog((LOG_ERR, "esp_3descbc_decrypt: bad keylen %d\n",
846 _KEYBITS(sav->key_enc)));
847 return EINVAL;
848 }
849 if (sav->flags & SADB_X_EXT_OLD) {
850 ipseclog((LOG_ERR,
851 "esp_3descbc_decrypt: unsupported ESP version\n"));
852 return EINVAL;
853 }
854 if (ivlen != 8) {
855 ipseclog((LOG_ERR,
856 "esp_3descbc_decrypt: unsupported ivlen %d\n", ivlen));
857 return EINVAL;
858 }
859
860 ivoff = off + sizeof(struct newesp);
861 bodyoff = off + sizeof(struct newesp) + ivlen;
862 iv = &tiv[0];
863 m_copydata(m, ivoff, 8, &tiv[0]);
864
865 plen = m->m_pkthdr.len;
866 if (plen < bodyoff)
867 panic("esp_3descbc_decrypt: too short packet: len=%lu",
868 (u_long)plen);
869
870 plen -= bodyoff;
871
872 if (plen % 8) {
873 ipseclog((LOG_ERR, "esp_3descbc_decrypt: "
874 "payload length must be multiple of 8\n"));
875 return EINVAL;
876 }
877
878 /* decrypt packet */
879 {
880 int deserr[3];
881 des_key_schedule ks[3];
882
883 deserr[0] = des_key_sched((C_Block *)_KEYBUF(sav->key_enc),ks[0]);
884 deserr[1] = des_key_sched((C_Block *)(_KEYBUF(sav->key_enc) + 8), ks[1]);
885 deserr[2] = des_key_sched((C_Block *)(_KEYBUF(sav->key_enc) + 16), ks[2]);
886 if ((deserr[0] != 0) || (deserr[1] != 0) || (deserr[2] != 0)) {
887 ipseclog((LOG_ERR, "esp_3descbc_decrypt: key error %d/%d/%d\n",
888 deserr[0], deserr[1], deserr[2]));
889 return EINVAL;
890 }
891
892 des_3cbc_process(m, bodyoff, plen, ks, (C_Block *)iv, DES_DECRYPT);
893
894 /* for safety */
895 bzero(ks[0], sizeof(des_key_schedule)*3);
896 }
897
898 /* for safety */
899 bzero(&tiv[0], sizeof(tiv));
900
901 return 0;
902}
903
904static int
905esp_3descbc_encrypt(m, off, plen, sav, algo, ivlen)
906 struct mbuf *m;
907 size_t off;
908 size_t plen;
909 struct secasvar *sav;
910 struct esp_algorithm *algo;
911 int ivlen;
912{
913 size_t ivoff;
914 size_t bodyoff;
915 u_int8_t *iv;
916
917 /* sanity check */
918 if (plen % 8) {
919 ipseclog((LOG_ERR, "esp_3descbc_encrypt: "
920 "payload length must be multiple of 8\n"));
921 return EINVAL;
922 }
923 if (sav->ivlen != ivlen) {
924 ipseclog((LOG_ERR, "esp_3descbc_encrypt: bad ivlen %d/%d\n",
925 ivlen, sav->ivlen));
926 return EINVAL;
927 }
928 if (_KEYBITS(sav->key_enc) < algo->keymin
929 || algo->keymax < _KEYBITS(sav->key_enc)) {
930 ipseclog((LOG_ERR, "esp_3descbc_encrypt: bad keylen %d\n",
931 _KEYBITS(sav->key_enc)));
932 return EINVAL;
933 }
934 if (sav->flags & SADB_X_EXT_OLD) {
935 ipseclog((LOG_ERR,
936 "esp_3descbc_encrypt: unsupported ESP version\n"));
937 return EINVAL;
938 }
939 if (ivlen != 8) {
940 ipseclog((LOG_ERR,
941 "esp_3descbc_encrypt: unsupported ivlen %d\n", ivlen));
942 return EINVAL;
943 }
944
945 ivoff = off + sizeof(struct newesp);
946 bodyoff = off + sizeof(struct newesp) + ivlen;
947
948 if (m->m_pkthdr.len < bodyoff)
949 panic("assumption failed: mbuf too short");
950 iv = mbuf_find_offset(m, ivoff, ivlen);
951 if (!iv)
952 panic("assumption failed: bad mbuf chain");
953
954 bcopy((caddr_t)sav->iv, (caddr_t)iv, ivlen);
955
956 /* encrypt packet */
957 {
958 int deserr[3];
959 des_key_schedule ks[3];
960
961 deserr[0] = des_key_sched((C_Block *)_KEYBUF(sav->key_enc), ks[0]);
962 deserr[1] = des_key_sched((C_Block *)(_KEYBUF(sav->key_enc) + 8), ks[1]);
963 deserr[2] = des_key_sched((C_Block *)(_KEYBUF(sav->key_enc) + 16), ks[2]);
964 if ((deserr[0] != 0) || (deserr[1] != 0) || (deserr[2] != 0)) {
965 ipseclog((LOG_ERR, "esp_3descbc_encrypt: key error %d/%d/%d\n",
966 deserr[0], deserr[1], deserr[2]));
967 return EINVAL;
968 }
969
970 des_3cbc_process(m, bodyoff, plen, ks, (C_Block *)iv, DES_ENCRYPT);
971
972 /* for safety */
973 bzero(ks[0], sizeof(des_key_schedule)*3);
974 }
975
976 esp_increment_iv(sav);
977
978 return 0;
979}
980
981static int
982esp_rc5cbc_ivlen(sav)
983 struct secasvar *sav;
984{
985 return 8;
986}
987
988static int
989esp_rc5cbc_decrypt(m, off, sav, algo, ivlen)
990 struct mbuf *m;
991 size_t off;
992 struct secasvar *sav;
993 struct esp_algorithm *algo;
994 int ivlen;
995{
996 size_t ivoff;
997 size_t bodyoff;
998 u_int8_t iv[8];
999 size_t plen;
1000
1001 /* sanity check */
1002 if (sav->ivlen != ivlen) {
1003 ipseclog((LOG_ERR, "esp_rc5cbc_decrypt: bad ivlen %d/%d\n",
1004 ivlen, sav->ivlen));
1005 return EINVAL;
1006 }
1007 if ((_KEYBITS(sav->key_enc) < 40) || (_KEYBITS(sav->key_enc) > 2040)) {
1008 ipseclog((LOG_ERR,
1009 "esp_rc5cbc_decrypt: unsupported key length %d: "
1010 "need 40 to 2040 bit\n", _KEYBITS(sav->key_enc)));
1011 return EINVAL;
1012 }
1013 if (sav->flags & SADB_X_EXT_OLD) {
1014 ipseclog((LOG_ERR,
1015 "esp_rc5cbc_decrypt: unsupported ESP version\n"));
1016 return EINVAL;
1017 }
1018 if (ivlen != 8) {
1019 ipseclog((LOG_ERR, "esp_rc5cbc_decrypt: unsupported ivlen %d\n",
1020 ivlen));
1021 return EINVAL;
1022 }
1023
1024 ivoff = off + sizeof(struct newesp);
1025 bodyoff = off + sizeof(struct newesp) + ivlen;
1026
1027 /* copy mbuf's IV into iv */
1028 m_copydata(m, ivoff, 8, iv);
1029
1030 plen = m->m_pkthdr.len;
1031 if (plen < bodyoff) {
1032 panic("esp_rc5cbc_decrypt: too short packet: len=%lu",
1033 (u_long)plen);
1034 }
1035 plen -= bodyoff;
1036
1037 if (plen % 8) {
1038 ipseclog((LOG_ERR, "esp_rc5cbc_decrypt: "
1039 "payload length must be multiple of 8\n"));
1040 return EINVAL;
1041 }
1042
1043 /* decrypt */
1044 {
1045 RC5_WORD e_key[34];
1046
1047 set_rc5_expandkey(e_key, _KEYBUF(sav->key_enc),
1048 _KEYBITS(sav->key_enc) / 8, 16);
1049 rc5_cbc_process(m, bodyoff, plen, e_key, iv, RC5_DECRYPT);
1050
1051 /* for safety */
1052 bzero(e_key, sizeof(e_key));
1053 }
1054
1055 return 0;
1056}
1057
1058static int
1059esp_rc5cbc_encrypt(m, off, plen, sav, algo, ivlen)
1060 struct mbuf *m;
1061 size_t off;
1062 size_t plen;
1063 struct secasvar *sav;
1064 struct esp_algorithm *algo;
1065 int ivlen;
1066{
1067 size_t ivoff;
1068 size_t bodyoff;
1069 u_int8_t *iv;
1070
1071 /* sanity check */
1072 if (plen % 8) {
1073 ipseclog((LOG_ERR, "esp_rc5cbc_encrypt: "
1074 "payload length must be multiple of 8\n"));
1075 return EINVAL;
1076 }
1077 if (sav->ivlen != ivlen) {
1078 ipseclog((LOG_ERR, "esp_rc5cbc_encrypt: bad ivlen %d/%d\n",
1079 ivlen, sav->ivlen));
1080 return EINVAL;
1081 }
1082 if (_KEYBITS(sav->key_enc) < algo->keymin
1083 || _KEYBITS(sav->key_enc) > algo->keymax) {
1084 ipseclog((LOG_ERR,
1085 "esp_rc5cbc_encrypt: unsupported key length %d: "
1086 "need %d to %d bits\n", _KEYBITS(sav->key_enc),
1087 algo->keymin, algo->keymax));
1088 return EINVAL;
1089 }
1090 if (sav->flags & SADB_X_EXT_OLD) {
1091 ipseclog((LOG_ERR,
1092 "esp_rc5cbc_encrypt: unsupported ESP version\n"));
1093 return EINVAL;
1094 }
1095 if (ivlen != 8) {
1096 ipseclog((LOG_ERR, "esp_rc5cbc_encrypt: unsupported ivlen %d\n",
1097 ivlen));
1098 return EINVAL;
1099 }
1100
1101 ivoff = off + sizeof(struct newesp);
1102 bodyoff = off + sizeof(struct newesp) + ivlen;
1103
1104 if (m->m_pkthdr.len < bodyoff)
1105 panic("assumption failed: mbuf too short");
1106 iv = mbuf_find_offset(m, ivoff, ivlen);
1107 if (!iv)
1108 panic("assumption failed: bad mbuf chain");
1109
1110 bcopy(sav->iv, iv, ivlen);
1111
1112 /* encrypt */
1113 {
1114 RC5_WORD e_key[34];
1115
1116 set_rc5_expandkey(e_key, _KEYBUF(sav->key_enc),
1117 _KEYBITS(sav->key_enc) / 8, 16);
1118 rc5_cbc_process(m, bodyoff, plen, e_key, iv, RC5_ENCRYPT);
1119
1120 /* for safety */
1121 bzero(e_key, sizeof(e_key));
1122 }
1123
1124 esp_increment_iv(sav);
1125
1126 return 0;
1127}
1128
1129/*
1130 * increment iv.
1131 */
1132static void
1133esp_increment_iv(sav)
1134 struct secasvar *sav;
1135{
1136 u_int8_t *x;
1137 u_int8_t y;
1138 int i;
1139
1140#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
1141 y = time.tv_sec & 0xff;
1142#else
1143 y = time_second & 0xff;
1144#endif
1145 if (!y) y++;
1146 x = (u_int8_t *)sav->iv;
1147 for (i = 0; i < sav->ivlen; i++) {
1148 *x = (*x + y) & 0xff;
1149 x++;
1150 }
1151}
1152
1153static caddr_t
1154mbuf_find_offset(m, off, len)
1155 struct mbuf *m;
1156 size_t off;
1157 size_t len;
1158{
1159 struct mbuf *n;
1160 size_t cnt;
1161
1162 if (m->m_pkthdr.len < off || m->m_pkthdr.len < off + len)
1163 return (caddr_t)NULL;
1164 cnt = 0;
1165 for (n = m; n; n = n->m_next) {
1166 if (cnt + n->m_len <= off) {
1167 cnt += n->m_len;
1168 continue;
1169 }
1170 if (cnt <= off && off < cnt + n->m_len
1171 && cnt <= off + len && off + len <= cnt + n->m_len) {
1172 return mtod(n, caddr_t) + off - cnt;
1173 } else
1174 return (caddr_t)NULL;
1175 }
1176 return (caddr_t)NULL;
1177}
1178
1179/*------------------------------------------------------------*/
1180
1181int
1182esp_auth(m0, skip, length, sav, sum)
1183 struct mbuf *m0;
1184 size_t skip; /* offset to ESP header */
1185 size_t length; /* payload length */
1186 struct secasvar *sav;
1187 u_char *sum;
1188{
1189 struct mbuf *m;
1190 size_t off;
1191 struct ah_algorithm_state s;
1192 u_char sumbuf[AH_MAXSUMSIZE];
1193 struct ah_algorithm *algo;
1194 size_t siz;
1195
1196 /* sanity checks */
1197 if (m0->m_pkthdr.len < skip) {
1198 ipseclog((LOG_DEBUG, "esp_auth: mbuf length < skip\n"));
1199 return EINVAL;
1200 }
1201 if (m0->m_pkthdr.len < skip + length) {
1202 ipseclog((LOG_DEBUG,
1203 "esp_auth: mbuf length < skip + length\n"));
1204 return EINVAL;
1205 }
1206 /*
1207 * length of esp part (excluding authentication data) must be 4n,
1208 * since nexthdr must be at offset 4n+3.
1209 */
1210 if (length % 4) {
1211 ipseclog((LOG_ERR, "esp_auth: length is not multiple of 4\n"));
1212 return EINVAL;
1213 }
1214 if (!sav) {
1215 ipseclog((LOG_DEBUG, "esp_auth: NULL SA passed\n"));
1216 return EINVAL;
1217 }
1218 if (!sav->alg_auth) {
1219 ipseclog((LOG_ERR,
1220 "esp_auth: bad ESP auth algorithm passed: %d\n",
1221 sav->alg_auth));
1222 return EINVAL;
1223 }
1224
1225 m = m0;
1226 off = 0;
1227
1228 algo = &ah_algorithms[sav->alg_auth];
1229 siz = (((*algo->sumsiz)(sav) + 3) & ~(4 - 1));
1230 if (sizeof(sumbuf) < siz) {
1231 ipseclog((LOG_DEBUG,
1232 "esp_auth: AH_MAXSUMSIZE is too small: siz=%lu\n",
1233 (u_long)siz));
1234 return EINVAL;
1235 }
1236
1237 /* skip the header */
1238 while (skip) {
1239 if (!m)
1240 panic("mbuf chain?");
1241 if (m->m_len <= skip) {
1242 skip -= m->m_len;
1243 m = m->m_next;
1244 off = 0;
1245 } else {
1246 off = skip;
1247 skip = 0;
1248 }
1249 }
1250
1251 (*algo->init)(&s, sav);
1252 while (0 < length) {
1253 if (!m)
1254 panic("mbuf chain?");
1255
1256 if (m->m_len - off < length) {
1257 (*algo->update)(&s, mtod(m, u_char *) + off,
1258 m->m_len - off);
1259 length -= m->m_len - off;
1260 m = m->m_next;
1261 off = 0;
1262 } else {
1263 (*algo->update)(&s, mtod(m, u_char *) + off, length);
1264 break;
1265 }
1266 }
1267 (*algo->result)(&s, sumbuf);
1268 bcopy(sumbuf, sum, siz); /*XXX*/
1269
1270 return 0;
1271}