aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ah6.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2006-08-20 00:24:50 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2006-09-20 21:46:18 -0400
commit07d4ee583e21830ec5604d31f65cdc60a6eca19e (patch)
tree32962ef0dd13d0d1f66b143ca5d03a88d8b9f772 /net/ipv6/ah6.c
parente9d41164e2fdd897fe4520c2079ea0000f6e0ec3 (diff)
[IPSEC]: Use HMAC template and hash interface
This patch converts IPsec to use the new HMAC template. The names of existing simple digest algorithms may still be used to refer to their HMAC composites. The same structure can be used by other MACs such as AES-XCBC-MAC. This patch also switches from the digest interface to hash. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/ah6.c')
-rw-r--r--net/ipv6/ah6.c35
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)
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}