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/serpent.h>
0018
0019 #include "serpent-avx.h"
0020 #include "ecb_cbc_helpers.h"
0021
0022
0023 asmlinkage void serpent_ecb_enc_8way_avx(const void *ctx, u8 *dst,
0024 const u8 *src);
0025 EXPORT_SYMBOL_GPL(serpent_ecb_enc_8way_avx);
0026
0027 asmlinkage void serpent_ecb_dec_8way_avx(const void *ctx, u8 *dst,
0028 const u8 *src);
0029 EXPORT_SYMBOL_GPL(serpent_ecb_dec_8way_avx);
0030
0031 asmlinkage void serpent_cbc_dec_8way_avx(const void *ctx, u8 *dst,
0032 const u8 *src);
0033 EXPORT_SYMBOL_GPL(serpent_cbc_dec_8way_avx);
0034
0035 static int serpent_setkey_skcipher(struct crypto_skcipher *tfm,
0036 const u8 *key, unsigned int keylen)
0037 {
0038 return __serpent_setkey(crypto_skcipher_ctx(tfm), key, keylen);
0039 }
0040
0041 static int ecb_encrypt(struct skcipher_request *req)
0042 {
0043 ECB_WALK_START(req, SERPENT_BLOCK_SIZE, SERPENT_PARALLEL_BLOCKS);
0044 ECB_BLOCK(SERPENT_PARALLEL_BLOCKS, serpent_ecb_enc_8way_avx);
0045 ECB_BLOCK(1, __serpent_encrypt);
0046 ECB_WALK_END();
0047 }
0048
0049 static int ecb_decrypt(struct skcipher_request *req)
0050 {
0051 ECB_WALK_START(req, SERPENT_BLOCK_SIZE, SERPENT_PARALLEL_BLOCKS);
0052 ECB_BLOCK(SERPENT_PARALLEL_BLOCKS, serpent_ecb_dec_8way_avx);
0053 ECB_BLOCK(1, __serpent_decrypt);
0054 ECB_WALK_END();
0055 }
0056
0057 static int cbc_encrypt(struct skcipher_request *req)
0058 {
0059 CBC_WALK_START(req, SERPENT_BLOCK_SIZE, -1);
0060 CBC_ENC_BLOCK(__serpent_encrypt);
0061 CBC_WALK_END();
0062 }
0063
0064 static int cbc_decrypt(struct skcipher_request *req)
0065 {
0066 CBC_WALK_START(req, SERPENT_BLOCK_SIZE, SERPENT_PARALLEL_BLOCKS);
0067 CBC_DEC_BLOCK(SERPENT_PARALLEL_BLOCKS, serpent_cbc_dec_8way_avx);
0068 CBC_DEC_BLOCK(1, __serpent_decrypt);
0069 CBC_WALK_END();
0070 }
0071
0072 static struct skcipher_alg serpent_algs[] = {
0073 {
0074 .base.cra_name = "__ecb(serpent)",
0075 .base.cra_driver_name = "__ecb-serpent-avx",
0076 .base.cra_priority = 500,
0077 .base.cra_flags = CRYPTO_ALG_INTERNAL,
0078 .base.cra_blocksize = SERPENT_BLOCK_SIZE,
0079 .base.cra_ctxsize = sizeof(struct serpent_ctx),
0080 .base.cra_module = THIS_MODULE,
0081 .min_keysize = SERPENT_MIN_KEY_SIZE,
0082 .max_keysize = SERPENT_MAX_KEY_SIZE,
0083 .setkey = serpent_setkey_skcipher,
0084 .encrypt = ecb_encrypt,
0085 .decrypt = ecb_decrypt,
0086 }, {
0087 .base.cra_name = "__cbc(serpent)",
0088 .base.cra_driver_name = "__cbc-serpent-avx",
0089 .base.cra_priority = 500,
0090 .base.cra_flags = CRYPTO_ALG_INTERNAL,
0091 .base.cra_blocksize = SERPENT_BLOCK_SIZE,
0092 .base.cra_ctxsize = sizeof(struct serpent_ctx),
0093 .base.cra_module = THIS_MODULE,
0094 .min_keysize = SERPENT_MIN_KEY_SIZE,
0095 .max_keysize = SERPENT_MAX_KEY_SIZE,
0096 .ivsize = SERPENT_BLOCK_SIZE,
0097 .setkey = serpent_setkey_skcipher,
0098 .encrypt = cbc_encrypt,
0099 .decrypt = cbc_decrypt,
0100 },
0101 };
0102
0103 static struct simd_skcipher_alg *serpent_simd_algs[ARRAY_SIZE(serpent_algs)];
0104
0105 static int __init serpent_init(void)
0106 {
0107 const char *feature_name;
0108
0109 if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM,
0110 &feature_name)) {
0111 pr_info("CPU feature '%s' is not supported.\n", feature_name);
0112 return -ENODEV;
0113 }
0114
0115 return simd_register_skciphers_compat(serpent_algs,
0116 ARRAY_SIZE(serpent_algs),
0117 serpent_simd_algs);
0118 }
0119
0120 static void __exit serpent_exit(void)
0121 {
0122 simd_unregister_skciphers(serpent_algs, ARRAY_SIZE(serpent_algs),
0123 serpent_simd_algs);
0124 }
0125
0126 module_init(serpent_init);
0127 module_exit(serpent_exit);
0128
0129 MODULE_DESCRIPTION("Serpent Cipher Algorithm, AVX optimized");
0130 MODULE_LICENSE("GPL");
0131 MODULE_ALIAS_CRYPTO("serpent");