diff options
Diffstat (limited to 'net/ipv6/ah6.c')
-rw-r--r-- | net/ipv6/ah6.c | 35 |
1 files changed, 23 insertions, 12 deletions
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) | |||
310 | free_out: | 317 | free_out: |
311 | kfree(tmp_hdr); | 318 | kfree(tmp_hdr); |
312 | out: | 319 | out: |
313 | return -EINVAL; | 320 | return err; |
314 | } | 321 | } |
315 | 322 | ||
316 | static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 323 | static 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) | |||
396 | error: | 407 | error: |
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 | } |