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/ipv6 | |
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/ipv6')
-rw-r--r-- | net/ipv6/esp6.c | 77 |
1 files changed, 61 insertions, 16 deletions
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index dc821acf3d33..ca48c56c4b17 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -382,35 +382,53 @@ static void esp6_destroy(struct xfrm_state *x) | |||
382 | kfree(esp); | 382 | kfree(esp); |
383 | } | 383 | } |
384 | 384 | ||
385 | static int esp6_init_state(struct xfrm_state *x) | 385 | static int esp_init_aead(struct xfrm_state *x) |
386 | { | ||
387 | struct esp_data *esp = x->data; | ||
388 | struct crypto_aead *aead; | ||
389 | int err; | ||
390 | |||
391 | aead = crypto_alloc_aead(x->aead->alg_name, 0, 0); | ||
392 | err = PTR_ERR(aead); | ||
393 | if (IS_ERR(aead)) | ||
394 | goto error; | ||
395 | |||
396 | esp->aead = aead; | ||
397 | |||
398 | err = crypto_aead_setkey(aead, x->aead->alg_key, | ||
399 | (x->aead->alg_key_len + 7) / 8); | ||
400 | if (err) | ||
401 | goto error; | ||
402 | |||
403 | err = crypto_aead_setauthsize(aead, x->aead->alg_icv_len / 8); | ||
404 | if (err) | ||
405 | goto error; | ||
406 | |||
407 | error: | ||
408 | return err; | ||
409 | } | ||
410 | |||
411 | static int esp_init_authenc(struct xfrm_state *x) | ||
386 | { | 412 | { |
387 | struct esp_data *esp = NULL; | 413 | struct esp_data *esp = x->data; |
388 | struct crypto_aead *aead; | 414 | struct crypto_aead *aead; |
389 | struct crypto_authenc_key_param *param; | 415 | struct crypto_authenc_key_param *param; |
390 | struct rtattr *rta; | 416 | struct rtattr *rta; |
391 | char *key; | 417 | char *key; |
392 | char *p; | 418 | char *p; |
393 | char authenc_name[CRYPTO_MAX_ALG_NAME]; | 419 | char authenc_name[CRYPTO_MAX_ALG_NAME]; |
394 | u32 align; | ||
395 | unsigned int keylen; | 420 | unsigned int keylen; |
396 | int err; | 421 | int err; |
397 | 422 | ||
423 | err = -EINVAL; | ||
398 | if (x->ealg == NULL) | 424 | if (x->ealg == NULL) |
399 | return -EINVAL; | 425 | goto error; |
400 | |||
401 | if (x->encap) | ||
402 | return -EINVAL; | ||
403 | 426 | ||
427 | err = -ENAMETOOLONG; | ||
404 | if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)", | 428 | if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)", |
405 | x->aalg ? x->aalg->alg_name : "digest_null", | 429 | x->aalg ? x->aalg->alg_name : "digest_null", |
406 | x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME) | 430 | x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME) |
407 | return -ENAMETOOLONG; | 431 | goto error; |
408 | |||
409 | esp = kzalloc(sizeof(*esp), GFP_KERNEL); | ||
410 | if (esp == NULL) | ||
411 | return -ENOMEM; | ||
412 | |||
413 | x->data = esp; | ||
414 | 432 | ||
415 | aead = crypto_alloc_aead(authenc_name, 0, 0); | 433 | aead = crypto_alloc_aead(authenc_name, 0, 0); |
416 | err = PTR_ERR(aead); | 434 | err = PTR_ERR(aead); |
@@ -458,8 +476,6 @@ static int esp6_init_state(struct xfrm_state *x) | |||
458 | goto free_key; | 476 | goto free_key; |
459 | } | 477 | } |
460 | 478 | ||
461 | esp->padlen = 0; | ||
462 | |||
463 | param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8); | 479 | param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8); |
464 | memcpy(p, x->ealg->alg_key, (x->ealg->alg_key_len + 7) / 8); | 480 | memcpy(p, x->ealg->alg_key, (x->ealg->alg_key_len + 7) / 8); |
465 | 481 | ||
@@ -468,9 +484,38 @@ static int esp6_init_state(struct xfrm_state *x) | |||
468 | free_key: | 484 | free_key: |
469 | kfree(key); | 485 | kfree(key); |
470 | 486 | ||
487 | error: | ||
488 | return err; | ||
489 | } | ||
490 | |||
491 | static int esp6_init_state(struct xfrm_state *x) | ||
492 | { | ||
493 | struct esp_data *esp; | ||
494 | struct crypto_aead *aead; | ||
495 | u32 align; | ||
496 | int err; | ||
497 | |||
498 | if (x->encap) | ||
499 | return -EINVAL; | ||
500 | |||
501 | esp = kzalloc(sizeof(*esp), GFP_KERNEL); | ||
502 | if (esp == NULL) | ||
503 | return -ENOMEM; | ||
504 | |||
505 | x->data = esp; | ||
506 | |||
507 | if (x->aead) | ||
508 | err = esp_init_aead(x); | ||
509 | else | ||
510 | err = esp_init_authenc(x); | ||
511 | |||
471 | if (err) | 512 | if (err) |
472 | goto error; | 513 | goto error; |
473 | 514 | ||
515 | aead = esp->aead; | ||
516 | |||
517 | esp->padlen = 0; | ||
518 | |||
474 | x->props.header_len = sizeof(struct ip_esp_hdr) + | 519 | x->props.header_len = sizeof(struct ip_esp_hdr) + |
475 | crypto_aead_ivsize(aead); | 520 | crypto_aead_ivsize(aead); |
476 | switch (x->props.mode) { | 521 | switch (x->props.mode) { |