1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 26574e6c6SJussi Kivilinna /* 36574e6c6SJussi Kivilinna * Glue Code for assembler optimized version of 3DES 46574e6c6SJussi Kivilinna * 56574e6c6SJussi Kivilinna * Copyright © 2014 Jussi Kivilinna <jussi.kivilinna@mbnet.fi> 66574e6c6SJussi Kivilinna * 76574e6c6SJussi Kivilinna * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by: 86574e6c6SJussi Kivilinna * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> 96574e6c6SJussi Kivilinna */ 106574e6c6SJussi Kivilinna 1109c0f03bSEric Biggers #include <crypto/algapi.h> 12cc1d24b9SArd Biesheuvel #include <crypto/des.h> 1309c0f03bSEric Biggers #include <crypto/internal/skcipher.h> 146574e6c6SJussi Kivilinna #include <linux/crypto.h> 156574e6c6SJussi Kivilinna #include <linux/init.h> 166574e6c6SJussi Kivilinna #include <linux/module.h> 176574e6c6SJussi Kivilinna #include <linux/types.h> 186574e6c6SJussi Kivilinna 196574e6c6SJussi Kivilinna struct des3_ede_x86_ctx { 20cc1d24b9SArd Biesheuvel struct des3_ede_ctx enc; 21cc1d24b9SArd Biesheuvel struct des3_ede_ctx dec; 226574e6c6SJussi Kivilinna }; 236574e6c6SJussi Kivilinna 246574e6c6SJussi Kivilinna /* regular block cipher functions */ 256574e6c6SJussi Kivilinna asmlinkage void des3_ede_x86_64_crypt_blk(const u32 *expkey, u8 *dst, 266574e6c6SJussi Kivilinna const u8 *src); 276574e6c6SJussi Kivilinna 286574e6c6SJussi Kivilinna /* 3-way parallel cipher functions */ 296574e6c6SJussi Kivilinna asmlinkage void des3_ede_x86_64_crypt_blk_3way(const u32 *expkey, u8 *dst, 306574e6c6SJussi Kivilinna const u8 *src); 316574e6c6SJussi Kivilinna 326574e6c6SJussi Kivilinna static inline void des3_ede_enc_blk(struct des3_ede_x86_ctx *ctx, u8 *dst, 336574e6c6SJussi Kivilinna const u8 *src) 346574e6c6SJussi Kivilinna { 35cc1d24b9SArd Biesheuvel u32 *enc_ctx = ctx->enc.expkey; 366574e6c6SJussi Kivilinna 376574e6c6SJussi Kivilinna des3_ede_x86_64_crypt_blk(enc_ctx, dst, src); 386574e6c6SJussi Kivilinna } 396574e6c6SJussi Kivilinna 406574e6c6SJussi Kivilinna static inline void des3_ede_dec_blk(struct des3_ede_x86_ctx *ctx, u8 *dst, 416574e6c6SJussi Kivilinna const u8 *src) 426574e6c6SJussi Kivilinna { 43cc1d24b9SArd Biesheuvel u32 *dec_ctx = ctx->dec.expkey; 446574e6c6SJussi Kivilinna 456574e6c6SJussi Kivilinna des3_ede_x86_64_crypt_blk(dec_ctx, dst, src); 466574e6c6SJussi Kivilinna } 476574e6c6SJussi Kivilinna 486574e6c6SJussi Kivilinna static inline void des3_ede_enc_blk_3way(struct des3_ede_x86_ctx *ctx, u8 *dst, 496574e6c6SJussi Kivilinna const u8 *src) 506574e6c6SJussi Kivilinna { 51cc1d24b9SArd Biesheuvel u32 *enc_ctx = ctx->enc.expkey; 526574e6c6SJussi Kivilinna 536574e6c6SJussi Kivilinna des3_ede_x86_64_crypt_blk_3way(enc_ctx, dst, src); 546574e6c6SJussi Kivilinna } 556574e6c6SJussi Kivilinna 566574e6c6SJussi Kivilinna static inline void des3_ede_dec_blk_3way(struct des3_ede_x86_ctx *ctx, u8 *dst, 576574e6c6SJussi Kivilinna const u8 *src) 586574e6c6SJussi Kivilinna { 59cc1d24b9SArd Biesheuvel u32 *dec_ctx = ctx->dec.expkey; 606574e6c6SJussi Kivilinna 616574e6c6SJussi Kivilinna des3_ede_x86_64_crypt_blk_3way(dec_ctx, dst, src); 626574e6c6SJussi Kivilinna } 636574e6c6SJussi Kivilinna 646574e6c6SJussi Kivilinna static void des3_ede_x86_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 656574e6c6SJussi Kivilinna { 666574e6c6SJussi Kivilinna des3_ede_enc_blk(crypto_tfm_ctx(tfm), dst, src); 676574e6c6SJussi Kivilinna } 686574e6c6SJussi Kivilinna 696574e6c6SJussi Kivilinna static void des3_ede_x86_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 706574e6c6SJussi Kivilinna { 716574e6c6SJussi Kivilinna des3_ede_dec_blk(crypto_tfm_ctx(tfm), dst, src); 726574e6c6SJussi Kivilinna } 736574e6c6SJussi Kivilinna 7409c0f03bSEric Biggers static int ecb_crypt(struct skcipher_request *req, const u32 *expkey) 756574e6c6SJussi Kivilinna { 7609c0f03bSEric Biggers const unsigned int bsize = DES3_EDE_BLOCK_SIZE; 7709c0f03bSEric Biggers struct skcipher_walk walk; 786574e6c6SJussi Kivilinna unsigned int nbytes; 796574e6c6SJussi Kivilinna int err; 806574e6c6SJussi Kivilinna 8109c0f03bSEric Biggers err = skcipher_walk_virt(&walk, req, false); 826574e6c6SJussi Kivilinna 8309c0f03bSEric Biggers while ((nbytes = walk.nbytes)) { 8409c0f03bSEric Biggers u8 *wsrc = walk.src.virt.addr; 8509c0f03bSEric Biggers u8 *wdst = walk.dst.virt.addr; 866574e6c6SJussi Kivilinna 876574e6c6SJussi Kivilinna /* Process four block batch */ 886574e6c6SJussi Kivilinna if (nbytes >= bsize * 3) { 896574e6c6SJussi Kivilinna do { 906574e6c6SJussi Kivilinna des3_ede_x86_64_crypt_blk_3way(expkey, wdst, 916574e6c6SJussi Kivilinna wsrc); 926574e6c6SJussi Kivilinna 936574e6c6SJussi Kivilinna wsrc += bsize * 3; 946574e6c6SJussi Kivilinna wdst += bsize * 3; 956574e6c6SJussi Kivilinna nbytes -= bsize * 3; 966574e6c6SJussi Kivilinna } while (nbytes >= bsize * 3); 976574e6c6SJussi Kivilinna 986574e6c6SJussi Kivilinna if (nbytes < bsize) 996574e6c6SJussi Kivilinna goto done; 1006574e6c6SJussi Kivilinna } 1016574e6c6SJussi Kivilinna 1026574e6c6SJussi Kivilinna /* Handle leftovers */ 1036574e6c6SJussi Kivilinna do { 1046574e6c6SJussi Kivilinna des3_ede_x86_64_crypt_blk(expkey, wdst, wsrc); 1056574e6c6SJussi Kivilinna 1066574e6c6SJussi Kivilinna wsrc += bsize; 1076574e6c6SJussi Kivilinna wdst += bsize; 1086574e6c6SJussi Kivilinna nbytes -= bsize; 1096574e6c6SJussi Kivilinna } while (nbytes >= bsize); 1106574e6c6SJussi Kivilinna 1116574e6c6SJussi Kivilinna done: 11209c0f03bSEric Biggers err = skcipher_walk_done(&walk, nbytes); 1136574e6c6SJussi Kivilinna } 1146574e6c6SJussi Kivilinna 1156574e6c6SJussi Kivilinna return err; 1166574e6c6SJussi Kivilinna } 1176574e6c6SJussi Kivilinna 11809c0f03bSEric Biggers static int ecb_encrypt(struct skcipher_request *req) 1196574e6c6SJussi Kivilinna { 12009c0f03bSEric Biggers struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 12109c0f03bSEric Biggers struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm); 1226574e6c6SJussi Kivilinna 123cc1d24b9SArd Biesheuvel return ecb_crypt(req, ctx->enc.expkey); 1246574e6c6SJussi Kivilinna } 1256574e6c6SJussi Kivilinna 12609c0f03bSEric Biggers static int ecb_decrypt(struct skcipher_request *req) 1276574e6c6SJussi Kivilinna { 12809c0f03bSEric Biggers struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 12909c0f03bSEric Biggers struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm); 1306574e6c6SJussi Kivilinna 131cc1d24b9SArd Biesheuvel return ecb_crypt(req, ctx->dec.expkey); 1326574e6c6SJussi Kivilinna } 1336574e6c6SJussi Kivilinna 13409c0f03bSEric Biggers static unsigned int __cbc_encrypt(struct des3_ede_x86_ctx *ctx, 13509c0f03bSEric Biggers struct skcipher_walk *walk) 1366574e6c6SJussi Kivilinna { 1376574e6c6SJussi Kivilinna unsigned int bsize = DES3_EDE_BLOCK_SIZE; 1386574e6c6SJussi Kivilinna unsigned int nbytes = walk->nbytes; 1396574e6c6SJussi Kivilinna u64 *src = (u64 *)walk->src.virt.addr; 1406574e6c6SJussi Kivilinna u64 *dst = (u64 *)walk->dst.virt.addr; 1416574e6c6SJussi Kivilinna u64 *iv = (u64 *)walk->iv; 1426574e6c6SJussi Kivilinna 1436574e6c6SJussi Kivilinna do { 1446574e6c6SJussi Kivilinna *dst = *src ^ *iv; 1456574e6c6SJussi Kivilinna des3_ede_enc_blk(ctx, (u8 *)dst, (u8 *)dst); 1466574e6c6SJussi Kivilinna iv = dst; 1476574e6c6SJussi Kivilinna 1486574e6c6SJussi Kivilinna src += 1; 1496574e6c6SJussi Kivilinna dst += 1; 1506574e6c6SJussi Kivilinna nbytes -= bsize; 1516574e6c6SJussi Kivilinna } while (nbytes >= bsize); 1526574e6c6SJussi Kivilinna 1536574e6c6SJussi Kivilinna *(u64 *)walk->iv = *iv; 1546574e6c6SJussi Kivilinna return nbytes; 1556574e6c6SJussi Kivilinna } 1566574e6c6SJussi Kivilinna 15709c0f03bSEric Biggers static int cbc_encrypt(struct skcipher_request *req) 1586574e6c6SJussi Kivilinna { 15909c0f03bSEric Biggers struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 16009c0f03bSEric Biggers struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm); 16109c0f03bSEric Biggers struct skcipher_walk walk; 16209c0f03bSEric Biggers unsigned int nbytes; 1636574e6c6SJussi Kivilinna int err; 1646574e6c6SJussi Kivilinna 16509c0f03bSEric Biggers err = skcipher_walk_virt(&walk, req, false); 1666574e6c6SJussi Kivilinna 167*015e42c8SColin Ian King while (walk.nbytes) { 16809c0f03bSEric Biggers nbytes = __cbc_encrypt(ctx, &walk); 16909c0f03bSEric Biggers err = skcipher_walk_done(&walk, nbytes); 1706574e6c6SJussi Kivilinna } 1716574e6c6SJussi Kivilinna 1726574e6c6SJussi Kivilinna return err; 1736574e6c6SJussi Kivilinna } 1746574e6c6SJussi Kivilinna 17509c0f03bSEric Biggers static unsigned int __cbc_decrypt(struct des3_ede_x86_ctx *ctx, 17609c0f03bSEric Biggers struct skcipher_walk *walk) 1776574e6c6SJussi Kivilinna { 1786574e6c6SJussi Kivilinna unsigned int bsize = DES3_EDE_BLOCK_SIZE; 1796574e6c6SJussi Kivilinna unsigned int nbytes = walk->nbytes; 1806574e6c6SJussi Kivilinna u64 *src = (u64 *)walk->src.virt.addr; 1816574e6c6SJussi Kivilinna u64 *dst = (u64 *)walk->dst.virt.addr; 1826574e6c6SJussi Kivilinna u64 ivs[3 - 1]; 1836574e6c6SJussi Kivilinna u64 last_iv; 1846574e6c6SJussi Kivilinna 1856574e6c6SJussi Kivilinna /* Start of the last block. */ 1866574e6c6SJussi Kivilinna src += nbytes / bsize - 1; 1876574e6c6SJussi Kivilinna dst += nbytes / bsize - 1; 1886574e6c6SJussi Kivilinna 1896574e6c6SJussi Kivilinna last_iv = *src; 1906574e6c6SJussi Kivilinna 1916574e6c6SJussi Kivilinna /* Process four block batch */ 1926574e6c6SJussi Kivilinna if (nbytes >= bsize * 3) { 1936574e6c6SJussi Kivilinna do { 1946574e6c6SJussi Kivilinna nbytes -= bsize * 3 - bsize; 1956574e6c6SJussi Kivilinna src -= 3 - 1; 1966574e6c6SJussi Kivilinna dst -= 3 - 1; 1976574e6c6SJussi Kivilinna 1986574e6c6SJussi Kivilinna ivs[0] = src[0]; 1996574e6c6SJussi Kivilinna ivs[1] = src[1]; 2006574e6c6SJussi Kivilinna 2016574e6c6SJussi Kivilinna des3_ede_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src); 2026574e6c6SJussi Kivilinna 2036574e6c6SJussi Kivilinna dst[1] ^= ivs[0]; 2046574e6c6SJussi Kivilinna dst[2] ^= ivs[1]; 2056574e6c6SJussi Kivilinna 2066574e6c6SJussi Kivilinna nbytes -= bsize; 2076574e6c6SJussi Kivilinna if (nbytes < bsize) 2086574e6c6SJussi Kivilinna goto done; 2096574e6c6SJussi Kivilinna 2106574e6c6SJussi Kivilinna *dst ^= *(src - 1); 2116574e6c6SJussi Kivilinna src -= 1; 2126574e6c6SJussi Kivilinna dst -= 1; 2136574e6c6SJussi Kivilinna } while (nbytes >= bsize * 3); 2146574e6c6SJussi Kivilinna } 2156574e6c6SJussi Kivilinna 2166574e6c6SJussi Kivilinna /* Handle leftovers */ 2176574e6c6SJussi Kivilinna for (;;) { 2186574e6c6SJussi Kivilinna des3_ede_dec_blk(ctx, (u8 *)dst, (u8 *)src); 2196574e6c6SJussi Kivilinna 2206574e6c6SJussi Kivilinna nbytes -= bsize; 2216574e6c6SJussi Kivilinna if (nbytes < bsize) 2226574e6c6SJussi Kivilinna break; 2236574e6c6SJussi Kivilinna 2246574e6c6SJussi Kivilinna *dst ^= *(src - 1); 2256574e6c6SJussi Kivilinna src -= 1; 2266574e6c6SJussi Kivilinna dst -= 1; 2276574e6c6SJussi Kivilinna } 2286574e6c6SJussi Kivilinna 2296574e6c6SJussi Kivilinna done: 2306574e6c6SJussi Kivilinna *dst ^= *(u64 *)walk->iv; 2316574e6c6SJussi Kivilinna *(u64 *)walk->iv = last_iv; 2326574e6c6SJussi Kivilinna 2336574e6c6SJussi Kivilinna return nbytes; 2346574e6c6SJussi Kivilinna } 2356574e6c6SJussi Kivilinna 23609c0f03bSEric Biggers static int cbc_decrypt(struct skcipher_request *req) 2376574e6c6SJussi Kivilinna { 23809c0f03bSEric Biggers struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 23909c0f03bSEric Biggers struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm); 24009c0f03bSEric Biggers struct skcipher_walk walk; 24109c0f03bSEric Biggers unsigned int nbytes; 2426574e6c6SJussi Kivilinna int err; 2436574e6c6SJussi Kivilinna 24409c0f03bSEric Biggers err = skcipher_walk_virt(&walk, req, false); 2456574e6c6SJussi Kivilinna 246*015e42c8SColin Ian King while (walk.nbytes) { 24709c0f03bSEric Biggers nbytes = __cbc_decrypt(ctx, &walk); 24809c0f03bSEric Biggers err = skcipher_walk_done(&walk, nbytes); 2496574e6c6SJussi Kivilinna } 2506574e6c6SJussi Kivilinna 2516574e6c6SJussi Kivilinna return err; 2526574e6c6SJussi Kivilinna } 2536574e6c6SJussi Kivilinna 2546574e6c6SJussi Kivilinna static int des3_ede_x86_setkey(struct crypto_tfm *tfm, const u8 *key, 2556574e6c6SJussi Kivilinna unsigned int keylen) 2566574e6c6SJussi Kivilinna { 2576574e6c6SJussi Kivilinna struct des3_ede_x86_ctx *ctx = crypto_tfm_ctx(tfm); 2586574e6c6SJussi Kivilinna u32 i, j, tmp; 2596574e6c6SJussi Kivilinna int err; 2606574e6c6SJussi Kivilinna 261cc1d24b9SArd Biesheuvel err = des3_ede_expand_key(&ctx->enc, key, keylen); 262cc1d24b9SArd Biesheuvel if (err == -ENOKEY) { 263cc1d24b9SArd Biesheuvel if (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) 264cc1d24b9SArd Biesheuvel err = -EINVAL; 265cc1d24b9SArd Biesheuvel else 266cc1d24b9SArd Biesheuvel err = 0; 267cc1d24b9SArd Biesheuvel } 2684fd4be05SArd Biesheuvel 269cc1d24b9SArd Biesheuvel if (err) { 270cc1d24b9SArd Biesheuvel memset(ctx, 0, sizeof(*ctx)); 2716574e6c6SJussi Kivilinna return err; 272cc1d24b9SArd Biesheuvel } 2736574e6c6SJussi Kivilinna 2746574e6c6SJussi Kivilinna /* Fix encryption context for this implementation and form decryption 2756574e6c6SJussi Kivilinna * context. */ 2766574e6c6SJussi Kivilinna j = DES3_EDE_EXPKEY_WORDS - 2; 2776574e6c6SJussi Kivilinna for (i = 0; i < DES3_EDE_EXPKEY_WORDS; i += 2, j -= 2) { 278cc1d24b9SArd Biesheuvel tmp = ror32(ctx->enc.expkey[i + 1], 4); 279cc1d24b9SArd Biesheuvel ctx->enc.expkey[i + 1] = tmp; 2806574e6c6SJussi Kivilinna 281cc1d24b9SArd Biesheuvel ctx->dec.expkey[j + 0] = ctx->enc.expkey[i + 0]; 282cc1d24b9SArd Biesheuvel ctx->dec.expkey[j + 1] = tmp; 2836574e6c6SJussi Kivilinna } 2846574e6c6SJussi Kivilinna 2856574e6c6SJussi Kivilinna return 0; 2866574e6c6SJussi Kivilinna } 2876574e6c6SJussi Kivilinna 28809c0f03bSEric Biggers static int des3_ede_x86_setkey_skcipher(struct crypto_skcipher *tfm, 28909c0f03bSEric Biggers const u8 *key, 29009c0f03bSEric Biggers unsigned int keylen) 29109c0f03bSEric Biggers { 29209c0f03bSEric Biggers return des3_ede_x86_setkey(&tfm->base, key, keylen); 29309c0f03bSEric Biggers } 29409c0f03bSEric Biggers 29509c0f03bSEric Biggers static struct crypto_alg des3_ede_cipher = { 2966574e6c6SJussi Kivilinna .cra_name = "des3_ede", 2976574e6c6SJussi Kivilinna .cra_driver_name = "des3_ede-asm", 2986574e6c6SJussi Kivilinna .cra_priority = 200, 2996574e6c6SJussi Kivilinna .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 3006574e6c6SJussi Kivilinna .cra_blocksize = DES3_EDE_BLOCK_SIZE, 3016574e6c6SJussi Kivilinna .cra_ctxsize = sizeof(struct des3_ede_x86_ctx), 3026574e6c6SJussi Kivilinna .cra_alignmask = 0, 3036574e6c6SJussi Kivilinna .cra_module = THIS_MODULE, 3046574e6c6SJussi Kivilinna .cra_u = { 3056574e6c6SJussi Kivilinna .cipher = { 3066574e6c6SJussi Kivilinna .cia_min_keysize = DES3_EDE_KEY_SIZE, 3076574e6c6SJussi Kivilinna .cia_max_keysize = DES3_EDE_KEY_SIZE, 3086574e6c6SJussi Kivilinna .cia_setkey = des3_ede_x86_setkey, 3096574e6c6SJussi Kivilinna .cia_encrypt = des3_ede_x86_encrypt, 3106574e6c6SJussi Kivilinna .cia_decrypt = des3_ede_x86_decrypt, 3116574e6c6SJussi Kivilinna } 3126574e6c6SJussi Kivilinna } 31309c0f03bSEric Biggers }; 31409c0f03bSEric Biggers 3159cc16b4dSWu Fengguang static struct skcipher_alg des3_ede_skciphers[] = { 31609c0f03bSEric Biggers { 31709c0f03bSEric Biggers .base.cra_name = "ecb(des3_ede)", 31809c0f03bSEric Biggers .base.cra_driver_name = "ecb-des3_ede-asm", 31909c0f03bSEric Biggers .base.cra_priority = 300, 32009c0f03bSEric Biggers .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, 32109c0f03bSEric Biggers .base.cra_ctxsize = sizeof(struct des3_ede_x86_ctx), 32209c0f03bSEric Biggers .base.cra_module = THIS_MODULE, 3236574e6c6SJussi Kivilinna .min_keysize = DES3_EDE_KEY_SIZE, 3246574e6c6SJussi Kivilinna .max_keysize = DES3_EDE_KEY_SIZE, 32509c0f03bSEric Biggers .setkey = des3_ede_x86_setkey_skcipher, 3266574e6c6SJussi Kivilinna .encrypt = ecb_encrypt, 3276574e6c6SJussi Kivilinna .decrypt = ecb_decrypt, 3286574e6c6SJussi Kivilinna }, { 32909c0f03bSEric Biggers .base.cra_name = "cbc(des3_ede)", 33009c0f03bSEric Biggers .base.cra_driver_name = "cbc-des3_ede-asm", 33109c0f03bSEric Biggers .base.cra_priority = 300, 33209c0f03bSEric Biggers .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, 33309c0f03bSEric Biggers .base.cra_ctxsize = sizeof(struct des3_ede_x86_ctx), 33409c0f03bSEric Biggers .base.cra_module = THIS_MODULE, 3356574e6c6SJussi Kivilinna .min_keysize = DES3_EDE_KEY_SIZE, 3366574e6c6SJussi Kivilinna .max_keysize = DES3_EDE_KEY_SIZE, 3376574e6c6SJussi Kivilinna .ivsize = DES3_EDE_BLOCK_SIZE, 33809c0f03bSEric Biggers .setkey = des3_ede_x86_setkey_skcipher, 3396574e6c6SJussi Kivilinna .encrypt = cbc_encrypt, 3406574e6c6SJussi Kivilinna .decrypt = cbc_decrypt, 34109c0f03bSEric Biggers } 34209c0f03bSEric Biggers }; 3436574e6c6SJussi Kivilinna 3446574e6c6SJussi Kivilinna static bool is_blacklisted_cpu(void) 3456574e6c6SJussi Kivilinna { 3466574e6c6SJussi Kivilinna if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) 3476574e6c6SJussi Kivilinna return false; 3486574e6c6SJussi Kivilinna 3496574e6c6SJussi Kivilinna if (boot_cpu_data.x86 == 0x0f) { 3506574e6c6SJussi Kivilinna /* 3516574e6c6SJussi Kivilinna * On Pentium 4, des3_ede-x86_64 is slower than generic C 3526574e6c6SJussi Kivilinna * implementation because use of 64bit rotates (which are really 3536574e6c6SJussi Kivilinna * slow on P4). Therefore blacklist P4s. 3546574e6c6SJussi Kivilinna */ 3556574e6c6SJussi Kivilinna return true; 3566574e6c6SJussi Kivilinna } 3576574e6c6SJussi Kivilinna 3586574e6c6SJussi Kivilinna return false; 3596574e6c6SJussi Kivilinna } 3606574e6c6SJussi Kivilinna 3616574e6c6SJussi Kivilinna static int force; 3626574e6c6SJussi Kivilinna module_param(force, int, 0); 3636574e6c6SJussi Kivilinna MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist"); 3646574e6c6SJussi Kivilinna 3656574e6c6SJussi Kivilinna static int __init des3_ede_x86_init(void) 3666574e6c6SJussi Kivilinna { 36709c0f03bSEric Biggers int err; 36809c0f03bSEric Biggers 3696574e6c6SJussi Kivilinna if (!force && is_blacklisted_cpu()) { 3706574e6c6SJussi Kivilinna pr_info("des3_ede-x86_64: performance on this CPU would be suboptimal: disabling des3_ede-x86_64.\n"); 3716574e6c6SJussi Kivilinna return -ENODEV; 3726574e6c6SJussi Kivilinna } 3736574e6c6SJussi Kivilinna 37409c0f03bSEric Biggers err = crypto_register_alg(&des3_ede_cipher); 37509c0f03bSEric Biggers if (err) 37609c0f03bSEric Biggers return err; 37709c0f03bSEric Biggers 37809c0f03bSEric Biggers err = crypto_register_skciphers(des3_ede_skciphers, 37909c0f03bSEric Biggers ARRAY_SIZE(des3_ede_skciphers)); 38009c0f03bSEric Biggers if (err) 38109c0f03bSEric Biggers crypto_unregister_alg(&des3_ede_cipher); 38209c0f03bSEric Biggers 38309c0f03bSEric Biggers return err; 3846574e6c6SJussi Kivilinna } 3856574e6c6SJussi Kivilinna 3866574e6c6SJussi Kivilinna static void __exit des3_ede_x86_fini(void) 3876574e6c6SJussi Kivilinna { 38809c0f03bSEric Biggers crypto_unregister_alg(&des3_ede_cipher); 38909c0f03bSEric Biggers crypto_unregister_skciphers(des3_ede_skciphers, 39009c0f03bSEric Biggers ARRAY_SIZE(des3_ede_skciphers)); 3916574e6c6SJussi Kivilinna } 3926574e6c6SJussi Kivilinna 3936574e6c6SJussi Kivilinna module_init(des3_ede_x86_init); 3946574e6c6SJussi Kivilinna module_exit(des3_ede_x86_fini); 3956574e6c6SJussi Kivilinna 3966574e6c6SJussi Kivilinna MODULE_LICENSE("GPL"); 3976574e6c6SJussi Kivilinna MODULE_DESCRIPTION("Triple DES EDE Cipher Algorithm, asm optimized"); 3985d26a105SKees Cook MODULE_ALIAS_CRYPTO("des3_ede"); 3995d26a105SKees Cook MODULE_ALIAS_CRYPTO("des3_ede-asm"); 4006574e6c6SJussi Kivilinna MODULE_AUTHOR("Jussi Kivilinna <jussi.kivilinna@iki.fi>"); 401