Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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 */
24asmlinkage void twofish_ecb_enc_8way(const void *ctx, u8 *dst, const u8 *src);
25asmlinkage void twofish_ecb_dec_8way(const void *ctx, u8 *dst, const u8 *src);
26
27asmlinkage void twofish_cbc_dec_8way(const void *ctx, u8 *dst, const u8 *src);
28
29static 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
35static 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
40static 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
49static 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
58static 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
65static 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
74static 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
103static 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
116static void __exit twofish_exit(void)
117{
118 crypto_unregister_skciphers(twofish_algs, ARRAY_SIZE(twofish_algs));
119}
120
121module_init(twofish_init);
122module_exit(twofish_exit);
123
124MODULE_DESCRIPTION("Twofish Cipher Algorithm, AVX optimized");
125MODULE_LICENSE("GPL");
126MODULE_ALIAS_CRYPTO("twofish");