1*6574e6c6SJussi Kivilinna /* 2*6574e6c6SJussi Kivilinna * Glue Code for assembler optimized version of 3DES 3*6574e6c6SJussi Kivilinna * 4*6574e6c6SJussi Kivilinna * Copyright © 2014 Jussi Kivilinna <jussi.kivilinna@mbnet.fi> 5*6574e6c6SJussi Kivilinna * 6*6574e6c6SJussi Kivilinna * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by: 7*6574e6c6SJussi Kivilinna * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> 8*6574e6c6SJussi Kivilinna * CTR part based on code (crypto/ctr.c) by: 9*6574e6c6SJussi Kivilinna * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com> 10*6574e6c6SJussi Kivilinna * 11*6574e6c6SJussi Kivilinna * This program is free software; you can redistribute it and/or modify 12*6574e6c6SJussi Kivilinna * it under the terms of the GNU General Public License as published by 13*6574e6c6SJussi Kivilinna * the Free Software Foundation; either version 2 of the License, or 14*6574e6c6SJussi Kivilinna * (at your option) any later version. 15*6574e6c6SJussi Kivilinna * 16*6574e6c6SJussi Kivilinna * This program is distributed in the hope that it will be useful, 17*6574e6c6SJussi Kivilinna * but WITHOUT ANY WARRANTY; without even the implied warranty of 18*6574e6c6SJussi Kivilinna * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19*6574e6c6SJussi Kivilinna * GNU General Public License for more details. 20*6574e6c6SJussi Kivilinna * 21*6574e6c6SJussi Kivilinna */ 22*6574e6c6SJussi Kivilinna 23*6574e6c6SJussi Kivilinna #include <asm/processor.h> 24*6574e6c6SJussi Kivilinna #include <crypto/des.h> 25*6574e6c6SJussi Kivilinna #include <linux/crypto.h> 26*6574e6c6SJussi Kivilinna #include <linux/init.h> 27*6574e6c6SJussi Kivilinna #include <linux/module.h> 28*6574e6c6SJussi Kivilinna #include <linux/types.h> 29*6574e6c6SJussi Kivilinna #include <crypto/algapi.h> 30*6574e6c6SJussi Kivilinna 31*6574e6c6SJussi Kivilinna struct des3_ede_x86_ctx { 32*6574e6c6SJussi Kivilinna u32 enc_expkey[DES3_EDE_EXPKEY_WORDS]; 33*6574e6c6SJussi Kivilinna u32 dec_expkey[DES3_EDE_EXPKEY_WORDS]; 34*6574e6c6SJussi Kivilinna }; 35*6574e6c6SJussi Kivilinna 36*6574e6c6SJussi Kivilinna /* regular block cipher functions */ 37*6574e6c6SJussi Kivilinna asmlinkage void des3_ede_x86_64_crypt_blk(const u32 *expkey, u8 *dst, 38*6574e6c6SJussi Kivilinna const u8 *src); 39*6574e6c6SJussi Kivilinna 40*6574e6c6SJussi Kivilinna /* 3-way parallel cipher functions */ 41*6574e6c6SJussi Kivilinna asmlinkage void des3_ede_x86_64_crypt_blk_3way(const u32 *expkey, u8 *dst, 42*6574e6c6SJussi Kivilinna const u8 *src); 43*6574e6c6SJussi Kivilinna 44*6574e6c6SJussi Kivilinna static inline void des3_ede_enc_blk(struct des3_ede_x86_ctx *ctx, u8 *dst, 45*6574e6c6SJussi Kivilinna const u8 *src) 46*6574e6c6SJussi Kivilinna { 47*6574e6c6SJussi Kivilinna u32 *enc_ctx = ctx->enc_expkey; 48*6574e6c6SJussi Kivilinna 49*6574e6c6SJussi Kivilinna des3_ede_x86_64_crypt_blk(enc_ctx, dst, src); 50*6574e6c6SJussi Kivilinna } 51*6574e6c6SJussi Kivilinna 52*6574e6c6SJussi Kivilinna static inline void des3_ede_dec_blk(struct des3_ede_x86_ctx *ctx, u8 *dst, 53*6574e6c6SJussi Kivilinna const u8 *src) 54*6574e6c6SJussi Kivilinna { 55*6574e6c6SJussi Kivilinna u32 *dec_ctx = ctx->dec_expkey; 56*6574e6c6SJussi Kivilinna 57*6574e6c6SJussi Kivilinna des3_ede_x86_64_crypt_blk(dec_ctx, dst, src); 58*6574e6c6SJussi Kivilinna } 59*6574e6c6SJussi Kivilinna 60*6574e6c6SJussi Kivilinna static inline void des3_ede_enc_blk_3way(struct des3_ede_x86_ctx *ctx, u8 *dst, 61*6574e6c6SJussi Kivilinna const u8 *src) 62*6574e6c6SJussi Kivilinna { 63*6574e6c6SJussi Kivilinna u32 *enc_ctx = ctx->enc_expkey; 64*6574e6c6SJussi Kivilinna 65*6574e6c6SJussi Kivilinna des3_ede_x86_64_crypt_blk_3way(enc_ctx, dst, src); 66*6574e6c6SJussi Kivilinna } 67*6574e6c6SJussi Kivilinna 68*6574e6c6SJussi Kivilinna static inline void des3_ede_dec_blk_3way(struct des3_ede_x86_ctx *ctx, u8 *dst, 69*6574e6c6SJussi Kivilinna const u8 *src) 70*6574e6c6SJussi Kivilinna { 71*6574e6c6SJussi Kivilinna u32 *dec_ctx = ctx->dec_expkey; 72*6574e6c6SJussi Kivilinna 73*6574e6c6SJussi Kivilinna des3_ede_x86_64_crypt_blk_3way(dec_ctx, dst, src); 74*6574e6c6SJussi Kivilinna } 75*6574e6c6SJussi Kivilinna 76*6574e6c6SJussi Kivilinna static void des3_ede_x86_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 77*6574e6c6SJussi Kivilinna { 78*6574e6c6SJussi Kivilinna des3_ede_enc_blk(crypto_tfm_ctx(tfm), dst, src); 79*6574e6c6SJussi Kivilinna } 80*6574e6c6SJussi Kivilinna 81*6574e6c6SJussi Kivilinna static void des3_ede_x86_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 82*6574e6c6SJussi Kivilinna { 83*6574e6c6SJussi Kivilinna des3_ede_dec_blk(crypto_tfm_ctx(tfm), dst, src); 84*6574e6c6SJussi Kivilinna } 85*6574e6c6SJussi Kivilinna 86*6574e6c6SJussi Kivilinna static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk, 87*6574e6c6SJussi Kivilinna const u32 *expkey) 88*6574e6c6SJussi Kivilinna { 89*6574e6c6SJussi Kivilinna unsigned int bsize = DES3_EDE_BLOCK_SIZE; 90*6574e6c6SJussi Kivilinna unsigned int nbytes; 91*6574e6c6SJussi Kivilinna int err; 92*6574e6c6SJussi Kivilinna 93*6574e6c6SJussi Kivilinna err = blkcipher_walk_virt(desc, walk); 94*6574e6c6SJussi Kivilinna 95*6574e6c6SJussi Kivilinna while ((nbytes = walk->nbytes)) { 96*6574e6c6SJussi Kivilinna u8 *wsrc = walk->src.virt.addr; 97*6574e6c6SJussi Kivilinna u8 *wdst = walk->dst.virt.addr; 98*6574e6c6SJussi Kivilinna 99*6574e6c6SJussi Kivilinna /* Process four block batch */ 100*6574e6c6SJussi Kivilinna if (nbytes >= bsize * 3) { 101*6574e6c6SJussi Kivilinna do { 102*6574e6c6SJussi Kivilinna des3_ede_x86_64_crypt_blk_3way(expkey, wdst, 103*6574e6c6SJussi Kivilinna wsrc); 104*6574e6c6SJussi Kivilinna 105*6574e6c6SJussi Kivilinna wsrc += bsize * 3; 106*6574e6c6SJussi Kivilinna wdst += bsize * 3; 107*6574e6c6SJussi Kivilinna nbytes -= bsize * 3; 108*6574e6c6SJussi Kivilinna } while (nbytes >= bsize * 3); 109*6574e6c6SJussi Kivilinna 110*6574e6c6SJussi Kivilinna if (nbytes < bsize) 111*6574e6c6SJussi Kivilinna goto done; 112*6574e6c6SJussi Kivilinna } 113*6574e6c6SJussi Kivilinna 114*6574e6c6SJussi Kivilinna /* Handle leftovers */ 115*6574e6c6SJussi Kivilinna do { 116*6574e6c6SJussi Kivilinna des3_ede_x86_64_crypt_blk(expkey, wdst, wsrc); 117*6574e6c6SJussi Kivilinna 118*6574e6c6SJussi Kivilinna wsrc += bsize; 119*6574e6c6SJussi Kivilinna wdst += bsize; 120*6574e6c6SJussi Kivilinna nbytes -= bsize; 121*6574e6c6SJussi Kivilinna } while (nbytes >= bsize); 122*6574e6c6SJussi Kivilinna 123*6574e6c6SJussi Kivilinna done: 124*6574e6c6SJussi Kivilinna err = blkcipher_walk_done(desc, walk, nbytes); 125*6574e6c6SJussi Kivilinna } 126*6574e6c6SJussi Kivilinna 127*6574e6c6SJussi Kivilinna return err; 128*6574e6c6SJussi Kivilinna } 129*6574e6c6SJussi Kivilinna 130*6574e6c6SJussi Kivilinna static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, 131*6574e6c6SJussi Kivilinna struct scatterlist *src, unsigned int nbytes) 132*6574e6c6SJussi Kivilinna { 133*6574e6c6SJussi Kivilinna struct des3_ede_x86_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 134*6574e6c6SJussi Kivilinna struct blkcipher_walk walk; 135*6574e6c6SJussi Kivilinna 136*6574e6c6SJussi Kivilinna blkcipher_walk_init(&walk, dst, src, nbytes); 137*6574e6c6SJussi Kivilinna return ecb_crypt(desc, &walk, ctx->enc_expkey); 138*6574e6c6SJussi Kivilinna } 139*6574e6c6SJussi Kivilinna 140*6574e6c6SJussi Kivilinna static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, 141*6574e6c6SJussi Kivilinna struct scatterlist *src, unsigned int nbytes) 142*6574e6c6SJussi Kivilinna { 143*6574e6c6SJussi Kivilinna struct des3_ede_x86_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 144*6574e6c6SJussi Kivilinna struct blkcipher_walk walk; 145*6574e6c6SJussi Kivilinna 146*6574e6c6SJussi Kivilinna blkcipher_walk_init(&walk, dst, src, nbytes); 147*6574e6c6SJussi Kivilinna return ecb_crypt(desc, &walk, ctx->dec_expkey); 148*6574e6c6SJussi Kivilinna } 149*6574e6c6SJussi Kivilinna 150*6574e6c6SJussi Kivilinna static unsigned int __cbc_encrypt(struct blkcipher_desc *desc, 151*6574e6c6SJussi Kivilinna struct blkcipher_walk *walk) 152*6574e6c6SJussi Kivilinna { 153*6574e6c6SJussi Kivilinna struct des3_ede_x86_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 154*6574e6c6SJussi Kivilinna unsigned int bsize = DES3_EDE_BLOCK_SIZE; 155*6574e6c6SJussi Kivilinna unsigned int nbytes = walk->nbytes; 156*6574e6c6SJussi Kivilinna u64 *src = (u64 *)walk->src.virt.addr; 157*6574e6c6SJussi Kivilinna u64 *dst = (u64 *)walk->dst.virt.addr; 158*6574e6c6SJussi Kivilinna u64 *iv = (u64 *)walk->iv; 159*6574e6c6SJussi Kivilinna 160*6574e6c6SJussi Kivilinna do { 161*6574e6c6SJussi Kivilinna *dst = *src ^ *iv; 162*6574e6c6SJussi Kivilinna des3_ede_enc_blk(ctx, (u8 *)dst, (u8 *)dst); 163*6574e6c6SJussi Kivilinna iv = dst; 164*6574e6c6SJussi Kivilinna 165*6574e6c6SJussi Kivilinna src += 1; 166*6574e6c6SJussi Kivilinna dst += 1; 167*6574e6c6SJussi Kivilinna nbytes -= bsize; 168*6574e6c6SJussi Kivilinna } while (nbytes >= bsize); 169*6574e6c6SJussi Kivilinna 170*6574e6c6SJussi Kivilinna *(u64 *)walk->iv = *iv; 171*6574e6c6SJussi Kivilinna return nbytes; 172*6574e6c6SJussi Kivilinna } 173*6574e6c6SJussi Kivilinna 174*6574e6c6SJussi Kivilinna static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, 175*6574e6c6SJussi Kivilinna struct scatterlist *src, unsigned int nbytes) 176*6574e6c6SJussi Kivilinna { 177*6574e6c6SJussi Kivilinna struct blkcipher_walk walk; 178*6574e6c6SJussi Kivilinna int err; 179*6574e6c6SJussi Kivilinna 180*6574e6c6SJussi Kivilinna blkcipher_walk_init(&walk, dst, src, nbytes); 181*6574e6c6SJussi Kivilinna err = blkcipher_walk_virt(desc, &walk); 182*6574e6c6SJussi Kivilinna 183*6574e6c6SJussi Kivilinna while ((nbytes = walk.nbytes)) { 184*6574e6c6SJussi Kivilinna nbytes = __cbc_encrypt(desc, &walk); 185*6574e6c6SJussi Kivilinna err = blkcipher_walk_done(desc, &walk, nbytes); 186*6574e6c6SJussi Kivilinna } 187*6574e6c6SJussi Kivilinna 188*6574e6c6SJussi Kivilinna return err; 189*6574e6c6SJussi Kivilinna } 190*6574e6c6SJussi Kivilinna 191*6574e6c6SJussi Kivilinna static unsigned int __cbc_decrypt(struct blkcipher_desc *desc, 192*6574e6c6SJussi Kivilinna struct blkcipher_walk *walk) 193*6574e6c6SJussi Kivilinna { 194*6574e6c6SJussi Kivilinna struct des3_ede_x86_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 195*6574e6c6SJussi Kivilinna unsigned int bsize = DES3_EDE_BLOCK_SIZE; 196*6574e6c6SJussi Kivilinna unsigned int nbytes = walk->nbytes; 197*6574e6c6SJussi Kivilinna u64 *src = (u64 *)walk->src.virt.addr; 198*6574e6c6SJussi Kivilinna u64 *dst = (u64 *)walk->dst.virt.addr; 199*6574e6c6SJussi Kivilinna u64 ivs[3 - 1]; 200*6574e6c6SJussi Kivilinna u64 last_iv; 201*6574e6c6SJussi Kivilinna 202*6574e6c6SJussi Kivilinna /* Start of the last block. */ 203*6574e6c6SJussi Kivilinna src += nbytes / bsize - 1; 204*6574e6c6SJussi Kivilinna dst += nbytes / bsize - 1; 205*6574e6c6SJussi Kivilinna 206*6574e6c6SJussi Kivilinna last_iv = *src; 207*6574e6c6SJussi Kivilinna 208*6574e6c6SJussi Kivilinna /* Process four block batch */ 209*6574e6c6SJussi Kivilinna if (nbytes >= bsize * 3) { 210*6574e6c6SJussi Kivilinna do { 211*6574e6c6SJussi Kivilinna nbytes -= bsize * 3 - bsize; 212*6574e6c6SJussi Kivilinna src -= 3 - 1; 213*6574e6c6SJussi Kivilinna dst -= 3 - 1; 214*6574e6c6SJussi Kivilinna 215*6574e6c6SJussi Kivilinna ivs[0] = src[0]; 216*6574e6c6SJussi Kivilinna ivs[1] = src[1]; 217*6574e6c6SJussi Kivilinna 218*6574e6c6SJussi Kivilinna des3_ede_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src); 219*6574e6c6SJussi Kivilinna 220*6574e6c6SJussi Kivilinna dst[1] ^= ivs[0]; 221*6574e6c6SJussi Kivilinna dst[2] ^= ivs[1]; 222*6574e6c6SJussi Kivilinna 223*6574e6c6SJussi Kivilinna nbytes -= bsize; 224*6574e6c6SJussi Kivilinna if (nbytes < bsize) 225*6574e6c6SJussi Kivilinna goto done; 226*6574e6c6SJussi Kivilinna 227*6574e6c6SJussi Kivilinna *dst ^= *(src - 1); 228*6574e6c6SJussi Kivilinna src -= 1; 229*6574e6c6SJussi Kivilinna dst -= 1; 230*6574e6c6SJussi Kivilinna } while (nbytes >= bsize * 3); 231*6574e6c6SJussi Kivilinna } 232*6574e6c6SJussi Kivilinna 233*6574e6c6SJussi Kivilinna /* Handle leftovers */ 234*6574e6c6SJussi Kivilinna for (;;) { 235*6574e6c6SJussi Kivilinna des3_ede_dec_blk(ctx, (u8 *)dst, (u8 *)src); 236*6574e6c6SJussi Kivilinna 237*6574e6c6SJussi Kivilinna nbytes -= bsize; 238*6574e6c6SJussi Kivilinna if (nbytes < bsize) 239*6574e6c6SJussi Kivilinna break; 240*6574e6c6SJussi Kivilinna 241*6574e6c6SJussi Kivilinna *dst ^= *(src - 1); 242*6574e6c6SJussi Kivilinna src -= 1; 243*6574e6c6SJussi Kivilinna dst -= 1; 244*6574e6c6SJussi Kivilinna } 245*6574e6c6SJussi Kivilinna 246*6574e6c6SJussi Kivilinna done: 247*6574e6c6SJussi Kivilinna *dst ^= *(u64 *)walk->iv; 248*6574e6c6SJussi Kivilinna *(u64 *)walk->iv = last_iv; 249*6574e6c6SJussi Kivilinna 250*6574e6c6SJussi Kivilinna return nbytes; 251*6574e6c6SJussi Kivilinna } 252*6574e6c6SJussi Kivilinna 253*6574e6c6SJussi Kivilinna static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, 254*6574e6c6SJussi Kivilinna struct scatterlist *src, unsigned int nbytes) 255*6574e6c6SJussi Kivilinna { 256*6574e6c6SJussi Kivilinna struct blkcipher_walk walk; 257*6574e6c6SJussi Kivilinna int err; 258*6574e6c6SJussi Kivilinna 259*6574e6c6SJussi Kivilinna blkcipher_walk_init(&walk, dst, src, nbytes); 260*6574e6c6SJussi Kivilinna err = blkcipher_walk_virt(desc, &walk); 261*6574e6c6SJussi Kivilinna 262*6574e6c6SJussi Kivilinna while ((nbytes = walk.nbytes)) { 263*6574e6c6SJussi Kivilinna nbytes = __cbc_decrypt(desc, &walk); 264*6574e6c6SJussi Kivilinna err = blkcipher_walk_done(desc, &walk, nbytes); 265*6574e6c6SJussi Kivilinna } 266*6574e6c6SJussi Kivilinna 267*6574e6c6SJussi Kivilinna return err; 268*6574e6c6SJussi Kivilinna } 269*6574e6c6SJussi Kivilinna 270*6574e6c6SJussi Kivilinna static void ctr_crypt_final(struct des3_ede_x86_ctx *ctx, 271*6574e6c6SJussi Kivilinna struct blkcipher_walk *walk) 272*6574e6c6SJussi Kivilinna { 273*6574e6c6SJussi Kivilinna u8 *ctrblk = walk->iv; 274*6574e6c6SJussi Kivilinna u8 keystream[DES3_EDE_BLOCK_SIZE]; 275*6574e6c6SJussi Kivilinna u8 *src = walk->src.virt.addr; 276*6574e6c6SJussi Kivilinna u8 *dst = walk->dst.virt.addr; 277*6574e6c6SJussi Kivilinna unsigned int nbytes = walk->nbytes; 278*6574e6c6SJussi Kivilinna 279*6574e6c6SJussi Kivilinna des3_ede_enc_blk(ctx, keystream, ctrblk); 280*6574e6c6SJussi Kivilinna crypto_xor(keystream, src, nbytes); 281*6574e6c6SJussi Kivilinna memcpy(dst, keystream, nbytes); 282*6574e6c6SJussi Kivilinna 283*6574e6c6SJussi Kivilinna crypto_inc(ctrblk, DES3_EDE_BLOCK_SIZE); 284*6574e6c6SJussi Kivilinna } 285*6574e6c6SJussi Kivilinna 286*6574e6c6SJussi Kivilinna static unsigned int __ctr_crypt(struct blkcipher_desc *desc, 287*6574e6c6SJussi Kivilinna struct blkcipher_walk *walk) 288*6574e6c6SJussi Kivilinna { 289*6574e6c6SJussi Kivilinna struct des3_ede_x86_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 290*6574e6c6SJussi Kivilinna unsigned int bsize = DES3_EDE_BLOCK_SIZE; 291*6574e6c6SJussi Kivilinna unsigned int nbytes = walk->nbytes; 292*6574e6c6SJussi Kivilinna u64 *src = (u64 *)walk->src.virt.addr; 293*6574e6c6SJussi Kivilinna u64 *dst = (u64 *)walk->dst.virt.addr; 294*6574e6c6SJussi Kivilinna u64 ctrblk = be64_to_cpu(*(__be64 *)walk->iv); 295*6574e6c6SJussi Kivilinna __be64 ctrblocks[3]; 296*6574e6c6SJussi Kivilinna 297*6574e6c6SJussi Kivilinna /* Process four block batch */ 298*6574e6c6SJussi Kivilinna if (nbytes >= bsize * 3) { 299*6574e6c6SJussi Kivilinna do { 300*6574e6c6SJussi Kivilinna /* create ctrblks for parallel encrypt */ 301*6574e6c6SJussi Kivilinna ctrblocks[0] = cpu_to_be64(ctrblk++); 302*6574e6c6SJussi Kivilinna ctrblocks[1] = cpu_to_be64(ctrblk++); 303*6574e6c6SJussi Kivilinna ctrblocks[2] = cpu_to_be64(ctrblk++); 304*6574e6c6SJussi Kivilinna 305*6574e6c6SJussi Kivilinna des3_ede_enc_blk_3way(ctx, (u8 *)ctrblocks, 306*6574e6c6SJussi Kivilinna (u8 *)ctrblocks); 307*6574e6c6SJussi Kivilinna 308*6574e6c6SJussi Kivilinna dst[0] = src[0] ^ ctrblocks[0]; 309*6574e6c6SJussi Kivilinna dst[1] = src[1] ^ ctrblocks[1]; 310*6574e6c6SJussi Kivilinna dst[2] = src[2] ^ ctrblocks[2]; 311*6574e6c6SJussi Kivilinna 312*6574e6c6SJussi Kivilinna src += 3; 313*6574e6c6SJussi Kivilinna dst += 3; 314*6574e6c6SJussi Kivilinna } while ((nbytes -= bsize * 3) >= bsize * 3); 315*6574e6c6SJussi Kivilinna 316*6574e6c6SJussi Kivilinna if (nbytes < bsize) 317*6574e6c6SJussi Kivilinna goto done; 318*6574e6c6SJussi Kivilinna } 319*6574e6c6SJussi Kivilinna 320*6574e6c6SJussi Kivilinna /* Handle leftovers */ 321*6574e6c6SJussi Kivilinna do { 322*6574e6c6SJussi Kivilinna ctrblocks[0] = cpu_to_be64(ctrblk++); 323*6574e6c6SJussi Kivilinna 324*6574e6c6SJussi Kivilinna des3_ede_enc_blk(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks); 325*6574e6c6SJussi Kivilinna 326*6574e6c6SJussi Kivilinna dst[0] = src[0] ^ ctrblocks[0]; 327*6574e6c6SJussi Kivilinna 328*6574e6c6SJussi Kivilinna src += 1; 329*6574e6c6SJussi Kivilinna dst += 1; 330*6574e6c6SJussi Kivilinna } while ((nbytes -= bsize) >= bsize); 331*6574e6c6SJussi Kivilinna 332*6574e6c6SJussi Kivilinna done: 333*6574e6c6SJussi Kivilinna *(__be64 *)walk->iv = cpu_to_be64(ctrblk); 334*6574e6c6SJussi Kivilinna return nbytes; 335*6574e6c6SJussi Kivilinna } 336*6574e6c6SJussi Kivilinna 337*6574e6c6SJussi Kivilinna static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, 338*6574e6c6SJussi Kivilinna struct scatterlist *src, unsigned int nbytes) 339*6574e6c6SJussi Kivilinna { 340*6574e6c6SJussi Kivilinna struct blkcipher_walk walk; 341*6574e6c6SJussi Kivilinna int err; 342*6574e6c6SJussi Kivilinna 343*6574e6c6SJussi Kivilinna blkcipher_walk_init(&walk, dst, src, nbytes); 344*6574e6c6SJussi Kivilinna err = blkcipher_walk_virt_block(desc, &walk, DES3_EDE_BLOCK_SIZE); 345*6574e6c6SJussi Kivilinna 346*6574e6c6SJussi Kivilinna while ((nbytes = walk.nbytes) >= DES3_EDE_BLOCK_SIZE) { 347*6574e6c6SJussi Kivilinna nbytes = __ctr_crypt(desc, &walk); 348*6574e6c6SJussi Kivilinna err = blkcipher_walk_done(desc, &walk, nbytes); 349*6574e6c6SJussi Kivilinna } 350*6574e6c6SJussi Kivilinna 351*6574e6c6SJussi Kivilinna if (walk.nbytes) { 352*6574e6c6SJussi Kivilinna ctr_crypt_final(crypto_blkcipher_ctx(desc->tfm), &walk); 353*6574e6c6SJussi Kivilinna err = blkcipher_walk_done(desc, &walk, 0); 354*6574e6c6SJussi Kivilinna } 355*6574e6c6SJussi Kivilinna 356*6574e6c6SJussi Kivilinna return err; 357*6574e6c6SJussi Kivilinna } 358*6574e6c6SJussi Kivilinna 359*6574e6c6SJussi Kivilinna static int des3_ede_x86_setkey(struct crypto_tfm *tfm, const u8 *key, 360*6574e6c6SJussi Kivilinna unsigned int keylen) 361*6574e6c6SJussi Kivilinna { 362*6574e6c6SJussi Kivilinna struct des3_ede_x86_ctx *ctx = crypto_tfm_ctx(tfm); 363*6574e6c6SJussi Kivilinna u32 i, j, tmp; 364*6574e6c6SJussi Kivilinna int err; 365*6574e6c6SJussi Kivilinna 366*6574e6c6SJussi Kivilinna /* Generate encryption context using generic implementation. */ 367*6574e6c6SJussi Kivilinna err = __des3_ede_setkey(ctx->enc_expkey, &tfm->crt_flags, key, keylen); 368*6574e6c6SJussi Kivilinna if (err < 0) 369*6574e6c6SJussi Kivilinna return err; 370*6574e6c6SJussi Kivilinna 371*6574e6c6SJussi Kivilinna /* Fix encryption context for this implementation and form decryption 372*6574e6c6SJussi Kivilinna * context. */ 373*6574e6c6SJussi Kivilinna j = DES3_EDE_EXPKEY_WORDS - 2; 374*6574e6c6SJussi Kivilinna for (i = 0; i < DES3_EDE_EXPKEY_WORDS; i += 2, j -= 2) { 375*6574e6c6SJussi Kivilinna tmp = ror32(ctx->enc_expkey[i + 1], 4); 376*6574e6c6SJussi Kivilinna ctx->enc_expkey[i + 1] = tmp; 377*6574e6c6SJussi Kivilinna 378*6574e6c6SJussi Kivilinna ctx->dec_expkey[j + 0] = ctx->enc_expkey[i + 0]; 379*6574e6c6SJussi Kivilinna ctx->dec_expkey[j + 1] = tmp; 380*6574e6c6SJussi Kivilinna } 381*6574e6c6SJussi Kivilinna 382*6574e6c6SJussi Kivilinna return 0; 383*6574e6c6SJussi Kivilinna } 384*6574e6c6SJussi Kivilinna 385*6574e6c6SJussi Kivilinna static struct crypto_alg des3_ede_algs[4] = { { 386*6574e6c6SJussi Kivilinna .cra_name = "des3_ede", 387*6574e6c6SJussi Kivilinna .cra_driver_name = "des3_ede-asm", 388*6574e6c6SJussi Kivilinna .cra_priority = 200, 389*6574e6c6SJussi Kivilinna .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 390*6574e6c6SJussi Kivilinna .cra_blocksize = DES3_EDE_BLOCK_SIZE, 391*6574e6c6SJussi Kivilinna .cra_ctxsize = sizeof(struct des3_ede_x86_ctx), 392*6574e6c6SJussi Kivilinna .cra_alignmask = 0, 393*6574e6c6SJussi Kivilinna .cra_module = THIS_MODULE, 394*6574e6c6SJussi Kivilinna .cra_u = { 395*6574e6c6SJussi Kivilinna .cipher = { 396*6574e6c6SJussi Kivilinna .cia_min_keysize = DES3_EDE_KEY_SIZE, 397*6574e6c6SJussi Kivilinna .cia_max_keysize = DES3_EDE_KEY_SIZE, 398*6574e6c6SJussi Kivilinna .cia_setkey = des3_ede_x86_setkey, 399*6574e6c6SJussi Kivilinna .cia_encrypt = des3_ede_x86_encrypt, 400*6574e6c6SJussi Kivilinna .cia_decrypt = des3_ede_x86_decrypt, 401*6574e6c6SJussi Kivilinna } 402*6574e6c6SJussi Kivilinna } 403*6574e6c6SJussi Kivilinna }, { 404*6574e6c6SJussi Kivilinna .cra_name = "ecb(des3_ede)", 405*6574e6c6SJussi Kivilinna .cra_driver_name = "ecb-des3_ede-asm", 406*6574e6c6SJussi Kivilinna .cra_priority = 300, 407*6574e6c6SJussi Kivilinna .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 408*6574e6c6SJussi Kivilinna .cra_blocksize = DES3_EDE_BLOCK_SIZE, 409*6574e6c6SJussi Kivilinna .cra_ctxsize = sizeof(struct des3_ede_x86_ctx), 410*6574e6c6SJussi Kivilinna .cra_alignmask = 0, 411*6574e6c6SJussi Kivilinna .cra_type = &crypto_blkcipher_type, 412*6574e6c6SJussi Kivilinna .cra_module = THIS_MODULE, 413*6574e6c6SJussi Kivilinna .cra_u = { 414*6574e6c6SJussi Kivilinna .blkcipher = { 415*6574e6c6SJussi Kivilinna .min_keysize = DES3_EDE_KEY_SIZE, 416*6574e6c6SJussi Kivilinna .max_keysize = DES3_EDE_KEY_SIZE, 417*6574e6c6SJussi Kivilinna .setkey = des3_ede_x86_setkey, 418*6574e6c6SJussi Kivilinna .encrypt = ecb_encrypt, 419*6574e6c6SJussi Kivilinna .decrypt = ecb_decrypt, 420*6574e6c6SJussi Kivilinna }, 421*6574e6c6SJussi Kivilinna }, 422*6574e6c6SJussi Kivilinna }, { 423*6574e6c6SJussi Kivilinna .cra_name = "cbc(des3_ede)", 424*6574e6c6SJussi Kivilinna .cra_driver_name = "cbc-des3_ede-asm", 425*6574e6c6SJussi Kivilinna .cra_priority = 300, 426*6574e6c6SJussi Kivilinna .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 427*6574e6c6SJussi Kivilinna .cra_blocksize = DES3_EDE_BLOCK_SIZE, 428*6574e6c6SJussi Kivilinna .cra_ctxsize = sizeof(struct des3_ede_x86_ctx), 429*6574e6c6SJussi Kivilinna .cra_alignmask = 0, 430*6574e6c6SJussi Kivilinna .cra_type = &crypto_blkcipher_type, 431*6574e6c6SJussi Kivilinna .cra_module = THIS_MODULE, 432*6574e6c6SJussi Kivilinna .cra_u = { 433*6574e6c6SJussi Kivilinna .blkcipher = { 434*6574e6c6SJussi Kivilinna .min_keysize = DES3_EDE_KEY_SIZE, 435*6574e6c6SJussi Kivilinna .max_keysize = DES3_EDE_KEY_SIZE, 436*6574e6c6SJussi Kivilinna .ivsize = DES3_EDE_BLOCK_SIZE, 437*6574e6c6SJussi Kivilinna .setkey = des3_ede_x86_setkey, 438*6574e6c6SJussi Kivilinna .encrypt = cbc_encrypt, 439*6574e6c6SJussi Kivilinna .decrypt = cbc_decrypt, 440*6574e6c6SJussi Kivilinna }, 441*6574e6c6SJussi Kivilinna }, 442*6574e6c6SJussi Kivilinna }, { 443*6574e6c6SJussi Kivilinna .cra_name = "ctr(des3_ede)", 444*6574e6c6SJussi Kivilinna .cra_driver_name = "ctr-des3_ede-asm", 445*6574e6c6SJussi Kivilinna .cra_priority = 300, 446*6574e6c6SJussi Kivilinna .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 447*6574e6c6SJussi Kivilinna .cra_blocksize = 1, 448*6574e6c6SJussi Kivilinna .cra_ctxsize = sizeof(struct des3_ede_x86_ctx), 449*6574e6c6SJussi Kivilinna .cra_alignmask = 0, 450*6574e6c6SJussi Kivilinna .cra_type = &crypto_blkcipher_type, 451*6574e6c6SJussi Kivilinna .cra_module = THIS_MODULE, 452*6574e6c6SJussi Kivilinna .cra_u = { 453*6574e6c6SJussi Kivilinna .blkcipher = { 454*6574e6c6SJussi Kivilinna .min_keysize = DES3_EDE_KEY_SIZE, 455*6574e6c6SJussi Kivilinna .max_keysize = DES3_EDE_KEY_SIZE, 456*6574e6c6SJussi Kivilinna .ivsize = DES3_EDE_BLOCK_SIZE, 457*6574e6c6SJussi Kivilinna .setkey = des3_ede_x86_setkey, 458*6574e6c6SJussi Kivilinna .encrypt = ctr_crypt, 459*6574e6c6SJussi Kivilinna .decrypt = ctr_crypt, 460*6574e6c6SJussi Kivilinna }, 461*6574e6c6SJussi Kivilinna }, 462*6574e6c6SJussi Kivilinna } }; 463*6574e6c6SJussi Kivilinna 464*6574e6c6SJussi Kivilinna static bool is_blacklisted_cpu(void) 465*6574e6c6SJussi Kivilinna { 466*6574e6c6SJussi Kivilinna if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) 467*6574e6c6SJussi Kivilinna return false; 468*6574e6c6SJussi Kivilinna 469*6574e6c6SJussi Kivilinna if (boot_cpu_data.x86 == 0x0f) { 470*6574e6c6SJussi Kivilinna /* 471*6574e6c6SJussi Kivilinna * On Pentium 4, des3_ede-x86_64 is slower than generic C 472*6574e6c6SJussi Kivilinna * implementation because use of 64bit rotates (which are really 473*6574e6c6SJussi Kivilinna * slow on P4). Therefore blacklist P4s. 474*6574e6c6SJussi Kivilinna */ 475*6574e6c6SJussi Kivilinna return true; 476*6574e6c6SJussi Kivilinna } 477*6574e6c6SJussi Kivilinna 478*6574e6c6SJussi Kivilinna return false; 479*6574e6c6SJussi Kivilinna } 480*6574e6c6SJussi Kivilinna 481*6574e6c6SJussi Kivilinna static int force; 482*6574e6c6SJussi Kivilinna module_param(force, int, 0); 483*6574e6c6SJussi Kivilinna MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist"); 484*6574e6c6SJussi Kivilinna 485*6574e6c6SJussi Kivilinna static int __init des3_ede_x86_init(void) 486*6574e6c6SJussi Kivilinna { 487*6574e6c6SJussi Kivilinna if (!force && is_blacklisted_cpu()) { 488*6574e6c6SJussi Kivilinna pr_info("des3_ede-x86_64: performance on this CPU would be suboptimal: disabling des3_ede-x86_64.\n"); 489*6574e6c6SJussi Kivilinna return -ENODEV; 490*6574e6c6SJussi Kivilinna } 491*6574e6c6SJussi Kivilinna 492*6574e6c6SJussi Kivilinna return crypto_register_algs(des3_ede_algs, ARRAY_SIZE(des3_ede_algs)); 493*6574e6c6SJussi Kivilinna } 494*6574e6c6SJussi Kivilinna 495*6574e6c6SJussi Kivilinna static void __exit des3_ede_x86_fini(void) 496*6574e6c6SJussi Kivilinna { 497*6574e6c6SJussi Kivilinna crypto_unregister_algs(des3_ede_algs, ARRAY_SIZE(des3_ede_algs)); 498*6574e6c6SJussi Kivilinna } 499*6574e6c6SJussi Kivilinna 500*6574e6c6SJussi Kivilinna module_init(des3_ede_x86_init); 501*6574e6c6SJussi Kivilinna module_exit(des3_ede_x86_fini); 502*6574e6c6SJussi Kivilinna 503*6574e6c6SJussi Kivilinna MODULE_LICENSE("GPL"); 504*6574e6c6SJussi Kivilinna MODULE_DESCRIPTION("Triple DES EDE Cipher Algorithm, asm optimized"); 505*6574e6c6SJussi Kivilinna MODULE_ALIAS("des3_ede"); 506*6574e6c6SJussi Kivilinna MODULE_ALIAS("des3_ede-asm"); 507*6574e6c6SJussi Kivilinna MODULE_ALIAS("des"); 508*6574e6c6SJussi Kivilinna MODULE_ALIAS("des-asm"); 509*6574e6c6SJussi Kivilinna MODULE_AUTHOR("Jussi Kivilinna <jussi.kivilinna@iki.fi>"); 510