Merge tag 'pwm/for-5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry...
[linux-2.6-microblaze.git] / arch / x86 / crypto / ecb_cbc_helpers.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2
3 #ifndef _CRYPTO_ECB_CBC_HELPER_H
4 #define _CRYPTO_ECB_CBC_HELPER_H
5
6 #include <crypto/internal/skcipher.h>
7 #include <asm/fpu/api.h>
8
9 /*
10  * Mode helpers to instantiate parameterized skcipher ECB/CBC modes without
11  * having to rely on indirect calls and retpolines.
12  */
13
14 #define ECB_WALK_START(req, bsize, fpu_blocks) do {                     \
15         void *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));   \
16         const int __bsize = (bsize);                                    \
17         struct skcipher_walk walk;                                      \
18         int err = skcipher_walk_virt(&walk, (req), false);              \
19         while (walk.nbytes > 0) {                                       \
20                 unsigned int nbytes = walk.nbytes;                      \
21                 bool do_fpu = (fpu_blocks) != -1 &&                     \
22                               nbytes >= (fpu_blocks) * __bsize;         \
23                 const u8 *src = walk.src.virt.addr;                     \
24                 u8 *dst = walk.dst.virt.addr;                           \
25                 u8 __maybe_unused buf[(bsize)];                         \
26                 if (do_fpu) kernel_fpu_begin()
27
28 #define CBC_WALK_START(req, bsize, fpu_blocks)                          \
29         ECB_WALK_START(req, bsize, fpu_blocks)
30
31 #define ECB_WALK_ADVANCE(blocks) do {                                   \
32         dst += (blocks) * __bsize;                                      \
33         src += (blocks) * __bsize;                                      \
34         nbytes -= (blocks) * __bsize;                                   \
35 } while (0)
36
37 #define ECB_BLOCK(blocks, func) do {                                    \
38         while (nbytes >= (blocks) * __bsize) {                          \
39                 (func)(ctx, dst, src);                                  \
40                 ECB_WALK_ADVANCE(blocks);                               \
41         }                                                               \
42 } while (0)
43
44 #define CBC_ENC_BLOCK(func) do {                                        \
45         const u8 *__iv = walk.iv;                                       \
46         while (nbytes >= __bsize) {                                     \
47                 crypto_xor_cpy(dst, src, __iv, __bsize);                \
48                 (func)(ctx, dst, dst);                                  \
49                 __iv = dst;                                             \
50                 ECB_WALK_ADVANCE(1);                                    \
51         }                                                               \
52         memcpy(walk.iv, __iv, __bsize);                                 \
53 } while (0)
54
55 #define CBC_DEC_BLOCK(blocks, func) do {                                \
56         while (nbytes >= (blocks) * __bsize) {                          \
57                 const u8 *__iv = src + ((blocks) - 1) * __bsize;        \
58                 if (dst == src)                                         \
59                         __iv = memcpy(buf, __iv, __bsize);              \
60                 (func)(ctx, dst, src);                                  \
61                 crypto_xor(dst, walk.iv, __bsize);                      \
62                 memcpy(walk.iv, __iv, __bsize);                         \
63                 ECB_WALK_ADVANCE(blocks);                               \
64         }                                                               \
65 } while (0)
66
67 #define ECB_WALK_END()                                                  \
68                 if (do_fpu) kernel_fpu_end();                           \
69                 err = skcipher_walk_done(&walk, nbytes);                \
70         }                                                               \
71         return err;                                                     \
72 } while (0)
73
74 #define CBC_WALK_END() ECB_WALK_END()
75
76 #endif