Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/crypto/blowfish_glue.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Glue Code for assembler optimized version of Blowfish
4
*
5
* Copyright (c) 2011 Jussi Kivilinna <[email protected]>
6
*
7
* CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
8
* Copyright (c) 2006 Herbert Xu <[email protected]>
9
*/
10
11
#include <crypto/algapi.h>
12
#include <crypto/blowfish.h>
13
#include <crypto/internal/skcipher.h>
14
#include <linux/crypto.h>
15
#include <linux/init.h>
16
#include <linux/module.h>
17
#include <linux/types.h>
18
19
#include "ecb_cbc_helpers.h"
20
21
/* regular block cipher functions */
22
asmlinkage void blowfish_enc_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src);
23
asmlinkage void blowfish_dec_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src);
24
25
/* 4-way parallel cipher functions */
26
asmlinkage void blowfish_enc_blk_4way(struct bf_ctx *ctx, u8 *dst,
27
const u8 *src);
28
asmlinkage void __blowfish_dec_blk_4way(struct bf_ctx *ctx, u8 *dst,
29
const u8 *src, bool cbc);
30
31
static inline void blowfish_dec_ecb_4way(struct bf_ctx *ctx, u8 *dst,
32
const u8 *src)
33
{
34
return __blowfish_dec_blk_4way(ctx, dst, src, false);
35
}
36
37
static inline void blowfish_dec_cbc_4way(struct bf_ctx *ctx, u8 *dst,
38
const u8 *src)
39
{
40
return __blowfish_dec_blk_4way(ctx, dst, src, true);
41
}
42
43
static void blowfish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
44
{
45
blowfish_enc_blk(crypto_tfm_ctx(tfm), dst, src);
46
}
47
48
static void blowfish_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
49
{
50
blowfish_dec_blk(crypto_tfm_ctx(tfm), dst, src);
51
}
52
53
static int blowfish_setkey_skcipher(struct crypto_skcipher *tfm,
54
const u8 *key, unsigned int keylen)
55
{
56
return blowfish_setkey(&tfm->base, key, keylen);
57
}
58
59
static int ecb_encrypt(struct skcipher_request *req)
60
{
61
ECB_WALK_START(req, BF_BLOCK_SIZE, -1);
62
ECB_BLOCK(4, blowfish_enc_blk_4way);
63
ECB_BLOCK(1, blowfish_enc_blk);
64
ECB_WALK_END();
65
}
66
67
static int ecb_decrypt(struct skcipher_request *req)
68
{
69
ECB_WALK_START(req, BF_BLOCK_SIZE, -1);
70
ECB_BLOCK(4, blowfish_dec_ecb_4way);
71
ECB_BLOCK(1, blowfish_dec_blk);
72
ECB_WALK_END();
73
}
74
75
static int cbc_encrypt(struct skcipher_request *req)
76
{
77
CBC_WALK_START(req, BF_BLOCK_SIZE, -1);
78
CBC_ENC_BLOCK(blowfish_enc_blk);
79
CBC_WALK_END();
80
}
81
82
static int cbc_decrypt(struct skcipher_request *req)
83
{
84
CBC_WALK_START(req, BF_BLOCK_SIZE, -1);
85
CBC_DEC_BLOCK(4, blowfish_dec_cbc_4way);
86
CBC_DEC_BLOCK(1, blowfish_dec_blk);
87
CBC_WALK_END();
88
}
89
90
static struct crypto_alg bf_cipher_alg = {
91
.cra_name = "blowfish",
92
.cra_driver_name = "blowfish-asm",
93
.cra_priority = 200,
94
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
95
.cra_blocksize = BF_BLOCK_SIZE,
96
.cra_ctxsize = sizeof(struct bf_ctx),
97
.cra_module = THIS_MODULE,
98
.cra_u = {
99
.cipher = {
100
.cia_min_keysize = BF_MIN_KEY_SIZE,
101
.cia_max_keysize = BF_MAX_KEY_SIZE,
102
.cia_setkey = blowfish_setkey,
103
.cia_encrypt = blowfish_encrypt,
104
.cia_decrypt = blowfish_decrypt,
105
}
106
}
107
};
108
109
static struct skcipher_alg bf_skcipher_algs[] = {
110
{
111
.base.cra_name = "ecb(blowfish)",
112
.base.cra_driver_name = "ecb-blowfish-asm",
113
.base.cra_priority = 300,
114
.base.cra_blocksize = BF_BLOCK_SIZE,
115
.base.cra_ctxsize = sizeof(struct bf_ctx),
116
.base.cra_module = THIS_MODULE,
117
.min_keysize = BF_MIN_KEY_SIZE,
118
.max_keysize = BF_MAX_KEY_SIZE,
119
.setkey = blowfish_setkey_skcipher,
120
.encrypt = ecb_encrypt,
121
.decrypt = ecb_decrypt,
122
}, {
123
.base.cra_name = "cbc(blowfish)",
124
.base.cra_driver_name = "cbc-blowfish-asm",
125
.base.cra_priority = 300,
126
.base.cra_blocksize = BF_BLOCK_SIZE,
127
.base.cra_ctxsize = sizeof(struct bf_ctx),
128
.base.cra_module = THIS_MODULE,
129
.min_keysize = BF_MIN_KEY_SIZE,
130
.max_keysize = BF_MAX_KEY_SIZE,
131
.ivsize = BF_BLOCK_SIZE,
132
.setkey = blowfish_setkey_skcipher,
133
.encrypt = cbc_encrypt,
134
.decrypt = cbc_decrypt,
135
},
136
};
137
138
static bool is_blacklisted_cpu(void)
139
{
140
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
141
return false;
142
143
if (boot_cpu_data.x86 == 0x0f) {
144
/*
145
* On Pentium 4, blowfish-x86_64 is slower than generic C
146
* implementation because use of 64bit rotates (which are really
147
* slow on P4). Therefore blacklist P4s.
148
*/
149
return true;
150
}
151
152
return false;
153
}
154
155
static int force;
156
module_param(force, int, 0);
157
MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist");
158
159
static int __init blowfish_init(void)
160
{
161
int err;
162
163
if (!force && is_blacklisted_cpu()) {
164
printk(KERN_INFO
165
"blowfish-x86_64: performance on this CPU "
166
"would be suboptimal: disabling "
167
"blowfish-x86_64.\n");
168
return -ENODEV;
169
}
170
171
err = crypto_register_alg(&bf_cipher_alg);
172
if (err)
173
return err;
174
175
err = crypto_register_skciphers(bf_skcipher_algs,
176
ARRAY_SIZE(bf_skcipher_algs));
177
if (err)
178
crypto_unregister_alg(&bf_cipher_alg);
179
180
return err;
181
}
182
183
static void __exit blowfish_fini(void)
184
{
185
crypto_unregister_alg(&bf_cipher_alg);
186
crypto_unregister_skciphers(bf_skcipher_algs,
187
ARRAY_SIZE(bf_skcipher_algs));
188
}
189
190
module_init(blowfish_init);
191
module_exit(blowfish_fini);
192
193
MODULE_LICENSE("GPL");
194
MODULE_DESCRIPTION("Blowfish Cipher Algorithm, asm optimized");
195
MODULE_ALIAS_CRYPTO("blowfish");
196
MODULE_ALIAS_CRYPTO("blowfish-asm");
197
198