aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/gcm.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-12-07 07:31:10 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2008-01-10 16:16:47 -0500
commitd00aa19b507b39ee9a680d0d2ac2ae483686453a (patch)
tree87c4ad0b7aeee3524beec9f6b96fff0a84ec5dd8 /crypto/gcm.c
parent9ffde35a8edd3486cd7c80af931c15cec99a1a0d (diff)
[CRYPTO] gcm: Allow block cipher parameter
This patch adds the gcm_base template which takes a block cipher parameter instead of cipher. This allows the user to specify a specific CTR implementation. This also fixes a leak of the cipher algorithm that was previously looked up but never freed. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/gcm.c')
-rw-r--r--crypto/gcm.c113
1 files changed, 89 insertions, 24 deletions
diff --git a/crypto/gcm.c b/crypto/gcm.c
index f6bee6f209a6..e87e5de8e7b3 100644
--- a/crypto/gcm.c
+++ b/crypto/gcm.c
@@ -413,30 +413,23 @@ static void crypto_gcm_exit_tfm(struct crypto_tfm *tfm)
413 crypto_free_ablkcipher(ctx->ctr); 413 crypto_free_ablkcipher(ctx->ctr);
414} 414}
415 415
416static struct crypto_instance *crypto_gcm_alloc(struct rtattr **tb) 416static struct crypto_instance *crypto_gcm_alloc_common(struct rtattr **tb,
417 const char *full_name,
418 const char *ctr_name)
417{ 419{
420 struct crypto_attr_type *algt;
418 struct crypto_instance *inst; 421 struct crypto_instance *inst;
419 struct crypto_alg *ctr; 422 struct crypto_alg *ctr;
420 struct crypto_alg *cipher;
421 struct gcm_instance_ctx *ctx; 423 struct gcm_instance_ctx *ctx;
422 int err; 424 int err;
423 char ctr_name[CRYPTO_MAX_ALG_NAME];
424 425
425 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD); 426 algt = crypto_get_attr_type(tb);
426 if (err) 427 err = PTR_ERR(algt);
428 if (IS_ERR(algt))
427 return ERR_PTR(err); 429 return ERR_PTR(err);
428 430
429 cipher = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_CIPHER, 431 if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
430 CRYPTO_ALG_TYPE_MASK); 432 return ERR_PTR(-EINVAL);
431
432 inst = ERR_PTR(PTR_ERR(cipher));
433 if (IS_ERR(cipher))
434 return inst;
435
436 inst = ERR_PTR(ENAMETOOLONG);
437 if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)",
438 cipher->cra_name) >= CRYPTO_MAX_ALG_NAME)
439 return inst;
440 433
441 ctr = crypto_alg_mod_lookup(ctr_name, CRYPTO_ALG_TYPE_BLKCIPHER, 434 ctr = crypto_alg_mod_lookup(ctr_name, CRYPTO_ALG_TYPE_BLKCIPHER,
442 CRYPTO_ALG_TYPE_MASK); 435 CRYPTO_ALG_TYPE_MASK);
@@ -444,7 +437,14 @@ static struct crypto_instance *crypto_gcm_alloc(struct rtattr **tb)
444 if (IS_ERR(ctr)) 437 if (IS_ERR(ctr))
445 return ERR_PTR(PTR_ERR(ctr)); 438 return ERR_PTR(PTR_ERR(ctr));
446 439
447 if (cipher->cra_blocksize != 16) 440 /* We only support 16-byte blocks. */
441 if ((ctr->cra_type == &crypto_blkcipher_type ?
442 ctr->cra_blkcipher.ivsize : ctr->cra_ablkcipher.ivsize) != 16)
443 goto out_put_ctr;
444
445 /* Not a stream cipher? */
446 err = -EINVAL;
447 if (ctr->cra_blocksize != 1)
448 goto out_put_ctr; 448 goto out_put_ctr;
449 449
450 inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); 450 inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
@@ -453,21 +453,21 @@ static struct crypto_instance *crypto_gcm_alloc(struct rtattr **tb)
453 goto out_put_ctr; 453 goto out_put_ctr;
454 454
455 err = -ENAMETOOLONG; 455 err = -ENAMETOOLONG;
456 if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, 456 if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
457 "gcm(%s)", cipher->cra_name) >= CRYPTO_MAX_ALG_NAME || 457 "gcm_base(%s)", ctr->cra_driver_name) >=
458 snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, 458 CRYPTO_MAX_ALG_NAME)
459 "gcm(%s)", cipher->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
460 goto err_free_inst; 459 goto err_free_inst;
461 460
462
463 ctx = crypto_instance_ctx(inst); 461 ctx = crypto_instance_ctx(inst);
464 err = crypto_init_spawn(&ctx->ctr, ctr, inst, CRYPTO_ALG_TYPE_MASK); 462 err = crypto_init_spawn(&ctx->ctr, ctr, inst, CRYPTO_ALG_TYPE_MASK);
465 if (err) 463 if (err)
466 goto err_free_inst; 464 goto err_free_inst;
467 465
466 memcpy(inst->alg.cra_name, full_name, CRYPTO_MAX_ALG_NAME);
467
468 inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC; 468 inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC;
469 inst->alg.cra_priority = ctr->cra_priority; 469 inst->alg.cra_priority = ctr->cra_priority;
470 inst->alg.cra_blocksize = 16; 470 inst->alg.cra_blocksize = 1;
471 inst->alg.cra_alignmask = ctr->cra_alignmask | (__alignof__(u64) - 1); 471 inst->alg.cra_alignmask = ctr->cra_alignmask | (__alignof__(u64) - 1);
472 inst->alg.cra_type = &crypto_aead_type; 472 inst->alg.cra_type = &crypto_aead_type;
473 inst->alg.cra_aead.ivsize = 16; 473 inst->alg.cra_aead.ivsize = 16;
@@ -489,6 +489,29 @@ out_put_ctr:
489 goto out; 489 goto out;
490} 490}
491 491
492static struct crypto_instance *crypto_gcm_alloc(struct rtattr **tb)
493{
494 int err;
495 const char *cipher_name;
496 char ctr_name[CRYPTO_MAX_ALG_NAME];
497 char full_name[CRYPTO_MAX_ALG_NAME];
498
499 cipher_name = crypto_attr_alg_name(tb[1]);
500 err = PTR_ERR(cipher_name);
501 if (IS_ERR(cipher_name))
502 return ERR_PTR(err);
503
504 if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)", cipher_name) >=
505 CRYPTO_MAX_ALG_NAME)
506 return ERR_PTR(-ENAMETOOLONG);
507
508 if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "gcm(%s)", cipher_name) >=
509 CRYPTO_MAX_ALG_NAME)
510 return ERR_PTR(-ENAMETOOLONG);
511
512 return crypto_gcm_alloc_common(tb, full_name, ctr_name);
513}
514
492static void crypto_gcm_free(struct crypto_instance *inst) 515static void crypto_gcm_free(struct crypto_instance *inst)
493{ 516{
494 struct gcm_instance_ctx *ctx = crypto_instance_ctx(inst); 517 struct gcm_instance_ctx *ctx = crypto_instance_ctx(inst);
@@ -504,14 +527,55 @@ static struct crypto_template crypto_gcm_tmpl = {
504 .module = THIS_MODULE, 527 .module = THIS_MODULE,
505}; 528};
506 529
530static struct crypto_instance *crypto_gcm_base_alloc(struct rtattr **tb)
531{
532 int err;
533 const char *ctr_name;
534 char full_name[CRYPTO_MAX_ALG_NAME];
535
536 ctr_name = crypto_attr_alg_name(tb[1]);
537 err = PTR_ERR(ctr_name);
538 if (IS_ERR(ctr_name))
539 return ERR_PTR(err);
540
541 if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "gcm_base(%s)",
542 ctr_name) >= CRYPTO_MAX_ALG_NAME)
543 return ERR_PTR(-ENAMETOOLONG);
544
545 return crypto_gcm_alloc_common(tb, full_name, ctr_name);
546}
547
548static struct crypto_template crypto_gcm_base_tmpl = {
549 .name = "gcm_base",
550 .alloc = crypto_gcm_base_alloc,
551 .free = crypto_gcm_free,
552 .module = THIS_MODULE,
553};
554
507static int __init crypto_gcm_module_init(void) 555static int __init crypto_gcm_module_init(void)
508{ 556{
509 return crypto_register_template(&crypto_gcm_tmpl); 557 int err;
558
559 err = crypto_register_template(&crypto_gcm_base_tmpl);
560 if (err)
561 goto out;
562
563 err = crypto_register_template(&crypto_gcm_tmpl);
564 if (err)
565 goto out_undo_base;
566
567out:
568 return err;
569
570out_undo_base:
571 crypto_unregister_template(&crypto_gcm_base_tmpl);
572 goto out;
510} 573}
511 574
512static void __exit crypto_gcm_module_exit(void) 575static void __exit crypto_gcm_module_exit(void)
513{ 576{
514 crypto_unregister_template(&crypto_gcm_tmpl); 577 crypto_unregister_template(&crypto_gcm_tmpl);
578 crypto_unregister_template(&crypto_gcm_base_tmpl);
515} 579}
516 580
517module_init(crypto_gcm_module_init); 581module_init(crypto_gcm_module_init);
@@ -520,3 +584,4 @@ module_exit(crypto_gcm_module_exit);
520MODULE_LICENSE("GPL"); 584MODULE_LICENSE("GPL");
521MODULE_DESCRIPTION("Galois/Counter Mode"); 585MODULE_DESCRIPTION("Galois/Counter Mode");
522MODULE_AUTHOR("Mikko Herranen <mh1@iki.fi>"); 586MODULE_AUTHOR("Mikko Herranen <mh1@iki.fi>");
587MODULE_ALIAS("gcm_base");