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