summaryrefslogtreecommitdiffstats
path: root/crypto/ccm.c
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2019-04-18 17:44:27 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2019-04-19 01:53:13 -0400
commit6a1faa4a43f5fabf9cbeaa742d916e7b5e73120f (patch)
tree425f361f7dab371971766f65fffc28189db11985 /crypto/ccm.c
parentf699594d436960160f6d5ba84ed4a222f20d11cd (diff)
crypto: ccm - fix incompatibility between "ccm" and "ccm_base"
CCM instances can be created by either the "ccm" template, which only allows choosing the block cipher, e.g. "ccm(aes)"; or by "ccm_base", which allows choosing the ctr and cbcmac implementations, e.g. "ccm_base(ctr(aes-generic),cbcmac(aes-generic))". However, a "ccm_base" instance prevents a "ccm" instance from being registered using the same implementations. Nor will the instance be found by lookups of "ccm". This can be used as a denial of service. Moreover, "ccm_base" instances are never tested by the crypto self-tests, even if there are compatible "ccm" tests. The root cause of these problems is that instances of the two templates use different cra_names. Therefore, fix these problems by making "ccm_base" instances set the same cra_name as "ccm" instances, e.g. "ccm(aes)" instead of "ccm_base(ctr(aes-generic),cbcmac(aes-generic))". This requires extracting the block cipher name from the name of the ctr and cbcmac algorithms. It also requires starting to verify that the algorithms are really ctr and cbcmac using the same block cipher, not something else entirely. But it would be bizarre if anyone were actually using non-ccm-compatible algorithms with ccm_base, so this shouldn't break anyone in practice. Fixes: 4a49b499dfa0 ("[CRYPTO] ccm: Added CCM mode") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/ccm.c')
-rw-r--r--crypto/ccm.c44
1 files changed, 18 insertions, 26 deletions
diff --git a/crypto/ccm.c b/crypto/ccm.c
index 3d036df0f4d4..c1ef9d0b4271 100644
--- a/crypto/ccm.c
+++ b/crypto/ccm.c
@@ -458,7 +458,6 @@ static void crypto_ccm_free(struct aead_instance *inst)
458 458
459static int crypto_ccm_create_common(struct crypto_template *tmpl, 459static int crypto_ccm_create_common(struct crypto_template *tmpl,
460 struct rtattr **tb, 460 struct rtattr **tb,
461 const char *full_name,
462 const char *ctr_name, 461 const char *ctr_name,
463 const char *mac_name) 462 const char *mac_name)
464{ 463{
@@ -486,7 +485,8 @@ static int crypto_ccm_create_common(struct crypto_template *tmpl,
486 485
487 mac = __crypto_hash_alg_common(mac_alg); 486 mac = __crypto_hash_alg_common(mac_alg);
488 err = -EINVAL; 487 err = -EINVAL;
489 if (mac->digestsize != 16) 488 if (strncmp(mac->base.cra_name, "cbcmac(", 7) != 0 ||
489 mac->digestsize != 16)
490 goto out_put_mac; 490 goto out_put_mac;
491 491
492 inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL); 492 inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL);
@@ -509,23 +509,27 @@ static int crypto_ccm_create_common(struct crypto_template *tmpl,
509 509
510 ctr = crypto_spawn_skcipher_alg(&ictx->ctr); 510 ctr = crypto_spawn_skcipher_alg(&ictx->ctr);
511 511
512 /* Not a stream cipher? */ 512 /* The skcipher algorithm must be CTR mode, using 16-byte blocks. */
513 err = -EINVAL; 513 err = -EINVAL;
514 if (ctr->base.cra_blocksize != 1) 514 if (strncmp(ctr->base.cra_name, "ctr(", 4) != 0 ||
515 crypto_skcipher_alg_ivsize(ctr) != 16 ||
516 ctr->base.cra_blocksize != 1)
515 goto err_drop_ctr; 517 goto err_drop_ctr;
516 518
517 /* We want the real thing! */ 519 /* ctr and cbcmac must use the same underlying block cipher. */
518 if (crypto_skcipher_alg_ivsize(ctr) != 16) 520 if (strcmp(ctr->base.cra_name + 4, mac->base.cra_name + 7) != 0)
519 goto err_drop_ctr; 521 goto err_drop_ctr;
520 522
521 err = -ENAMETOOLONG; 523 err = -ENAMETOOLONG;
524 if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
525 "ccm(%s", ctr->base.cra_name + 4) >= CRYPTO_MAX_ALG_NAME)
526 goto err_drop_ctr;
527
522 if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, 528 if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
523 "ccm_base(%s,%s)", ctr->base.cra_driver_name, 529 "ccm_base(%s,%s)", ctr->base.cra_driver_name,
524 mac->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) 530 mac->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
525 goto err_drop_ctr; 531 goto err_drop_ctr;
526 532
527 memcpy(inst->alg.base.cra_name, full_name, CRYPTO_MAX_ALG_NAME);
528
529 inst->alg.base.cra_flags = ctr->base.cra_flags & CRYPTO_ALG_ASYNC; 533 inst->alg.base.cra_flags = ctr->base.cra_flags & CRYPTO_ALG_ASYNC;
530 inst->alg.base.cra_priority = (mac->base.cra_priority + 534 inst->alg.base.cra_priority = (mac->base.cra_priority +
531 ctr->base.cra_priority) / 2; 535 ctr->base.cra_priority) / 2;
@@ -567,7 +571,6 @@ static int crypto_ccm_create(struct crypto_template *tmpl, struct rtattr **tb)
567 const char *cipher_name; 571 const char *cipher_name;
568 char ctr_name[CRYPTO_MAX_ALG_NAME]; 572 char ctr_name[CRYPTO_MAX_ALG_NAME];
569 char mac_name[CRYPTO_MAX_ALG_NAME]; 573 char mac_name[CRYPTO_MAX_ALG_NAME];
570 char full_name[CRYPTO_MAX_ALG_NAME];
571 574
572 cipher_name = crypto_attr_alg_name(tb[1]); 575 cipher_name = crypto_attr_alg_name(tb[1]);
573 if (IS_ERR(cipher_name)) 576 if (IS_ERR(cipher_name))
@@ -581,35 +584,24 @@ static int crypto_ccm_create(struct crypto_template *tmpl, struct rtattr **tb)
581 cipher_name) >= CRYPTO_MAX_ALG_NAME) 584 cipher_name) >= CRYPTO_MAX_ALG_NAME)
582 return -ENAMETOOLONG; 585 return -ENAMETOOLONG;
583 586
584 if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm(%s)", cipher_name) >= 587 return crypto_ccm_create_common(tmpl, tb, ctr_name, mac_name);
585 CRYPTO_MAX_ALG_NAME)
586 return -ENAMETOOLONG;
587
588 return crypto_ccm_create_common(tmpl, tb, full_name, ctr_name,
589 mac_name);
590} 588}
591 589
592static int crypto_ccm_base_create(struct crypto_template *tmpl, 590static int crypto_ccm_base_create(struct crypto_template *tmpl,
593 struct rtattr **tb) 591 struct rtattr **tb)
594{ 592{
595 const char *ctr_name; 593 const char *ctr_name;
596 const char *cipher_name; 594 const char *mac_name;
597 char full_name[CRYPTO_MAX_ALG_NAME];
598 595
599 ctr_name = crypto_attr_alg_name(tb[1]); 596 ctr_name = crypto_attr_alg_name(tb[1]);
600 if (IS_ERR(ctr_name)) 597 if (IS_ERR(ctr_name))
601 return PTR_ERR(ctr_name); 598 return PTR_ERR(ctr_name);
602 599
603 cipher_name = crypto_attr_alg_name(tb[2]); 600 mac_name = crypto_attr_alg_name(tb[2]);
604 if (IS_ERR(cipher_name)) 601 if (IS_ERR(mac_name))
605 return PTR_ERR(cipher_name); 602 return PTR_ERR(mac_name);
606
607 if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm_base(%s,%s)",
608 ctr_name, cipher_name) >= CRYPTO_MAX_ALG_NAME)
609 return -ENAMETOOLONG;
610 603
611 return crypto_ccm_create_common(tmpl, tb, full_name, ctr_name, 604 return crypto_ccm_create_common(tmpl, tb, ctr_name, mac_name);
612 cipher_name);
613} 605}
614 606
615static int crypto_rfc4309_setkey(struct crypto_aead *parent, const u8 *key, 607static int crypto_rfc4309_setkey(struct crypto_aead *parent, const u8 *key,