Commit d00aa19b507b39ee9a680d0d2ac2ae483686453a
1 parent
9ffde35a8e
Exists in
master
and in
7 other branches
[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
crypto/gcm.c
... | ... | @@ -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"); |