Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Glue Code for assembler optimized version of 3DES
  4 *
  5 * Copyright © 2014 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
  6 *
  7 * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
  8 *   Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
  9 */
 10
 11#include <crypto/algapi.h>
 12#include <crypto/des.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
 19struct des3_ede_x86_ctx {
 20	struct des3_ede_ctx enc;
 21	struct des3_ede_ctx dec;
 22};
 23
 24/* regular block cipher functions */
 25asmlinkage void des3_ede_x86_64_crypt_blk(const u32 *expkey, u8 *dst,
 26					  const u8 *src);
 27
 28/* 3-way parallel cipher functions */
 29asmlinkage void des3_ede_x86_64_crypt_blk_3way(const u32 *expkey, u8 *dst,
 30					       const u8 *src);
 31
 32static inline void des3_ede_enc_blk(struct des3_ede_x86_ctx *ctx, u8 *dst,
 33				    const u8 *src)
 34{
 35	u32 *enc_ctx = ctx->enc.expkey;
 36
 37	des3_ede_x86_64_crypt_blk(enc_ctx, dst, src);
 38}
 39
 40static inline void des3_ede_dec_blk(struct des3_ede_x86_ctx *ctx, u8 *dst,
 41				    const u8 *src)
 42{
 43	u32 *dec_ctx = ctx->dec.expkey;
 44
 45	des3_ede_x86_64_crypt_blk(dec_ctx, dst, src);
 46}
 47
 48static inline void des3_ede_enc_blk_3way(struct des3_ede_x86_ctx *ctx, u8 *dst,
 49					 const u8 *src)
 50{
 51	u32 *enc_ctx = ctx->enc.expkey;
 52
 53	des3_ede_x86_64_crypt_blk_3way(enc_ctx, dst, src);
 54}
 55
 56static inline void des3_ede_dec_blk_3way(struct des3_ede_x86_ctx *ctx, u8 *dst,
 57					 const u8 *src)
 58{
 59	u32 *dec_ctx = ctx->dec.expkey;
 60
 61	des3_ede_x86_64_crypt_blk_3way(dec_ctx, dst, src);
 62}
 63
 64static void des3_ede_x86_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 65{
 66	des3_ede_enc_blk(crypto_tfm_ctx(tfm), dst, src);
 67}
 68
 69static void des3_ede_x86_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 70{
 71	des3_ede_dec_blk(crypto_tfm_ctx(tfm), dst, src);
 72}
 73
 74static int ecb_crypt(struct skcipher_request *req, const u32 *expkey)
 75{
 76	const unsigned int bsize = DES3_EDE_BLOCK_SIZE;
 77	struct skcipher_walk walk;
 78	unsigned int nbytes;
 79	int err;
 80
 81	err = skcipher_walk_virt(&walk, req, false);
 82
 83	while ((nbytes = walk.nbytes)) {
 84		u8 *wsrc = walk.src.virt.addr;
 85		u8 *wdst = walk.dst.virt.addr;
 86
 87		/* Process four block batch */
 88		if (nbytes >= bsize * 3) {
 89			do {
 90				des3_ede_x86_64_crypt_blk_3way(expkey, wdst,
 91							       wsrc);
 92
 93				wsrc += bsize * 3;
 94				wdst += bsize * 3;
 95				nbytes -= bsize * 3;
 96			} while (nbytes >= bsize * 3);
 97
 98			if (nbytes < bsize)
 99				goto done;
100		}
101
102		/* Handle leftovers */
103		do {
104			des3_ede_x86_64_crypt_blk(expkey, wdst, wsrc);
105
106			wsrc += bsize;
107			wdst += bsize;
108			nbytes -= bsize;
109		} while (nbytes >= bsize);
110
111done:
112		err = skcipher_walk_done(&walk, nbytes);
113	}
114
115	return err;
116}
117
118static int ecb_encrypt(struct skcipher_request *req)
119{
120	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
121	struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm);
122
123	return ecb_crypt(req, ctx->enc.expkey);
124}
125
126static int ecb_decrypt(struct skcipher_request *req)
127{
128	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
129	struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm);
130
131	return ecb_crypt(req, ctx->dec.expkey);
132}
133
134static unsigned int __cbc_encrypt(struct des3_ede_x86_ctx *ctx,
135				  struct skcipher_walk *walk)
136{
137	unsigned int bsize = DES3_EDE_BLOCK_SIZE;
138	unsigned int nbytes = walk->nbytes;
139	u64 *src = (u64 *)walk->src.virt.addr;
140	u64 *dst = (u64 *)walk->dst.virt.addr;
141	u64 *iv = (u64 *)walk->iv;
142
143	do {
144		*dst = *src ^ *iv;
145		des3_ede_enc_blk(ctx, (u8 *)dst, (u8 *)dst);
146		iv = dst;
147
148		src += 1;
149		dst += 1;
150		nbytes -= bsize;
151	} while (nbytes >= bsize);
152
153	*(u64 *)walk->iv = *iv;
154	return nbytes;
155}
156
157static int cbc_encrypt(struct skcipher_request *req)
158{
159	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
160	struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm);
161	struct skcipher_walk walk;
162	unsigned int nbytes;
163	int err;
164
165	err = skcipher_walk_virt(&walk, req, false);
166
167	while ((nbytes = walk.nbytes)) {
168		nbytes = __cbc_encrypt(ctx, &walk);
169		err = skcipher_walk_done(&walk, nbytes);
170	}
171
172	return err;
173}
174
175static unsigned int __cbc_decrypt(struct des3_ede_x86_ctx *ctx,
176				  struct skcipher_walk *walk)
177{
178	unsigned int bsize = DES3_EDE_BLOCK_SIZE;
179	unsigned int nbytes = walk->nbytes;
180	u64 *src = (u64 *)walk->src.virt.addr;
181	u64 *dst = (u64 *)walk->dst.virt.addr;
182	u64 ivs[3 - 1];
183	u64 last_iv;
184
185	/* Start of the last block. */
186	src += nbytes / bsize - 1;
187	dst += nbytes / bsize - 1;
188
189	last_iv = *src;
190
191	/* Process four block batch */
192	if (nbytes >= bsize * 3) {
193		do {
194			nbytes -= bsize * 3 - bsize;
195			src -= 3 - 1;
196			dst -= 3 - 1;
197
198			ivs[0] = src[0];
199			ivs[1] = src[1];
200
201			des3_ede_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src);
202
203			dst[1] ^= ivs[0];
204			dst[2] ^= ivs[1];
205
206			nbytes -= bsize;
207			if (nbytes < bsize)
208				goto done;
209
210			*dst ^= *(src - 1);
211			src -= 1;
212			dst -= 1;
213		} while (nbytes >= bsize * 3);
214	}
215
216	/* Handle leftovers */
217	for (;;) {
218		des3_ede_dec_blk(ctx, (u8 *)dst, (u8 *)src);
219
220		nbytes -= bsize;
221		if (nbytes < bsize)
222			break;
223
224		*dst ^= *(src - 1);
225		src -= 1;
226		dst -= 1;
227	}
228
229done:
230	*dst ^= *(u64 *)walk->iv;
231	*(u64 *)walk->iv = last_iv;
232
233	return nbytes;
234}
235
236static int cbc_decrypt(struct skcipher_request *req)
237{
238	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
239	struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm);
240	struct skcipher_walk walk;
241	unsigned int nbytes;
242	int err;
243
244	err = skcipher_walk_virt(&walk, req, false);
245
246	while ((nbytes = walk.nbytes)) {
247		nbytes = __cbc_decrypt(ctx, &walk);
248		err = skcipher_walk_done(&walk, nbytes);
249	}
250
251	return err;
252}
253
254static int des3_ede_x86_setkey(struct crypto_tfm *tfm, const u8 *key,
255			       unsigned int keylen)
256{
257	struct des3_ede_x86_ctx *ctx = crypto_tfm_ctx(tfm);
258	u32 i, j, tmp;
259	int err;
260
261	err = des3_ede_expand_key(&ctx->enc, key, keylen);
262	if (err == -ENOKEY) {
263		if (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)
264			err = -EINVAL;
265		else
266			err = 0;
267	}
268
269	if (err) {
270		memset(ctx, 0, sizeof(*ctx));
271		return err;
272	}
273
274	/* Fix encryption context for this implementation and form decryption
275	 * context. */
276	j = DES3_EDE_EXPKEY_WORDS - 2;
277	for (i = 0; i < DES3_EDE_EXPKEY_WORDS; i += 2, j -= 2) {
278		tmp = ror32(ctx->enc.expkey[i + 1], 4);
279		ctx->enc.expkey[i + 1] = tmp;
280
281		ctx->dec.expkey[j + 0] = ctx->enc.expkey[i + 0];
282		ctx->dec.expkey[j + 1] = tmp;
283	}
284
285	return 0;
286}
287
288static int des3_ede_x86_setkey_skcipher(struct crypto_skcipher *tfm,
289					const u8 *key,
290					unsigned int keylen)
291{
292	return des3_ede_x86_setkey(&tfm->base, key, keylen);
293}
294
295static struct crypto_alg des3_ede_cipher = {
296	.cra_name		= "des3_ede",
297	.cra_driver_name	= "des3_ede-asm",
298	.cra_priority		= 200,
299	.cra_flags		= CRYPTO_ALG_TYPE_CIPHER,
300	.cra_blocksize		= DES3_EDE_BLOCK_SIZE,
301	.cra_ctxsize		= sizeof(struct des3_ede_x86_ctx),
302	.cra_alignmask		= 0,
303	.cra_module		= THIS_MODULE,
304	.cra_u = {
305		.cipher = {
306			.cia_min_keysize	= DES3_EDE_KEY_SIZE,
307			.cia_max_keysize	= DES3_EDE_KEY_SIZE,
308			.cia_setkey		= des3_ede_x86_setkey,
309			.cia_encrypt		= des3_ede_x86_encrypt,
310			.cia_decrypt		= des3_ede_x86_decrypt,
311		}
312	}
313};
314
315static struct skcipher_alg des3_ede_skciphers[] = {
316	{
317		.base.cra_name		= "ecb(des3_ede)",
318		.base.cra_driver_name	= "ecb-des3_ede-asm",
319		.base.cra_priority	= 300,
320		.base.cra_blocksize	= DES3_EDE_BLOCK_SIZE,
321		.base.cra_ctxsize	= sizeof(struct des3_ede_x86_ctx),
322		.base.cra_module	= THIS_MODULE,
323		.min_keysize		= DES3_EDE_KEY_SIZE,
324		.max_keysize		= DES3_EDE_KEY_SIZE,
325		.setkey			= des3_ede_x86_setkey_skcipher,
326		.encrypt		= ecb_encrypt,
327		.decrypt		= ecb_decrypt,
328	}, {
329		.base.cra_name		= "cbc(des3_ede)",
330		.base.cra_driver_name	= "cbc-des3_ede-asm",
331		.base.cra_priority	= 300,
332		.base.cra_blocksize	= DES3_EDE_BLOCK_SIZE,
333		.base.cra_ctxsize	= sizeof(struct des3_ede_x86_ctx),
334		.base.cra_module	= THIS_MODULE,
335		.min_keysize		= DES3_EDE_KEY_SIZE,
336		.max_keysize		= DES3_EDE_KEY_SIZE,
337		.ivsize			= DES3_EDE_BLOCK_SIZE,
338		.setkey			= des3_ede_x86_setkey_skcipher,
339		.encrypt		= cbc_encrypt,
340		.decrypt		= cbc_decrypt,
341	}
342};
343
344static bool is_blacklisted_cpu(void)
345{
346	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
347		return false;
348
349	if (boot_cpu_data.x86 == 0x0f) {
350		/*
351		 * On Pentium 4, des3_ede-x86_64 is slower than generic C
352		 * implementation because use of 64bit rotates (which are really
353		 * slow on P4). Therefore blacklist P4s.
354		 */
355		return true;
356	}
357
358	return false;
359}
360
361static int force;
362module_param(force, int, 0);
363MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist");
364
365static int __init des3_ede_x86_init(void)
366{
367	int err;
368
369	if (!force && is_blacklisted_cpu()) {
370		pr_info("des3_ede-x86_64: performance on this CPU would be suboptimal: disabling des3_ede-x86_64.\n");
371		return -ENODEV;
372	}
373
374	err = crypto_register_alg(&des3_ede_cipher);
375	if (err)
376		return err;
377
378	err = crypto_register_skciphers(des3_ede_skciphers,
379					ARRAY_SIZE(des3_ede_skciphers));
380	if (err)
381		crypto_unregister_alg(&des3_ede_cipher);
382
383	return err;
384}
385
386static void __exit des3_ede_x86_fini(void)
387{
388	crypto_unregister_alg(&des3_ede_cipher);
389	crypto_unregister_skciphers(des3_ede_skciphers,
390				    ARRAY_SIZE(des3_ede_skciphers));
391}
392
393module_init(des3_ede_x86_init);
394module_exit(des3_ede_x86_fini);
395
396MODULE_LICENSE("GPL");
397MODULE_DESCRIPTION("Triple DES EDE Cipher Algorithm, asm optimized");
398MODULE_ALIAS_CRYPTO("des3_ede");
399MODULE_ALIAS_CRYPTO("des3_ede-asm");
400MODULE_AUTHOR("Jussi Kivilinna <jussi.kivilinna@iki.fi>");