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 $ */
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/malloc.h>
39 #include <sys/domain.h>
40 #include <sys/protosw.h>
41 #include <sys/socket.h>
42 #include <sys/errno.h>
44 #include <sys/kernel.h>
45 #include <sys/syslog.h>
48 #include <net/route.h>
50 #include <netinet/in.h>
51 #include <netinet/in_var.h>
53 #include <netinet/ip6.h>
54 #include <netinet6/ip6_var.h>
55 #include <netinet/icmp6.h>
58 #include <netinet6/ipsec.h>
60 #include <netinet6/ipsec6.h>
62 #include <netinet6/ah.h>
64 #include <netinet6/ah6.h>
66 #include <netinet6/esp.h>
68 #include <netinet6/esp6.h>
70 #include <netinet6/esp_rijndael.h>
71 #include <net/pfkeyv2.h>
72 #include <netkey/keydb.h>
73 #include <netkey/key.h>
74 #include <crypto/des/des.h>
75 #include <crypto/blowfish/blowfish.h>
76 #include <crypto/cast128/cast128.h>
78 #include <net/net_osdep.h>
80 static int esp_null_mature
__P((struct secasvar
*));
81 static int esp_null_decrypt
__P((struct mbuf
*, size_t,
82 struct secasvar
*, const struct esp_algorithm
*, int));
83 static int esp_null_encrypt
__P((struct mbuf
*, size_t, size_t,
84 struct secasvar
*, const struct esp_algorithm
*, int));
85 static int esp_descbc_mature
__P((struct secasvar
*));
86 static int esp_descbc_ivlen
__P((const struct esp_algorithm
*,
88 static int esp_des_schedule
__P((const struct esp_algorithm
*,
90 static int esp_des_schedlen
__P((const struct esp_algorithm
*));
91 static int esp_des_blockdecrypt
__P((const struct esp_algorithm
*,
92 struct secasvar
*, u_int8_t
*, u_int8_t
*));
93 static int esp_des_blockencrypt
__P((const struct esp_algorithm
*,
94 struct secasvar
*, u_int8_t
*, u_int8_t
*));
95 static int esp_cbc_mature
__P((struct secasvar
*));
96 static int esp_blowfish_schedule
__P((const struct esp_algorithm
*,
98 static int esp_blowfish_schedlen
__P((const struct esp_algorithm
*));
99 static int esp_blowfish_blockdecrypt
__P((const struct esp_algorithm
*,
100 struct secasvar
*, u_int8_t
*, u_int8_t
*));
101 static int esp_blowfish_blockencrypt
__P((const struct esp_algorithm
*,
102 struct secasvar
*, u_int8_t
*, u_int8_t
*));
103 static int esp_cast128_schedule
__P((const struct esp_algorithm
*,
105 static int esp_cast128_schedlen
__P((const struct esp_algorithm
*));
106 static int esp_cast128_blockdecrypt
__P((const struct esp_algorithm
*,
107 struct secasvar
*, u_int8_t
*, u_int8_t
*));
108 static int esp_cast128_blockencrypt
__P((const struct esp_algorithm
*,
109 struct secasvar
*, u_int8_t
*, u_int8_t
*));
110 static int esp_3des_schedule
__P((const struct esp_algorithm
*,
112 static int esp_3des_schedlen
__P((const struct esp_algorithm
*));
113 static int esp_3des_blockdecrypt
__P((const struct esp_algorithm
*,
114 struct secasvar
*, u_int8_t
*, u_int8_t
*));
115 static int esp_3des_blockencrypt
__P((const struct esp_algorithm
*,
116 struct secasvar
*, u_int8_t
*, u_int8_t
*));
117 static int esp_common_ivlen
__P((const struct esp_algorithm
*,
119 static int esp_cbc_decrypt
__P((struct mbuf
*, size_t,
120 struct secasvar
*, const struct esp_algorithm
*, int));
121 static int esp_cbc_encrypt
__P((struct mbuf
*, size_t, size_t,
122 struct secasvar
*, const struct esp_algorithm
*, int));
126 static const struct esp_algorithm esp_algorithms
[] = {
127 { 8, -1, esp_descbc_mature
, 64, 64, esp_des_schedlen
,
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
,
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
,
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
,
151 esp_common_ivlen
, esp_cbc_decrypt
,
152 esp_cbc_encrypt
, esp_rijndael_schedule
,
153 esp_rijndael_blockdecrypt
, esp_rijndael_blockencrypt
},
156 const struct esp_algorithm
*
157 esp_algorithm_lookup(idx
)
162 case SADB_EALG_DESCBC
:
163 return &esp_algorithms
[0];
164 case SADB_EALG_3DESCBC
:
165 return &esp_algorithms
[1];
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];
186 for (idx
= 0; idx
< sizeof(esp_algorithms
)/sizeof(esp_algorithms
[0]);
188 if (esp_algorithms
[idx
].ivlenval
> ivlen
)
189 ivlen
= esp_algorithms
[idx
].ivlenval
;
196 esp_schedule(algo
, sav
)
197 const struct esp_algorithm
*algo
;
198 struct secasvar
*sav
;
202 /* check for key length */
203 if (_KEYBITS(sav
->key_enc
) < algo
->keymin
||
204 _KEYBITS(sav
->key_enc
) > algo
->keymax
) {
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
));
212 /* already allocated */
213 if (sav
->sched
&& sav
->schedlen
!= 0)
215 /* no schedule necessary */
216 if (!algo
->schedule
|| !algo
->schedlen
)
219 sav
->schedlen
= (*algo
->schedlen
)(algo
);
220 if (sav
->schedlen
< 0)
222 sav
->sched
= _MALLOC(sav
->schedlen
, M_SECA
, M_DONTWAIT
);
228 error
= (*algo
->schedule
)(algo
, sav
);
230 ipseclog((LOG_ERR
, "esp_schedule %s: error %d\n",
232 FREE(sav
->sched
, M_SECA
);
241 struct secasvar
*sav
;
244 /* anything is okay */
249 esp_null_decrypt(m
, off
, sav
, algo
, ivlen
)
251 size_t off
; /* offset to ESP header */
252 struct secasvar
*sav
;
253 const struct esp_algorithm
*algo
;
257 return 0; /* do nothing */
261 esp_null_encrypt(m
, off
, plen
, sav
, algo
, ivlen
)
263 size_t off
; /* offset to ESP header */
264 size_t plen
; /* payload length (to be encrypted) */
265 struct secasvar
*sav
;
266 const struct esp_algorithm
*algo
;
270 return 0; /* do nothing */
274 esp_descbc_mature(sav
)
275 struct secasvar
*sav
;
277 const struct esp_algorithm
*algo
;
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"));
286 ipseclog((LOG_ERR
, "esp_descbc_mature: no key is given.\n"));
290 algo
= esp_algorithm_lookup(sav
->alg_enc
);
293 "esp_descbc_mature: unsupported algorithm.\n"));
297 if (_KEYBITS(sav
->key_enc
) < algo
->keymin
||
298 _KEYBITS(sav
->key_enc
) > algo
->keymax
) {
300 "esp_descbc_mature: invalid key length %d.\n",
301 _KEYBITS(sav
->key_enc
)));
306 if (des_is_weak_key((des_cblock
*)_KEYBUF(sav
->key_enc
))) {
308 "esp_descbc_mature: weak key was passed.\n"));
316 esp_descbc_ivlen(algo
, sav
)
317 const struct esp_algorithm
*algo
;
318 struct secasvar
*sav
;
323 if ((sav
->flags
& SADB_X_EXT_OLD
) && (sav
->flags
& SADB_X_EXT_IV4B
))
325 if (!(sav
->flags
& SADB_X_EXT_OLD
) && (sav
->flags
& SADB_X_EXT_DERIV
))
331 esp_des_schedlen(algo
)
332 const struct esp_algorithm
*algo
;
335 return sizeof(des_key_schedule
);
339 esp_des_schedule(algo
, sav
)
340 const struct esp_algorithm
*algo
;
341 struct secasvar
*sav
;
344 if (des_key_sched((des_cblock
*)_KEYBUF(sav
->key_enc
),
345 *(des_key_schedule
*)sav
->sched
))
352 esp_des_blockdecrypt(algo
, sav
, s
, d
)
353 const struct esp_algorithm
*algo
;
354 struct secasvar
*sav
;
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
);
367 esp_des_blockencrypt(algo
, sav
, s
, d
)
368 const struct esp_algorithm
*algo
;
369 struct secasvar
*sav
;
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
);
383 struct secasvar
*sav
;
386 const struct esp_algorithm
*algo
;
388 if (sav
->flags
& SADB_X_EXT_OLD
) {
390 "esp_cbc_mature: algorithm incompatible with esp-old\n"));
393 if (sav
->flags
& SADB_X_EXT_DERIV
) {
395 "esp_cbc_mature: algorithm incompatible with derived\n"));
400 ipseclog((LOG_ERR
, "esp_cbc_mature: no key is given.\n"));
404 algo
= esp_algorithm_lookup(sav
->alg_enc
);
407 "esp_cbc_mature %s: unsupported algorithm.\n", algo
->name
));
411 keylen
= sav
->key_enc
->sadb_key_bits
;
412 if (keylen
< algo
->keymin
|| algo
->keymax
< keylen
) {
414 "esp_cbc_mature %s: invalid key length %d.\n",
415 algo
->name
, sav
->key_enc
->sadb_key_bits
));
418 switch (sav
->alg_enc
) {
419 case SADB_EALG_3DESCBC
:
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))) {
425 "esp_cbc_mature %s: weak key was passed.\n",
430 case SADB_X_EALG_BLOWFISHCBC
:
431 case SADB_X_EALG_CAST128CBC
:
433 case SADB_X_EALG_RIJNDAELCBC
:
434 /* allows specific key sizes only */
435 if (!(keylen
== 128 || keylen
== 192 || keylen
== 256)) {
437 "esp_cbc_mature %s: invalid key length %d.\n",
438 algo
->name
, keylen
));
448 esp_blowfish_schedlen(algo
)
449 const struct esp_algorithm
*algo
;
452 return sizeof(BF_KEY
);
456 esp_blowfish_schedule(algo
, sav
)
457 const struct esp_algorithm
*algo
;
458 struct secasvar
*sav
;
461 BF_set_key((BF_KEY
*)sav
->sched
, _KEYLEN(sav
->key_enc
),
462 _KEYBUF(sav
->key_enc
));
467 esp_blowfish_blockdecrypt(algo
, sav
, s
, d
)
468 const struct esp_algorithm
*algo
;
469 struct secasvar
*sav
;
473 /* HOLY COW! BF_encrypt() takes values in host byteorder */
476 bcopy(s
, t
, sizeof(t
));
479 BF_encrypt(t
, (BF_KEY
*)sav
->sched
, BF_DECRYPT
);
482 bcopy(t
, d
, sizeof(t
));
487 esp_blowfish_blockencrypt(algo
, sav
, s
, d
)
488 const struct esp_algorithm
*algo
;
489 struct secasvar
*sav
;
493 /* HOLY COW! BF_encrypt() takes values in host byteorder */
496 bcopy(s
, t
, sizeof(t
));
499 BF_encrypt(t
, (BF_KEY
*)sav
->sched
, BF_ENCRYPT
);
502 bcopy(t
, d
, sizeof(t
));
507 esp_cast128_schedlen(algo
)
508 const struct esp_algorithm
*algo
;
511 return sizeof(u_int32_t
) * 32;
515 esp_cast128_schedule(algo
, sav
)
516 const struct esp_algorithm
*algo
;
517 struct secasvar
*sav
;
520 set_cast128_subkey((u_int32_t
*)sav
->sched
, _KEYBUF(sav
->key_enc
),
521 _KEYLEN(sav
->key_enc
));
526 esp_cast128_blockdecrypt(algo
, sav
, s
, d
)
527 const struct esp_algorithm
*algo
;
528 struct secasvar
*sav
;
533 if (_KEYLEN(sav
->key_enc
) <= 80 / 8)
534 cast128_decrypt_round12(d
, s
, (u_int32_t
*)sav
->sched
);
536 cast128_decrypt_round16(d
, s
, (u_int32_t
*)sav
->sched
);
541 esp_cast128_blockencrypt(algo
, sav
, s
, d
)
542 const struct esp_algorithm
*algo
;
543 struct secasvar
*sav
;
548 if (_KEYLEN(sav
->key_enc
) <= 80 / 8)
549 cast128_encrypt_round12(d
, s
, (u_int32_t
*)sav
->sched
);
551 cast128_encrypt_round16(d
, s
, (u_int32_t
*)sav
->sched
);
556 esp_3des_schedlen(algo
)
557 const struct esp_algorithm
*algo
;
560 return sizeof(des_key_schedule
) * 3;
564 esp_3des_schedule(algo
, sav
)
565 const struct esp_algorithm
*algo
;
566 struct secasvar
*sav
;
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
]);
584 esp_3des_blockdecrypt(algo
, sav
, s
, d
)
585 const struct esp_algorithm
*algo
;
586 struct secasvar
*sav
;
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
);
602 esp_3des_blockencrypt(algo
, sav
, s
, d
)
603 const struct esp_algorithm
*algo
;
604 struct secasvar
*sav
;
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
);
620 esp_common_ivlen(algo
, sav
)
621 const struct esp_algorithm
*algo
;
622 struct secasvar
*sav
;
626 panic("esp_common_ivlen: unknown algorithm");
627 return algo
->ivlenval
;
631 esp_cbc_decrypt(m
, off
, sav
, algo
, ivlen
)
634 struct secasvar
*sav
;
635 const struct esp_algorithm
*algo
;
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
;
652 if (ivlen
!= sav
->ivlen
|| ivlen
> sizeof(iv
)) {
653 ipseclog((LOG_ERR
, "esp_cbc_decrypt %s: "
654 "unsupported ivlen %d\n", algo
->name
, ivlen
));
659 /* assumes blocklen == padbound */
660 blocklen
= algo
->padbound
;
663 if (blocklen
> sizeof(iv
)) {
664 ipseclog((LOG_ERR
, "esp_cbc_decrypt %s: "
665 "unsupported blocklen %d\n", algo
->name
, blocklen
));
671 if (sav
->flags
& SADB_X_EXT_OLD
) {
673 ivoff
= off
+ sizeof(struct esp
);
674 bodyoff
= off
+ sizeof(struct esp
) + ivlen
;
678 if (sav
->flags
& SADB_X_EXT_DERIV
) {
680 * draft-ietf-ipsec-ciph-des-derived-00.txt
681 * uses sequence number field as IV field.
683 ivoff
= off
+ sizeof(struct esp
);
684 bodyoff
= off
+ sizeof(struct esp
) + sizeof(u_int32_t
);
685 ivlen
= sizeof(u_int32_t
);
688 ivoff
= off
+ sizeof(struct newesp
);
689 bodyoff
= off
+ sizeof(struct newesp
) + ivlen
;
695 m_copydata(m
, ivoff
, ivlen
, iv
);
698 if (ivlen
== blocklen
)
700 else if (ivlen
== 4 && blocklen
== 8) {
701 bcopy(&iv
[0], &iv
[4], 4);
707 ipseclog((LOG_ERR
, "esp_cbc_encrypt %s: "
708 "unsupported ivlen/blocklen: %d %d\n",
709 algo
->name
, ivlen
, blocklen
));
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
));
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
));
730 soff
= doff
= sn
= dn
= 0;
734 while (soff
< bodyoff
) {
735 if (soff
+ s
->m_len
> bodyoff
) {
746 /* skip over empty mbuf */
747 while (s
&& s
->m_len
== 0)
750 while (soff
< m
->m_pkthdr
.len
) {
752 if (sn
+ blocklen
<= s
->m_len
) {
753 /* body is continuous */
754 sp
= mtod(s
, u_int8_t
*) + sn
;
756 /* body is non-continuous */
757 m_copydata(s
, sn
, blocklen
, sbuf
);
762 if (!d
|| dn
+ blocklen
> d
->m_len
) {
765 MGET(d
, M_DONTWAIT
, MT_DATA
);
766 i
= m
->m_pkthdr
.len
- (soff
+ sn
);
768 MCLGET(d
, M_DONTWAIT
);
769 if ((d
->m_flags
& M_EXT
) == 0) {
785 d
->m_len
= (M_TRAILINGSPACE(d
) / blocklen
) * blocklen
;
792 (*algo
->blockdecrypt
)(algo
, sav
, sp
, mtod(d
, u_int8_t
*) + dn
);
796 q
= mtod(d
, u_int8_t
*) + dn
;
797 for (i
= 0; i
< blocklen
; i
++)
802 bcopy(sbuf
, iv
, blocklen
);
810 /* find the next source block */
811 while (s
&& sn
>= s
->m_len
) {
817 /* skip over empty mbuf */
818 while (s
&& s
->m_len
== 0)
822 m_freem(scut
->m_next
);
823 scut
->m_len
= scutoff
;
827 bzero(iv
, sizeof(iv
));
828 bzero(sbuf
, sizeof(sbuf
));
834 esp_cbc_encrypt(m
, off
, plen
, sav
, algo
, ivlen
)
838 struct secasvar
*sav
;
839 const struct esp_algorithm
*algo
;
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
;
856 if (ivlen
!= sav
->ivlen
|| ivlen
> sizeof(iv
)) {
857 ipseclog((LOG_ERR
, "esp_cbc_encrypt %s: "
858 "unsupported ivlen %d\n", algo
->name
, ivlen
));
863 /* assumes blocklen == padbound */
864 blocklen
= algo
->padbound
;
867 if (blocklen
> sizeof(iv
)) {
868 ipseclog((LOG_ERR
, "esp_cbc_encrypt %s: "
869 "unsupported blocklen %d\n", algo
->name
, blocklen
));
875 if (sav
->flags
& SADB_X_EXT_OLD
) {
877 ivoff
= off
+ sizeof(struct esp
);
878 bodyoff
= off
+ sizeof(struct esp
) + ivlen
;
882 if (sav
->flags
& SADB_X_EXT_DERIV
) {
884 * draft-ietf-ipsec-ciph-des-derived-00.txt
885 * uses sequence number field as IV field.
887 ivoff
= off
+ sizeof(struct esp
);
888 bodyoff
= off
+ sizeof(struct esp
) + sizeof(u_int32_t
);
889 ivlen
= sizeof(u_int32_t
);
892 ivoff
= off
+ sizeof(struct newesp
);
893 bodyoff
= off
+ sizeof(struct newesp
) + ivlen
;
898 /* put iv into the packet. if we are in derived mode, use seqno. */
900 m_copydata(m
, ivoff
, ivlen
, iv
);
902 bcopy(sav
->iv
, iv
, ivlen
);
903 /* maybe it is better to overwrite dest, not source */
904 m_copyback(m
, ivoff
, ivlen
, iv
);
908 if (ivlen
== blocklen
)
910 else if (ivlen
== 4 && blocklen
== 8) {
911 bcopy(&iv
[0], &iv
[4], 4);
917 ipseclog((LOG_ERR
, "esp_cbc_encrypt %s: "
918 "unsupported ivlen/blocklen: %d %d\n",
919 algo
->name
, ivlen
, blocklen
));
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
));
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
));
940 soff
= doff
= sn
= dn
= 0;
944 while (soff
< bodyoff
) {
945 if (soff
+ s
->m_len
> bodyoff
) {
956 /* skip over empty mbuf */
957 while (s
&& s
->m_len
== 0)
960 while (soff
< m
->m_pkthdr
.len
) {
962 if (sn
+ blocklen
<= s
->m_len
) {
963 /* body is continuous */
964 sp
= mtod(s
, u_int8_t
*) + sn
;
966 /* body is non-continuous */
967 m_copydata(s
, sn
, blocklen
, sbuf
);
972 if (!d
|| dn
+ blocklen
> d
->m_len
) {
975 MGET(d
, M_DONTWAIT
, MT_DATA
);
976 i
= m
->m_pkthdr
.len
- (soff
+ sn
);
978 MCLGET(d
, M_DONTWAIT
);
979 if ((d
->m_flags
& M_EXT
) == 0) {
995 d
->m_len
= (M_TRAILINGSPACE(d
) / blocklen
) * blocklen
;
1004 for (i
= 0; i
< blocklen
; i
++)
1008 (*algo
->blockencrypt
)(algo
, sav
, sp
, mtod(d
, u_int8_t
*) + dn
);
1011 ivp
= mtod(d
, u_int8_t
*) + dn
;
1016 /* find the next source block */
1017 while (s
&& sn
>= s
->m_len
) {
1023 /* skip over empty mbuf */
1024 while (s
&& s
->m_len
== 0)
1028 m_freem(scut
->m_next
);
1029 scut
->m_len
= scutoff
;
1033 bzero(iv
, sizeof(iv
));
1034 bzero(sbuf
, sizeof(sbuf
));
1036 key_sa_stir_iv(sav
);
1041 /*------------------------------------------------------------*/
1043 /* does not free m0 on error */
1045 esp_auth(m0
, skip
, length
, sav
, sum
)
1047 size_t skip
; /* offset to ESP header */
1048 size_t length
; /* payload length */
1049 struct secasvar
*sav
;
1054 struct ah_algorithm_state s
;
1055 u_char sumbuf
[AH_MAXSUMSIZE
];
1056 const struct ah_algorithm
*algo
;
1061 if (m0
->m_pkthdr
.len
< skip
) {
1062 ipseclog((LOG_DEBUG
, "esp_auth: mbuf length < skip\n"));
1065 if (m0
->m_pkthdr
.len
< skip
+ length
) {
1066 ipseclog((LOG_DEBUG
,
1067 "esp_auth: mbuf length < skip + length\n"));
1071 * length of esp part (excluding authentication data) must be 4n,
1072 * since nexthdr must be at offset 4n+3.
1075 ipseclog((LOG_ERR
, "esp_auth: length is not multiple of 4\n"));
1079 ipseclog((LOG_DEBUG
, "esp_auth: NULL SA passed\n"));
1082 algo
= ah_algorithm_lookup(sav
->alg_auth
);
1085 "esp_auth: bad ESP auth algorithm passed: %d\n",
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",
1101 /* skip the header */
1104 panic("mbuf chain?");
1105 if (m
->m_len
<= skip
) {
1115 error
= (*algo
->init
)(&s
, sav
);
1119 while (0 < length
) {
1121 panic("mbuf chain?");
1123 if (m
->m_len
- off
< length
) {
1124 (*algo
->update
)(&s
, mtod(m
, u_char
*) + off
,
1126 length
-= m
->m_len
- off
;
1130 (*algo
->update
)(&s
, mtod(m
, u_char
*) + off
, length
);
1134 (*algo
->result
)(&s
, sumbuf
);
1135 bcopy(sumbuf
, sum
, siz
); /*XXX*/