1 /* $FreeBSD: src/sys/netinet6/esp_core.c,v 1.1.2.4 2002/03/26 10:12:29 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 #include <sys/kdebug.h>
81 #define DBG_LAYER_BEG NETDBG_CODE(DBG_NETIPSEC, 1)
82 #define DBG_LAYER_END NETDBG_CODE(DBG_NETIPSEC, 3)
83 #define DBG_FNC_ESPAUTH NETDBG_CODE(DBG_NETIPSEC, (8 << 8))
85 static int esp_null_mature
__P((struct secasvar
*));
86 static int esp_null_decrypt
__P((struct mbuf
*, size_t,
87 struct secasvar
*, const struct esp_algorithm
*, int));
88 static int esp_null_encrypt
__P((struct mbuf
*, size_t, size_t,
89 struct secasvar
*, const struct esp_algorithm
*, int));
90 static int esp_descbc_mature
__P((struct secasvar
*));
91 static int esp_descbc_ivlen
__P((const struct esp_algorithm
*,
93 static int esp_des_schedule
__P((const struct esp_algorithm
*,
95 static int esp_des_schedlen
__P((const struct esp_algorithm
*));
96 static int esp_des_blockdecrypt
__P((const struct esp_algorithm
*,
97 struct secasvar
*, u_int8_t
*, u_int8_t
*));
98 static int esp_des_blockencrypt
__P((const struct esp_algorithm
*,
99 struct secasvar
*, u_int8_t
*, u_int8_t
*));
100 static int esp_cbc_mature
__P((struct secasvar
*));
101 static int esp_blowfish_schedule
__P((const struct esp_algorithm
*,
103 static int esp_blowfish_schedlen
__P((const struct esp_algorithm
*));
104 static int esp_blowfish_blockdecrypt
__P((const struct esp_algorithm
*,
105 struct secasvar
*, u_int8_t
*, u_int8_t
*));
106 static int esp_blowfish_blockencrypt
__P((const struct esp_algorithm
*,
107 struct secasvar
*, u_int8_t
*, u_int8_t
*));
108 static int esp_cast128_schedule
__P((const struct esp_algorithm
*,
110 static int esp_cast128_schedlen
__P((const struct esp_algorithm
*));
111 static int esp_cast128_blockdecrypt
__P((const struct esp_algorithm
*,
112 struct secasvar
*, u_int8_t
*, u_int8_t
*));
113 static int esp_cast128_blockencrypt
__P((const struct esp_algorithm
*,
114 struct secasvar
*, u_int8_t
*, u_int8_t
*));
115 static int esp_3des_schedule
__P((const struct esp_algorithm
*,
117 static int esp_3des_schedlen
__P((const struct esp_algorithm
*));
118 static int esp_3des_blockdecrypt
__P((const struct esp_algorithm
*,
119 struct secasvar
*, u_int8_t
*, u_int8_t
*));
120 static int esp_3des_blockencrypt
__P((const struct esp_algorithm
*,
121 struct secasvar
*, u_int8_t
*, u_int8_t
*));
122 static int esp_common_ivlen
__P((const struct esp_algorithm
*,
124 static int esp_cbc_decrypt
__P((struct mbuf
*, size_t,
125 struct secasvar
*, const struct esp_algorithm
*, int));
126 static int esp_cbc_encrypt
__P((struct mbuf
*, size_t, size_t,
127 struct secasvar
*, const struct esp_algorithm
*, int));
131 static const struct esp_algorithm esp_algorithms
[] = {
132 { 8, -1, esp_descbc_mature
, 64, 64, esp_des_schedlen
,
134 esp_descbc_ivlen
, esp_cbc_decrypt
,
135 esp_cbc_encrypt
, esp_des_schedule
,
136 esp_des_blockdecrypt
, esp_des_blockencrypt
, },
137 { 8, 8, esp_cbc_mature
, 192, 192, esp_3des_schedlen
,
139 esp_common_ivlen
, esp_cbc_decrypt
,
140 esp_cbc_encrypt
, esp_3des_schedule
,
141 esp_3des_blockdecrypt
, esp_3des_blockencrypt
, },
142 { 1, 0, esp_null_mature
, 0, 2048, 0, "null",
143 esp_common_ivlen
, esp_null_decrypt
,
144 esp_null_encrypt
, NULL
, },
145 { 8, 8, esp_cbc_mature
, 40, 448, esp_blowfish_schedlen
, "blowfish-cbc",
146 esp_common_ivlen
, esp_cbc_decrypt
,
147 esp_cbc_encrypt
, esp_blowfish_schedule
,
148 esp_blowfish_blockdecrypt
, esp_blowfish_blockencrypt
, },
149 { 8, 8, esp_cbc_mature
, 40, 128, esp_cast128_schedlen
,
151 esp_common_ivlen
, esp_cbc_decrypt
,
152 esp_cbc_encrypt
, esp_cast128_schedule
,
153 esp_cast128_blockdecrypt
, esp_cast128_blockencrypt
, },
154 { 16, 16, esp_cbc_mature
, 128, 256, esp_rijndael_schedlen
,
156 esp_common_ivlen
, esp_cbc_decrypt
,
157 esp_cbc_encrypt
, esp_rijndael_schedule
,
158 esp_rijndael_blockdecrypt
, esp_rijndael_blockencrypt
},
161 const struct esp_algorithm
*
162 esp_algorithm_lookup(idx
)
167 case SADB_EALG_DESCBC
:
168 return &esp_algorithms
[0];
169 case SADB_EALG_3DESCBC
:
170 return &esp_algorithms
[1];
172 return &esp_algorithms
[2];
173 case SADB_X_EALG_BLOWFISHCBC
:
174 return &esp_algorithms
[3];
175 case SADB_X_EALG_CAST128CBC
:
176 return &esp_algorithms
[4];
177 case SADB_X_EALG_RIJNDAELCBC
:
178 return &esp_algorithms
[5];
191 for (idx
= 0; idx
< sizeof(esp_algorithms
)/sizeof(esp_algorithms
[0]);
193 if (esp_algorithms
[idx
].ivlenval
> ivlen
)
194 ivlen
= esp_algorithms
[idx
].ivlenval
;
201 esp_schedule(algo
, sav
)
202 const struct esp_algorithm
*algo
;
203 struct secasvar
*sav
;
207 /* check for key length */
208 if (_KEYBITS(sav
->key_enc
) < algo
->keymin
||
209 _KEYBITS(sav
->key_enc
) > algo
->keymax
) {
211 "esp_schedule %s: unsupported key length %d: "
212 "needs %d to %d bits\n", algo
->name
, _KEYBITS(sav
->key_enc
),
213 algo
->keymin
, algo
->keymax
));
217 /* already allocated */
218 if (sav
->sched
&& sav
->schedlen
!= 0)
220 /* no schedule necessary */
221 if (!algo
->schedule
|| !algo
->schedlen
)
224 sav
->schedlen
= (*algo
->schedlen
)(algo
);
225 if (sav
->schedlen
< 0)
228 //#### that malloc should be replaced by a saved buffer...
229 sav
->sched
= _MALLOC(sav
->schedlen
, M_SECA
, M_DONTWAIT
);
235 error
= (*algo
->schedule
)(algo
, sav
);
237 ipseclog((LOG_ERR
, "esp_schedule %s: error %d\n",
239 bzero(sav
->sched
, sav
->schedlen
);
240 FREE(sav
->sched
, M_SECA
);
249 struct secasvar
*sav
;
252 /* anything is okay */
257 esp_null_decrypt(m
, off
, sav
, algo
, ivlen
)
259 size_t off
; /* offset to ESP header */
260 struct secasvar
*sav
;
261 const struct esp_algorithm
*algo
;
265 return 0; /* do nothing */
269 esp_null_encrypt(m
, off
, plen
, sav
, algo
, ivlen
)
271 size_t off
; /* offset to ESP header */
272 size_t plen
; /* payload length (to be encrypted) */
273 struct secasvar
*sav
;
274 const struct esp_algorithm
*algo
;
278 return 0; /* do nothing */
282 esp_descbc_mature(sav
)
283 struct secasvar
*sav
;
285 const struct esp_algorithm
*algo
;
287 if (!(sav
->flags
& SADB_X_EXT_OLD
) && (sav
->flags
& SADB_X_EXT_IV4B
)) {
288 ipseclog((LOG_ERR
, "esp_cbc_mature: "
289 "algorithm incompatible with 4 octets IV length\n"));
294 ipseclog((LOG_ERR
, "esp_descbc_mature: no key is given.\n"));
298 algo
= esp_algorithm_lookup(sav
->alg_enc
);
301 "esp_descbc_mature: unsupported algorithm.\n"));
305 if (_KEYBITS(sav
->key_enc
) < algo
->keymin
||
306 _KEYBITS(sav
->key_enc
) > algo
->keymax
) {
308 "esp_descbc_mature: invalid key length %d.\n",
309 _KEYBITS(sav
->key_enc
)));
314 if (des_is_weak_key((des_cblock
*)_KEYBUF(sav
->key_enc
))) {
316 "esp_descbc_mature: weak key was passed.\n"));
324 esp_descbc_ivlen(algo
, sav
)
325 const struct esp_algorithm
*algo
;
326 struct secasvar
*sav
;
331 if ((sav
->flags
& SADB_X_EXT_OLD
) && (sav
->flags
& SADB_X_EXT_IV4B
))
333 if (!(sav
->flags
& SADB_X_EXT_OLD
) && (sav
->flags
& SADB_X_EXT_DERIV
))
339 esp_des_schedlen(algo
)
340 const struct esp_algorithm
*algo
;
343 return sizeof(des_key_schedule
);
347 esp_des_schedule(algo
, sav
)
348 const struct esp_algorithm
*algo
;
349 struct secasvar
*sav
;
352 if (des_key_sched((des_cblock
*)_KEYBUF(sav
->key_enc
),
353 *(des_key_schedule
*)sav
->sched
))
360 esp_des_blockdecrypt(algo
, sav
, s
, d
)
361 const struct esp_algorithm
*algo
;
362 struct secasvar
*sav
;
367 /* assumption: d has a good alignment */
368 bcopy(s
, d
, sizeof(DES_LONG
) * 2);
369 des_ecb_encrypt((des_cblock
*)d
, (des_cblock
*)d
,
370 *(des_key_schedule
*)sav
->sched
, DES_DECRYPT
);
375 esp_des_blockencrypt(algo
, sav
, s
, d
)
376 const struct esp_algorithm
*algo
;
377 struct secasvar
*sav
;
382 /* assumption: d has a good alignment */
383 bcopy(s
, d
, sizeof(DES_LONG
) * 2);
384 des_ecb_encrypt((des_cblock
*)d
, (des_cblock
*)d
,
385 *(des_key_schedule
*)sav
->sched
, DES_ENCRYPT
);
391 struct secasvar
*sav
;
394 const struct esp_algorithm
*algo
;
396 if (sav
->flags
& SADB_X_EXT_OLD
) {
398 "esp_cbc_mature: algorithm incompatible with esp-old\n"));
401 if (sav
->flags
& SADB_X_EXT_DERIV
) {
403 "esp_cbc_mature: algorithm incompatible with derived\n"));
408 ipseclog((LOG_ERR
, "esp_cbc_mature: no key is given.\n"));
412 algo
= esp_algorithm_lookup(sav
->alg_enc
);
415 "esp_cbc_mature %s: unsupported algorithm.\n", algo
->name
));
419 keylen
= sav
->key_enc
->sadb_key_bits
;
420 if (keylen
< algo
->keymin
|| algo
->keymax
< keylen
) {
422 "esp_cbc_mature %s: invalid key length %d.\n",
423 algo
->name
, sav
->key_enc
->sadb_key_bits
));
426 switch (sav
->alg_enc
) {
427 case SADB_EALG_3DESCBC
:
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))) {
433 "esp_cbc_mature %s: weak key was passed.\n",
438 case SADB_X_EALG_BLOWFISHCBC
:
439 case SADB_X_EALG_CAST128CBC
:
441 case SADB_X_EALG_RIJNDAELCBC
:
442 /* allows specific key sizes only */
443 if (!(keylen
== 128 || keylen
== 192 || keylen
== 256)) {
445 "esp_cbc_mature %s: invalid key length %d.\n",
446 algo
->name
, keylen
));
456 esp_blowfish_schedlen(algo
)
457 const struct esp_algorithm
*algo
;
460 return sizeof(BF_KEY
);
464 esp_blowfish_schedule(algo
, sav
)
465 const struct esp_algorithm
*algo
;
466 struct secasvar
*sav
;
469 BF_set_key((BF_KEY
*)sav
->sched
, _KEYLEN(sav
->key_enc
),
470 _KEYBUF(sav
->key_enc
));
475 esp_blowfish_blockdecrypt(algo
, sav
, s
, d
)
476 const struct esp_algorithm
*algo
;
477 struct secasvar
*sav
;
481 /* HOLY COW! BF_decrypt() takes values in host byteorder */
484 bcopy(s
, t
, sizeof(t
));
487 BF_decrypt(t
, (BF_KEY
*)sav
->sched
);
490 bcopy(t
, d
, sizeof(t
));
495 esp_blowfish_blockencrypt(algo
, sav
, s
, d
)
496 const struct esp_algorithm
*algo
;
497 struct secasvar
*sav
;
501 /* HOLY COW! BF_encrypt() takes values in host byteorder */
504 bcopy(s
, t
, sizeof(t
));
507 BF_encrypt(t
, (BF_KEY
*)sav
->sched
);
510 bcopy(t
, d
, sizeof(t
));
515 esp_cast128_schedlen(algo
)
516 const struct esp_algorithm
*algo
;
519 return sizeof(u_int32_t
) * 32;
523 esp_cast128_schedule(algo
, sav
)
524 const struct esp_algorithm
*algo
;
525 struct secasvar
*sav
;
528 set_cast128_subkey((u_int32_t
*)sav
->sched
, _KEYBUF(sav
->key_enc
),
529 _KEYLEN(sav
->key_enc
));
534 esp_cast128_blockdecrypt(algo
, sav
, s
, d
)
535 const struct esp_algorithm
*algo
;
536 struct secasvar
*sav
;
541 if (_KEYLEN(sav
->key_enc
) <= 80 / 8)
542 cast128_decrypt_round12(d
, s
, (u_int32_t
*)sav
->sched
);
544 cast128_decrypt_round16(d
, s
, (u_int32_t
*)sav
->sched
);
549 esp_cast128_blockencrypt(algo
, sav
, s
, d
)
550 const struct esp_algorithm
*algo
;
551 struct secasvar
*sav
;
556 if (_KEYLEN(sav
->key_enc
) <= 80 / 8)
557 cast128_encrypt_round12(d
, s
, (u_int32_t
*)sav
->sched
);
559 cast128_encrypt_round16(d
, s
, (u_int32_t
*)sav
->sched
);
564 esp_3des_schedlen(algo
)
565 const struct esp_algorithm
*algo
;
568 return sizeof(des_key_schedule
) * 3;
572 esp_3des_schedule(algo
, sav
)
573 const struct esp_algorithm
*algo
;
574 struct secasvar
*sav
;
581 p
= (des_key_schedule
*)sav
->sched
;
582 k
= _KEYBUF(sav
->key_enc
);
583 for (i
= 0; i
< 3; i
++) {
584 error
= des_key_sched((des_cblock
*)(k
+ 8 * i
), p
[i
]);
592 esp_3des_blockdecrypt(algo
, sav
, s
, d
)
593 const struct esp_algorithm
*algo
;
594 struct secasvar
*sav
;
600 /* assumption: d has a good alignment */
601 p
= (des_key_schedule
*)sav
->sched
;
602 bcopy(s
, d
, sizeof(DES_LONG
) * 2);
603 des_ecb3_encrypt((des_cblock
*)d
, (des_cblock
*)d
,
604 p
[0], p
[1], p
[2], DES_DECRYPT
);
609 esp_3des_blockencrypt(algo
, sav
, s
, d
)
610 const struct esp_algorithm
*algo
;
611 struct secasvar
*sav
;
617 /* assumption: d has a good alignment */
618 p
= (des_key_schedule
*)sav
->sched
;
619 bcopy(s
, d
, sizeof(DES_LONG
) * 2);
620 des_ecb3_encrypt((des_cblock
*)d
, (des_cblock
*)d
,
621 p
[0], p
[1], p
[2], DES_ENCRYPT
);
626 esp_common_ivlen(algo
, sav
)
627 const struct esp_algorithm
*algo
;
628 struct secasvar
*sav
;
632 panic("esp_common_ivlen: unknown algorithm");
633 return algo
->ivlenval
;
637 esp_cbc_decrypt(m
, off
, sav
, algo
, ivlen
)
640 struct secasvar
*sav
;
641 const struct esp_algorithm
*algo
;
645 struct mbuf
*d
, *d0
, *dp
;
646 int soff
, doff
; /* offset from the head of chain, to head of this mbuf */
647 int sn
, dn
; /* offset from the head of the mbuf, to meat */
648 size_t ivoff
, bodyoff
;
649 u_int8_t iv
[MAXIVLEN
], *ivp
;
650 u_int8_t sbuf
[MAXIVLEN
], *sp
;
658 if (ivlen
!= sav
->ivlen
|| ivlen
> sizeof(iv
)) {
659 ipseclog((LOG_ERR
, "esp_cbc_decrypt %s: "
660 "unsupported ivlen %d\n", algo
->name
, ivlen
));
665 /* assumes blocklen == padbound */
666 blocklen
= algo
->padbound
;
669 if (blocklen
> sizeof(iv
)) {
670 ipseclog((LOG_ERR
, "esp_cbc_decrypt %s: "
671 "unsupported blocklen %d\n", algo
->name
, blocklen
));
677 if (sav
->flags
& SADB_X_EXT_OLD
) {
679 ivoff
= off
+ sizeof(struct esp
);
680 bodyoff
= off
+ sizeof(struct esp
) + ivlen
;
684 if (sav
->flags
& SADB_X_EXT_DERIV
) {
686 * draft-ietf-ipsec-ciph-des-derived-00.txt
687 * uses sequence number field as IV field.
689 ivoff
= off
+ sizeof(struct esp
);
690 bodyoff
= off
+ sizeof(struct esp
) + sizeof(u_int32_t
);
691 ivlen
= sizeof(u_int32_t
);
694 ivoff
= off
+ sizeof(struct newesp
);
695 bodyoff
= off
+ sizeof(struct newesp
) + ivlen
;
701 m_copydata(m
, ivoff
, ivlen
, iv
);
704 if (ivlen
== blocklen
)
706 else if (ivlen
== 4 && blocklen
== 8) {
707 bcopy(&iv
[0], &iv
[4], 4);
713 ipseclog((LOG_ERR
, "esp_cbc_encrypt %s: "
714 "unsupported ivlen/blocklen: %d %d\n",
715 algo
->name
, ivlen
, blocklen
));
720 if (m
->m_pkthdr
.len
< bodyoff
) {
721 ipseclog((LOG_ERR
, "esp_cbc_decrypt %s: bad len %d/%lu\n",
722 algo
->name
, m
->m_pkthdr
.len
, (unsigned long)bodyoff
));
726 if ((m
->m_pkthdr
.len
- bodyoff
) % blocklen
) {
727 ipseclog((LOG_ERR
, "esp_cbc_decrypt %s: "
728 "payload length must be multiple of %d\n",
729 algo
->name
, blocklen
));
736 soff
= doff
= sn
= dn
= 0;
740 while (soff
< bodyoff
) {
741 if (soff
+ s
->m_len
> bodyoff
) {
752 /* skip over empty mbuf */
753 while (s
&& s
->m_len
== 0)
756 while (soff
< m
->m_pkthdr
.len
) {
758 if (sn
+ blocklen
<= s
->m_len
) {
759 /* body is continuous */
760 sp
= mtod(s
, u_int8_t
*) + sn
;
762 /* body is non-continuous */
763 m_copydata(s
, sn
, blocklen
, sbuf
);
768 if (!d
|| dn
+ blocklen
> d
->m_len
) {
771 MGET(d
, M_DONTWAIT
, MT_DATA
);
772 i
= m
->m_pkthdr
.len
- (soff
+ sn
);
774 MCLGET(d
, M_DONTWAIT
);
775 if ((d
->m_flags
& M_EXT
) == 0) {
791 d
->m_len
= (M_TRAILINGSPACE(d
) / blocklen
) * blocklen
;
798 (*algo
->blockdecrypt
)(algo
, sav
, sp
, mtod(d
, u_int8_t
*) + dn
);
802 q
= mtod(d
, u_int8_t
*) + dn
;
803 for (i
= 0; i
< blocklen
; i
++)
808 bcopy(sbuf
, iv
, blocklen
);
816 /* find the next source block */
817 while (s
&& sn
>= s
->m_len
) {
823 /* skip over empty mbuf */
824 while (s
&& s
->m_len
== 0)
828 m_freem(scut
->m_next
);
829 scut
->m_len
= scutoff
;
833 bzero(iv
, sizeof(iv
));
834 bzero(sbuf
, sizeof(sbuf
));
840 esp_cbc_encrypt(m
, off
, plen
, sav
, algo
, ivlen
)
844 struct secasvar
*sav
;
845 const struct esp_algorithm
*algo
;
849 struct mbuf
*d
, *d0
, *dp
;
850 int soff
, doff
; /* offset from the head of chain, to head of this mbuf */
851 int sn
, dn
; /* offset from the head of the mbuf, to meat */
852 size_t ivoff
, bodyoff
;
853 u_int8_t iv
[MAXIVLEN
], *ivp
;
854 u_int8_t sbuf
[MAXIVLEN
], *sp
;
862 if (ivlen
!= sav
->ivlen
|| ivlen
> sizeof(iv
)) {
863 ipseclog((LOG_ERR
, "esp_cbc_encrypt %s: "
864 "unsupported ivlen %d\n", algo
->name
, ivlen
));
869 /* assumes blocklen == padbound */
870 blocklen
= algo
->padbound
;
873 if (blocklen
> sizeof(iv
)) {
874 ipseclog((LOG_ERR
, "esp_cbc_encrypt %s: "
875 "unsupported blocklen %d\n", algo
->name
, blocklen
));
881 if (sav
->flags
& SADB_X_EXT_OLD
) {
883 ivoff
= off
+ sizeof(struct esp
);
884 bodyoff
= off
+ sizeof(struct esp
) + ivlen
;
888 if (sav
->flags
& SADB_X_EXT_DERIV
) {
890 * draft-ietf-ipsec-ciph-des-derived-00.txt
891 * uses sequence number field as IV field.
893 ivoff
= off
+ sizeof(struct esp
);
894 bodyoff
= off
+ sizeof(struct esp
) + sizeof(u_int32_t
);
895 ivlen
= sizeof(u_int32_t
);
898 ivoff
= off
+ sizeof(struct newesp
);
899 bodyoff
= off
+ sizeof(struct newesp
) + ivlen
;
904 /* put iv into the packet. if we are in derived mode, use seqno. */
906 m_copydata(m
, ivoff
, ivlen
, iv
);
908 bcopy(sav
->iv
, iv
, ivlen
);
909 /* maybe it is better to overwrite dest, not source */
910 m_copyback(m
, ivoff
, ivlen
, iv
);
914 if (ivlen
== blocklen
)
916 else if (ivlen
== 4 && blocklen
== 8) {
917 bcopy(&iv
[0], &iv
[4], 4);
923 ipseclog((LOG_ERR
, "esp_cbc_encrypt %s: "
924 "unsupported ivlen/blocklen: %d %d\n",
925 algo
->name
, ivlen
, blocklen
));
930 if (m
->m_pkthdr
.len
< bodyoff
) {
931 ipseclog((LOG_ERR
, "esp_cbc_encrypt %s: bad len %d/%lu\n",
932 algo
->name
, m
->m_pkthdr
.len
, (unsigned long)bodyoff
));
936 if ((m
->m_pkthdr
.len
- bodyoff
) % blocklen
) {
937 ipseclog((LOG_ERR
, "esp_cbc_encrypt %s: "
938 "payload length must be multiple of %lu\n",
939 algo
->name
, (unsigned long)algo
->padbound
));
946 soff
= doff
= sn
= dn
= 0;
950 while (soff
< bodyoff
) {
951 if (soff
+ s
->m_len
> bodyoff
) {
962 /* skip over empty mbuf */
963 while (s
&& s
->m_len
== 0)
966 while (soff
< m
->m_pkthdr
.len
) {
968 if (sn
+ blocklen
<= s
->m_len
) {
969 /* body is continuous */
970 sp
= mtod(s
, u_int8_t
*) + sn
;
972 /* body is non-continuous */
973 m_copydata(s
, sn
, blocklen
, sbuf
);
978 if (!d
|| dn
+ blocklen
> d
->m_len
) {
981 MGET(d
, M_DONTWAIT
, MT_DATA
);
982 i
= m
->m_pkthdr
.len
- (soff
+ sn
);
984 MCLGET(d
, M_DONTWAIT
);
985 if ((d
->m_flags
& M_EXT
) == 0) {
1001 d
->m_len
= (M_TRAILINGSPACE(d
) / blocklen
) * blocklen
;
1010 for (i
= 0; i
< blocklen
; i
++)
1014 (*algo
->blockencrypt
)(algo
, sav
, sp
, mtod(d
, u_int8_t
*) + dn
);
1017 ivp
= mtod(d
, u_int8_t
*) + dn
;
1022 /* find the next source block */
1023 while (s
&& sn
>= s
->m_len
) {
1029 /* skip over empty mbuf */
1030 while (s
&& s
->m_len
== 0)
1034 m_freem(scut
->m_next
);
1035 scut
->m_len
= scutoff
;
1039 bzero(iv
, sizeof(iv
));
1040 bzero(sbuf
, sizeof(sbuf
));
1042 key_sa_stir_iv(sav
);
1047 /*------------------------------------------------------------*/
1049 /* does not free m0 on error */
1051 esp_auth(m0
, skip
, length
, sav
, sum
)
1053 size_t skip
; /* offset to ESP header */
1054 size_t length
; /* payload length */
1055 struct secasvar
*sav
;
1060 struct ah_algorithm_state s
;
1061 u_char sumbuf
[AH_MAXSUMSIZE
];
1062 const struct ah_algorithm
*algo
;
1067 if (m0
->m_pkthdr
.len
< skip
) {
1068 ipseclog((LOG_DEBUG
, "esp_auth: mbuf length < skip\n"));
1071 if (m0
->m_pkthdr
.len
< skip
+ length
) {
1072 ipseclog((LOG_DEBUG
,
1073 "esp_auth: mbuf length < skip + length\n"));
1077 KERNEL_DEBUG(DBG_FNC_ESPAUTH
| DBG_FUNC_START
, skip
,length
,0,0,0);
1079 * length of esp part (excluding authentication data) must be 4n,
1080 * since nexthdr must be at offset 4n+3.
1083 ipseclog((LOG_ERR
, "esp_auth: length is not multiple of 4\n"));
1084 KERNEL_DEBUG(DBG_FNC_ESPAUTH
| DBG_FUNC_END
, 1,0,0,0,0);
1088 ipseclog((LOG_DEBUG
, "esp_auth: NULL SA passed\n"));
1089 KERNEL_DEBUG(DBG_FNC_ESPAUTH
| DBG_FUNC_END
, 2,0,0,0,0);
1092 algo
= ah_algorithm_lookup(sav
->alg_auth
);
1095 "esp_auth: bad ESP auth algorithm passed: %d\n",
1097 KERNEL_DEBUG(DBG_FNC_ESPAUTH
| DBG_FUNC_END
, 3,0,0,0,0);
1104 siz
= (((*algo
->sumsiz
)(sav
) + 3) & ~(4 - 1));
1105 if (sizeof(sumbuf
) < siz
) {
1106 ipseclog((LOG_DEBUG
,
1107 "esp_auth: AH_MAXSUMSIZE is too small: siz=%lu\n",
1109 KERNEL_DEBUG(DBG_FNC_ESPAUTH
| DBG_FUNC_END
, 4,0,0,0,0);
1113 /* skip the header */
1116 panic("mbuf chain?");
1117 if (m
->m_len
<= skip
) {
1127 error
= (*algo
->init
)(&s
, sav
);
1129 KERNEL_DEBUG(DBG_FNC_ESPAUTH
| DBG_FUNC_END
, 5,0,0,0,0);
1133 while (0 < length
) {
1135 panic("mbuf chain?");
1137 if (m
->m_len
- off
< length
) {
1138 (*algo
->update
)(&s
, mtod(m
, u_char
*) + off
,
1140 length
-= m
->m_len
- off
;
1144 (*algo
->update
)(&s
, mtod(m
, u_char
*) + off
, length
);
1148 (*algo
->result
)(&s
, sumbuf
);
1149 bcopy(sumbuf
, sum
, siz
); /*XXX*/
1151 KERNEL_DEBUG(DBG_FNC_ESPAUTH
| DBG_FUNC_END
, 6,0,0,0,0);