diff options
Diffstat (limited to 'net/ipv6/esp6.c')
-rw-r--r-- | net/ipv6/esp6.c | 90 |
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 | |||
128 | error: | 133 | error: |
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: | |||
225 | static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) | 235 | static 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) | |||
280 | static int esp6_init_state(struct xfrm_state *x) | 290 | static 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) |