Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: x86/blowfish - Convert to use ECB/CBC helpers

We can simplify the blowfish-x86_64 glue code by using the preexisting
ECB/CBC helper macros. Additionally, this allows for easier reuse of asm
functions in later x86 implementations of blowfish.

This involves:
1 - Modifying blowfish_dec_blk_4way() to xor outputs when a flag is
passed.
2 - Renaming blowfish_dec_blk_4way() to __blowfish_dec_blk_4way().
3 - Creating two wrapper functions around __blowfish_dec_blk_4way() for
use in the ECB/CBC macros.
4 - Removing the custom ecb_encrypt() and cbc_encrypt() routines in
favor of macro-based routines.

Signed-off-by: Peter Lafreniere <peter@n8pjl.ca>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Peter Lafreniere and committed by
Herbert Xu
bc3f42ac b529ea65

+58 -168
+27 -3
arch/x86/crypto/blowfish-x86_64-asm_64.S
··· 260 260 bswapq RX3; \ 261 261 movq RX3, 24(RIO); 262 262 263 + #define xor_block4() \ 264 + movq (RIO), RT0; \ 265 + bswapq RT0; \ 266 + xorq RT0, RX1; \ 267 + \ 268 + movq 8(RIO), RT2; \ 269 + bswapq RT2; \ 270 + xorq RT2, RX2; \ 271 + \ 272 + movq 16(RIO), RT3; \ 273 + bswapq RT3; \ 274 + xorq RT3, RX3; 275 + 263 276 SYM_TYPED_FUNC_START(blowfish_enc_blk_4way) 264 277 /* input: 265 278 * %rdi: ctx ··· 308 295 RET; 309 296 SYM_FUNC_END(blowfish_enc_blk_4way) 310 297 311 - SYM_TYPED_FUNC_START(blowfish_dec_blk_4way) 298 + SYM_TYPED_FUNC_START(__blowfish_dec_blk_4way) 312 299 /* input: 313 300 * %rdi: ctx 314 301 * %rsi: dst 315 302 * %rdx: src 303 + * %rcx: cbc (bool) 316 304 */ 317 305 pushq %r12; 318 306 pushq %rbx; 307 + pushq %rcx; 308 + pushq %rdx; 319 309 320 310 movq %rdi, CTX; 321 - movq %rsi, %r11 311 + movq %rsi, %r11; 322 312 movq %rdx, RIO; 323 313 324 314 preload_roundkey_dec(17); ··· 337 321 round_dec4(3); 338 322 add_preloaded_roundkey4(); 339 323 324 + popq RIO; 325 + popq %r12; 326 + testq %r12, %r12; 327 + jz .L_no_cbc_xor; 328 + 329 + xor_block4(); 330 + 331 + .L_no_cbc_xor: 340 332 movq %r11, RIO; 341 333 write_block4(); 342 334 ··· 352 328 popq %r12; 353 329 354 330 RET; 355 - SYM_FUNC_END(blowfish_dec_blk_4way) 331 + SYM_FUNC_END(__blowfish_dec_blk_4way)
+31 -165
arch/x86/crypto/blowfish_glue.c
··· 16 16 #include <linux/module.h> 17 17 #include <linux/types.h> 18 18 19 + #include "ecb_cbc_helpers.h" 20 + 19 21 /* regular block cipher functions */ 20 22 asmlinkage void blowfish_enc_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src); 21 23 asmlinkage void blowfish_dec_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src); ··· 25 23 /* 4-way parallel cipher functions */ 26 24 asmlinkage void blowfish_enc_blk_4way(struct bf_ctx *ctx, u8 *dst, 27 25 const u8 *src); 28 - asmlinkage void blowfish_dec_blk_4way(struct bf_ctx *ctx, u8 *dst, 29 - const u8 *src); 26 + asmlinkage void __blowfish_dec_blk_4way(struct bf_ctx *ctx, u8 *dst, 27 + const u8 *src, bool cbc); 28 + 29 + static inline void blowfish_dec_ecb_4way(struct bf_ctx *ctx, u8 *dst, 30 + const u8 *src) 31 + { 32 + return __blowfish_dec_blk_4way(ctx, dst, src, false); 33 + } 34 + 35 + static inline void blowfish_dec_cbc_4way(struct bf_ctx *ctx, u8 *dst, 36 + const u8 *src) 37 + { 38 + return __blowfish_dec_blk_4way(ctx, dst, src, true); 39 + } 30 40 31 41 static void blowfish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 32 42 { ··· 56 42 return blowfish_setkey(&tfm->base, key, keylen); 57 43 } 58 44 59 - static int ecb_crypt(struct skcipher_request *req, 60 - void (*fn)(struct bf_ctx *, u8 *, const u8 *), 61 - void (*fn_4way)(struct bf_ctx *, u8 *, const u8 *)) 62 - { 63 - unsigned int bsize = BF_BLOCK_SIZE; 64 - struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 65 - struct bf_ctx *ctx = crypto_skcipher_ctx(tfm); 66 - struct skcipher_walk walk; 67 - unsigned int nbytes; 68 - int err; 69 - 70 - err = skcipher_walk_virt(&walk, req, false); 71 - 72 - while ((nbytes = walk.nbytes)) { 73 - u8 *wsrc = walk.src.virt.addr; 74 - u8 *wdst = walk.dst.virt.addr; 75 - 76 - /* Process four block batch */ 77 - if (nbytes >= bsize * 4) { 78 - do { 79 - fn_4way(ctx, wdst, wsrc); 80 - 81 - wsrc += bsize * 4; 82 - wdst += bsize * 4; 83 - nbytes -= bsize * 4; 84 - } while (nbytes >= bsize * 4); 85 - 86 - if (nbytes < bsize) 87 - goto done; 88 - } 89 - 90 - /* Handle leftovers */ 91 - do { 92 - fn(ctx, wdst, wsrc); 93 - 94 - wsrc += bsize; 95 - wdst += bsize; 96 - nbytes -= bsize; 97 - } while (nbytes >= bsize); 98 - 99 - done: 100 - err = skcipher_walk_done(&walk, nbytes); 101 - } 102 - 103 - return err; 104 - } 105 - 106 45 static int ecb_encrypt(struct skcipher_request *req) 107 46 { 108 - return ecb_crypt(req, blowfish_enc_blk, blowfish_enc_blk_4way); 47 + ECB_WALK_START(req, BF_BLOCK_SIZE, -1); 48 + ECB_BLOCK(4, blowfish_enc_blk_4way); 49 + ECB_BLOCK(1, blowfish_enc_blk); 50 + ECB_WALK_END(); 109 51 } 110 52 111 53 static int ecb_decrypt(struct skcipher_request *req) 112 54 { 113 - return ecb_crypt(req, blowfish_dec_blk, blowfish_dec_blk_4way); 114 - } 115 - 116 - static unsigned int __cbc_encrypt(struct bf_ctx *ctx, 117 - struct skcipher_walk *walk) 118 - { 119 - unsigned int bsize = BF_BLOCK_SIZE; 120 - unsigned int nbytes = walk->nbytes; 121 - u64 *src = (u64 *)walk->src.virt.addr; 122 - u64 *dst = (u64 *)walk->dst.virt.addr; 123 - u64 *iv = (u64 *)walk->iv; 124 - 125 - do { 126 - *dst = *src ^ *iv; 127 - blowfish_enc_blk(ctx, (u8 *)dst, (u8 *)dst); 128 - iv = dst; 129 - 130 - src += 1; 131 - dst += 1; 132 - nbytes -= bsize; 133 - } while (nbytes >= bsize); 134 - 135 - *(u64 *)walk->iv = *iv; 136 - return nbytes; 55 + ECB_WALK_START(req, BF_BLOCK_SIZE, -1); 56 + ECB_BLOCK(4, blowfish_dec_ecb_4way); 57 + ECB_BLOCK(1, blowfish_dec_blk); 58 + ECB_WALK_END(); 137 59 } 138 60 139 61 static int cbc_encrypt(struct skcipher_request *req) 140 62 { 141 - struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 142 - struct bf_ctx *ctx = crypto_skcipher_ctx(tfm); 143 - struct skcipher_walk walk; 144 - unsigned int nbytes; 145 - int err; 146 - 147 - err = skcipher_walk_virt(&walk, req, false); 148 - 149 - while (walk.nbytes) { 150 - nbytes = __cbc_encrypt(ctx, &walk); 151 - err = skcipher_walk_done(&walk, nbytes); 152 - } 153 - 154 - return err; 155 - } 156 - 157 - static unsigned int __cbc_decrypt(struct bf_ctx *ctx, 158 - struct skcipher_walk *walk) 159 - { 160 - unsigned int bsize = BF_BLOCK_SIZE; 161 - unsigned int nbytes = walk->nbytes; 162 - u64 *src = (u64 *)walk->src.virt.addr; 163 - u64 *dst = (u64 *)walk->dst.virt.addr; 164 - u64 ivs[4 - 1]; 165 - u64 last_iv; 166 - 167 - /* Start of the last block. */ 168 - src += nbytes / bsize - 1; 169 - dst += nbytes / bsize - 1; 170 - 171 - last_iv = *src; 172 - 173 - /* Process four block batch */ 174 - if (nbytes >= bsize * 4) { 175 - do { 176 - nbytes -= bsize * 4 - bsize; 177 - src -= 4 - 1; 178 - dst -= 4 - 1; 179 - 180 - ivs[0] = src[0]; 181 - ivs[1] = src[1]; 182 - ivs[2] = src[2]; 183 - 184 - blowfish_dec_blk_4way(ctx, (u8 *)dst, (u8 *)src); 185 - 186 - dst[1] ^= ivs[0]; 187 - dst[2] ^= ivs[1]; 188 - dst[3] ^= ivs[2]; 189 - 190 - nbytes -= bsize; 191 - if (nbytes < bsize) 192 - goto done; 193 - 194 - *dst ^= *(src - 1); 195 - src -= 1; 196 - dst -= 1; 197 - } while (nbytes >= bsize * 4); 198 - } 199 - 200 - /* Handle leftovers */ 201 - for (;;) { 202 - blowfish_dec_blk(ctx, (u8 *)dst, (u8 *)src); 203 - 204 - nbytes -= bsize; 205 - if (nbytes < bsize) 206 - break; 207 - 208 - *dst ^= *(src - 1); 209 - src -= 1; 210 - dst -= 1; 211 - } 212 - 213 - done: 214 - *dst ^= *(u64 *)walk->iv; 215 - *(u64 *)walk->iv = last_iv; 216 - 217 - return nbytes; 63 + CBC_WALK_START(req, BF_BLOCK_SIZE, -1); 64 + CBC_ENC_BLOCK(blowfish_enc_blk); 65 + CBC_WALK_END(); 218 66 } 219 67 220 68 static int cbc_decrypt(struct skcipher_request *req) 221 69 { 222 - struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 223 - struct bf_ctx *ctx = crypto_skcipher_ctx(tfm); 224 - struct skcipher_walk walk; 225 - unsigned int nbytes; 226 - int err; 227 - 228 - err = skcipher_walk_virt(&walk, req, false); 229 - 230 - while (walk.nbytes) { 231 - nbytes = __cbc_decrypt(ctx, &walk); 232 - err = skcipher_walk_done(&walk, nbytes); 233 - } 234 - 235 - return err; 70 + CBC_WALK_START(req, BF_BLOCK_SIZE, -1); 71 + CBC_DEC_BLOCK(4, blowfish_dec_cbc_4way); 72 + CBC_DEC_BLOCK(1, blowfish_dec_blk); 73 + CBC_WALK_END(); 236 74 } 237 75 238 76 static struct crypto_alg bf_cipher_alg = {