Commit d00aa19b507b39ee9a680d0d2ac2ae483686453a

Authored by Herbert Xu
1 parent 9ffde35a8e

[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>

Showing 1 changed file with 89 additions and 24 deletions Side-by-side Diff

... ... @@ -413,61 +413,61 @@
413 413 crypto_free_ablkcipher(ctx->ctr);
414 414 }
415 415  
416   -static struct crypto_instance *crypto_gcm_alloc(struct rtattr **tb)
  416 +static 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 421 struct crypto_instance *inst;
419 422 struct crypto_alg *ctr;
420   - struct crypto_alg *cipher;
421 423 struct gcm_instance_ctx *ctx;
422 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   - if (err)
  426 + algt = crypto_get_attr_type(tb);
  427 + err = PTR_ERR(algt);
  428 + if (IS_ERR(algt))
427 429 return ERR_PTR(err);
428 430  
429   - cipher = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_CIPHER,
430   - CRYPTO_ALG_TYPE_MASK);
  431 + if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
  432 + return ERR_PTR(-EINVAL);
431 433  
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   -
441 434 ctr = crypto_alg_mod_lookup(ctr_name, CRYPTO_ALG_TYPE_BLKCIPHER,
442 435 CRYPTO_ALG_TYPE_MASK);
443 436  
444 437 if (IS_ERR(ctr))
445 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)
448 443 goto out_put_ctr;
449 444  
  445 + /* Not a stream cipher? */
  446 + err = -EINVAL;
  447 + if (ctr->cra_blocksize != 1)
  448 + goto out_put_ctr;
  449 +
450 450 inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
451 451 err = -ENOMEM;
452 452 if (!inst)
453 453 goto out_put_ctr;
454 454  
455 455 err = -ENAMETOOLONG;
456   - if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
457   - "gcm(%s)", cipher->cra_name) >= CRYPTO_MAX_ALG_NAME ||
458   - snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
459   - "gcm(%s)", cipher->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
  456 + if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
  457 + "gcm_base(%s)", ctr->cra_driver_name) >=
  458 + CRYPTO_MAX_ALG_NAME)
460 459 goto err_free_inst;
461 460  
462   -
463 461 ctx = crypto_instance_ctx(inst);
464 462 err = crypto_init_spawn(&ctx->ctr, ctr, inst, CRYPTO_ALG_TYPE_MASK);
465 463 if (err)
466 464 goto err_free_inst;
467 465  
  466 + memcpy(inst->alg.cra_name, full_name, CRYPTO_MAX_ALG_NAME);
  467 +
468 468 inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC;
469 469 inst->alg.cra_priority = ctr->cra_priority;
470   - inst->alg.cra_blocksize = 16;
  470 + inst->alg.cra_blocksize = 1;
471 471 inst->alg.cra_alignmask = ctr->cra_alignmask | (__alignof__(u64) - 1);
472 472 inst->alg.cra_type = &crypto_aead_type;
473 473 inst->alg.cra_aead.ivsize = 16;
... ... @@ -489,6 +489,29 @@
489 489 goto out;
490 490 }
491 491  
  492 +static 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 +
492 515 static void crypto_gcm_free(struct crypto_instance *inst)
493 516 {
494 517 struct gcm_instance_ctx *ctx = crypto_instance_ctx(inst);
495 518  
496 519  
... ... @@ -504,14 +527,55 @@
504 527 .module = THIS_MODULE,
505 528 };
506 529  
  530 +static 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 +
  548 +static 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 +
507 555 static 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 +
  567 +out:
  568 + return err;
  569 +
  570 +out_undo_base:
  571 + crypto_unregister_template(&crypto_gcm_base_tmpl);
  572 + goto out;
510 573 }
511 574  
512 575 static void __exit crypto_gcm_module_exit(void)
513 576 {
514 577 crypto_unregister_template(&crypto_gcm_tmpl);
  578 + crypto_unregister_template(&crypto_gcm_base_tmpl);
515 579 }
516 580  
517 581 module_init(crypto_gcm_module_init);
... ... @@ -520,4 +584,5 @@
520 584 MODULE_LICENSE("GPL");
521 585 MODULE_DESCRIPTION("Galois/Counter Mode");
522 586 MODULE_AUTHOR("Mikko Herranen <mh1@iki.fi>");
  587 +MODULE_ALIAS("gcm_base");