aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/esp4.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/esp4.c')
-rw-r--r--net/ipv4/esp4.c52
1 files changed, 32 insertions, 20 deletions
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 477937465a20..d95631d09248 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -23,6 +23,11 @@ struct esp_skb_cb {
23 void *tmp; 23 void *tmp;
24}; 24};
25 25
26struct esp_output_extra {
27 __be32 seqhi;
28 u32 esphoff;
29};
30
26#define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0])) 31#define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0]))
27 32
28static u32 esp4_get_mtu(struct xfrm_state *x, int mtu); 33static u32 esp4_get_mtu(struct xfrm_state *x, int mtu);
@@ -35,11 +40,11 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu);
35 * 40 *
36 * TODO: Use spare space in skb for this where possible. 41 * TODO: Use spare space in skb for this where possible.
37 */ 42 */
38static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int seqhilen) 43static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int extralen)
39{ 44{
40 unsigned int len; 45 unsigned int len;
41 46
42 len = seqhilen; 47 len = extralen;
43 48
44 len += crypto_aead_ivsize(aead); 49 len += crypto_aead_ivsize(aead);
45 50
@@ -57,15 +62,16 @@ static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int seqhilen)
57 return kmalloc(len, GFP_ATOMIC); 62 return kmalloc(len, GFP_ATOMIC);
58} 63}
59 64
60static inline __be32 *esp_tmp_seqhi(void *tmp) 65static inline void *esp_tmp_extra(void *tmp)
61{ 66{
62 return PTR_ALIGN((__be32 *)tmp, __alignof__(__be32)); 67 return PTR_ALIGN(tmp, __alignof__(struct esp_output_extra));
63} 68}
64static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp, int seqhilen) 69
70static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp, int extralen)
65{ 71{
66 return crypto_aead_ivsize(aead) ? 72 return crypto_aead_ivsize(aead) ?
67 PTR_ALIGN((u8 *)tmp + seqhilen, 73 PTR_ALIGN((u8 *)tmp + extralen,
68 crypto_aead_alignmask(aead) + 1) : tmp + seqhilen; 74 crypto_aead_alignmask(aead) + 1) : tmp + extralen;
69} 75}
70 76
71static inline struct aead_request *esp_tmp_req(struct crypto_aead *aead, u8 *iv) 77static inline struct aead_request *esp_tmp_req(struct crypto_aead *aead, u8 *iv)
@@ -99,7 +105,7 @@ static void esp_restore_header(struct sk_buff *skb, unsigned int offset)
99{ 105{
100 struct ip_esp_hdr *esph = (void *)(skb->data + offset); 106 struct ip_esp_hdr *esph = (void *)(skb->data + offset);
101 void *tmp = ESP_SKB_CB(skb)->tmp; 107 void *tmp = ESP_SKB_CB(skb)->tmp;
102 __be32 *seqhi = esp_tmp_seqhi(tmp); 108 __be32 *seqhi = esp_tmp_extra(tmp);
103 109
104 esph->seq_no = esph->spi; 110 esph->seq_no = esph->spi;
105 esph->spi = *seqhi; 111 esph->spi = *seqhi;
@@ -107,7 +113,11 @@ static void esp_restore_header(struct sk_buff *skb, unsigned int offset)
107 113
108static void esp_output_restore_header(struct sk_buff *skb) 114static void esp_output_restore_header(struct sk_buff *skb)
109{ 115{
110 esp_restore_header(skb, skb_transport_offset(skb) - sizeof(__be32)); 116 void *tmp = ESP_SKB_CB(skb)->tmp;
117 struct esp_output_extra *extra = esp_tmp_extra(tmp);
118
119 esp_restore_header(skb, skb_transport_offset(skb) + extra->esphoff -
120 sizeof(__be32));
111} 121}
112 122
113static void esp_output_done_esn(struct crypto_async_request *base, int err) 123static void esp_output_done_esn(struct crypto_async_request *base, int err)
@@ -121,6 +131,7 @@ static void esp_output_done_esn(struct crypto_async_request *base, int err)
121static int esp_output(struct xfrm_state *x, struct sk_buff *skb) 131static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
122{ 132{
123 int err; 133 int err;
134 struct esp_output_extra *extra;
124 struct ip_esp_hdr *esph; 135 struct ip_esp_hdr *esph;
125 struct crypto_aead *aead; 136 struct crypto_aead *aead;
126 struct aead_request *req; 137 struct aead_request *req;
@@ -137,8 +148,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
137 int tfclen; 148 int tfclen;
138 int nfrags; 149 int nfrags;
139 int assoclen; 150 int assoclen;
140 int seqhilen; 151 int extralen;
141 __be32 *seqhi;
142 __be64 seqno; 152 __be64 seqno;
143 153
144 /* skb is pure payload to encrypt */ 154 /* skb is pure payload to encrypt */
@@ -166,21 +176,21 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
166 nfrags = err; 176 nfrags = err;
167 177
168 assoclen = sizeof(*esph); 178 assoclen = sizeof(*esph);
169 seqhilen = 0; 179 extralen = 0;
170 180
171 if (x->props.flags & XFRM_STATE_ESN) { 181 if (x->props.flags & XFRM_STATE_ESN) {
172 seqhilen += sizeof(__be32); 182 extralen += sizeof(*extra);
173 assoclen += seqhilen; 183 assoclen += sizeof(__be32);
174 } 184 }
175 185
176 tmp = esp_alloc_tmp(aead, nfrags, seqhilen); 186 tmp = esp_alloc_tmp(aead, nfrags, extralen);
177 if (!tmp) { 187 if (!tmp) {
178 err = -ENOMEM; 188 err = -ENOMEM;
179 goto error; 189 goto error;
180 } 190 }
181 191
182 seqhi = esp_tmp_seqhi(tmp); 192 extra = esp_tmp_extra(tmp);
183 iv = esp_tmp_iv(aead, tmp, seqhilen); 193 iv = esp_tmp_iv(aead, tmp, extralen);
184 req = esp_tmp_req(aead, iv); 194 req = esp_tmp_req(aead, iv);
185 sg = esp_req_sg(aead, req); 195 sg = esp_req_sg(aead, req);
186 196
@@ -247,8 +257,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
247 * encryption. 257 * encryption.
248 */ 258 */
249 if ((x->props.flags & XFRM_STATE_ESN)) { 259 if ((x->props.flags & XFRM_STATE_ESN)) {
250 esph = (void *)(skb_transport_header(skb) - sizeof(__be32)); 260 extra->esphoff = (unsigned char *)esph -
251 *seqhi = esph->spi; 261 skb_transport_header(skb);
262 esph = (struct ip_esp_hdr *)((unsigned char *)esph - 4);
263 extra->seqhi = esph->spi;
252 esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.hi); 264 esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
253 aead_request_set_callback(req, 0, esp_output_done_esn, skb); 265 aead_request_set_callback(req, 0, esp_output_done_esn, skb);
254 } 266 }
@@ -445,7 +457,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
445 goto out; 457 goto out;
446 458
447 ESP_SKB_CB(skb)->tmp = tmp; 459 ESP_SKB_CB(skb)->tmp = tmp;
448 seqhi = esp_tmp_seqhi(tmp); 460 seqhi = esp_tmp_extra(tmp);
449 iv = esp_tmp_iv(aead, tmp, seqhilen); 461 iv = esp_tmp_iv(aead, tmp, seqhilen);
450 req = esp_tmp_req(aead, iv); 462 req = esp_tmp_req(aead, iv);
451 sg = esp_req_sg(aead, req); 463 sg = esp_req_sg(aead, req);