aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2005-10-11 00:11:34 -0400
committerDavid S. Miller <davem@davemloft.net>2005-10-11 00:11:34 -0400
commitd4875b049b2e6401a6e1fae90b7f09e20a636fcf (patch)
treea5021c091cbd141675cdd90ac330d33188284c03 /net
parenta02a64223eddb410712b015fb3342c9a316ab70b (diff)
[IPSEC] Fix block size/MTU bugs in ESP
This patch fixes the following bugs in ESP: * Fix transport mode MTU overestimate. This means that the inner MTU is smaller than it needs be. Worse yet, given an input MTU which is a multiple of 4 it will always produce an estimate which is not a multiple of 4. For example, given a standard ESP/3DES/MD5 transform and an MTU of 1500, the resulting MTU for transport mode is 1462 when it should be 1464. The reason for this is because IP header lengths are always a multiple of 4 for IPv4 and 8 for IPv6. * Ensure that the block size is at least 4. This is required by RFC2406 and corresponds to what the esp_output function does. At the moment this only affects crypto_null as its block size is 1. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/esp4.c6
-rw-r--r--net/ipv6/esp6.c7
2 files changed, 7 insertions, 6 deletions
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index e911c6dd8296..1b18ce66e7b7 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -144,7 +144,7 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc
144 struct ip_esp_hdr *esph; 144 struct ip_esp_hdr *esph;
145 struct esp_data *esp = x->data; 145 struct esp_data *esp = x->data;
146 struct sk_buff *trailer; 146 struct sk_buff *trailer;
147 int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); 147 int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
148 int alen = esp->auth.icv_trunc_len; 148 int alen = esp->auth.icv_trunc_len;
149 int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen; 149 int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen;
150 int nfrags; 150 int nfrags;
@@ -305,13 +305,13 @@ static int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap,
305static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) 305static u32 esp4_get_max_size(struct xfrm_state *x, int mtu)
306{ 306{
307 struct esp_data *esp = x->data; 307 struct esp_data *esp = x->data;
308 u32 blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); 308 u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
309 309
310 if (x->props.mode) { 310 if (x->props.mode) {
311 mtu = ALIGN(mtu + 2, blksize); 311 mtu = ALIGN(mtu + 2, blksize);
312 } else { 312 } else {
313 /* The worst case. */ 313 /* The worst case. */
314 mtu += 2 + blksize; 314 mtu = ALIGN(mtu + 2, 4) + blksize - 4;
315 } 315 }
316 if (esp->conf.padlen) 316 if (esp->conf.padlen)
317 mtu = ALIGN(mtu, esp->conf.padlen); 317 mtu = ALIGN(mtu, esp->conf.padlen);
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 0c7d7b42c80b..40d9a1935ab5 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -134,7 +134,7 @@ static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, stru
134 struct ipv6_esp_hdr *esph; 134 struct ipv6_esp_hdr *esph;
135 struct esp_data *esp = x->data; 135 struct esp_data *esp = x->data;
136 struct sk_buff *trailer; 136 struct sk_buff *trailer;
137 int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); 137 int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
138 int alen = esp->auth.icv_trunc_len; 138 int alen = esp->auth.icv_trunc_len;
139 int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen; 139 int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen;
140 140
@@ -236,13 +236,14 @@ out_nofree:
236static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) 236static u32 esp6_get_max_size(struct xfrm_state *x, int mtu)
237{ 237{
238 struct esp_data *esp = x->data; 238 struct esp_data *esp = x->data;
239 u32 blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); 239 u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
240 240
241 if (x->props.mode) { 241 if (x->props.mode) {
242 mtu = ALIGN(mtu + 2, blksize); 242 mtu = ALIGN(mtu + 2, blksize);
243 } else { 243 } else {
244 /* The worst case. */ 244 /* The worst case. */
245 mtu += 2 + blksize; 245 u32 padsize = ((blksize - 1) & 7) + 1;
246 mtu = ALIGN(mtu + 2, padsize) + blksize - padsize;
246 } 247 }
247 if (esp->conf.padlen) 248 if (esp->conf.padlen)
248 mtu = ALIGN(mtu, esp->conf.padlen); 249 mtu = ALIGN(mtu, esp->conf.padlen);