diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2008-01-28 22:37:29 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-31 22:27:03 -0500 |
commit | 1a6509d991225ad210de54c63314fd9542922095 (patch) | |
tree | afe5c560388558bebd3e21b7c6f789a28a323a51 /net/ipv4/esp4.c | |
parent | 6fbf2cb77461a0cd0675228d20dd0f70d7b2251f (diff) |
[IPSEC]: Add support for combined mode algorithms
This patch adds support for combined mode algorithms with GCM being
the first algorithm supported.
Combined mode algorithms can be added through the xfrm_user interface
using the new algorithm payload type XFRMA_ALG_AEAD. Each algorithms
is identified by its name and the ICV length.
For the purposes of matching algorithms in xfrm_tmpl structures,
combined mode algorithms occupy the same name space as encryption
algorithms. This is in line with how they are negotiated using IKE.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/esp4.c')
-rw-r--r-- | net/ipv4/esp4.c | 71 |
1 files changed, 58 insertions, 13 deletions
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index c4047223bfbe..fac4f102c9f9 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
@@ -439,32 +439,53 @@ static void esp_destroy(struct xfrm_state *x) | |||
439 | kfree(esp); | 439 | kfree(esp); |
440 | } | 440 | } |
441 | 441 | ||
442 | static int esp_init_state(struct xfrm_state *x) | 442 | static int esp_init_aead(struct xfrm_state *x) |
443 | { | 443 | { |
444 | struct esp_data *esp = NULL; | 444 | struct esp_data *esp = x->data; |
445 | struct crypto_aead *aead; | ||
446 | int err; | ||
447 | |||
448 | aead = crypto_alloc_aead(x->aead->alg_name, 0, 0); | ||
449 | err = PTR_ERR(aead); | ||
450 | if (IS_ERR(aead)) | ||
451 | goto error; | ||
452 | |||
453 | esp->aead = aead; | ||
454 | |||
455 | err = crypto_aead_setkey(aead, x->aead->alg_key, | ||
456 | (x->aead->alg_key_len + 7) / 8); | ||
457 | if (err) | ||
458 | goto error; | ||
459 | |||
460 | err = crypto_aead_setauthsize(aead, x->aead->alg_icv_len / 8); | ||
461 | if (err) | ||
462 | goto error; | ||
463 | |||
464 | error: | ||
465 | return err; | ||
466 | } | ||
467 | |||
468 | static int esp_init_authenc(struct xfrm_state *x) | ||
469 | { | ||
470 | struct esp_data *esp = x->data; | ||
445 | struct crypto_aead *aead; | 471 | struct crypto_aead *aead; |
446 | struct crypto_authenc_key_param *param; | 472 | struct crypto_authenc_key_param *param; |
447 | struct rtattr *rta; | 473 | struct rtattr *rta; |
448 | char *key; | 474 | char *key; |
449 | char *p; | 475 | char *p; |
450 | char authenc_name[CRYPTO_MAX_ALG_NAME]; | 476 | char authenc_name[CRYPTO_MAX_ALG_NAME]; |
451 | u32 align; | ||
452 | unsigned int keylen; | 477 | unsigned int keylen; |
453 | int err; | 478 | int err; |
454 | 479 | ||
480 | err = -EINVAL; | ||
455 | if (x->ealg == NULL) | 481 | if (x->ealg == NULL) |
456 | return -EINVAL; | 482 | goto error; |
457 | 483 | ||
484 | err = -ENAMETOOLONG; | ||
458 | if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)", | 485 | if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)", |
459 | x->aalg ? x->aalg->alg_name : "digest_null", | 486 | x->aalg ? x->aalg->alg_name : "digest_null", |
460 | x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME) | 487 | x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME) |
461 | return -ENAMETOOLONG; | 488 | goto error; |
462 | |||
463 | esp = kzalloc(sizeof(*esp), GFP_KERNEL); | ||
464 | if (esp == NULL) | ||
465 | return -ENOMEM; | ||
466 | |||
467 | x->data = esp; | ||
468 | 489 | ||
469 | aead = crypto_alloc_aead(authenc_name, 0, 0); | 490 | aead = crypto_alloc_aead(authenc_name, 0, 0); |
470 | err = PTR_ERR(aead); | 491 | err = PTR_ERR(aead); |
@@ -512,8 +533,6 @@ static int esp_init_state(struct xfrm_state *x) | |||
512 | goto free_key; | 533 | goto free_key; |
513 | } | 534 | } |
514 | 535 | ||
515 | esp->padlen = 0; | ||
516 | |||
517 | param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8); | 536 | param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8); |
518 | memcpy(p, x->ealg->alg_key, (x->ealg->alg_key_len + 7) / 8); | 537 | memcpy(p, x->ealg->alg_key, (x->ealg->alg_key_len + 7) / 8); |
519 | 538 | ||
@@ -522,9 +541,35 @@ static int esp_init_state(struct xfrm_state *x) | |||
522 | free_key: | 541 | free_key: |
523 | kfree(key); | 542 | kfree(key); |
524 | 543 | ||
544 | error: | ||
545 | return err; | ||
546 | } | ||
547 | |||
548 | static int esp_init_state(struct xfrm_state *x) | ||
549 | { | ||
550 | struct esp_data *esp; | ||
551 | struct crypto_aead *aead; | ||
552 | u32 align; | ||
553 | int err; | ||
554 | |||
555 | esp = kzalloc(sizeof(*esp), GFP_KERNEL); | ||
556 | if (esp == NULL) | ||
557 | return -ENOMEM; | ||
558 | |||
559 | x->data = esp; | ||
560 | |||
561 | if (x->aead) | ||
562 | err = esp_init_aead(x); | ||
563 | else | ||
564 | err = esp_init_authenc(x); | ||
565 | |||
525 | if (err) | 566 | if (err) |
526 | goto error; | 567 | goto error; |
527 | 568 | ||
569 | aead = esp->aead; | ||
570 | |||
571 | esp->padlen = 0; | ||
572 | |||
528 | x->props.header_len = sizeof(struct ip_esp_hdr) + | 573 | x->props.header_len = sizeof(struct ip_esp_hdr) + |
529 | crypto_aead_ivsize(aead); | 574 | crypto_aead_ivsize(aead); |
530 | if (x->props.mode == XFRM_MODE_TUNNEL) | 575 | if (x->props.mode == XFRM_MODE_TUNNEL) |