Commit 878afc35 authored by Eric Biggers's avatar Eric Biggers Committed by Herbert Xu

crypto: poly1305 - use structures for key and accumulator

In preparation for exposing a low-level Poly1305 API which implements
the ε-almost-∆-universal (εA∆U) hash function underlying the Poly1305
MAC and supports block-aligned inputs only, create structures
poly1305_key and poly1305_state which hold the limbs of the Poly1305
"r" key and accumulator, respectively.

These structures could actually have the same type (e.g. poly1305_val),
but different types are preferable, to prevent misuse.
Acked-by: default avatarMartin Willi <martin@strongswan.org>
Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
Acked-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent bdb063a7
...@@ -83,35 +83,37 @@ static unsigned int poly1305_simd_blocks(struct poly1305_desc_ctx *dctx, ...@@ -83,35 +83,37 @@ static unsigned int poly1305_simd_blocks(struct poly1305_desc_ctx *dctx,
if (poly1305_use_avx2 && srclen >= POLY1305_BLOCK_SIZE * 4) { if (poly1305_use_avx2 && srclen >= POLY1305_BLOCK_SIZE * 4) {
if (unlikely(!sctx->wset)) { if (unlikely(!sctx->wset)) {
if (!sctx->uset) { if (!sctx->uset) {
memcpy(sctx->u, dctx->r, sizeof(sctx->u)); memcpy(sctx->u, dctx->r.r, sizeof(sctx->u));
poly1305_simd_mult(sctx->u, dctx->r); poly1305_simd_mult(sctx->u, dctx->r.r);
sctx->uset = true; sctx->uset = true;
} }
memcpy(sctx->u + 5, sctx->u, sizeof(sctx->u)); memcpy(sctx->u + 5, sctx->u, sizeof(sctx->u));
poly1305_simd_mult(sctx->u + 5, dctx->r); poly1305_simd_mult(sctx->u + 5, dctx->r.r);
memcpy(sctx->u + 10, sctx->u + 5, sizeof(sctx->u)); memcpy(sctx->u + 10, sctx->u + 5, sizeof(sctx->u));
poly1305_simd_mult(sctx->u + 10, dctx->r); poly1305_simd_mult(sctx->u + 10, dctx->r.r);
sctx->wset = true; sctx->wset = true;
} }
blocks = srclen / (POLY1305_BLOCK_SIZE * 4); blocks = srclen / (POLY1305_BLOCK_SIZE * 4);
poly1305_4block_avx2(dctx->h, src, dctx->r, blocks, sctx->u); poly1305_4block_avx2(dctx->h.h, src, dctx->r.r, blocks,
sctx->u);
src += POLY1305_BLOCK_SIZE * 4 * blocks; src += POLY1305_BLOCK_SIZE * 4 * blocks;
srclen -= POLY1305_BLOCK_SIZE * 4 * blocks; srclen -= POLY1305_BLOCK_SIZE * 4 * blocks;
} }
#endif #endif
if (likely(srclen >= POLY1305_BLOCK_SIZE * 2)) { if (likely(srclen >= POLY1305_BLOCK_SIZE * 2)) {
if (unlikely(!sctx->uset)) { if (unlikely(!sctx->uset)) {
memcpy(sctx->u, dctx->r, sizeof(sctx->u)); memcpy(sctx->u, dctx->r.r, sizeof(sctx->u));
poly1305_simd_mult(sctx->u, dctx->r); poly1305_simd_mult(sctx->u, dctx->r.r);
sctx->uset = true; sctx->uset = true;
} }
blocks = srclen / (POLY1305_BLOCK_SIZE * 2); blocks = srclen / (POLY1305_BLOCK_SIZE * 2);
poly1305_2block_sse2(dctx->h, src, dctx->r, blocks, sctx->u); poly1305_2block_sse2(dctx->h.h, src, dctx->r.r, blocks,
sctx->u);
src += POLY1305_BLOCK_SIZE * 2 * blocks; src += POLY1305_BLOCK_SIZE * 2 * blocks;
srclen -= POLY1305_BLOCK_SIZE * 2 * blocks; srclen -= POLY1305_BLOCK_SIZE * 2 * blocks;
} }
if (srclen >= POLY1305_BLOCK_SIZE) { if (srclen >= POLY1305_BLOCK_SIZE) {
poly1305_block_sse2(dctx->h, src, dctx->r, 1); poly1305_block_sse2(dctx->h.h, src, dctx->r.r, 1);
srclen -= POLY1305_BLOCK_SIZE; srclen -= POLY1305_BLOCK_SIZE;
} }
return srclen; return srclen;
......
...@@ -38,7 +38,7 @@ int crypto_poly1305_init(struct shash_desc *desc) ...@@ -38,7 +38,7 @@ int crypto_poly1305_init(struct shash_desc *desc)
{ {
struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc); struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
memset(dctx->h, 0, sizeof(dctx->h)); memset(dctx->h.h, 0, sizeof(dctx->h.h));
dctx->buflen = 0; dctx->buflen = 0;
dctx->rset = false; dctx->rset = false;
dctx->sset = false; dctx->sset = false;
...@@ -50,11 +50,11 @@ EXPORT_SYMBOL_GPL(crypto_poly1305_init); ...@@ -50,11 +50,11 @@ EXPORT_SYMBOL_GPL(crypto_poly1305_init);
static void poly1305_setrkey(struct poly1305_desc_ctx *dctx, const u8 *key) static void poly1305_setrkey(struct poly1305_desc_ctx *dctx, const u8 *key)
{ {
/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
dctx->r[0] = (get_unaligned_le32(key + 0) >> 0) & 0x3ffffff; dctx->r.r[0] = (get_unaligned_le32(key + 0) >> 0) & 0x3ffffff;
dctx->r[1] = (get_unaligned_le32(key + 3) >> 2) & 0x3ffff03; dctx->r.r[1] = (get_unaligned_le32(key + 3) >> 2) & 0x3ffff03;
dctx->r[2] = (get_unaligned_le32(key + 6) >> 4) & 0x3ffc0ff; dctx->r.r[2] = (get_unaligned_le32(key + 6) >> 4) & 0x3ffc0ff;
dctx->r[3] = (get_unaligned_le32(key + 9) >> 6) & 0x3f03fff; dctx->r.r[3] = (get_unaligned_le32(key + 9) >> 6) & 0x3f03fff;
dctx->r[4] = (get_unaligned_le32(key + 12) >> 8) & 0x00fffff; dctx->r.r[4] = (get_unaligned_le32(key + 12) >> 8) & 0x00fffff;
} }
static void poly1305_setskey(struct poly1305_desc_ctx *dctx, const u8 *key) static void poly1305_setskey(struct poly1305_desc_ctx *dctx, const u8 *key)
...@@ -107,22 +107,22 @@ static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx, ...@@ -107,22 +107,22 @@ static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx,
srclen = datalen; srclen = datalen;
} }
r0 = dctx->r[0]; r0 = dctx->r.r[0];
r1 = dctx->r[1]; r1 = dctx->r.r[1];
r2 = dctx->r[2]; r2 = dctx->r.r[2];
r3 = dctx->r[3]; r3 = dctx->r.r[3];
r4 = dctx->r[4]; r4 = dctx->r.r[4];
s1 = r1 * 5; s1 = r1 * 5;
s2 = r2 * 5; s2 = r2 * 5;
s3 = r3 * 5; s3 = r3 * 5;
s4 = r4 * 5; s4 = r4 * 5;
h0 = dctx->h[0]; h0 = dctx->h.h[0];
h1 = dctx->h[1]; h1 = dctx->h.h[1];
h2 = dctx->h[2]; h2 = dctx->h.h[2];
h3 = dctx->h[3]; h3 = dctx->h.h[3];
h4 = dctx->h[4]; h4 = dctx->h.h[4];
while (likely(srclen >= POLY1305_BLOCK_SIZE)) { while (likely(srclen >= POLY1305_BLOCK_SIZE)) {
...@@ -157,11 +157,11 @@ static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx, ...@@ -157,11 +157,11 @@ static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx,
srclen -= POLY1305_BLOCK_SIZE; srclen -= POLY1305_BLOCK_SIZE;
} }
dctx->h[0] = h0; dctx->h.h[0] = h0;
dctx->h[1] = h1; dctx->h.h[1] = h1;
dctx->h[2] = h2; dctx->h.h[2] = h2;
dctx->h[3] = h3; dctx->h.h[3] = h3;
dctx->h[4] = h4; dctx->h.h[4] = h4;
return srclen; return srclen;
} }
...@@ -220,11 +220,11 @@ int crypto_poly1305_final(struct shash_desc *desc, u8 *dst) ...@@ -220,11 +220,11 @@ int crypto_poly1305_final(struct shash_desc *desc, u8 *dst)
} }
/* fully carry h */ /* fully carry h */
h0 = dctx->h[0]; h0 = dctx->h.h[0];
h1 = dctx->h[1]; h1 = dctx->h.h[1];
h2 = dctx->h[2]; h2 = dctx->h.h[2];
h3 = dctx->h[3]; h3 = dctx->h.h[3];
h4 = dctx->h[4]; h4 = dctx->h.h[4];
h2 += (h1 >> 26); h1 = h1 & 0x3ffffff; h2 += (h1 >> 26); h1 = h1 & 0x3ffffff;
h3 += (h2 >> 26); h2 = h2 & 0x3ffffff; h3 += (h2 >> 26); h2 = h2 & 0x3ffffff;
......
...@@ -13,13 +13,21 @@ ...@@ -13,13 +13,21 @@
#define POLY1305_KEY_SIZE 32 #define POLY1305_KEY_SIZE 32
#define POLY1305_DIGEST_SIZE 16 #define POLY1305_DIGEST_SIZE 16
struct poly1305_key {
u32 r[5]; /* key, base 2^26 */
};
struct poly1305_state {
u32 h[5]; /* accumulator, base 2^26 */
};
struct poly1305_desc_ctx { struct poly1305_desc_ctx {
/* key */ /* key */
u32 r[5]; struct poly1305_key r;
/* finalize key */ /* finalize key */
u32 s[4]; u32 s[4];
/* accumulator */ /* accumulator */
u32 h[5]; struct poly1305_state h;
/* partial buffer */ /* partial buffer */
u8 buf[POLY1305_BLOCK_SIZE]; u8 buf[POLY1305_BLOCK_SIZE];
/* bytes used in partial buffer */ /* bytes used in partial buffer */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment