mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-22 00:40:03 +00:00
![Jason A. Donenfeld](/assets/img/avatar_default.png)
These two C implementations from Zinc -- a 32x32 one and a 64x64 one, depending on the platform -- come from Andrew Moon's public domain poly1305-donna portable code, modified for usage in the kernel. The precomputation in the 32-bit version and the use of 64x64 multiplies in the 64-bit version make these perform better than the code it replaces. Moon's code is also very widespread and has received many eyeballs of scrutiny. There's a bit of interference between the x86 implementation, which relies on internal details of the old scalar implementation. In the next commit, the x86 implementation will be replaced with a faster one that doesn't rely on this, so none of this matters much. But for now, to keep this passing the tests, we inline the bits of the old implementation that the x86 implementation relied on. Also, since we now support a slightly larger key space, via the union, some offsets had to be fixed up. Nonce calculation was folded in with the emit function, to take advantage of 64x64 arithmetic. However, Adiantum appeared to rely on no nonce handling in emit, so this path was conditionalized. We also introduced a new struct, poly1305_core_key, to represent the precise amount of space that particular implementation uses. Testing with kbench9000, depending on the CPU, the update function for the 32x32 version has been improved by 4%-7%, and for the 64x64 by 19%-30%. The 32x32 gains are small, but I think there's great value in having a parallel implementation to the 64x64 one so that the two can be compared side-by-side as nice stand-alone units. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
97 lines
2.4 KiB
C
97 lines
2.4 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Common values for the Poly1305 algorithm
|
|
*/
|
|
|
|
#ifndef _CRYPTO_POLY1305_H
|
|
#define _CRYPTO_POLY1305_H
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/crypto.h>
|
|
|
|
#define POLY1305_BLOCK_SIZE 16
|
|
#define POLY1305_KEY_SIZE 32
|
|
#define POLY1305_DIGEST_SIZE 16
|
|
|
|
/* The poly1305_key and poly1305_state types are mostly opaque and
|
|
* implementation-defined. Limbs might be in base 2^64 or base 2^26, or
|
|
* different yet. The union type provided keeps these 64-bit aligned for the
|
|
* case in which this is implemented using 64x64 multiplies.
|
|
*/
|
|
|
|
struct poly1305_key {
|
|
union {
|
|
u32 r[5];
|
|
u64 r64[3];
|
|
};
|
|
};
|
|
|
|
struct poly1305_core_key {
|
|
struct poly1305_key key;
|
|
struct poly1305_key precomputed_s;
|
|
};
|
|
|
|
struct poly1305_state {
|
|
union {
|
|
u32 h[5];
|
|
u64 h64[3];
|
|
};
|
|
};
|
|
|
|
struct poly1305_desc_ctx {
|
|
/* partial buffer */
|
|
u8 buf[POLY1305_BLOCK_SIZE];
|
|
/* bytes used in partial buffer */
|
|
unsigned int buflen;
|
|
/* how many keys have been set in r[] */
|
|
unsigned short rset;
|
|
/* whether s[] has been set */
|
|
bool sset;
|
|
/* finalize key */
|
|
u32 s[4];
|
|
/* accumulator */
|
|
struct poly1305_state h;
|
|
/* key */
|
|
union {
|
|
struct poly1305_key opaque_r[CONFIG_CRYPTO_LIB_POLY1305_RSIZE];
|
|
struct poly1305_core_key core_r;
|
|
};
|
|
};
|
|
|
|
void poly1305_init_arch(struct poly1305_desc_ctx *desc, const u8 *key);
|
|
void poly1305_init_generic(struct poly1305_desc_ctx *desc, const u8 *key);
|
|
|
|
static inline void poly1305_init(struct poly1305_desc_ctx *desc, const u8 *key)
|
|
{
|
|
if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305))
|
|
poly1305_init_arch(desc, key);
|
|
else
|
|
poly1305_init_generic(desc, key);
|
|
}
|
|
|
|
void poly1305_update_arch(struct poly1305_desc_ctx *desc, const u8 *src,
|
|
unsigned int nbytes);
|
|
void poly1305_update_generic(struct poly1305_desc_ctx *desc, const u8 *src,
|
|
unsigned int nbytes);
|
|
|
|
static inline void poly1305_update(struct poly1305_desc_ctx *desc,
|
|
const u8 *src, unsigned int nbytes)
|
|
{
|
|
if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305))
|
|
poly1305_update_arch(desc, src, nbytes);
|
|
else
|
|
poly1305_update_generic(desc, src, nbytes);
|
|
}
|
|
|
|
void poly1305_final_arch(struct poly1305_desc_ctx *desc, u8 *digest);
|
|
void poly1305_final_generic(struct poly1305_desc_ctx *desc, u8 *digest);
|
|
|
|
static inline void poly1305_final(struct poly1305_desc_ctx *desc, u8 *digest)
|
|
{
|
|
if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305))
|
|
poly1305_final_arch(desc, digest);
|
|
else
|
|
poly1305_final_generic(desc, digest);
|
|
}
|
|
|
|
#endif
|