aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/ah.h29
-rw-r--r--include/net/esp.h28
-rw-r--r--include/net/xfrm.h9
-rw-r--r--net/ipv4/ah4.c36
-rw-r--r--net/ipv4/esp4.c36
-rw-r--r--net/ipv6/ah6.c35
-rw-r--r--net/ipv6/esp6.c42
-rw-r--r--net/xfrm/xfrm_algo.c40
8 files changed, 158 insertions, 97 deletions
diff --git a/include/net/ah.h b/include/net/ah.h
index 8e27c9ba8b84..8f257c159902 100644
--- a/include/net/ah.h
+++ b/include/net/ah.h
@@ -15,22 +15,29 @@ struct ah_data
15 int icv_full_len; 15 int icv_full_len;
16 int icv_trunc_len; 16 int icv_trunc_len;
17 17
18 void (*icv)(struct ah_data*, 18 struct crypto_hash *tfm;
19 struct sk_buff *skb, u8 *icv);
20
21 struct crypto_tfm *tfm;
22}; 19};
23 20
24static inline void 21static inline int ah_mac_digest(struct ah_data *ahp, struct sk_buff *skb,
25ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data) 22 u8 *auth_data)
26{ 23{
27 struct crypto_tfm *tfm = ahp->tfm; 24 struct hash_desc desc;
25 int err;
26
27 desc.tfm = ahp->tfm;
28 desc.flags = 0;
28 29
29 memset(auth_data, 0, ahp->icv_trunc_len); 30 memset(auth_data, 0, ahp->icv_trunc_len);
30 crypto_hmac_init(tfm, ahp->key, &ahp->key_len); 31 err = crypto_hash_init(&desc);
31 skb_icv_walk(skb, tfm, 0, skb->len, crypto_hmac_update); 32 if (unlikely(err))
32 crypto_hmac_final(tfm, ahp->key, &ahp->key_len, ahp->work_icv); 33 goto out;
33 memcpy(auth_data, ahp->work_icv, ahp->icv_trunc_len); 34 err = skb_icv_walk(skb, &desc, 0, skb->len, crypto_hash_update);
35 if (unlikely(err))
36 goto out;
37 err = crypto_hash_final(&desc, ahp->work_icv);
38
39out:
40 return err;
34} 41}
35 42
36#endif 43#endif
diff --git a/include/net/esp.h b/include/net/esp.h
index af2ff18700c7..064366d66eea 100644
--- a/include/net/esp.h
+++ b/include/net/esp.h
@@ -35,7 +35,7 @@ struct esp_data
35 void (*icv)(struct esp_data*, 35 void (*icv)(struct esp_data*,
36 struct sk_buff *skb, 36 struct sk_buff *skb,
37 int offset, int len, u8 *icv); 37 int offset, int len, u8 *icv);
38 struct crypto_tfm *tfm; 38 struct crypto_hash *tfm;
39 } auth; 39 } auth;
40}; 40};
41 41
@@ -43,18 +43,22 @@ extern int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset,
43extern int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer); 43extern int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer);
44extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len); 44extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len);
45 45
46static inline void 46static inline int esp_mac_digest(struct esp_data *esp, struct sk_buff *skb,
47esp_hmac_digest(struct esp_data *esp, struct sk_buff *skb, int offset, 47 int offset, int len)
48 int len, u8 *auth_data)
49{ 48{
50 struct crypto_tfm *tfm = esp->auth.tfm; 49 struct hash_desc desc;
51 char *icv = esp->auth.work_icv; 50 int err;
52 51
53 memset(auth_data, 0, esp->auth.icv_trunc_len); 52 desc.tfm = esp->auth.tfm;
54 crypto_hmac_init(tfm, esp->auth.key, &esp->auth.key_len); 53 desc.flags = 0;
55 skb_icv_walk(skb, tfm, offset, len, crypto_hmac_update); 54
56 crypto_hmac_final(tfm, esp->auth.key, &esp->auth.key_len, icv); 55 err = crypto_hash_init(&desc);
57 memcpy(auth_data, icv, esp->auth.icv_trunc_len); 56 if (unlikely(err))
57 return err;
58 err = skb_icv_walk(skb, &desc, offset, len, crypto_hash_update);
59 if (unlikely(err))
60 return err;
61 return crypto_hash_final(&desc, esp->auth.work_icv);
58} 62}
59 63
60#endif 64#endif
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index e9114e41affc..3ecd9fa1ed4b 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -984,12 +984,13 @@ extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe);
984extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe); 984extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe);
985extern struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe); 985extern struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe);
986 986
987struct crypto_tfm; 987struct hash_desc;
988struct scatterlist; 988struct scatterlist;
989typedef void (icv_update_fn_t)(struct crypto_tfm *, struct scatterlist *, unsigned int); 989typedef int (icv_update_fn_t)(struct hash_desc *, struct scatterlist *,
990 unsigned int);
990 991
991extern void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm, 992extern int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *tfm,
992 int offset, int len, icv_update_fn_t icv_update); 993 int offset, int len, icv_update_fn_t icv_update);
993 994
994static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b, 995static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b,
995 int family) 996 int family)
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 1366bc6ce6a5..2b98943e6b02 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -1,3 +1,4 @@
1#include <linux/err.h>
1#include <linux/module.h> 2#include <linux/module.h>
2#include <net/ip.h> 3#include <net/ip.h>
3#include <net/xfrm.h> 4#include <net/xfrm.h>
@@ -97,7 +98,10 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
97 ah->spi = x->id.spi; 98 ah->spi = x->id.spi;
98 ah->seq_no = htonl(++x->replay.oseq); 99 ah->seq_no = htonl(++x->replay.oseq);
99 xfrm_aevent_doreplay(x); 100 xfrm_aevent_doreplay(x);
100 ahp->icv(ahp, skb, ah->auth_data); 101 err = ah_mac_digest(ahp, skb, ah->auth_data);
102 if (err)
103 goto error;
104 memcpy(ah->auth_data, ahp->work_icv, ahp->icv_trunc_len);
101 105
102 top_iph->tos = iph->tos; 106 top_iph->tos = iph->tos;
103 top_iph->ttl = iph->ttl; 107 top_iph->ttl = iph->ttl;
@@ -119,6 +123,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
119{ 123{
120 int ah_hlen; 124 int ah_hlen;
121 int ihl; 125 int ihl;
126 int err = -EINVAL;
122 struct iphdr *iph; 127 struct iphdr *iph;
123 struct ip_auth_hdr *ah; 128 struct ip_auth_hdr *ah;
124 struct ah_data *ahp; 129 struct ah_data *ahp;
@@ -166,8 +171,11 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
166 171
167 memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); 172 memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
168 skb_push(skb, ihl); 173 skb_push(skb, ihl);
169 ahp->icv(ahp, skb, ah->auth_data); 174 err = ah_mac_digest(ahp, skb, ah->auth_data);
170 if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { 175 if (err)
176 goto out;
177 err = -EINVAL;
178 if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len)) {
171 x->stats.integrity_failed++; 179 x->stats.integrity_failed++;
172 goto out; 180 goto out;
173 } 181 }
@@ -179,7 +187,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
179 return 0; 187 return 0;
180 188
181out: 189out:
182 return -EINVAL; 190 return err;
183} 191}
184 192
185static void ah4_err(struct sk_buff *skb, u32 info) 193static void ah4_err(struct sk_buff *skb, u32 info)
@@ -204,6 +212,7 @@ static int ah_init_state(struct xfrm_state *x)
204{ 212{
205 struct ah_data *ahp = NULL; 213 struct ah_data *ahp = NULL;
206 struct xfrm_algo_desc *aalg_desc; 214 struct xfrm_algo_desc *aalg_desc;
215 struct crypto_hash *tfm;
207 216
208 if (!x->aalg) 217 if (!x->aalg)
209 goto error; 218 goto error;
@@ -221,24 +230,27 @@ static int ah_init_state(struct xfrm_state *x)
221 230
222 ahp->key = x->aalg->alg_key; 231 ahp->key = x->aalg->alg_key;
223 ahp->key_len = (x->aalg->alg_key_len+7)/8; 232 ahp->key_len = (x->aalg->alg_key_len+7)/8;
224 ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); 233 tfm = crypto_alloc_hash(x->aalg->alg_name, 0, CRYPTO_ALG_ASYNC);
225 if (!ahp->tfm) 234 if (IS_ERR(tfm))
235 goto error;
236
237 ahp->tfm = tfm;
238 if (crypto_hash_setkey(tfm, ahp->key, ahp->key_len))
226 goto error; 239 goto error;
227 ahp->icv = ah_hmac_digest;
228 240
229 /* 241 /*
230 * Lookup the algorithm description maintained by xfrm_algo, 242 * Lookup the algorithm description maintained by xfrm_algo,
231 * verify crypto transform properties, and store information 243 * verify crypto transform properties, and store information
232 * we need for AH processing. This lookup cannot fail here 244 * we need for AH processing. This lookup cannot fail here
233 * after a successful crypto_alloc_tfm(). 245 * after a successful crypto_alloc_hash().
234 */ 246 */
235 aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); 247 aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
236 BUG_ON(!aalg_desc); 248 BUG_ON(!aalg_desc);
237 249
238 if (aalg_desc->uinfo.auth.icv_fullbits/8 != 250 if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
239 crypto_tfm_alg_digestsize(ahp->tfm)) { 251 crypto_hash_digestsize(tfm)) {
240 printk(KERN_INFO "AH: %s digestsize %u != %hu\n", 252 printk(KERN_INFO "AH: %s digestsize %u != %hu\n",
241 x->aalg->alg_name, crypto_tfm_alg_digestsize(ahp->tfm), 253 x->aalg->alg_name, crypto_hash_digestsize(tfm),
242 aalg_desc->uinfo.auth.icv_fullbits/8); 254 aalg_desc->uinfo.auth.icv_fullbits/8);
243 goto error; 255 goto error;
244 } 256 }
@@ -262,7 +274,7 @@ static int ah_init_state(struct xfrm_state *x)
262error: 274error:
263 if (ahp) { 275 if (ahp) {
264 kfree(ahp->work_icv); 276 kfree(ahp->work_icv);
265 crypto_free_tfm(ahp->tfm); 277 crypto_free_hash(ahp->tfm);
266 kfree(ahp); 278 kfree(ahp);
267 } 279 }
268 return -EINVAL; 280 return -EINVAL;
@@ -277,7 +289,7 @@ static void ah_destroy(struct xfrm_state *x)
277 289
278 kfree(ahp->work_icv); 290 kfree(ahp->work_icv);
279 ahp->work_icv = NULL; 291 ahp->work_icv = NULL;
280 crypto_free_tfm(ahp->tfm); 292 crypto_free_hash(ahp->tfm);
281 ahp->tfm = NULL; 293 ahp->tfm = NULL;
282 kfree(ahp); 294 kfree(ahp);
283} 295}
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 7c63ae494742..b428489f6ccd 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -121,9 +121,9 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
121 } 121 }
122 122
123 if (esp->auth.icv_full_len) { 123 if (esp->auth.icv_full_len) {
124 esp->auth.icv(esp, skb, (u8*)esph-skb->data, 124 err = esp_mac_digest(esp, skb, (u8 *)esph - skb->data,
125 sizeof(struct ip_esp_hdr) + esp->conf.ivlen+clen, trailer->tail); 125 sizeof(*esph) + esp->conf.ivlen + clen);
126 pskb_put(skb, trailer, alen); 126 memcpy(pskb_put(skb, trailer, alen), esp->auth.work_icv, alen);
127 } 127 }
128 128
129 ip_send_check(top_iph); 129 ip_send_check(top_iph);
@@ -163,15 +163,16 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
163 163
164 /* If integrity check is required, do this. */ 164 /* If integrity check is required, do this. */
165 if (esp->auth.icv_full_len) { 165 if (esp->auth.icv_full_len) {
166 u8 sum[esp->auth.icv_full_len]; 166 u8 sum[alen];
167 u8 sum1[alen];
168
169 esp->auth.icv(esp, skb, 0, skb->len-alen, sum);
170 167
171 if (skb_copy_bits(skb, skb->len-alen, sum1, alen)) 168 err = esp_mac_digest(esp, skb, 0, skb->len - alen);
169 if (err)
170 goto out;
171
172 if (skb_copy_bits(skb, skb->len - alen, sum, alen))
172 BUG(); 173 BUG();
173 174
174 if (unlikely(memcmp(sum, sum1, alen))) { 175 if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) {
175 x->stats.integrity_failed++; 176 x->stats.integrity_failed++;
176 goto out; 177 goto out;
177 } 178 }
@@ -307,7 +308,7 @@ static void esp_destroy(struct xfrm_state *x)
307 esp->conf.tfm = NULL; 308 esp->conf.tfm = NULL;
308 kfree(esp->conf.ivec); 309 kfree(esp->conf.ivec);
309 esp->conf.ivec = NULL; 310 esp->conf.ivec = NULL;
310 crypto_free_tfm(esp->auth.tfm); 311 crypto_free_hash(esp->auth.tfm);
311 esp->auth.tfm = NULL; 312 esp->auth.tfm = NULL;
312 kfree(esp->auth.work_icv); 313 kfree(esp->auth.work_icv);
313 esp->auth.work_icv = NULL; 314 esp->auth.work_icv = NULL;
@@ -333,22 +334,27 @@ static int esp_init_state(struct xfrm_state *x)
333 334
334 if (x->aalg) { 335 if (x->aalg) {
335 struct xfrm_algo_desc *aalg_desc; 336 struct xfrm_algo_desc *aalg_desc;
337 struct crypto_hash *hash;
336 338
337 esp->auth.key = x->aalg->alg_key; 339 esp->auth.key = x->aalg->alg_key;
338 esp->auth.key_len = (x->aalg->alg_key_len+7)/8; 340 esp->auth.key_len = (x->aalg->alg_key_len+7)/8;
339 esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); 341 hash = crypto_alloc_hash(x->aalg->alg_name, 0,
340 if (esp->auth.tfm == NULL) 342 CRYPTO_ALG_ASYNC);
343 if (IS_ERR(hash))
344 goto error;
345
346 esp->auth.tfm = hash;
347 if (crypto_hash_setkey(hash, esp->auth.key, esp->auth.key_len))
341 goto error; 348 goto error;
342 esp->auth.icv = esp_hmac_digest;
343 349
344 aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); 350 aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
345 BUG_ON(!aalg_desc); 351 BUG_ON(!aalg_desc);
346 352
347 if (aalg_desc->uinfo.auth.icv_fullbits/8 != 353 if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
348 crypto_tfm_alg_digestsize(esp->auth.tfm)) { 354 crypto_hash_digestsize(hash)) {
349 NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n", 355 NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n",
350 x->aalg->alg_name, 356 x->aalg->alg_name,
351 crypto_tfm_alg_digestsize(esp->auth.tfm), 357 crypto_hash_digestsize(hash),
352 aalg_desc->uinfo.auth.icv_fullbits/8); 358 aalg_desc->uinfo.auth.icv_fullbits/8);
353 goto error; 359 goto error;
354 } 360 }
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 9d4831bd4335..00ffa7bc6c9f 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -213,7 +213,10 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
213 ah->spi = x->id.spi; 213 ah->spi = x->id.spi;
214 ah->seq_no = htonl(++x->replay.oseq); 214 ah->seq_no = htonl(++x->replay.oseq);
215 xfrm_aevent_doreplay(x); 215 xfrm_aevent_doreplay(x);
216 ahp->icv(ahp, skb, ah->auth_data); 216 err = ah_mac_digest(ahp, skb, ah->auth_data);
217 if (err)
218 goto error_free_iph;
219 memcpy(ah->auth_data, ahp->work_icv, ahp->icv_trunc_len);
217 220
218 err = 0; 221 err = 0;
219 222
@@ -251,6 +254,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
251 u16 hdr_len; 254 u16 hdr_len;
252 u16 ah_hlen; 255 u16 ah_hlen;
253 int nexthdr; 256 int nexthdr;
257 int err = -EINVAL;
254 258
255 if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr))) 259 if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr)))
256 goto out; 260 goto out;
@@ -292,8 +296,11 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
292 memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); 296 memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
293 memset(ah->auth_data, 0, ahp->icv_trunc_len); 297 memset(ah->auth_data, 0, ahp->icv_trunc_len);
294 skb_push(skb, hdr_len); 298 skb_push(skb, hdr_len);
295 ahp->icv(ahp, skb, ah->auth_data); 299 err = ah_mac_digest(ahp, skb, ah->auth_data);
296 if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { 300 if (err)
301 goto free_out;
302 err = -EINVAL;
303 if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len)) {
297 LIMIT_NETDEBUG(KERN_WARNING "ipsec ah authentication error\n"); 304 LIMIT_NETDEBUG(KERN_WARNING "ipsec ah authentication error\n");
298 x->stats.integrity_failed++; 305 x->stats.integrity_failed++;
299 goto free_out; 306 goto free_out;
@@ -310,7 +317,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
310free_out: 317free_out:
311 kfree(tmp_hdr); 318 kfree(tmp_hdr);
312out: 319out:
313 return -EINVAL; 320 return err;
314} 321}
315 322
316static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 323static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
@@ -338,6 +345,7 @@ static int ah6_init_state(struct xfrm_state *x)
338{ 345{
339 struct ah_data *ahp = NULL; 346 struct ah_data *ahp = NULL;
340 struct xfrm_algo_desc *aalg_desc; 347 struct xfrm_algo_desc *aalg_desc;
348 struct crypto_hash *tfm;
341 349
342 if (!x->aalg) 350 if (!x->aalg)
343 goto error; 351 goto error;
@@ -355,24 +363,27 @@ static int ah6_init_state(struct xfrm_state *x)
355 363
356 ahp->key = x->aalg->alg_key; 364 ahp->key = x->aalg->alg_key;
357 ahp->key_len = (x->aalg->alg_key_len+7)/8; 365 ahp->key_len = (x->aalg->alg_key_len+7)/8;
358 ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); 366 tfm = crypto_alloc_hash(x->aalg->alg_name, 0, CRYPTO_ALG_ASYNC);
359 if (!ahp->tfm) 367 if (IS_ERR(tfm))
368 goto error;
369
370 ahp->tfm = tfm;
371 if (crypto_hash_setkey(tfm, ahp->key, ahp->key_len))
360 goto error; 372 goto error;
361 ahp->icv = ah_hmac_digest;
362 373
363 /* 374 /*
364 * Lookup the algorithm description maintained by xfrm_algo, 375 * Lookup the algorithm description maintained by xfrm_algo,
365 * verify crypto transform properties, and store information 376 * verify crypto transform properties, and store information
366 * we need for AH processing. This lookup cannot fail here 377 * we need for AH processing. This lookup cannot fail here
367 * after a successful crypto_alloc_tfm(). 378 * after a successful crypto_alloc_hash().
368 */ 379 */
369 aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); 380 aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
370 BUG_ON(!aalg_desc); 381 BUG_ON(!aalg_desc);
371 382
372 if (aalg_desc->uinfo.auth.icv_fullbits/8 != 383 if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
373 crypto_tfm_alg_digestsize(ahp->tfm)) { 384 crypto_hash_digestsize(tfm)) {
374 printk(KERN_INFO "AH: %s digestsize %u != %hu\n", 385 printk(KERN_INFO "AH: %s digestsize %u != %hu\n",
375 x->aalg->alg_name, crypto_tfm_alg_digestsize(ahp->tfm), 386 x->aalg->alg_name, crypto_hash_digestsize(tfm),
376 aalg_desc->uinfo.auth.icv_fullbits/8); 387 aalg_desc->uinfo.auth.icv_fullbits/8);
377 goto error; 388 goto error;
378 } 389 }
@@ -396,7 +407,7 @@ static int ah6_init_state(struct xfrm_state *x)
396error: 407error:
397 if (ahp) { 408 if (ahp) {
398 kfree(ahp->work_icv); 409 kfree(ahp->work_icv);
399 crypto_free_tfm(ahp->tfm); 410 crypto_free_hash(ahp->tfm);
400 kfree(ahp); 411 kfree(ahp);
401 } 412 }
402 return -EINVAL; 413 return -EINVAL;
@@ -411,7 +422,7 @@ static void ah6_destroy(struct xfrm_state *x)
411 422
412 kfree(ahp->work_icv); 423 kfree(ahp->work_icv);
413 ahp->work_icv = NULL; 424 ahp->work_icv = NULL;
414 crypto_free_tfm(ahp->tfm); 425 crypto_free_hash(ahp->tfm);
415 ahp->tfm = NULL; 426 ahp->tfm = NULL;
416 kfree(ahp); 427 kfree(ahp);
417} 428}
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 46a7e687948e..2ebfd281e721 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -125,9 +125,9 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
125 } 125 }
126 126
127 if (esp->auth.icv_full_len) { 127 if (esp->auth.icv_full_len) {
128 esp->auth.icv(esp, skb, (u8*)esph-skb->data, 128 err = esp_mac_digest(esp, skb, (u8 *)esph - skb->data,
129 sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen+clen, trailer->tail); 129 sizeof(*esph) + esp->conf.ivlen + clen);
130 pskb_put(skb, trailer, alen); 130 memcpy(pskb_put(skb, trailer, alen), esp->auth.work_icv, alen);
131 } 131 }
132 132
133error: 133error:
@@ -162,15 +162,16 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
162 162
163 /* If integrity check is required, do this. */ 163 /* If integrity check is required, do this. */
164 if (esp->auth.icv_full_len) { 164 if (esp->auth.icv_full_len) {
165 u8 sum[esp->auth.icv_full_len]; 165 u8 sum[alen];
166 u8 sum1[alen];
167 166
168 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;
169 170
170 if (skb_copy_bits(skb, skb->len-alen, sum1, alen)) 171 if (skb_copy_bits(skb, skb->len - alen, sum, alen))
171 BUG(); 172 BUG();
172 173
173 if (unlikely(memcmp(sum, sum1, alen))) { 174 if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) {
174 x->stats.integrity_failed++; 175 x->stats.integrity_failed++;
175 ret = -EINVAL; 176 ret = -EINVAL;
176 goto out; 177 goto out;
@@ -279,7 +280,7 @@ static void esp6_destroy(struct xfrm_state *x)
279 esp->conf.tfm = NULL; 280 esp->conf.tfm = NULL;
280 kfree(esp->conf.ivec); 281 kfree(esp->conf.ivec);
281 esp->conf.ivec = NULL; 282 esp->conf.ivec = NULL;
282 crypto_free_tfm(esp->auth.tfm); 283 crypto_free_hash(esp->auth.tfm);
283 esp->auth.tfm = NULL; 284 esp->auth.tfm = NULL;
284 kfree(esp->auth.work_icv); 285 kfree(esp->auth.work_icv);
285 esp->auth.work_icv = NULL; 286 esp->auth.work_icv = NULL;
@@ -308,24 +309,29 @@ static int esp6_init_state(struct xfrm_state *x)
308 309
309 if (x->aalg) { 310 if (x->aalg) {
310 struct xfrm_algo_desc *aalg_desc; 311 struct xfrm_algo_desc *aalg_desc;
312 struct crypto_hash *hash;
311 313
312 esp->auth.key = x->aalg->alg_key; 314 esp->auth.key = x->aalg->alg_key;
313 esp->auth.key_len = (x->aalg->alg_key_len+7)/8; 315 esp->auth.key_len = (x->aalg->alg_key_len+7)/8;
314 esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); 316 hash = crypto_alloc_hash(x->aalg->alg_name, 0,
315 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))
316 goto error; 323 goto error;
317 esp->auth.icv = esp_hmac_digest;
318 324
319 aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); 325 aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
320 BUG_ON(!aalg_desc); 326 BUG_ON(!aalg_desc);
321 327
322 if (aalg_desc->uinfo.auth.icv_fullbits/8 != 328 if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
323 crypto_tfm_alg_digestsize(esp->auth.tfm)) { 329 crypto_hash_digestsize(hash)) {
324 printk(KERN_INFO "ESP: %s digestsize %u != %hu\n", 330 NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n",
325 x->aalg->alg_name, 331 x->aalg->alg_name,
326 crypto_tfm_alg_digestsize(esp->auth.tfm), 332 crypto_hash_digestsize(hash),
327 aalg_desc->uinfo.auth.icv_fullbits/8); 333 aalg_desc->uinfo.auth.icv_fullbits/8);
328 goto error; 334 goto error;
329 } 335 }
330 336
331 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;
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index 9b03d8497fba..87918f281bb4 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -30,7 +30,8 @@
30 */ 30 */
31static struct xfrm_algo_desc aalg_list[] = { 31static struct xfrm_algo_desc aalg_list[] = {
32{ 32{
33 .name = "digest_null", 33 .name = "hmac(digest_null)",
34 .compat = "digest_null",
34 35
35 .uinfo = { 36 .uinfo = {
36 .auth = { 37 .auth = {
@@ -47,7 +48,8 @@ static struct xfrm_algo_desc aalg_list[] = {
47 } 48 }
48}, 49},
49{ 50{
50 .name = "md5", 51 .name = "hmac(md5)",
52 .compat = "md5",
51 53
52 .uinfo = { 54 .uinfo = {
53 .auth = { 55 .auth = {
@@ -64,7 +66,8 @@ static struct xfrm_algo_desc aalg_list[] = {
64 } 66 }
65}, 67},
66{ 68{
67 .name = "sha1", 69 .name = "hmac(sha1)",
70 .compat = "sha1",
68 71
69 .uinfo = { 72 .uinfo = {
70 .auth = { 73 .auth = {
@@ -81,7 +84,8 @@ static struct xfrm_algo_desc aalg_list[] = {
81 } 84 }
82}, 85},
83{ 86{
84 .name = "sha256", 87 .name = "hmac(sha256)",
88 .compat = "sha256",
85 89
86 .uinfo = { 90 .uinfo = {
87 .auth = { 91 .auth = {
@@ -98,7 +102,8 @@ static struct xfrm_algo_desc aalg_list[] = {
98 } 102 }
99}, 103},
100{ 104{
101 .name = "ripemd160", 105 .name = "hmac(ripemd160)",
106 .compat = "ripemd160",
102 107
103 .uinfo = { 108 .uinfo = {
104 .auth = { 109 .auth = {
@@ -480,11 +485,12 @@ EXPORT_SYMBOL_GPL(xfrm_count_enc_supported);
480 485
481/* Move to common area: it is shared with AH. */ 486/* Move to common area: it is shared with AH. */
482 487
483void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm, 488int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc,
484 int offset, int len, icv_update_fn_t icv_update) 489 int offset, int len, icv_update_fn_t icv_update)
485{ 490{
486 int start = skb_headlen(skb); 491 int start = skb_headlen(skb);
487 int i, copy = start - offset; 492 int i, copy = start - offset;
493 int err;
488 struct scatterlist sg; 494 struct scatterlist sg;
489 495
490 /* Checksum header. */ 496 /* Checksum header. */
@@ -496,10 +502,12 @@ void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
496 sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; 502 sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
497 sg.length = copy; 503 sg.length = copy;
498 504
499 icv_update(tfm, &sg, 1); 505 err = icv_update(desc, &sg, copy);
506 if (unlikely(err))
507 return err;
500 508
501 if ((len -= copy) == 0) 509 if ((len -= copy) == 0)
502 return; 510 return 0;
503 offset += copy; 511 offset += copy;
504 } 512 }
505 513
@@ -519,10 +527,12 @@ void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
519 sg.offset = frag->page_offset + offset-start; 527 sg.offset = frag->page_offset + offset-start;
520 sg.length = copy; 528 sg.length = copy;
521 529
522 icv_update(tfm, &sg, 1); 530 err = icv_update(desc, &sg, copy);
531 if (unlikely(err))
532 return err;
523 533
524 if (!(len -= copy)) 534 if (!(len -= copy))
525 return; 535 return 0;
526 offset += copy; 536 offset += copy;
527 } 537 }
528 start = end; 538 start = end;
@@ -540,15 +550,19 @@ void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
540 if ((copy = end - offset) > 0) { 550 if ((copy = end - offset) > 0) {
541 if (copy > len) 551 if (copy > len)
542 copy = len; 552 copy = len;
543 skb_icv_walk(list, tfm, offset-start, copy, icv_update); 553 err = skb_icv_walk(list, desc, offset-start,
554 copy, icv_update);
555 if (unlikely(err))
556 return err;
544 if ((len -= copy) == 0) 557 if ((len -= copy) == 0)
545 return; 558 return 0;
546 offset += copy; 559 offset += copy;
547 } 560 }
548 start = end; 561 start = end;
549 } 562 }
550 } 563 }
551 BUG_ON(len); 564 BUG_ON(len);
565 return 0;
552} 566}
553EXPORT_SYMBOL_GPL(skb_icv_walk); 567EXPORT_SYMBOL_GPL(skb_icv_walk);
554 568