1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Glue Code for AVX assembler version of Twofish Cipher 4 * 5 * Copyright (C) 2012 Johannes Goetzfried 6 * <Johannes.Goetzfried@informatik.stud.uni-erlangen.de> 7 * 8 * Copyright © 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi> 9 */ 10 11 #include <linux/module.h> 12 #include <linux/types.h> 13 #include <linux/crypto.h> 14 #include <linux/err.h> 15 #include <crypto/algapi.h> 16 #include <crypto/twofish.h> 17 18 #include "twofish.h" 19 #include "ecb_cbc_helpers.h" 20 21 #define TWOFISH_PARALLEL_BLOCKS 8 22 23 /* 8-way parallel cipher functions */ 24 asmlinkage void twofish_ecb_enc_8way(const void *ctx, u8 *dst, const u8 *src); 25 asmlinkage void twofish_ecb_dec_8way(const void *ctx, u8 *dst, const u8 *src); 26 27 asmlinkage void twofish_cbc_dec_8way(const void *ctx, u8 *dst, const u8 *src); 28 29 static int twofish_setkey_skcipher(struct crypto_skcipher *tfm, 30 const u8 *key, unsigned int keylen) 31 { 32 return twofish_setkey(&tfm->base, key, keylen); 33 } 34 35 static inline void twofish_enc_blk_3way(const void *ctx, u8 *dst, const u8 *src) 36 { 37 __twofish_enc_blk_3way(ctx, dst, src, false); 38 } 39 40 static int ecb_encrypt(struct skcipher_request *req) 41 { 42 ECB_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS); 43 ECB_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_ecb_enc_8way); 44 ECB_BLOCK(3, twofish_enc_blk_3way); 45 ECB_BLOCK(1, twofish_enc_blk); 46 ECB_WALK_END(); 47 } 48 49 static int ecb_decrypt(struct skcipher_request *req) 50 { 51 ECB_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS); 52 ECB_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_ecb_dec_8way); 53 ECB_BLOCK(3, twofish_dec_blk_3way); 54 ECB_BLOCK(1, twofish_dec_blk); 55 ECB_WALK_END(); 56 } 57 58 static int cbc_encrypt(struct skcipher_request *req) 59 { 60 CBC_WALK_START(req, TF_BLOCK_SIZE, -1); 61 CBC_ENC_BLOCK(twofish_enc_blk); 62 CBC_WALK_END(); 63 } 64 65 static int cbc_decrypt(struct skcipher_request *req) 66 { 67 CBC_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS); 68 CBC_DEC_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_cbc_dec_8way); 69 CBC_DEC_BLOCK(3, twofish_dec_blk_cbc_3way); 70 CBC_DEC_BLOCK(1, twofish_dec_blk); 71 CBC_WALK_END(); 72 } 73 74 static struct skcipher_alg twofish_algs[] = { 75 { 76 .base.cra_name = "ecb(twofish)", 77 .base.cra_driver_name = "ecb-twofish-avx", 78 .base.cra_priority = 400, 79 .base.cra_blocksize = TF_BLOCK_SIZE, 80 .base.cra_ctxsize = sizeof(struct twofish_ctx), 81 .base.cra_module = THIS_MODULE, 82 .min_keysize = TF_MIN_KEY_SIZE, 83 .max_keysize = TF_MAX_KEY_SIZE, 84 .setkey = twofish_setkey_skcipher, 85 .encrypt = ecb_encrypt, 86 .decrypt = ecb_decrypt, 87 }, { 88 .base.cra_name = "cbc(twofish)", 89 .base.cra_driver_name = "cbc-twofish-avx", 90 .base.cra_priority = 400, 91 .base.cra_blocksize = TF_BLOCK_SIZE, 92 .base.cra_ctxsize = sizeof(struct twofish_ctx), 93 .base.cra_module = THIS_MODULE, 94 .min_keysize = TF_MIN_KEY_SIZE, 95 .max_keysize = TF_MAX_KEY_SIZE, 96 .ivsize = TF_BLOCK_SIZE, 97 .setkey = twofish_setkey_skcipher, 98 .encrypt = cbc_encrypt, 99 .decrypt = cbc_decrypt, 100 }, 101 }; 102 103 static int __init twofish_init(void) 104 { 105 const char *feature_name; 106 107 if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, &feature_name)) { 108 pr_info("CPU feature '%s' is not supported.\n", feature_name); 109 return -ENODEV; 110 } 111 112 return crypto_register_skciphers(twofish_algs, 113 ARRAY_SIZE(twofish_algs)); 114 } 115 116 static void __exit twofish_exit(void) 117 { 118 crypto_unregister_skciphers(twofish_algs, ARRAY_SIZE(twofish_algs)); 119 } 120 121 module_init(twofish_init); 122 module_exit(twofish_exit); 123 124 MODULE_DESCRIPTION("Twofish Cipher Algorithm, AVX optimized"); 125 MODULE_LICENSE("GPL"); 126 MODULE_ALIAS_CRYPTO("twofish"); 127