0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <linux/types.h>
0013 #include <linux/crypto.h>
0014 #include <linux/err.h>
0015 #include <crypto/algapi.h>
0016 #include <crypto/internal/simd.h>
0017 #include <crypto/twofish.h>
0018
0019 #include "twofish.h"
0020 #include "ecb_cbc_helpers.h"
0021
0022 #define TWOFISH_PARALLEL_BLOCKS 8
0023
0024
0025 asmlinkage void twofish_ecb_enc_8way(const void *ctx, u8 *dst, const u8 *src);
0026 asmlinkage void twofish_ecb_dec_8way(const void *ctx, u8 *dst, const u8 *src);
0027
0028 asmlinkage void twofish_cbc_dec_8way(const void *ctx, u8 *dst, const u8 *src);
0029
0030 static int twofish_setkey_skcipher(struct crypto_skcipher *tfm,
0031 const u8 *key, unsigned int keylen)
0032 {
0033 return twofish_setkey(&tfm->base, key, keylen);
0034 }
0035
0036 static inline void twofish_enc_blk_3way(const void *ctx, u8 *dst, const u8 *src)
0037 {
0038 __twofish_enc_blk_3way(ctx, dst, src, false);
0039 }
0040
0041 static int ecb_encrypt(struct skcipher_request *req)
0042 {
0043 ECB_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS);
0044 ECB_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_ecb_enc_8way);
0045 ECB_BLOCK(3, twofish_enc_blk_3way);
0046 ECB_BLOCK(1, twofish_enc_blk);
0047 ECB_WALK_END();
0048 }
0049
0050 static int ecb_decrypt(struct skcipher_request *req)
0051 {
0052 ECB_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS);
0053 ECB_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_ecb_dec_8way);
0054 ECB_BLOCK(3, twofish_dec_blk_3way);
0055 ECB_BLOCK(1, twofish_dec_blk);
0056 ECB_WALK_END();
0057 }
0058
0059 static int cbc_encrypt(struct skcipher_request *req)
0060 {
0061 CBC_WALK_START(req, TF_BLOCK_SIZE, -1);
0062 CBC_ENC_BLOCK(twofish_enc_blk);
0063 CBC_WALK_END();
0064 }
0065
0066 static int cbc_decrypt(struct skcipher_request *req)
0067 {
0068 CBC_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS);
0069 CBC_DEC_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_cbc_dec_8way);
0070 CBC_DEC_BLOCK(3, twofish_dec_blk_cbc_3way);
0071 CBC_DEC_BLOCK(1, twofish_dec_blk);
0072 CBC_WALK_END();
0073 }
0074
0075 static struct skcipher_alg twofish_algs[] = {
0076 {
0077 .base.cra_name = "__ecb(twofish)",
0078 .base.cra_driver_name = "__ecb-twofish-avx",
0079 .base.cra_priority = 400,
0080 .base.cra_flags = CRYPTO_ALG_INTERNAL,
0081 .base.cra_blocksize = TF_BLOCK_SIZE,
0082 .base.cra_ctxsize = sizeof(struct twofish_ctx),
0083 .base.cra_module = THIS_MODULE,
0084 .min_keysize = TF_MIN_KEY_SIZE,
0085 .max_keysize = TF_MAX_KEY_SIZE,
0086 .setkey = twofish_setkey_skcipher,
0087 .encrypt = ecb_encrypt,
0088 .decrypt = ecb_decrypt,
0089 }, {
0090 .base.cra_name = "__cbc(twofish)",
0091 .base.cra_driver_name = "__cbc-twofish-avx",
0092 .base.cra_priority = 400,
0093 .base.cra_flags = CRYPTO_ALG_INTERNAL,
0094 .base.cra_blocksize = TF_BLOCK_SIZE,
0095 .base.cra_ctxsize = sizeof(struct twofish_ctx),
0096 .base.cra_module = THIS_MODULE,
0097 .min_keysize = TF_MIN_KEY_SIZE,
0098 .max_keysize = TF_MAX_KEY_SIZE,
0099 .ivsize = TF_BLOCK_SIZE,
0100 .setkey = twofish_setkey_skcipher,
0101 .encrypt = cbc_encrypt,
0102 .decrypt = cbc_decrypt,
0103 },
0104 };
0105
0106 static struct simd_skcipher_alg *twofish_simd_algs[ARRAY_SIZE(twofish_algs)];
0107
0108 static int __init twofish_init(void)
0109 {
0110 const char *feature_name;
0111
0112 if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, &feature_name)) {
0113 pr_info("CPU feature '%s' is not supported.\n", feature_name);
0114 return -ENODEV;
0115 }
0116
0117 return simd_register_skciphers_compat(twofish_algs,
0118 ARRAY_SIZE(twofish_algs),
0119 twofish_simd_algs);
0120 }
0121
0122 static void __exit twofish_exit(void)
0123 {
0124 simd_unregister_skciphers(twofish_algs, ARRAY_SIZE(twofish_algs),
0125 twofish_simd_algs);
0126 }
0127
0128 module_init(twofish_init);
0129 module_exit(twofish_exit);
0130
0131 MODULE_DESCRIPTION("Twofish Cipher Algorithm, AVX optimized");
0132 MODULE_LICENSE("GPL");
0133 MODULE_ALIAS_CRYPTO("twofish");