Commit d4875b04 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller

[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: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a02a6422
...@@ -144,7 +144,7 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc ...@@ -144,7 +144,7 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc
struct ip_esp_hdr *esph; struct ip_esp_hdr *esph;
struct esp_data *esp = x->data; struct esp_data *esp = x->data;
struct sk_buff *trailer; struct sk_buff *trailer;
int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
int alen = esp->auth.icv_trunc_len; int alen = esp->auth.icv_trunc_len;
int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen; int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen;
int nfrags; int nfrags;
...@@ -305,13 +305,13 @@ static int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap, ...@@ -305,13 +305,13 @@ static int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap,
static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) static u32 esp4_get_max_size(struct xfrm_state *x, int mtu)
{ {
struct esp_data *esp = x->data; struct esp_data *esp = x->data;
u32 blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
if (x->props.mode) { if (x->props.mode) {
mtu = ALIGN(mtu + 2, blksize); mtu = ALIGN(mtu + 2, blksize);
} else { } else {
/* The worst case. */ /* The worst case. */
mtu += 2 + blksize; mtu = ALIGN(mtu + 2, 4) + blksize - 4;
} }
if (esp->conf.padlen) if (esp->conf.padlen)
mtu = ALIGN(mtu, esp->conf.padlen); mtu = ALIGN(mtu, esp->conf.padlen);
......
...@@ -134,7 +134,7 @@ static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, stru ...@@ -134,7 +134,7 @@ static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, stru
struct ipv6_esp_hdr *esph; struct ipv6_esp_hdr *esph;
struct esp_data *esp = x->data; struct esp_data *esp = x->data;
struct sk_buff *trailer; struct sk_buff *trailer;
int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
int alen = esp->auth.icv_trunc_len; int alen = esp->auth.icv_trunc_len;
int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen; int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen;
...@@ -236,13 +236,14 @@ static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, stru ...@@ -236,13 +236,14 @@ static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, stru
static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) static u32 esp6_get_max_size(struct xfrm_state *x, int mtu)
{ {
struct esp_data *esp = x->data; struct esp_data *esp = x->data;
u32 blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
if (x->props.mode) { if (x->props.mode) {
mtu = ALIGN(mtu + 2, blksize); mtu = ALIGN(mtu + 2, blksize);
} else { } else {
/* The worst case. */ /* The worst case. */
mtu += 2 + blksize; u32 padsize = ((blksize - 1) & 7) + 1;
mtu = ALIGN(mtu + 2, padsize) + blksize - padsize;
} }
if (esp->conf.padlen) if (esp->conf.padlen)
mtu = ALIGN(mtu, esp->conf.padlen); mtu = ALIGN(mtu, esp->conf.padlen);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment