Merge tag 'leds-5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/pavel...
[linux-2.6-microblaze.git] / arch / x86 / crypto / twofish_avx_glue.c
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/internal/simd.h>
17 #include <crypto/twofish.h>
18
19 #include "twofish.h"
20 #include "ecb_cbc_helpers.h"
21
22 #define TWOFISH_PARALLEL_BLOCKS 8
23
24 /* 8-way parallel cipher functions */
25 asmlinkage void twofish_ecb_enc_8way(const void *ctx, u8 *dst, const u8 *src);
26 asmlinkage void twofish_ecb_dec_8way(const void *ctx, u8 *dst, const u8 *src);
27
28 asmlinkage void twofish_cbc_dec_8way(const void *ctx, u8 *dst, const u8 *src);
29
30 static int twofish_setkey_skcipher(struct crypto_skcipher *tfm,
31                                    const u8 *key, unsigned int keylen)
32 {
33         return twofish_setkey(&tfm->base, key, keylen);
34 }
35
36 static inline void twofish_enc_blk_3way(const void *ctx, u8 *dst, const u8 *src)
37 {
38         __twofish_enc_blk_3way(ctx, dst, src, false);
39 }
40
41 static int ecb_encrypt(struct skcipher_request *req)
42 {
43         ECB_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS);
44         ECB_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_ecb_enc_8way);
45         ECB_BLOCK(3, twofish_enc_blk_3way);
46         ECB_BLOCK(1, twofish_enc_blk);
47         ECB_WALK_END();
48 }
49
50 static int ecb_decrypt(struct skcipher_request *req)
51 {
52         ECB_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS);
53         ECB_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_ecb_dec_8way);
54         ECB_BLOCK(3, twofish_dec_blk_3way);
55         ECB_BLOCK(1, twofish_dec_blk);
56         ECB_WALK_END();
57 }
58
59 static int cbc_encrypt(struct skcipher_request *req)
60 {
61         CBC_WALK_START(req, TF_BLOCK_SIZE, -1);
62         CBC_ENC_BLOCK(twofish_enc_blk);
63         CBC_WALK_END();
64 }
65
66 static int cbc_decrypt(struct skcipher_request *req)
67 {
68         CBC_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS);
69         CBC_DEC_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_cbc_dec_8way);
70         CBC_DEC_BLOCK(3, twofish_dec_blk_cbc_3way);
71         CBC_DEC_BLOCK(1, twofish_dec_blk);
72         CBC_WALK_END();
73 }
74
75 static struct skcipher_alg twofish_algs[] = {
76         {
77                 .base.cra_name          = "__ecb(twofish)",
78                 .base.cra_driver_name   = "__ecb-twofish-avx",
79                 .base.cra_priority      = 400,
80                 .base.cra_flags         = CRYPTO_ALG_INTERNAL,
81                 .base.cra_blocksize     = TF_BLOCK_SIZE,
82                 .base.cra_ctxsize       = sizeof(struct twofish_ctx),
83                 .base.cra_module        = THIS_MODULE,
84                 .min_keysize            = TF_MIN_KEY_SIZE,
85                 .max_keysize            = TF_MAX_KEY_SIZE,
86                 .setkey                 = twofish_setkey_skcipher,
87                 .encrypt                = ecb_encrypt,
88                 .decrypt                = ecb_decrypt,
89         }, {
90                 .base.cra_name          = "__cbc(twofish)",
91                 .base.cra_driver_name   = "__cbc-twofish-avx",
92                 .base.cra_priority      = 400,
93                 .base.cra_flags         = CRYPTO_ALG_INTERNAL,
94                 .base.cra_blocksize     = TF_BLOCK_SIZE,
95                 .base.cra_ctxsize       = sizeof(struct twofish_ctx),
96                 .base.cra_module        = THIS_MODULE,
97                 .min_keysize            = TF_MIN_KEY_SIZE,
98                 .max_keysize            = TF_MAX_KEY_SIZE,
99                 .ivsize                 = TF_BLOCK_SIZE,
100                 .setkey                 = twofish_setkey_skcipher,
101                 .encrypt                = cbc_encrypt,
102                 .decrypt                = cbc_decrypt,
103         },
104 };
105
106 static struct simd_skcipher_alg *twofish_simd_algs[ARRAY_SIZE(twofish_algs)];
107
108 static int __init twofish_init(void)
109 {
110         const char *feature_name;
111
112         if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, &feature_name)) {
113                 pr_info("CPU feature '%s' is not supported.\n", feature_name);
114                 return -ENODEV;
115         }
116
117         return simd_register_skciphers_compat(twofish_algs,
118                                               ARRAY_SIZE(twofish_algs),
119                                               twofish_simd_algs);
120 }
121
122 static void __exit twofish_exit(void)
123 {
124         simd_unregister_skciphers(twofish_algs, ARRAY_SIZE(twofish_algs),
125                                   twofish_simd_algs);
126 }
127
128 module_init(twofish_init);
129 module_exit(twofish_exit);
130
131 MODULE_DESCRIPTION("Twofish Cipher Algorithm, AVX optimized");
132 MODULE_LICENSE("GPL");
133 MODULE_ALIAS_CRYPTO("twofish");