diff options
author | Salman Qazi <sqazi@google.com> | 2012-10-05 17:24:14 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2012-10-15 10:33:20 -0400 |
commit | ba1ee070909fae01248b8117da1706f3cf2bfd1b (patch) | |
tree | 98d982702fdc17a9699387c59583e9a5ecf0b984 /crypto | |
parent | 7291a932c6e27d9768e374e9d648086636daf61c (diff) |
crypto: vmac - Make VMAC work when blocks aren't aligned
VMAC implementation, as it is, does not work with blocks that
are not multiples of 128-bytes. Furthermore, this is a problem
when using the implementation on scatterlists, even
when the complete plain text is 128-byte multiple, as the pieces
that get passed to vmac_update can be pretty much any size.
I also added test cases for unaligned blocks.
Signed-off-by: Salman Qazi <sqazi@google.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/testmgr.h | 33 | ||||
-rw-r--r-- | crypto/vmac.c | 47 |
2 files changed, 75 insertions, 5 deletions
diff --git a/crypto/testmgr.h b/crypto/testmgr.h index 76d7f6cc82f5..f8365e913de9 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h | |||
@@ -1707,7 +1707,7 @@ static struct hash_testvec aes_xcbc128_tv_template[] = { | |||
1707 | } | 1707 | } |
1708 | }; | 1708 | }; |
1709 | 1709 | ||
1710 | #define VMAC_AES_TEST_VECTORS 8 | 1710 | #define VMAC_AES_TEST_VECTORS 11 |
1711 | static char vmac_string1[128] = {'\x01', '\x01', '\x01', '\x01', | 1711 | static char vmac_string1[128] = {'\x01', '\x01', '\x01', '\x01', |
1712 | '\x02', '\x03', '\x02', '\x02', | 1712 | '\x02', '\x03', '\x02', '\x02', |
1713 | '\x02', '\x04', '\x01', '\x07', | 1713 | '\x02', '\x04', '\x01', '\x07', |
@@ -1723,6 +1723,19 @@ static char vmac_string3[128] = {'a', 'b', 'c', 'a', 'b', 'c', | |||
1723 | 'a', 'b', 'c', 'a', 'b', 'c', | 1723 | 'a', 'b', 'c', 'a', 'b', 'c', |
1724 | }; | 1724 | }; |
1725 | 1725 | ||
1726 | static char vmac_string4[17] = {'b', 'c', 'e', 'f', | ||
1727 | 'i', 'j', 'l', 'm', | ||
1728 | 'o', 'p', 'r', 's', | ||
1729 | 't', 'u', 'w', 'x', 'z'}; | ||
1730 | |||
1731 | static char vmac_string5[127] = {'r', 'm', 'b', 't', 'c', | ||
1732 | 'o', 'l', 'k', ']', '%', | ||
1733 | '9', '2', '7', '!', 'A'}; | ||
1734 | |||
1735 | static char vmac_string6[129] = {'p', 't', '*', '7', 'l', | ||
1736 | 'i', '!', '#', 'w', '0', | ||
1737 | 'z', '/', '4', 'A', 'n'}; | ||
1738 | |||
1726 | static struct hash_testvec aes_vmac128_tv_template[] = { | 1739 | static struct hash_testvec aes_vmac128_tv_template[] = { |
1727 | { | 1740 | { |
1728 | .key = "\x00\x01\x02\x03\x04\x05\x06\x07" | 1741 | .key = "\x00\x01\x02\x03\x04\x05\x06\x07" |
@@ -1776,6 +1789,24 @@ static struct hash_testvec aes_vmac128_tv_template[] = { | |||
1776 | .digest = "\x8b\x32\x8f\xe1\xed\x8f\xfa\xd4", | 1789 | .digest = "\x8b\x32\x8f\xe1\xed\x8f\xfa\xd4", |
1777 | .psize = 128, | 1790 | .psize = 128, |
1778 | .ksize = 16, | 1791 | .ksize = 16, |
1792 | }, { | ||
1793 | .key = "a09b5cd!f#07K\x00\x00\x00", | ||
1794 | .plaintext = vmac_string4, | ||
1795 | .digest = "\xab\xa5\x0f\xea\x42\x4e\xa1\x5f", | ||
1796 | .psize = sizeof(vmac_string4), | ||
1797 | .ksize = 16, | ||
1798 | }, { | ||
1799 | .key = "a09b5cd!f#07K\x00\x00\x00", | ||
1800 | .plaintext = vmac_string5, | ||
1801 | .digest = "\x25\x31\x98\xbc\x1d\xe8\x67\x60", | ||
1802 | .psize = sizeof(vmac_string5), | ||
1803 | .ksize = 16, | ||
1804 | }, { | ||
1805 | .key = "a09b5cd!f#07K\x00\x00\x00", | ||
1806 | .plaintext = vmac_string6, | ||
1807 | .digest = "\xc4\xae\x9b\x47\x95\x65\xeb\x41", | ||
1808 | .psize = sizeof(vmac_string6), | ||
1809 | .ksize = 16, | ||
1779 | }, | 1810 | }, |
1780 | }; | 1811 | }; |
1781 | 1812 | ||
diff --git a/crypto/vmac.c b/crypto/vmac.c index f2338ca98368..2eb11a30c29c 100644 --- a/crypto/vmac.c +++ b/crypto/vmac.c | |||
@@ -375,6 +375,11 @@ static void vhash_update(const unsigned char *m, | |||
375 | u64 pkh = ctx->polykey[0]; | 375 | u64 pkh = ctx->polykey[0]; |
376 | u64 pkl = ctx->polykey[1]; | 376 | u64 pkl = ctx->polykey[1]; |
377 | 377 | ||
378 | if (!mbytes) | ||
379 | return; | ||
380 | |||
381 | BUG_ON(mbytes % VMAC_NHBYTES); | ||
382 | |||
378 | mptr = (u64 *)m; | 383 | mptr = (u64 *)m; |
379 | i = mbytes / VMAC_NHBYTES; /* Must be non-zero */ | 384 | i = mbytes / VMAC_NHBYTES; /* Must be non-zero */ |
380 | 385 | ||
@@ -454,7 +459,7 @@ do_l3: | |||
454 | } | 459 | } |
455 | 460 | ||
456 | static u64 vmac(unsigned char m[], unsigned int mbytes, | 461 | static u64 vmac(unsigned char m[], unsigned int mbytes, |
457 | unsigned char n[16], u64 *tagl, | 462 | const unsigned char n[16], u64 *tagl, |
458 | struct vmac_ctx_t *ctx) | 463 | struct vmac_ctx_t *ctx) |
459 | { | 464 | { |
460 | u64 *in_n, *out_p; | 465 | u64 *in_n, *out_p; |
@@ -559,8 +564,33 @@ static int vmac_update(struct shash_desc *pdesc, const u8 *p, | |||
559 | { | 564 | { |
560 | struct crypto_shash *parent = pdesc->tfm; | 565 | struct crypto_shash *parent = pdesc->tfm; |
561 | struct vmac_ctx_t *ctx = crypto_shash_ctx(parent); | 566 | struct vmac_ctx_t *ctx = crypto_shash_ctx(parent); |
567 | int expand; | ||
568 | int min; | ||
569 | |||
570 | expand = VMAC_NHBYTES - ctx->partial_size > 0 ? | ||
571 | VMAC_NHBYTES - ctx->partial_size : 0; | ||
572 | |||
573 | min = len < expand ? len : expand; | ||
574 | |||
575 | memcpy(ctx->partial + ctx->partial_size, p, min); | ||
576 | ctx->partial_size += min; | ||
577 | |||
578 | if (len < expand) | ||
579 | return 0; | ||
562 | 580 | ||
563 | vhash_update(p, len, &ctx->__vmac_ctx); | 581 | vhash_update(ctx->partial, VMAC_NHBYTES, &ctx->__vmac_ctx); |
582 | ctx->partial_size = 0; | ||
583 | |||
584 | len -= expand; | ||
585 | p += expand; | ||
586 | |||
587 | if (len % VMAC_NHBYTES) { | ||
588 | memcpy(ctx->partial, p + len - (len % VMAC_NHBYTES), | ||
589 | len % VMAC_NHBYTES); | ||
590 | ctx->partial_size = len % VMAC_NHBYTES; | ||
591 | } | ||
592 | |||
593 | vhash_update(p, len - len % VMAC_NHBYTES, &ctx->__vmac_ctx); | ||
564 | 594 | ||
565 | return 0; | 595 | return 0; |
566 | } | 596 | } |
@@ -572,10 +602,20 @@ static int vmac_final(struct shash_desc *pdesc, u8 *out) | |||
572 | vmac_t mac; | 602 | vmac_t mac; |
573 | u8 nonce[16] = {}; | 603 | u8 nonce[16] = {}; |
574 | 604 | ||
575 | mac = vmac(NULL, 0, nonce, NULL, ctx); | 605 | /* vmac() ends up accessing outside the array bounds that |
606 | * we specify. In appears to access up to the next 2-word | ||
607 | * boundary. We'll just be uber cautious and zero the | ||
608 | * unwritten bytes in the buffer. | ||
609 | */ | ||
610 | if (ctx->partial_size) { | ||
611 | memset(ctx->partial + ctx->partial_size, 0, | ||
612 | VMAC_NHBYTES - ctx->partial_size); | ||
613 | } | ||
614 | mac = vmac(ctx->partial, ctx->partial_size, nonce, NULL, ctx); | ||
576 | memcpy(out, &mac, sizeof(vmac_t)); | 615 | memcpy(out, &mac, sizeof(vmac_t)); |
577 | memset(&mac, 0, sizeof(vmac_t)); | 616 | memset(&mac, 0, sizeof(vmac_t)); |
578 | memset(&ctx->__vmac_ctx, 0, sizeof(struct vmac_ctx)); | 617 | memset(&ctx->__vmac_ctx, 0, sizeof(struct vmac_ctx)); |
618 | ctx->partial_size = 0; | ||
579 | return 0; | 619 | return 0; |
580 | } | 620 | } |
581 | 621 | ||
@@ -673,4 +713,3 @@ module_exit(vmac_module_exit); | |||
673 | 713 | ||
674 | MODULE_LICENSE("GPL"); | 714 | MODULE_LICENSE("GPL"); |
675 | MODULE_DESCRIPTION("VMAC hash algorithm"); | 715 | MODULE_DESCRIPTION("VMAC hash algorithm"); |
676 | |||