aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/esp6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/esp6.c')
-rw-r--r--net/ipv6/esp6.c107
1 files changed, 63 insertions, 44 deletions
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index a15a6f320f70..e78680a9985b 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -24,7 +24,7 @@
24 * This file is derived from net/ipv4/esp.c 24 * This file is derived from net/ipv4/esp.c
25 */ 25 */
26 26
27#include <linux/config.h> 27#include <linux/err.h>
28#include <linux/module.h> 28#include <linux/module.h>
29#include <net/ip.h> 29#include <net/ip.h>
30#include <net/xfrm.h> 30#include <net/xfrm.h>
@@ -45,7 +45,8 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
45 int hdr_len; 45 int hdr_len;
46 struct ipv6hdr *top_iph; 46 struct ipv6hdr *top_iph;
47 struct ipv6_esp_hdr *esph; 47 struct ipv6_esp_hdr *esph;
48 struct crypto_tfm *tfm; 48 struct crypto_blkcipher *tfm;
49 struct blkcipher_desc desc;
49 struct esp_data *esp; 50 struct esp_data *esp;
50 struct sk_buff *trailer; 51 struct sk_buff *trailer;
51 int blksize; 52 int blksize;
@@ -68,7 +69,9 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
68 69
69 alen = esp->auth.icv_trunc_len; 70 alen = esp->auth.icv_trunc_len;
70 tfm = esp->conf.tfm; 71 tfm = esp->conf.tfm;
71 blksize = ALIGN(crypto_tfm_alg_blocksize(tfm), 4); 72 desc.tfm = tfm;
73 desc.flags = 0;
74 blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4);
72 clen = ALIGN(clen + 2, blksize); 75 clen = ALIGN(clen + 2, blksize);
73 if (esp->conf.padlen) 76 if (esp->conf.padlen)
74 clen = ALIGN(clen, esp->conf.padlen); 77 clen = ALIGN(clen, esp->conf.padlen);
@@ -96,8 +99,13 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
96 esph->seq_no = htonl(++x->replay.oseq); 99 esph->seq_no = htonl(++x->replay.oseq);
97 xfrm_aevent_doreplay(x); 100 xfrm_aevent_doreplay(x);
98 101
99 if (esp->conf.ivlen) 102 if (esp->conf.ivlen) {
100 crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); 103 if (unlikely(!esp->conf.ivinitted)) {
104 get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
105 esp->conf.ivinitted = 1;
106 }
107 crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen);
108 }
101 109
102 do { 110 do {
103 struct scatterlist *sg = &esp->sgbuf[0]; 111 struct scatterlist *sg = &esp->sgbuf[0];
@@ -108,24 +116,25 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
108 goto error; 116 goto error;
109 } 117 }
110 skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen); 118 skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen);
111 crypto_cipher_encrypt(tfm, sg, sg, clen); 119 err = crypto_blkcipher_encrypt(&desc, sg, sg, clen);
112 if (unlikely(sg != &esp->sgbuf[0])) 120 if (unlikely(sg != &esp->sgbuf[0]))
113 kfree(sg); 121 kfree(sg);
114 } while (0); 122 } while (0);
115 123
124 if (unlikely(err))
125 goto error;
126
116 if (esp->conf.ivlen) { 127 if (esp->conf.ivlen) {
117 memcpy(esph->enc_data, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); 128 memcpy(esph->enc_data, esp->conf.ivec, esp->conf.ivlen);
118 crypto_cipher_get_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); 129 crypto_blkcipher_get_iv(tfm, esp->conf.ivec, esp->conf.ivlen);
119 } 130 }
120 131
121 if (esp->auth.icv_full_len) { 132 if (esp->auth.icv_full_len) {
122 esp->auth.icv(esp, skb, (u8*)esph-skb->data, 133 err = esp_mac_digest(esp, skb, (u8 *)esph - skb->data,
123 sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen+clen, trailer->tail); 134 sizeof(*esph) + esp->conf.ivlen + clen);
124 pskb_put(skb, trailer, alen); 135 memcpy(pskb_put(skb, trailer, alen), esp->auth.work_icv, alen);
125 } 136 }
126 137
127 err = 0;
128
129error: 138error:
130 return err; 139 return err;
131} 140}
@@ -135,8 +144,10 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
135 struct ipv6hdr *iph; 144 struct ipv6hdr *iph;
136 struct ipv6_esp_hdr *esph; 145 struct ipv6_esp_hdr *esph;
137 struct esp_data *esp = x->data; 146 struct esp_data *esp = x->data;
147 struct crypto_blkcipher *tfm = esp->conf.tfm;
148 struct blkcipher_desc desc = { .tfm = tfm };
138 struct sk_buff *trailer; 149 struct sk_buff *trailer;
139 int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); 150 int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4);
140 int alen = esp->auth.icv_trunc_len; 151 int alen = esp->auth.icv_trunc_len;
141 int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen; 152 int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen;
142 153
@@ -156,15 +167,16 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
156 167
157 /* If integrity check is required, do this. */ 168 /* If integrity check is required, do this. */
158 if (esp->auth.icv_full_len) { 169 if (esp->auth.icv_full_len) {
159 u8 sum[esp->auth.icv_full_len]; 170 u8 sum[alen];
160 u8 sum1[alen];
161 171
162 esp->auth.icv(esp, skb, 0, skb->len-alen, sum); 172 ret = esp_mac_digest(esp, skb, 0, skb->len - alen);
173 if (ret)
174 goto out;
163 175
164 if (skb_copy_bits(skb, skb->len-alen, sum1, alen)) 176 if (skb_copy_bits(skb, skb->len - alen, sum, alen))
165 BUG(); 177 BUG();
166 178
167 if (unlikely(memcmp(sum, sum1, alen))) { 179 if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) {
168 x->stats.integrity_failed++; 180 x->stats.integrity_failed++;
169 ret = -EINVAL; 181 ret = -EINVAL;
170 goto out; 182 goto out;
@@ -183,7 +195,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
183 195
184 /* Get ivec. This can be wrong, check against another impls. */ 196 /* Get ivec. This can be wrong, check against another impls. */
185 if (esp->conf.ivlen) 197 if (esp->conf.ivlen)
186 crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm)); 198 crypto_blkcipher_set_iv(tfm, esph->enc_data, esp->conf.ivlen);
187 199
188 { 200 {
189 u8 nexthdr[2]; 201 u8 nexthdr[2];
@@ -198,9 +210,11 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
198 } 210 }
199 } 211 }
200 skb_to_sgvec(skb, sg, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen, elen); 212 skb_to_sgvec(skb, sg, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen, elen);
201 crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen); 213 ret = crypto_blkcipher_decrypt(&desc, sg, sg, elen);
202 if (unlikely(sg != &esp->sgbuf[0])) 214 if (unlikely(sg != &esp->sgbuf[0]))
203 kfree(sg); 215 kfree(sg);
216 if (unlikely(ret))
217 goto out;
204 218
205 if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) 219 if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2))
206 BUG(); 220 BUG();
@@ -226,9 +240,9 @@ out:
226static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) 240static u32 esp6_get_max_size(struct xfrm_state *x, int mtu)
227{ 241{
228 struct esp_data *esp = x->data; 242 struct esp_data *esp = x->data;
229 u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); 243 u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4);
230 244
231 if (x->props.mode) { 245 if (x->props.mode == XFRM_MODE_TUNNEL) {
232 mtu = ALIGN(mtu + 2, blksize); 246 mtu = ALIGN(mtu + 2, blksize);
233 } else { 247 } else {
234 /* The worst case. */ 248 /* The worst case. */
@@ -267,11 +281,11 @@ static void esp6_destroy(struct xfrm_state *x)
267 if (!esp) 281 if (!esp)
268 return; 282 return;
269 283
270 crypto_free_tfm(esp->conf.tfm); 284 crypto_free_blkcipher(esp->conf.tfm);
271 esp->conf.tfm = NULL; 285 esp->conf.tfm = NULL;
272 kfree(esp->conf.ivec); 286 kfree(esp->conf.ivec);
273 esp->conf.ivec = NULL; 287 esp->conf.ivec = NULL;
274 crypto_free_tfm(esp->auth.tfm); 288 crypto_free_hash(esp->auth.tfm);
275 esp->auth.tfm = NULL; 289 esp->auth.tfm = NULL;
276 kfree(esp->auth.work_icv); 290 kfree(esp->auth.work_icv);
277 esp->auth.work_icv = NULL; 291 esp->auth.work_icv = NULL;
@@ -281,6 +295,7 @@ static void esp6_destroy(struct xfrm_state *x)
281static int esp6_init_state(struct xfrm_state *x) 295static int esp6_init_state(struct xfrm_state *x)
282{ 296{
283 struct esp_data *esp = NULL; 297 struct esp_data *esp = NULL;
298 struct crypto_blkcipher *tfm;
284 299
285 /* null auth and encryption can have zero length keys */ 300 /* null auth and encryption can have zero length keys */
286 if (x->aalg) { 301 if (x->aalg) {
@@ -299,24 +314,29 @@ static int esp6_init_state(struct xfrm_state *x)
299 314
300 if (x->aalg) { 315 if (x->aalg) {
301 struct xfrm_algo_desc *aalg_desc; 316 struct xfrm_algo_desc *aalg_desc;
317 struct crypto_hash *hash;
302 318
303 esp->auth.key = x->aalg->alg_key; 319 esp->auth.key = x->aalg->alg_key;
304 esp->auth.key_len = (x->aalg->alg_key_len+7)/8; 320 esp->auth.key_len = (x->aalg->alg_key_len+7)/8;
305 esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); 321 hash = crypto_alloc_hash(x->aalg->alg_name, 0,
306 if (esp->auth.tfm == NULL) 322 CRYPTO_ALG_ASYNC);
323 if (IS_ERR(hash))
324 goto error;
325
326 esp->auth.tfm = hash;
327 if (crypto_hash_setkey(hash, esp->auth.key, esp->auth.key_len))
307 goto error; 328 goto error;
308 esp->auth.icv = esp_hmac_digest;
309 329
310 aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); 330 aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
311 BUG_ON(!aalg_desc); 331 BUG_ON(!aalg_desc);
312 332
313 if (aalg_desc->uinfo.auth.icv_fullbits/8 != 333 if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
314 crypto_tfm_alg_digestsize(esp->auth.tfm)) { 334 crypto_hash_digestsize(hash)) {
315 printk(KERN_INFO "ESP: %s digestsize %u != %hu\n", 335 NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n",
316 x->aalg->alg_name, 336 x->aalg->alg_name,
317 crypto_tfm_alg_digestsize(esp->auth.tfm), 337 crypto_hash_digestsize(hash),
318 aalg_desc->uinfo.auth.icv_fullbits/8); 338 aalg_desc->uinfo.auth.icv_fullbits/8);
319 goto error; 339 goto error;
320 } 340 }
321 341
322 esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8; 342 esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
@@ -328,24 +348,22 @@ static int esp6_init_state(struct xfrm_state *x)
328 } 348 }
329 esp->conf.key = x->ealg->alg_key; 349 esp->conf.key = x->ealg->alg_key;
330 esp->conf.key_len = (x->ealg->alg_key_len+7)/8; 350 esp->conf.key_len = (x->ealg->alg_key_len+7)/8;
331 if (x->props.ealgo == SADB_EALG_NULL) 351 tfm = crypto_alloc_blkcipher(x->ealg->alg_name, 0, CRYPTO_ALG_ASYNC);
332 esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB); 352 if (IS_ERR(tfm))
333 else
334 esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC);
335 if (esp->conf.tfm == NULL)
336 goto error; 353 goto error;
337 esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm); 354 esp->conf.tfm = tfm;
355 esp->conf.ivlen = crypto_blkcipher_ivsize(tfm);
338 esp->conf.padlen = 0; 356 esp->conf.padlen = 0;
339 if (esp->conf.ivlen) { 357 if (esp->conf.ivlen) {
340 esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); 358 esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
341 if (unlikely(esp->conf.ivec == NULL)) 359 if (unlikely(esp->conf.ivec == NULL))
342 goto error; 360 goto error;
343 get_random_bytes(esp->conf.ivec, esp->conf.ivlen); 361 esp->conf.ivinitted = 0;
344 } 362 }
345 if (crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len)) 363 if (crypto_blkcipher_setkey(tfm, esp->conf.key, esp->conf.key_len))
346 goto error; 364 goto error;
347 x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen; 365 x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
348 if (x->props.mode) 366 if (x->props.mode == XFRM_MODE_TUNNEL)
349 x->props.header_len += sizeof(struct ipv6hdr); 367 x->props.header_len += sizeof(struct ipv6hdr);
350 x->data = esp; 368 x->data = esp;
351 return 0; 369 return 0;
@@ -366,7 +384,8 @@ static struct xfrm_type esp6_type =
366 .destructor = esp6_destroy, 384 .destructor = esp6_destroy,
367 .get_max_size = esp6_get_max_size, 385 .get_max_size = esp6_get_max_size,
368 .input = esp6_input, 386 .input = esp6_input,
369 .output = esp6_output 387 .output = esp6_output,
388 .hdr_offset = xfrm6_find_1stfragopt,
370}; 389};
371 390
372static struct inet6_protocol esp6_protocol = { 391static struct inet6_protocol esp6_protocol = {