18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Shared glue code for 128bit block ciphers
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#ifndef _CRYPTO_GLUE_HELPER_H
78c2ecf20Sopenharmony_ci#define _CRYPTO_GLUE_HELPER_H
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <crypto/internal/skcipher.h>
108c2ecf20Sopenharmony_ci#include <linux/kernel.h>
118c2ecf20Sopenharmony_ci#include <asm/fpu/api.h>
128c2ecf20Sopenharmony_ci#include <crypto/b128ops.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_citypedef void (*common_glue_func_t)(const void *ctx, u8 *dst, const u8 *src);
158c2ecf20Sopenharmony_citypedef void (*common_glue_cbc_func_t)(const void *ctx, u8 *dst, const u8 *src);
168c2ecf20Sopenharmony_citypedef void (*common_glue_ctr_func_t)(const void *ctx, u8 *dst, const u8 *src,
178c2ecf20Sopenharmony_ci				       le128 *iv);
188c2ecf20Sopenharmony_citypedef void (*common_glue_xts_func_t)(const void *ctx, u8 *dst, const u8 *src,
198c2ecf20Sopenharmony_ci				       le128 *iv);
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cistruct common_glue_func_entry {
228c2ecf20Sopenharmony_ci	unsigned int num_blocks; /* number of blocks that @fn will process */
238c2ecf20Sopenharmony_ci	union {
248c2ecf20Sopenharmony_ci		common_glue_func_t ecb;
258c2ecf20Sopenharmony_ci		common_glue_cbc_func_t cbc;
268c2ecf20Sopenharmony_ci		common_glue_ctr_func_t ctr;
278c2ecf20Sopenharmony_ci		common_glue_xts_func_t xts;
288c2ecf20Sopenharmony_ci	} fn_u;
298c2ecf20Sopenharmony_ci};
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistruct common_glue_ctx {
328c2ecf20Sopenharmony_ci	unsigned int num_funcs;
338c2ecf20Sopenharmony_ci	int fpu_blocks_limit; /* -1 means fpu not needed at all */
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	/*
368c2ecf20Sopenharmony_ci	 * First funcs entry must have largest num_blocks and last funcs entry
378c2ecf20Sopenharmony_ci	 * must have num_blocks == 1!
388c2ecf20Sopenharmony_ci	 */
398c2ecf20Sopenharmony_ci	struct common_glue_func_entry funcs[];
408c2ecf20Sopenharmony_ci};
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistatic inline bool glue_fpu_begin(unsigned int bsize, int fpu_blocks_limit,
438c2ecf20Sopenharmony_ci				  struct skcipher_walk *walk,
448c2ecf20Sopenharmony_ci				  bool fpu_enabled, unsigned int nbytes)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	if (likely(fpu_blocks_limit < 0))
478c2ecf20Sopenharmony_ci		return false;
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	if (fpu_enabled)
508c2ecf20Sopenharmony_ci		return true;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	/*
538c2ecf20Sopenharmony_ci	 * Vector-registers are only used when chunk to be processed is large
548c2ecf20Sopenharmony_ci	 * enough, so do not enable FPU until it is necessary.
558c2ecf20Sopenharmony_ci	 */
568c2ecf20Sopenharmony_ci	if (nbytes < bsize * (unsigned int)fpu_blocks_limit)
578c2ecf20Sopenharmony_ci		return false;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	/* prevent sleeping if FPU is in use */
608c2ecf20Sopenharmony_ci	skcipher_walk_atomise(walk);
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	kernel_fpu_begin();
638c2ecf20Sopenharmony_ci	return true;
648c2ecf20Sopenharmony_ci}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistatic inline void glue_fpu_end(bool fpu_enabled)
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	if (fpu_enabled)
698c2ecf20Sopenharmony_ci		kernel_fpu_end();
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistatic inline void le128_to_be128(be128 *dst, const le128 *src)
738c2ecf20Sopenharmony_ci{
748c2ecf20Sopenharmony_ci	dst->a = cpu_to_be64(le64_to_cpu(src->a));
758c2ecf20Sopenharmony_ci	dst->b = cpu_to_be64(le64_to_cpu(src->b));
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cistatic inline void be128_to_le128(le128 *dst, const be128 *src)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	dst->a = cpu_to_le64(be64_to_cpu(src->a));
818c2ecf20Sopenharmony_ci	dst->b = cpu_to_le64(be64_to_cpu(src->b));
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistatic inline void le128_inc(le128 *i)
858c2ecf20Sopenharmony_ci{
868c2ecf20Sopenharmony_ci	u64 a = le64_to_cpu(i->a);
878c2ecf20Sopenharmony_ci	u64 b = le64_to_cpu(i->b);
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	b++;
908c2ecf20Sopenharmony_ci	if (!b)
918c2ecf20Sopenharmony_ci		a++;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	i->a = cpu_to_le64(a);
948c2ecf20Sopenharmony_ci	i->b = cpu_to_le64(b);
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ciextern int glue_ecb_req_128bit(const struct common_glue_ctx *gctx,
988c2ecf20Sopenharmony_ci			       struct skcipher_request *req);
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ciextern int glue_cbc_encrypt_req_128bit(const common_glue_func_t fn,
1018c2ecf20Sopenharmony_ci				       struct skcipher_request *req);
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ciextern int glue_cbc_decrypt_req_128bit(const struct common_glue_ctx *gctx,
1048c2ecf20Sopenharmony_ci				       struct skcipher_request *req);
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ciextern int glue_ctr_req_128bit(const struct common_glue_ctx *gctx,
1078c2ecf20Sopenharmony_ci			       struct skcipher_request *req);
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ciextern int glue_xts_req_128bit(const struct common_glue_ctx *gctx,
1108c2ecf20Sopenharmony_ci			       struct skcipher_request *req,
1118c2ecf20Sopenharmony_ci			       common_glue_func_t tweak_fn, void *tweak_ctx,
1128c2ecf20Sopenharmony_ci			       void *crypt_ctx, bool decrypt);
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ciextern void glue_xts_crypt_128bit_one(const void *ctx, u8 *dst,
1158c2ecf20Sopenharmony_ci				      const u8 *src, le128 *iv,
1168c2ecf20Sopenharmony_ci				      common_glue_func_t fn);
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci#endif /* _CRYPTO_GLUE_HELPER_H */
119