162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Common values for the Poly1305 algorithm
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#ifndef _CRYPTO_POLY1305_H
762306a36Sopenharmony_ci#define _CRYPTO_POLY1305_H
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/types.h>
1062306a36Sopenharmony_ci#include <linux/crypto.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#define POLY1305_BLOCK_SIZE	16
1362306a36Sopenharmony_ci#define POLY1305_KEY_SIZE	32
1462306a36Sopenharmony_ci#define POLY1305_DIGEST_SIZE	16
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/* The poly1305_key and poly1305_state types are mostly opaque and
1762306a36Sopenharmony_ci * implementation-defined. Limbs might be in base 2^64 or base 2^26, or
1862306a36Sopenharmony_ci * different yet. The union type provided keeps these 64-bit aligned for the
1962306a36Sopenharmony_ci * case in which this is implemented using 64x64 multiplies.
2062306a36Sopenharmony_ci */
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistruct poly1305_key {
2362306a36Sopenharmony_ci	union {
2462306a36Sopenharmony_ci		u32 r[5];
2562306a36Sopenharmony_ci		u64 r64[3];
2662306a36Sopenharmony_ci	};
2762306a36Sopenharmony_ci};
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistruct poly1305_core_key {
3062306a36Sopenharmony_ci	struct poly1305_key key;
3162306a36Sopenharmony_ci	struct poly1305_key precomputed_s;
3262306a36Sopenharmony_ci};
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistruct poly1305_state {
3562306a36Sopenharmony_ci	union {
3662306a36Sopenharmony_ci		u32 h[5];
3762306a36Sopenharmony_ci		u64 h64[3];
3862306a36Sopenharmony_ci	};
3962306a36Sopenharmony_ci};
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistruct poly1305_desc_ctx {
4262306a36Sopenharmony_ci	/* partial buffer */
4362306a36Sopenharmony_ci	u8 buf[POLY1305_BLOCK_SIZE];
4462306a36Sopenharmony_ci	/* bytes used in partial buffer */
4562306a36Sopenharmony_ci	unsigned int buflen;
4662306a36Sopenharmony_ci	/* how many keys have been set in r[] */
4762306a36Sopenharmony_ci	unsigned short rset;
4862306a36Sopenharmony_ci	/* whether s[] has been set */
4962306a36Sopenharmony_ci	bool sset;
5062306a36Sopenharmony_ci	/* finalize key */
5162306a36Sopenharmony_ci	u32 s[4];
5262306a36Sopenharmony_ci	/* accumulator */
5362306a36Sopenharmony_ci	struct poly1305_state h;
5462306a36Sopenharmony_ci	/* key */
5562306a36Sopenharmony_ci	union {
5662306a36Sopenharmony_ci		struct poly1305_key opaque_r[CONFIG_CRYPTO_LIB_POLY1305_RSIZE];
5762306a36Sopenharmony_ci		struct poly1305_core_key core_r;
5862306a36Sopenharmony_ci	};
5962306a36Sopenharmony_ci};
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_civoid poly1305_init_arch(struct poly1305_desc_ctx *desc,
6262306a36Sopenharmony_ci			const u8 key[POLY1305_KEY_SIZE]);
6362306a36Sopenharmony_civoid poly1305_init_generic(struct poly1305_desc_ctx *desc,
6462306a36Sopenharmony_ci			   const u8 key[POLY1305_KEY_SIZE]);
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistatic inline void poly1305_init(struct poly1305_desc_ctx *desc, const u8 *key)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305))
6962306a36Sopenharmony_ci		poly1305_init_arch(desc, key);
7062306a36Sopenharmony_ci	else
7162306a36Sopenharmony_ci		poly1305_init_generic(desc, key);
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_civoid poly1305_update_arch(struct poly1305_desc_ctx *desc, const u8 *src,
7562306a36Sopenharmony_ci			  unsigned int nbytes);
7662306a36Sopenharmony_civoid poly1305_update_generic(struct poly1305_desc_ctx *desc, const u8 *src,
7762306a36Sopenharmony_ci			     unsigned int nbytes);
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistatic inline void poly1305_update(struct poly1305_desc_ctx *desc,
8062306a36Sopenharmony_ci				   const u8 *src, unsigned int nbytes)
8162306a36Sopenharmony_ci{
8262306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305))
8362306a36Sopenharmony_ci		poly1305_update_arch(desc, src, nbytes);
8462306a36Sopenharmony_ci	else
8562306a36Sopenharmony_ci		poly1305_update_generic(desc, src, nbytes);
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_civoid poly1305_final_arch(struct poly1305_desc_ctx *desc, u8 *digest);
8962306a36Sopenharmony_civoid poly1305_final_generic(struct poly1305_desc_ctx *desc, u8 *digest);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_cistatic inline void poly1305_final(struct poly1305_desc_ctx *desc, u8 *digest)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305))
9462306a36Sopenharmony_ci		poly1305_final_arch(desc, digest);
9562306a36Sopenharmony_ci	else
9662306a36Sopenharmony_ci		poly1305_final_generic(desc, digest);
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci#endif
100