Skip to content

Commit

Permalink
crypto: vmac - Make VMAC work when blocks aren't aligned
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Herbert Xu <[email protected]>
  • Loading branch information
sqazi authored and herbertx committed Oct 15, 2012
1 parent 7291a93 commit ba1ee07
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 5 deletions.
33 changes: 32 additions & 1 deletion crypto/testmgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1707,7 +1707,7 @@ static struct hash_testvec aes_xcbc128_tv_template[] = {
}
};

#define VMAC_AES_TEST_VECTORS 8
#define VMAC_AES_TEST_VECTORS 11
static char vmac_string1[128] = {'\x01', '\x01', '\x01', '\x01',
'\x02', '\x03', '\x02', '\x02',
'\x02', '\x04', '\x01', '\x07',
Expand All @@ -1723,6 +1723,19 @@ static char vmac_string3[128] = {'a', 'b', 'c', 'a', 'b', 'c',
'a', 'b', 'c', 'a', 'b', 'c',
};

static char vmac_string4[17] = {'b', 'c', 'e', 'f',
'i', 'j', 'l', 'm',
'o', 'p', 'r', 's',
't', 'u', 'w', 'x', 'z'};

static char vmac_string5[127] = {'r', 'm', 'b', 't', 'c',
'o', 'l', 'k', ']', '%',
'9', '2', '7', '!', 'A'};

static char vmac_string6[129] = {'p', 't', '*', '7', 'l',
'i', '!', '#', 'w', '0',
'z', '/', '4', 'A', 'n'};

static struct hash_testvec aes_vmac128_tv_template[] = {
{
.key = "\x00\x01\x02\x03\x04\x05\x06\x07"
Expand Down Expand Up @@ -1776,6 +1789,24 @@ static struct hash_testvec aes_vmac128_tv_template[] = {
.digest = "\x8b\x32\x8f\xe1\xed\x8f\xfa\xd4",
.psize = 128,
.ksize = 16,
}, {
.key = "a09b5cd!f#07K\x00\x00\x00",
.plaintext = vmac_string4,
.digest = "\xab\xa5\x0f\xea\x42\x4e\xa1\x5f",
.psize = sizeof(vmac_string4),
.ksize = 16,
}, {
.key = "a09b5cd!f#07K\x00\x00\x00",
.plaintext = vmac_string5,
.digest = "\x25\x31\x98\xbc\x1d\xe8\x67\x60",
.psize = sizeof(vmac_string5),
.ksize = 16,
}, {
.key = "a09b5cd!f#07K\x00\x00\x00",
.plaintext = vmac_string6,
.digest = "\xc4\xae\x9b\x47\x95\x65\xeb\x41",
.psize = sizeof(vmac_string6),
.ksize = 16,
},
};

Expand Down
47 changes: 43 additions & 4 deletions crypto/vmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,11 @@ static void vhash_update(const unsigned char *m,
u64 pkh = ctx->polykey[0];
u64 pkl = ctx->polykey[1];

if (!mbytes)
return;

BUG_ON(mbytes % VMAC_NHBYTES);

mptr = (u64 *)m;
i = mbytes / VMAC_NHBYTES; /* Must be non-zero */

Expand Down Expand Up @@ -454,7 +459,7 @@ static u64 vhash(unsigned char m[], unsigned int mbytes,
}

static u64 vmac(unsigned char m[], unsigned int mbytes,
unsigned char n[16], u64 *tagl,
const unsigned char n[16], u64 *tagl,
struct vmac_ctx_t *ctx)
{
u64 *in_n, *out_p;
Expand Down Expand Up @@ -559,8 +564,33 @@ static int vmac_update(struct shash_desc *pdesc, const u8 *p,
{
struct crypto_shash *parent = pdesc->tfm;
struct vmac_ctx_t *ctx = crypto_shash_ctx(parent);
int expand;
int min;

expand = VMAC_NHBYTES - ctx->partial_size > 0 ?
VMAC_NHBYTES - ctx->partial_size : 0;

min = len < expand ? len : expand;

memcpy(ctx->partial + ctx->partial_size, p, min);
ctx->partial_size += min;

if (len < expand)
return 0;

vhash_update(p, len, &ctx->__vmac_ctx);
vhash_update(ctx->partial, VMAC_NHBYTES, &ctx->__vmac_ctx);
ctx->partial_size = 0;

len -= expand;
p += expand;

if (len % VMAC_NHBYTES) {
memcpy(ctx->partial, p + len - (len % VMAC_NHBYTES),
len % VMAC_NHBYTES);
ctx->partial_size = len % VMAC_NHBYTES;
}

vhash_update(p, len - len % VMAC_NHBYTES, &ctx->__vmac_ctx);

return 0;
}
Expand All @@ -572,10 +602,20 @@ static int vmac_final(struct shash_desc *pdesc, u8 *out)
vmac_t mac;
u8 nonce[16] = {};

mac = vmac(NULL, 0, nonce, NULL, ctx);
/* vmac() ends up accessing outside the array bounds that
* we specify. In appears to access up to the next 2-word
* boundary. We'll just be uber cautious and zero the
* unwritten bytes in the buffer.
*/
if (ctx->partial_size) {
memset(ctx->partial + ctx->partial_size, 0,
VMAC_NHBYTES - ctx->partial_size);
}
mac = vmac(ctx->partial, ctx->partial_size, nonce, NULL, ctx);
memcpy(out, &mac, sizeof(vmac_t));
memset(&mac, 0, sizeof(vmac_t));
memset(&ctx->__vmac_ctx, 0, sizeof(struct vmac_ctx));
ctx->partial_size = 0;
return 0;
}

Expand Down Expand Up @@ -673,4 +713,3 @@ module_exit(vmac_module_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("VMAC hash algorithm");

2 changes: 2 additions & 0 deletions include/crypto/vmac.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ typedef u64 vmac_t;
struct vmac_ctx_t {
struct crypto_cipher *child;
struct vmac_ctx __vmac_ctx;
u8 partial[VMAC_NHBYTES]; /* partial block */
int partial_size; /* size of the partial block */
};

#endif /* __CRYPTO_VMAC_H */

0 comments on commit ba1ee07

Please sign in to comment.