aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/esp6.c
diff options
context:
space:
mode:
authorMartin Willi <martin@strongswan.org>2010-12-07 23:37:51 -0500
committerDavid S. Miller <davem@davemloft.net>2010-12-10 17:43:59 -0500
commit040253c931e336360453c8d81f76d1b010b2b5e7 (patch)
treee9fa38b6cd2a12eec1f12f1a89258f3713cfabd7 /net/ipv6/esp6.c
parentd979e20f2b9f8a50c8d5f889e0b5d78580440d1f (diff)
xfrm: Traffic Flow Confidentiality for IPv6 ESP
Add TFC padding to all packets smaller than the boundary configured on the xfrm state. If the boundary is larger than the PMTU, limit padding to the PMTU. Signed-off-by: Martin Willi <martin@strongswan.org> Acked-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/esp6.c')
-rw-r--r--net/ipv6/esp6.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index ee9b93bdd6a2..1b5c9825743b 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -49,6 +49,8 @@ struct esp_skb_cb {
49 49
50#define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0])) 50#define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0]))
51 51
52static u32 esp6_get_mtu(struct xfrm_state *x, int mtu);
53
52/* 54/*
53 * Allocate an AEAD request structure with extra space for SG and IV. 55 * Allocate an AEAD request structure with extra space for SG and IV.
54 * 56 *
@@ -140,6 +142,8 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
140 int blksize; 142 int blksize;
141 int clen; 143 int clen;
142 int alen; 144 int alen;
145 int plen;
146 int tfclen;
143 int nfrags; 147 int nfrags;
144 u8 *iv; 148 u8 *iv;
145 u8 *tail; 149 u8 *tail;
@@ -148,18 +152,26 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
148 /* skb is pure payload to encrypt */ 152 /* skb is pure payload to encrypt */
149 err = -ENOMEM; 153 err = -ENOMEM;
150 154
151 /* Round to block size */
152 clen = skb->len;
153
154 aead = esp->aead; 155 aead = esp->aead;
155 alen = crypto_aead_authsize(aead); 156 alen = crypto_aead_authsize(aead);
156 157
158 tfclen = 0;
159 if (x->tfcpad) {
160 struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb);
161 u32 padto;
162
163 padto = min(x->tfcpad, esp6_get_mtu(x, dst->child_mtu_cached));
164 if (skb->len < padto)
165 tfclen = padto - skb->len;
166 }
157 blksize = ALIGN(crypto_aead_blocksize(aead), 4); 167 blksize = ALIGN(crypto_aead_blocksize(aead), 4);
158 clen = ALIGN(clen + 2, blksize); 168 clen = ALIGN(skb->len + 2 + tfclen, blksize);
159 if (esp->padlen) 169 if (esp->padlen)
160 clen = ALIGN(clen, esp->padlen); 170 clen = ALIGN(clen, esp->padlen);
171 plen = clen - skb->len - tfclen;
161 172
162 if ((err = skb_cow_data(skb, clen - skb->len + alen, &trailer)) < 0) 173 err = skb_cow_data(skb, tfclen + plen + alen, &trailer);
174 if (err < 0)
163 goto error; 175 goto error;
164 nfrags = err; 176 nfrags = err;
165 177
@@ -174,13 +186,17 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
174 186
175 /* Fill padding... */ 187 /* Fill padding... */
176 tail = skb_tail_pointer(trailer); 188 tail = skb_tail_pointer(trailer);
189 if (tfclen) {
190 memset(tail, 0, tfclen);
191 tail += tfclen;
192 }
177 do { 193 do {
178 int i; 194 int i;
179 for (i=0; i<clen-skb->len - 2; i++) 195 for (i = 0; i < plen - 2; i++)
180 tail[i] = i + 1; 196 tail[i] = i + 1;
181 } while (0); 197 } while (0);
182 tail[clen-skb->len - 2] = (clen - skb->len) - 2; 198 tail[plen - 2] = plen - 2;
183 tail[clen - skb->len - 1] = *skb_mac_header(skb); 199 tail[plen - 1] = *skb_mac_header(skb);
184 pskb_put(skb, trailer, clen - skb->len + alen); 200 pskb_put(skb, trailer, clen - skb->len + alen);
185 201
186 skb_push(skb, -skb_network_offset(skb)); 202 skb_push(skb, -skb_network_offset(skb));