Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba1ee070 authored by Salman Qazi's avatar Salman Qazi Committed by Herbert Xu
Browse files

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: default avatarSalman Qazi <sqazi@google.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 7291a932
Loading
Loading
Loading
Loading
+32 −1
Original line number Original line Diff line number Diff line
@@ -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',
static char vmac_string1[128] = {'\x01', '\x01', '\x01', '\x01',
				'\x02', '\x03', '\x02', '\x02',
				'\x02', '\x03', '\x02', '\x02',
				'\x02', '\x04', '\x01', '\x07',
				'\x02', '\x04', '\x01', '\x07',
@@ -1723,6 +1723,19 @@ static char vmac_string3[128] = {'a', 'b', 'c', 'a', 'b', 'c',
				'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[] = {
static struct hash_testvec aes_vmac128_tv_template[] = {
	{
	{
		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
@@ -1776,6 +1789,24 @@ static struct hash_testvec aes_vmac128_tv_template[] = {
		.digest = "\x8b\x32\x8f\xe1\xed\x8f\xfa\xd4",
		.digest = "\x8b\x32\x8f\xe1\xed\x8f\xfa\xd4",
		.psize  = 128,
		.psize  = 128,
		.ksize  = 16,
		.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,
	},
	},
};
};
+43 −4
Original line number Original line Diff line number Diff line
@@ -375,6 +375,11 @@ static void vhash_update(const unsigned char *m,
	u64 pkh = ctx->polykey[0];
	u64 pkh = ctx->polykey[0];
	u64 pkl = ctx->polykey[1];
	u64 pkl = ctx->polykey[1];


	if (!mbytes)
		return;

	BUG_ON(mbytes % VMAC_NHBYTES);

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


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


static u64 vmac(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)
			struct vmac_ctx_t *ctx)
{
{
	u64 *in_n, *out_p;
	u64 *in_n, *out_p;
@@ -559,8 +564,33 @@ static int vmac_update(struct shash_desc *pdesc, const u8 *p,
{
{
	struct crypto_shash *parent = pdesc->tfm;
	struct crypto_shash *parent = pdesc->tfm;
	struct vmac_ctx_t *ctx = crypto_shash_ctx(parent);
	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;
	return 0;
}
}
@@ -572,10 +602,20 @@ static int vmac_final(struct shash_desc *pdesc, u8 *out)
	vmac_t mac;
	vmac_t mac;
	u8 nonce[16] = {};
	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));
	memcpy(out, &mac, sizeof(vmac_t));
	memset(&mac, 0, sizeof(vmac_t));
	memset(&mac, 0, sizeof(vmac_t));
	memset(&ctx->__vmac_ctx, 0, sizeof(struct vmac_ctx));
	memset(&ctx->__vmac_ctx, 0, sizeof(struct vmac_ctx));
	ctx->partial_size = 0;
	return 0;
	return 0;
}
}


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


MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("VMAC hash algorithm");
MODULE_DESCRIPTION("VMAC hash algorithm");
+2 −0
Original line number Original line Diff line number Diff line
@@ -56,6 +56,8 @@ typedef u64 vmac_t;
struct vmac_ctx_t {
struct vmac_ctx_t {
	struct crypto_cipher *child;
	struct crypto_cipher *child;
	struct vmac_ctx __vmac_ctx;
	struct vmac_ctx __vmac_ctx;
	u8 partial[VMAC_NHBYTES];	/* partial block */
	int partial_size;		/* size of the partial block */
};
};


#endif /* __CRYPTO_VMAC_H */
#endif /* __CRYPTO_VMAC_H */