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.c90
1 files changed, 52 insertions, 38 deletions
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index a278d5e862fe..2ebfd281e721 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -24,6 +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/err.h>
27#include <linux/module.h> 28#include <linux/module.h>
28#include <net/ip.h> 29#include <net/ip.h>
29#include <net/xfrm.h> 30#include <net/xfrm.h>
@@ -44,7 +45,8 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
44 int hdr_len; 45 int hdr_len;
45 struct ipv6hdr *top_iph; 46 struct ipv6hdr *top_iph;
46 struct ipv6_esp_hdr *esph; 47 struct ipv6_esp_hdr *esph;
47 struct crypto_tfm *tfm; 48 struct crypto_blkcipher *tfm;
49 struct blkcipher_desc desc;
48 struct esp_data *esp; 50 struct esp_data *esp;
49 struct sk_buff *trailer; 51 struct sk_buff *trailer;
50 int blksize; 52 int blksize;
@@ -67,7 +69,9 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
67 69
68 alen = esp->auth.icv_trunc_len; 70 alen = esp->auth.icv_trunc_len;
69 tfm = esp->conf.tfm; 71 tfm = esp->conf.tfm;
70 blksize = ALIGN(crypto_tfm_alg_blocksize(tfm), 4); 72 desc.tfm = tfm;
73 desc.flags = 0;
74 blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4);
71 clen = ALIGN(clen + 2, blksize); 75 clen = ALIGN(clen + 2, blksize);
72 if (esp->conf.padlen) 76 if (esp->conf.padlen)
73 clen = ALIGN(clen, esp->conf.padlen); 77 clen = ALIGN(clen, esp->conf.padlen);
@@ -96,7 +100,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
96 xfrm_aevent_doreplay(x); 100 xfrm_aevent_doreplay(x);
97 101
98 if (esp->conf.ivlen) 102 if (esp->conf.ivlen)
99 crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); 103 crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen);
100 104
101 do { 105 do {
102 struct scatterlist *sg = &esp->sgbuf[0]; 106 struct scatterlist *sg = &esp->sgbuf[0];
@@ -107,24 +111,25 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
107 goto error; 111 goto error;
108 } 112 }
109 skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen); 113 skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen);
110 crypto_cipher_encrypt(tfm, sg, sg, clen); 114 err = crypto_blkcipher_encrypt(&desc, sg, sg, clen);
111 if (unlikely(sg != &esp->sgbuf[0])) 115 if (unlikely(sg != &esp->sgbuf[0]))
112 kfree(sg); 116 kfree(sg);
113 } while (0); 117 } while (0);
114 118
119 if (unlikely(err))
120 goto error;
121
115 if (esp->conf.ivlen) { 122 if (esp->conf.ivlen) {
116 memcpy(esph->enc_data, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); 123 memcpy(esph->enc_data, esp->conf.ivec, esp->conf.ivlen);
117 crypto_cipher_get_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); 124 crypto_blkcipher_get_iv(tfm, esp->conf.ivec, esp->conf.ivlen);
118 } 125 }
119 126
120 if (esp->auth.icv_full_len) { 127 if (esp->auth.icv_full_len) {
121 esp->auth.icv(esp, skb, (u8*)esph-skb->data, 128 err = esp_mac_digest(esp, skb, (u8 *)esph - skb->data,
122 sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen+clen, trailer->tail); 129 sizeof(*esph) + esp->conf.ivlen + clen);
123 pskb_put(skb, trailer, alen); 130 memcpy(pskb_put(skb, trailer, alen), esp->auth.work_icv, alen);
124 } 131 }
125 132
126 err = 0;
127
128error: 133error:
129 return err; 134 return err;
130} 135}
@@ -134,8 +139,10 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
134 struct ipv6hdr *iph; 139 struct ipv6hdr *iph;
135 struct ipv6_esp_hdr *esph; 140 struct ipv6_esp_hdr *esph;
136 struct esp_data *esp = x->data; 141 struct esp_data *esp = x->data;
142 struct crypto_blkcipher *tfm = esp->conf.tfm;
143 struct blkcipher_desc desc = { .tfm = tfm };
137 struct sk_buff *trailer; 144 struct sk_buff *trailer;
138 int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); 145 int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4);
139 int alen = esp->auth.icv_trunc_len; 146 int alen = esp->auth.icv_trunc_len;
140 int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen; 147 int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen;
141 148
@@ -155,15 +162,16 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
155 162
156 /* If integrity check is required, do this. */ 163 /* If integrity check is required, do this. */
157 if (esp->auth.icv_full_len) { 164 if (esp->auth.icv_full_len) {
158 u8 sum[esp->auth.icv_full_len]; 165 u8 sum[alen];
159 u8 sum1[alen];
160 166
161 esp->auth.icv(esp, skb, 0, skb->len-alen, sum); 167 ret = esp_mac_digest(esp, skb, 0, skb->len - alen);
168 if (ret)
169 goto out;
162 170
163 if (skb_copy_bits(skb, skb->len-alen, sum1, alen)) 171 if (skb_copy_bits(skb, skb->len - alen, sum, alen))
164 BUG(); 172 BUG();
165 173
166 if (unlikely(memcmp(sum, sum1, alen))) { 174 if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) {
167 x->stats.integrity_failed++; 175 x->stats.integrity_failed++;
168 ret = -EINVAL; 176 ret = -EINVAL;
169 goto out; 177 goto out;
@@ -182,7 +190,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
182 190
183 /* Get ivec. This can be wrong, check against another impls. */ 191 /* Get ivec. This can be wrong, check against another impls. */
184 if (esp->conf.ivlen) 192 if (esp->conf.ivlen)
185 crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm)); 193 crypto_blkcipher_set_iv(tfm, esph->enc_data, esp->conf.ivlen);
186 194
187 { 195 {
188 u8 nexthdr[2]; 196 u8 nexthdr[2];
@@ -197,9 +205,11 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
197 } 205 }
198 } 206 }
199 skb_to_sgvec(skb, sg, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen, elen); 207 skb_to_sgvec(skb, sg, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen, elen);
200 crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen); 208 ret = crypto_blkcipher_decrypt(&desc, sg, sg, elen);
201 if (unlikely(sg != &esp->sgbuf[0])) 209 if (unlikely(sg != &esp->sgbuf[0]))
202 kfree(sg); 210 kfree(sg);
211 if (unlikely(ret))
212 goto out;
203 213
204 if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) 214 if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2))
205 BUG(); 215 BUG();
@@ -225,7 +235,7 @@ out:
225static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) 235static u32 esp6_get_max_size(struct xfrm_state *x, int mtu)
226{ 236{
227 struct esp_data *esp = x->data; 237 struct esp_data *esp = x->data;
228 u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); 238 u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4);
229 239
230 if (x->props.mode) { 240 if (x->props.mode) {
231 mtu = ALIGN(mtu + 2, blksize); 241 mtu = ALIGN(mtu + 2, blksize);
@@ -266,11 +276,11 @@ static void esp6_destroy(struct xfrm_state *x)
266 if (!esp) 276 if (!esp)
267 return; 277 return;
268 278
269 crypto_free_tfm(esp->conf.tfm); 279 crypto_free_blkcipher(esp->conf.tfm);
270 esp->conf.tfm = NULL; 280 esp->conf.tfm = NULL;
271 kfree(esp->conf.ivec); 281 kfree(esp->conf.ivec);
272 esp->conf.ivec = NULL; 282 esp->conf.ivec = NULL;
273 crypto_free_tfm(esp->auth.tfm); 283 crypto_free_hash(esp->auth.tfm);
274 esp->auth.tfm = NULL; 284 esp->auth.tfm = NULL;
275 kfree(esp->auth.work_icv); 285 kfree(esp->auth.work_icv);
276 esp->auth.work_icv = NULL; 286 esp->auth.work_icv = NULL;
@@ -280,6 +290,7 @@ static void esp6_destroy(struct xfrm_state *x)
280static int esp6_init_state(struct xfrm_state *x) 290static int esp6_init_state(struct xfrm_state *x)
281{ 291{
282 struct esp_data *esp = NULL; 292 struct esp_data *esp = NULL;
293 struct crypto_blkcipher *tfm;
283 294
284 /* null auth and encryption can have zero length keys */ 295 /* null auth and encryption can have zero length keys */
285 if (x->aalg) { 296 if (x->aalg) {
@@ -298,24 +309,29 @@ static int esp6_init_state(struct xfrm_state *x)
298 309
299 if (x->aalg) { 310 if (x->aalg) {
300 struct xfrm_algo_desc *aalg_desc; 311 struct xfrm_algo_desc *aalg_desc;
312 struct crypto_hash *hash;
301 313
302 esp->auth.key = x->aalg->alg_key; 314 esp->auth.key = x->aalg->alg_key;
303 esp->auth.key_len = (x->aalg->alg_key_len+7)/8; 315 esp->auth.key_len = (x->aalg->alg_key_len+7)/8;
304 esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); 316 hash = crypto_alloc_hash(x->aalg->alg_name, 0,
305 if (esp->auth.tfm == NULL) 317 CRYPTO_ALG_ASYNC);
318 if (IS_ERR(hash))
319 goto error;
320
321 esp->auth.tfm = hash;
322 if (crypto_hash_setkey(hash, esp->auth.key, esp->auth.key_len))
306 goto error; 323 goto error;
307 esp->auth.icv = esp_hmac_digest;
308 324
309 aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); 325 aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
310 BUG_ON(!aalg_desc); 326 BUG_ON(!aalg_desc);
311 327
312 if (aalg_desc->uinfo.auth.icv_fullbits/8 != 328 if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
313 crypto_tfm_alg_digestsize(esp->auth.tfm)) { 329 crypto_hash_digestsize(hash)) {
314 printk(KERN_INFO "ESP: %s digestsize %u != %hu\n", 330 NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n",
315 x->aalg->alg_name, 331 x->aalg->alg_name,
316 crypto_tfm_alg_digestsize(esp->auth.tfm), 332 crypto_hash_digestsize(hash),
317 aalg_desc->uinfo.auth.icv_fullbits/8); 333 aalg_desc->uinfo.auth.icv_fullbits/8);
318 goto error; 334 goto error;
319 } 335 }
320 336
321 esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8; 337 esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
@@ -327,13 +343,11 @@ static int esp6_init_state(struct xfrm_state *x)
327 } 343 }
328 esp->conf.key = x->ealg->alg_key; 344 esp->conf.key = x->ealg->alg_key;
329 esp->conf.key_len = (x->ealg->alg_key_len+7)/8; 345 esp->conf.key_len = (x->ealg->alg_key_len+7)/8;
330 if (x->props.ealgo == SADB_EALG_NULL) 346 tfm = crypto_alloc_blkcipher(x->ealg->alg_name, 0, CRYPTO_ALG_ASYNC);
331 esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB); 347 if (IS_ERR(tfm))
332 else
333 esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC);
334 if (esp->conf.tfm == NULL)
335 goto error; 348 goto error;
336 esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm); 349 esp->conf.tfm = tfm;
350 esp->conf.ivlen = crypto_blkcipher_ivsize(tfm);
337 esp->conf.padlen = 0; 351 esp->conf.padlen = 0;
338 if (esp->conf.ivlen) { 352 if (esp->conf.ivlen) {
339 esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); 353 esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
@@ -341,7 +355,7 @@ static int esp6_init_state(struct xfrm_state *x)
341 goto error; 355 goto error;
342 get_random_bytes(esp->conf.ivec, esp->conf.ivlen); 356 get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
343 } 357 }
344 if (crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len)) 358 if (crypto_blkcipher_setkey(tfm, esp->conf.key, esp->conf.key_len))
345 goto error; 359 goto error;
346 x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen; 360 x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
347 if (x->props.mode) 361 if (x->props.mode)