summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2018-06-18 13:22:39 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2018-07-01 09:00:43 -0400
commited331adab35bcddc595dae066522ca6336ee9210 (patch)
tree7d9daa5ac6b7d61166803e51458e8f512ae88013
parentbb29648102335586e9a66289a1d98a0cb392b6e5 (diff)
crypto: vmac - add nonced version with big endian digest
Currently the VMAC template uses a "nonce" hardcoded to 0, which makes it insecure unless a unique key is set for every message. Also, the endianness of the final digest is wrong: the implementation uses little endian, but the VMAC specification has it as big endian, as do other VMAC implementations such as the one in Crypto++. Add a new VMAC template where the nonce is passed as the first 16 bytes of data (similar to what is done for Poly1305's nonce), and the digest is big endian. Call it "vmac64", since the old name of simply "vmac" didn't clarify whether the implementation is of VMAC-64 or of VMAC-128 (which produce 64-bit and 128-bit digests respectively); so we fix the naming ambiguity too. Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--crypto/testmgr.c6
-rw-r--r--crypto/testmgr.h155
-rw-r--r--crypto/vmac.c130
3 files changed, 273 insertions, 18 deletions
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 11e45352fd0b..60a557b0f8d3 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -3484,6 +3484,12 @@ static const struct alg_test_desc alg_test_descs[] = {
3484 .hash = __VECS(aes_vmac128_tv_template) 3484 .hash = __VECS(aes_vmac128_tv_template)
3485 } 3485 }
3486 }, { 3486 }, {
3487 .alg = "vmac64(aes)",
3488 .test = alg_test_hash,
3489 .suite = {
3490 .hash = __VECS(vmac64_aes_tv_template)
3491 }
3492 }, {
3487 .alg = "wp256", 3493 .alg = "wp256",
3488 .test = alg_test_hash, 3494 .test = alg_test_hash,
3489 .suite = { 3495 .suite = {
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index b950aa234e43..7b022c47a623 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -4705,6 +4705,161 @@ static const struct hash_testvec aes_vmac128_tv_template[] = {
4705 }, 4705 },
4706}; 4706};
4707 4707
4708static const char vmac64_string1[144] = {
4709 '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
4710 '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
4711 '\x01', '\x01', '\x01', '\x01', '\x02', '\x03', '\x02', '\x02',
4712 '\x02', '\x04', '\x01', '\x07', '\x04', '\x01', '\x04', '\x03',
4713};
4714
4715static const char vmac64_string2[144] = {
4716 '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
4717 '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
4718 'a', 'b', 'c',
4719};
4720
4721static const char vmac64_string3[144] = {
4722 '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
4723 '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
4724 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b',
4725 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a',
4726 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c',
4727 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b',
4728 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a',
4729 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c',
4730};
4731
4732static const char vmac64_string4[33] = {
4733 '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
4734 '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
4735 'b', 'c', 'e', 'f', 'i', 'j', 'l', 'm',
4736 'o', 'p', 'r', 's', 't', 'u', 'w', 'x',
4737 'z',
4738};
4739
4740static const char vmac64_string5[143] = {
4741 '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
4742 '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
4743 'r', 'm', 'b', 't', 'c', 'o', 'l', 'k',
4744 ']', '%', '9', '2', '7', '!', 'A',
4745};
4746
4747static const char vmac64_string6[145] = {
4748 '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
4749 '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
4750 'p', 't', '*', '7', 'l', 'i', '!', '#',
4751 'w', '0', 'z', '/', '4', 'A', 'n',
4752};
4753
4754static const struct hash_testvec vmac64_aes_tv_template[] = {
4755 { /* draft-krovetz-vmac-01 test vector 1 */
4756 .key = "abcdefghijklmnop",
4757 .ksize = 16,
4758 .plaintext = "\0\0\0\0\0\0\0\0bcdefghi",
4759 .psize = 16,
4760 .digest = "\x25\x76\xbe\x1c\x56\xd8\xb8\x1b",
4761 }, { /* draft-krovetz-vmac-01 test vector 2 */
4762 .key = "abcdefghijklmnop",
4763 .ksize = 16,
4764 .plaintext = "\0\0\0\0\0\0\0\0bcdefghiabc",
4765 .psize = 19,
4766 .digest = "\x2d\x37\x6c\xf5\xb1\x81\x3c\xe5",
4767 }, { /* draft-krovetz-vmac-01 test vector 3 */
4768 .key = "abcdefghijklmnop",
4769 .ksize = 16,
4770 .plaintext = "\0\0\0\0\0\0\0\0bcdefghi"
4771 "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc",
4772 .psize = 64,
4773 .digest = "\xe8\x42\x1f\x61\xd5\x73\xd2\x98",
4774 }, { /* draft-krovetz-vmac-01 test vector 4 */
4775 .key = "abcdefghijklmnop",
4776 .ksize = 16,
4777 .plaintext = "\0\0\0\0\0\0\0\0bcdefghi"
4778 "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc"
4779 "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc"
4780 "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc"
4781 "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc"
4782 "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc"
4783 "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabc",
4784 .psize = 316,
4785 .digest = "\x44\x92\xdf\x6c\x5c\xac\x1b\xbe",
4786 .tap = { 1, 100, 200, 15 },
4787 .np = 4,
4788 }, {
4789 .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
4790 "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
4791 .ksize = 16,
4792 .plaintext = "\x00\x00\x00\x00\x00\x00\x00\x00"
4793 "\x00\x00\x00\x00\x00\x00\x00\x00",
4794 .psize = 16,
4795 .digest = "\x54\x7b\xa4\x77\x35\x80\x58\x07",
4796 }, {
4797 .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
4798 "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
4799 .ksize = 16,
4800 .plaintext = vmac64_string1,
4801 .psize = sizeof(vmac64_string1),
4802 .digest = "\xa1\x8c\x68\xae\xd3\x3c\xf5\xce",
4803 }, {
4804 .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
4805 "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
4806 .ksize = 16,
4807 .plaintext = vmac64_string2,
4808 .psize = sizeof(vmac64_string2),
4809 .digest = "\x2d\x14\xbd\x81\x73\xb0\x27\xc9",
4810 }, {
4811 .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
4812 "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
4813 .ksize = 16,
4814 .plaintext = vmac64_string3,
4815 .psize = sizeof(vmac64_string3),
4816 .digest = "\x19\x0b\x47\x98\x8c\x95\x1a\x8d",
4817 }, {
4818 .key = "abcdefghijklmnop",
4819 .ksize = 16,
4820 .plaintext = "\x00\x00\x00\x00\x00\x00\x00\x00"
4821 "\x00\x00\x00\x00\x00\x00\x00\x00",
4822 .psize = 16,
4823 .digest = "\x84\x8f\x55\x9e\x26\xa1\x89\x3b",
4824 }, {
4825 .key = "abcdefghijklmnop",
4826 .ksize = 16,
4827 .plaintext = vmac64_string1,
4828 .psize = sizeof(vmac64_string1),
4829 .digest = "\xc2\x74\x8d\xf6\xb0\xab\x5e\xab",
4830 }, {
4831 .key = "abcdefghijklmnop",
4832 .ksize = 16,
4833 .plaintext = vmac64_string2,
4834 .psize = sizeof(vmac64_string2),
4835 .digest = "\xdf\x09\x7b\x3d\x42\x68\x15\x11",
4836 }, {
4837 .key = "abcdefghijklmnop",
4838 .ksize = 16,
4839 .plaintext = vmac64_string3,
4840 .psize = sizeof(vmac64_string3),
4841 .digest = "\xd4\xfa\x8f\xed\xe1\x8f\x32\x8b",
4842 }, {
4843 .key = "a09b5cd!f#07K\x00\x00\x00",
4844 .ksize = 16,
4845 .plaintext = vmac64_string4,
4846 .psize = sizeof(vmac64_string4),
4847 .digest = "\x5f\xa1\x4e\x42\xea\x0f\xa5\xab",
4848 }, {
4849 .key = "a09b5cd!f#07K\x00\x00\x00",
4850 .ksize = 16,
4851 .plaintext = vmac64_string5,
4852 .psize = sizeof(vmac64_string5),
4853 .digest = "\x60\x67\xe8\x1d\xbc\x98\x31\x25",
4854 }, {
4855 .key = "a09b5cd!f#07K\x00\x00\x00",
4856 .ksize = 16,
4857 .plaintext = vmac64_string6,
4858 .psize = sizeof(vmac64_string6),
4859 .digest = "\x41\xeb\x65\x95\x47\x9b\xae\xc4",
4860 },
4861};
4862
4708/* 4863/*
4709 * SHA384 HMAC test vectors from RFC4231 4864 * SHA384 HMAC test vectors from RFC4231
4710 */ 4865 */
diff --git a/crypto/vmac.c b/crypto/vmac.c
index bb2fc787d615..bf1e385bc684 100644
--- a/crypto/vmac.c
+++ b/crypto/vmac.c
@@ -45,6 +45,7 @@
45#define VMAC_KEY_SIZE 128/* Must be 128, 192 or 256 */ 45#define VMAC_KEY_SIZE 128/* Must be 128, 192 or 256 */
46#define VMAC_KEY_LEN (VMAC_KEY_SIZE/8) 46#define VMAC_KEY_LEN (VMAC_KEY_SIZE/8)
47#define VMAC_NHBYTES 128/* Must 2^i for any 3 < i < 13 Standard = 128*/ 47#define VMAC_NHBYTES 128/* Must 2^i for any 3 < i < 13 Standard = 128*/
48#define VMAC_NONCEBYTES 16
48 49
49/* per-transform (per-key) context */ 50/* per-transform (per-key) context */
50struct vmac_tfm_ctx { 51struct vmac_tfm_ctx {
@@ -63,6 +64,11 @@ struct vmac_desc_ctx {
63 unsigned int partial_size; /* size of the partial block */ 64 unsigned int partial_size; /* size of the partial block */
64 bool first_block_processed; 65 bool first_block_processed;
65 u64 polytmp[2*VMAC_TAG_LEN/64]; /* running total of L2-hash */ 66 u64 polytmp[2*VMAC_TAG_LEN/64]; /* running total of L2-hash */
67 union {
68 u8 bytes[VMAC_NONCEBYTES];
69 __be64 pads[VMAC_NONCEBYTES / 8];
70 } nonce;
71 unsigned int nonce_size; /* nonce bytes filled so far */
66}; 72};
67 73
68/* 74/*
@@ -480,6 +486,17 @@ static int vmac_init(struct shash_desc *desc)
480 dctx->partial_size = 0; 486 dctx->partial_size = 0;
481 dctx->first_block_processed = false; 487 dctx->first_block_processed = false;
482 memcpy(dctx->polytmp, tctx->polykey, sizeof(dctx->polytmp)); 488 memcpy(dctx->polytmp, tctx->polykey, sizeof(dctx->polytmp));
489 dctx->nonce_size = 0;
490 return 0;
491}
492
493static int vmac_init_with_hardcoded_nonce(struct shash_desc *desc)
494{
495 struct vmac_desc_ctx *dctx = shash_desc_ctx(desc);
496
497 vmac_init(desc);
498 memset(&dctx->nonce, 0, VMAC_NONCEBYTES);
499 dctx->nonce_size = VMAC_NONCEBYTES;
483 return 0; 500 return 0;
484} 501}
485 502
@@ -489,6 +506,15 @@ static int vmac_update(struct shash_desc *desc, const u8 *p, unsigned int len)
489 struct vmac_desc_ctx *dctx = shash_desc_ctx(desc); 506 struct vmac_desc_ctx *dctx = shash_desc_ctx(desc);
490 unsigned int n; 507 unsigned int n;
491 508
509 /* Nonce is passed as first VMAC_NONCEBYTES bytes of data */
510 if (dctx->nonce_size < VMAC_NONCEBYTES) {
511 n = min(len, VMAC_NONCEBYTES - dctx->nonce_size);
512 memcpy(&dctx->nonce.bytes[dctx->nonce_size], p, n);
513 dctx->nonce_size += n;
514 p += n;
515 len -= n;
516 }
517
492 if (dctx->partial_size) { 518 if (dctx->partial_size) {
493 n = min(len, VMAC_NHBYTES - dctx->partial_size); 519 n = min(len, VMAC_NHBYTES - dctx->partial_size);
494 memcpy(&dctx->partial[dctx->partial_size], p, n); 520 memcpy(&dctx->partial[dctx->partial_size], p, n);
@@ -544,30 +570,62 @@ static u64 vhash_final(const struct vmac_tfm_ctx *tctx,
544 return l3hash(ch, cl, tctx->l3key[0], tctx->l3key[1], partial * 8); 570 return l3hash(ch, cl, tctx->l3key[0], tctx->l3key[1], partial * 8);
545} 571}
546 572
547static int vmac_final(struct shash_desc *desc, u8 *out) 573static int __vmac_final(struct shash_desc *desc, u64 *mac)
548{ 574{
549 const struct vmac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); 575 const struct vmac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
550 struct vmac_desc_ctx *dctx = shash_desc_ctx(desc); 576 struct vmac_desc_ctx *dctx = shash_desc_ctx(desc);
551 static const u8 nonce[16] = {}; /* TODO: this is insecure */
552 union {
553 u8 bytes[16];
554 __be64 pads[2];
555 } block;
556 int index; 577 int index;
557 u64 hash, pad; 578 u64 hash, pad;
558 579
580 if (dctx->nonce_size != VMAC_NONCEBYTES)
581 return -EINVAL;
582
583 /*
584 * The VMAC specification requires a nonce at least 1 bit shorter than
585 * the block cipher's block length, so we actually only accept a 127-bit
586 * nonce. We define the unused bit to be the first one and require that
587 * it be 0, so the needed prepending of a 0 bit is implicit.
588 */
589 if (dctx->nonce.bytes[0] & 0x80)
590 return -EINVAL;
591
559 /* Finish calculating the VHASH of the message */ 592 /* Finish calculating the VHASH of the message */
560 hash = vhash_final(tctx, dctx); 593 hash = vhash_final(tctx, dctx);
561 594
562 /* Generate pseudorandom pad by encrypting the nonce */ 595 /* Generate pseudorandom pad by encrypting the nonce */
563 memcpy(&block, nonce, 16); 596 BUILD_BUG_ON(VMAC_NONCEBYTES != 2 * (VMAC_TAG_LEN / 8));
564 index = block.bytes[15] & 1; 597 index = dctx->nonce.bytes[VMAC_NONCEBYTES - 1] & 1;
565 block.bytes[15] &= ~1; 598 dctx->nonce.bytes[VMAC_NONCEBYTES - 1] &= ~1;
566 crypto_cipher_encrypt_one(tctx->cipher, block.bytes, block.bytes); 599 crypto_cipher_encrypt_one(tctx->cipher, dctx->nonce.bytes,
567 pad = be64_to_cpu(block.pads[index]); 600 dctx->nonce.bytes);
601 pad = be64_to_cpu(dctx->nonce.pads[index]);
568 602
569 /* The VMAC is the sum of VHASH and the pseudorandom pad */ 603 /* The VMAC is the sum of VHASH and the pseudorandom pad */
570 put_unaligned_le64(hash + pad, out); 604 *mac = hash + pad;
605 return 0;
606}
607
608static int vmac_final_le(struct shash_desc *desc, u8 *out)
609{
610 u64 mac;
611 int err;
612
613 err = __vmac_final(desc, &mac);
614 if (err)
615 return err;
616 put_unaligned_le64(mac, out);
617 return 0;
618}
619
620static int vmac_final_be(struct shash_desc *desc, u8 *out)
621{
622 u64 mac;
623 int err;
624
625 err = __vmac_final(desc, &mac);
626 if (err)
627 return err;
628 put_unaligned_be64(mac, out);
571 return 0; 629 return 0;
572} 630}
573 631
@@ -593,7 +651,8 @@ static void vmac_exit_tfm(struct crypto_tfm *tfm)
593 crypto_free_cipher(tctx->cipher); 651 crypto_free_cipher(tctx->cipher);
594} 652}
595 653
596static int vmac_create(struct crypto_template *tmpl, struct rtattr **tb) 654static int vmac_create_common(struct crypto_template *tmpl, struct rtattr **tb,
655 bool vmac64)
597{ 656{
598 struct shash_instance *inst; 657 struct shash_instance *inst;
599 struct crypto_alg *alg; 658 struct crypto_alg *alg;
@@ -609,10 +668,10 @@ static int vmac_create(struct crypto_template *tmpl, struct rtattr **tb)
609 return PTR_ERR(alg); 668 return PTR_ERR(alg);
610 669
611 err = -EINVAL; 670 err = -EINVAL;
612 if (alg->cra_blocksize != 16) 671 if (alg->cra_blocksize != VMAC_NONCEBYTES)
613 goto out_put_alg; 672 goto out_put_alg;
614 673
615 inst = shash_alloc_instance("vmac", alg); 674 inst = shash_alloc_instance(tmpl->name, alg);
616 err = PTR_ERR(inst); 675 err = PTR_ERR(inst);
617 if (IS_ERR(inst)) 676 if (IS_ERR(inst))
618 goto out_put_alg; 677 goto out_put_alg;
@@ -633,9 +692,15 @@ static int vmac_create(struct crypto_template *tmpl, struct rtattr **tb)
633 692
634 inst->alg.descsize = sizeof(struct vmac_desc_ctx); 693 inst->alg.descsize = sizeof(struct vmac_desc_ctx);
635 inst->alg.digestsize = VMAC_TAG_LEN / 8; 694 inst->alg.digestsize = VMAC_TAG_LEN / 8;
636 inst->alg.init = vmac_init; 695 if (vmac64) {
696 inst->alg.init = vmac_init;
697 inst->alg.final = vmac_final_be;
698 } else {
699 pr_warn("vmac: using insecure hardcoded nonce\n");
700 inst->alg.init = vmac_init_with_hardcoded_nonce;
701 inst->alg.final = vmac_final_le;
702 }
637 inst->alg.update = vmac_update; 703 inst->alg.update = vmac_update;
638 inst->alg.final = vmac_final;
639 inst->alg.setkey = vmac_setkey; 704 inst->alg.setkey = vmac_setkey;
640 705
641 err = shash_register_instance(tmpl, inst); 706 err = shash_register_instance(tmpl, inst);
@@ -649,6 +714,16 @@ out_put_alg:
649 return err; 714 return err;
650} 715}
651 716
717static int vmac_create(struct crypto_template *tmpl, struct rtattr **tb)
718{
719 return vmac_create_common(tmpl, tb, false);
720}
721
722static int vmac64_create(struct crypto_template *tmpl, struct rtattr **tb)
723{
724 return vmac_create_common(tmpl, tb, true);
725}
726
652static struct crypto_template vmac_tmpl = { 727static struct crypto_template vmac_tmpl = {
653 .name = "vmac", 728 .name = "vmac",
654 .create = vmac_create, 729 .create = vmac_create,
@@ -656,14 +731,32 @@ static struct crypto_template vmac_tmpl = {
656 .module = THIS_MODULE, 731 .module = THIS_MODULE,
657}; 732};
658 733
734static struct crypto_template vmac64_tmpl = {
735 .name = "vmac64",
736 .create = vmac64_create,
737 .free = shash_free_instance,
738 .module = THIS_MODULE,
739};
740
659static int __init vmac_module_init(void) 741static int __init vmac_module_init(void)
660{ 742{
661 return crypto_register_template(&vmac_tmpl); 743 int err;
744
745 err = crypto_register_template(&vmac_tmpl);
746 if (err)
747 return err;
748
749 err = crypto_register_template(&vmac64_tmpl);
750 if (err)
751 crypto_unregister_template(&vmac_tmpl);
752
753 return err;
662} 754}
663 755
664static void __exit vmac_module_exit(void) 756static void __exit vmac_module_exit(void)
665{ 757{
666 crypto_unregister_template(&vmac_tmpl); 758 crypto_unregister_template(&vmac_tmpl);
759 crypto_unregister_template(&vmac64_tmpl);
667} 760}
668 761
669module_init(vmac_module_init); 762module_init(vmac_module_init);
@@ -672,3 +765,4 @@ module_exit(vmac_module_exit);
672MODULE_LICENSE("GPL"); 765MODULE_LICENSE("GPL");
673MODULE_DESCRIPTION("VMAC hash algorithm"); 766MODULE_DESCRIPTION("VMAC hash algorithm");
674MODULE_ALIAS_CRYPTO("vmac"); 767MODULE_ALIAS_CRYPTO("vmac");
768MODULE_ALIAS_CRYPTO("vmac64");