xref: /openbmc/linux/arch/x86/crypto/ecb_cbc_helpers.h (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1827ee472SArd Biesheuvel /* SPDX-License-Identifier: GPL-2.0 */
2827ee472SArd Biesheuvel 
3827ee472SArd Biesheuvel #ifndef _CRYPTO_ECB_CBC_HELPER_H
4827ee472SArd Biesheuvel #define _CRYPTO_ECB_CBC_HELPER_H
5827ee472SArd Biesheuvel 
6827ee472SArd Biesheuvel #include <crypto/internal/skcipher.h>
7827ee472SArd Biesheuvel #include <asm/fpu/api.h>
8827ee472SArd Biesheuvel 
9827ee472SArd Biesheuvel /*
10827ee472SArd Biesheuvel  * Mode helpers to instantiate parameterized skcipher ECB/CBC modes without
11827ee472SArd Biesheuvel  * having to rely on indirect calls and retpolines.
12827ee472SArd Biesheuvel  */
13827ee472SArd Biesheuvel 
14827ee472SArd Biesheuvel #define ECB_WALK_START(req, bsize, fpu_blocks) do {			\
15827ee472SArd Biesheuvel 	void *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));	\
16*8a1955f9SPeter Lafreniere 	const int __fpu_blocks = (fpu_blocks);				\
17827ee472SArd Biesheuvel 	const int __bsize = (bsize);					\
18827ee472SArd Biesheuvel 	struct skcipher_walk walk;					\
19827ee472SArd Biesheuvel 	int err = skcipher_walk_virt(&walk, (req), false);		\
20827ee472SArd Biesheuvel 	while (walk.nbytes > 0) {					\
21827ee472SArd Biesheuvel 		unsigned int nbytes = walk.nbytes;			\
22*8a1955f9SPeter Lafreniere 		bool do_fpu = __fpu_blocks != -1 &&			\
23*8a1955f9SPeter Lafreniere 			      nbytes >= __fpu_blocks * __bsize;		\
24827ee472SArd Biesheuvel 		const u8 *src = walk.src.virt.addr;			\
25827ee472SArd Biesheuvel 		u8 *dst = walk.dst.virt.addr;				\
26827ee472SArd Biesheuvel 		u8 __maybe_unused buf[(bsize)];				\
27827ee472SArd Biesheuvel 		if (do_fpu) kernel_fpu_begin()
28827ee472SArd Biesheuvel 
29827ee472SArd Biesheuvel #define CBC_WALK_START(req, bsize, fpu_blocks)				\
30827ee472SArd Biesheuvel 	ECB_WALK_START(req, bsize, fpu_blocks)
31827ee472SArd Biesheuvel 
32827ee472SArd Biesheuvel #define ECB_WALK_ADVANCE(blocks) do {					\
33827ee472SArd Biesheuvel 	dst += (blocks) * __bsize;					\
34827ee472SArd Biesheuvel 	src += (blocks) * __bsize;					\
35827ee472SArd Biesheuvel 	nbytes -= (blocks) * __bsize;					\
36827ee472SArd Biesheuvel } while (0)
37827ee472SArd Biesheuvel 
38827ee472SArd Biesheuvel #define ECB_BLOCK(blocks, func) do {					\
39*8a1955f9SPeter Lafreniere 	const int __blocks = (blocks);					\
40*8a1955f9SPeter Lafreniere 	if (do_fpu && __blocks < __fpu_blocks) {			\
41*8a1955f9SPeter Lafreniere 		kernel_fpu_end();					\
42*8a1955f9SPeter Lafreniere 		do_fpu = false;						\
43*8a1955f9SPeter Lafreniere 	}								\
44*8a1955f9SPeter Lafreniere 	while (nbytes >= __blocks * __bsize) {				\
45827ee472SArd Biesheuvel 		(func)(ctx, dst, src);					\
46827ee472SArd Biesheuvel 		ECB_WALK_ADVANCE(blocks);				\
47827ee472SArd Biesheuvel 	}								\
48827ee472SArd Biesheuvel } while (0)
49827ee472SArd Biesheuvel 
50827ee472SArd Biesheuvel #define CBC_ENC_BLOCK(func) do {					\
51827ee472SArd Biesheuvel 	const u8 *__iv = walk.iv;					\
52827ee472SArd Biesheuvel 	while (nbytes >= __bsize) {					\
53827ee472SArd Biesheuvel 		crypto_xor_cpy(dst, src, __iv, __bsize);		\
54827ee472SArd Biesheuvel 		(func)(ctx, dst, dst);					\
55827ee472SArd Biesheuvel 		__iv = dst;						\
56827ee472SArd Biesheuvel 		ECB_WALK_ADVANCE(1);					\
57827ee472SArd Biesheuvel 	}								\
58827ee472SArd Biesheuvel 	memcpy(walk.iv, __iv, __bsize);					\
59827ee472SArd Biesheuvel } while (0)
60827ee472SArd Biesheuvel 
61827ee472SArd Biesheuvel #define CBC_DEC_BLOCK(blocks, func) do {				\
62*8a1955f9SPeter Lafreniere 	const int __blocks = (blocks);					\
63*8a1955f9SPeter Lafreniere 	if (do_fpu && __blocks <  __fpu_blocks) {			\
64*8a1955f9SPeter Lafreniere 		kernel_fpu_end();					\
65*8a1955f9SPeter Lafreniere 		do_fpu = false;						\
66*8a1955f9SPeter Lafreniere 	}								\
67*8a1955f9SPeter Lafreniere 	while (nbytes >= __blocks * __bsize) {				\
68827ee472SArd Biesheuvel 		const u8 *__iv = src + ((blocks) - 1) * __bsize;	\
69827ee472SArd Biesheuvel 		if (dst == src)						\
70827ee472SArd Biesheuvel 			__iv = memcpy(buf, __iv, __bsize);		\
71827ee472SArd Biesheuvel 		(func)(ctx, dst, src);					\
72827ee472SArd Biesheuvel 		crypto_xor(dst, walk.iv, __bsize);			\
73827ee472SArd Biesheuvel 		memcpy(walk.iv, __iv, __bsize);				\
74827ee472SArd Biesheuvel 		ECB_WALK_ADVANCE(blocks);				\
75827ee472SArd Biesheuvel 	}								\
76827ee472SArd Biesheuvel } while (0)
77827ee472SArd Biesheuvel 
78827ee472SArd Biesheuvel #define ECB_WALK_END()							\
79827ee472SArd Biesheuvel 		if (do_fpu) kernel_fpu_end();				\
80827ee472SArd Biesheuvel 		err = skcipher_walk_done(&walk, nbytes);		\
81827ee472SArd Biesheuvel 	}								\
82827ee472SArd Biesheuvel 	return err;							\
83827ee472SArd Biesheuvel } while (0)
84827ee472SArd Biesheuvel 
85827ee472SArd Biesheuvel #define CBC_WALK_END() ECB_WALK_END()
86827ee472SArd Biesheuvel 
87827ee472SArd Biesheuvel #endif
88