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 * CTR part based on code (crypto/ctr.c) by:
 10 *   (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
 11 */
 12
 13#include <crypto/algapi.h>
 14#include <crypto/des.h>
 15#include <crypto/internal/skcipher.h>
 16#include <linux/crypto.h>
 17#include <linux/init.h>
 18#include <linux/module.h>
 19#include <linux/types.h>
 20
 21struct des3_ede_x86_ctx {
 22	struct des3_ede_ctx enc;
 23	struct des3_ede_ctx dec;
 24};
 25
 26/* regular block cipher functions */
 27asmlinkage void des3_ede_x86_64_crypt_blk(const u32 *expkey, u8 *dst,
 28					  const u8 *src);
 29
 30/* 3-way parallel cipher functions */
 31asmlinkage void des3_ede_x86_64_crypt_blk_3way(const u32 *expkey, u8 *dst,
 32					       const u8 *src);
 33
 34static inline void des3_ede_enc_blk(struct des3_ede_x86_ctx *ctx, u8 *dst,
 35				    const u8 *src)
 36{
 37	u32 *enc_ctx = ctx->enc.expkey;
 38
 39	des3_ede_x86_64_crypt_blk(enc_ctx, dst, src);
 40}
 41
 42static inline void des3_ede_dec_blk(struct des3_ede_x86_ctx *ctx, u8 *dst,
 43				    const u8 *src)
 44{
 45	u32 *dec_ctx = ctx->dec.expkey;
 46
 47	des3_ede_x86_64_crypt_blk(dec_ctx, dst, src);
 48}
 49
 50static inline void des3_ede_enc_blk_3way(struct des3_ede_x86_ctx *ctx, u8 *dst,
 51					 const u8 *src)
 52{
 53	u32 *enc_ctx = ctx->enc.expkey;
 54
 55	des3_ede_x86_64_crypt_blk_3way(enc_ctx, dst, src);
 56}
 57
 58static inline void des3_ede_dec_blk_3way(struct des3_ede_x86_ctx *ctx, u8 *dst,
 59					 const u8 *src)
 60{
 61	u32 *dec_ctx = ctx->dec.expkey;
 62
 63	des3_ede_x86_64_crypt_blk_3way(dec_ctx, dst, src);
 64}
 65
 66static void des3_ede_x86_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 67{
 68	des3_ede_enc_blk(crypto_tfm_ctx(tfm), dst, src);
 69}
 70
 71static void des3_ede_x86_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 72{
 73	des3_ede_dec_blk(crypto_tfm_ctx(tfm), dst, src);
 74}
 75
 76static int ecb_crypt(struct skcipher_request *req, const u32 *expkey)
 77{
 78	const unsigned int bsize = DES3_EDE_BLOCK_SIZE;
 79	struct skcipher_walk walk;
 80	unsigned int nbytes;
 81	int err;
 82
 83	err = skcipher_walk_virt(&walk, req, false);
 84
 85	while ((nbytes = walk.nbytes)) {
 86		u8 *wsrc = walk.src.virt.addr;
 87		u8 *wdst = walk.dst.virt.addr;
 88
 89		/* Process four block batch */
 90		if (nbytes >= bsize * 3) {
 91			do {
 92				des3_ede_x86_64_crypt_blk_3way(expkey, wdst,
 93							       wsrc);
 94
 95				wsrc += bsize * 3;
 96				wdst += bsize * 3;
 97				nbytes -= bsize * 3;
 98			} while (nbytes >= bsize * 3);
 99
100			if (nbytes < bsize)
101				goto done;
102		}
103
104		/* Handle leftovers */
105		do {
106			des3_ede_x86_64_crypt_blk(expkey, wdst, wsrc);
107
108			wsrc += bsize;
109			wdst += bsize;
110			nbytes -= bsize;
111		} while (nbytes >= bsize);
112
113done:
114		err = skcipher_walk_done(&walk, nbytes);
115	}
116
117	return err;
118}
119
120static int ecb_encrypt(struct skcipher_request *req)
121{
122	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
123	struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm);
124
125	return ecb_crypt(req, ctx->enc.expkey);
126}
127
128static int ecb_decrypt(struct skcipher_request *req)
129{
130	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
131	struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm);
132
133	return ecb_crypt(req, ctx->dec.expkey);
134}
135
136static unsigned int __cbc_encrypt(struct des3_ede_x86_ctx *ctx,
137				  struct skcipher_walk *walk)
138{
139	unsigned int bsize = DES3_EDE_BLOCK_SIZE;
140	unsigned int nbytes = walk->nbytes;
141	u64 *src = (u64 *)walk->src.virt.addr;
142	u64 *dst = (u64 *)walk->dst.virt.addr;
143	u64 *iv = (u64 *)walk->iv;
144
145	do {
146		*dst = *src ^ *iv;
147		des3_ede_enc_blk(ctx, (u8 *)dst, (u8 *)dst);
148		iv = dst;
149
150		src += 1;
151		dst += 1;
152		nbytes -= bsize;
153	} while (nbytes >= bsize);
154
155	*(u64 *)walk->iv = *iv;
156	return nbytes;
157}
158
159static int cbc_encrypt(struct skcipher_request *req)
160{
161	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
162	struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm);
163	struct skcipher_walk walk;
164	unsigned int nbytes;
165	int err;
166
167	err = skcipher_walk_virt(&walk, req, false);
168
169	while ((nbytes = walk.nbytes)) {
170		nbytes = __cbc_encrypt(ctx, &walk);
171		err = skcipher_walk_done(&walk, nbytes);
172	}
173
174	return err;
175}
176
177static unsigned int __cbc_decrypt(struct des3_ede_x86_ctx *ctx,
178				  struct skcipher_walk *walk)
179{
180	unsigned int bsize = DES3_EDE_BLOCK_SIZE;
181	unsigned int nbytes = walk->nbytes;
182	u64 *src = (u64 *)walk->src.virt.addr;
183	u64 *dst = (u64 *)walk->dst.virt.addr;
184	u64 ivs[3 - 1];
185	u64 last_iv;
186
187	/* Start of the last block. */
188	src += nbytes / bsize - 1;
189	dst += nbytes / bsize - 1;
190
191	last_iv = *src;
192
193	/* Process four block batch */
194	if (nbytes >= bsize * 3) {
195		do {
196			nbytes -= bsize * 3 - bsize;
197			src -= 3 - 1;
198			dst -= 3 - 1;
199
200			ivs[0] = src[0];
201			ivs[1] = src[1];
202
203			des3_ede_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src);
204
205			dst[1] ^= ivs[0];
206			dst[2] ^= ivs[1];
207
208			nbytes -= bsize;
209			if (nbytes < bsize)
210				goto done;
211
212			*dst ^= *(src - 1);
213			src -= 1;
214			dst -= 1;
215		} while (nbytes >= bsize * 3);
216	}
217
218	/* Handle leftovers */
219	for (;;) {
220		des3_ede_dec_blk(ctx, (u8 *)dst, (u8 *)src);
221
222		nbytes -= bsize;
223		if (nbytes < bsize)
224			break;
225
226		*dst ^= *(src - 1);
227		src -= 1;
228		dst -= 1;
229	}
230
231done:
232	*dst ^= *(u64 *)walk->iv;
233	*(u64 *)walk->iv = last_iv;
234
235	return nbytes;
236}
237
238static int cbc_decrypt(struct skcipher_request *req)
239{
240	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
241	struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm);
242	struct skcipher_walk walk;
243	unsigned int nbytes;
244	int err;
245
246	err = skcipher_walk_virt(&walk, req, false);
247
248	while ((nbytes = walk.nbytes)) {
249		nbytes = __cbc_decrypt(ctx, &walk);
250		err = skcipher_walk_done(&walk, nbytes);
251	}
252
253	return err;
254}
255
256static void ctr_crypt_final(struct des3_ede_x86_ctx *ctx,
257			    struct skcipher_walk *walk)
258{
259	u8 *ctrblk = walk->iv;
260	u8 keystream[DES3_EDE_BLOCK_SIZE];
261	u8 *src = walk->src.virt.addr;
262	u8 *dst = walk->dst.virt.addr;
263	unsigned int nbytes = walk->nbytes;
264
265	des3_ede_enc_blk(ctx, keystream, ctrblk);
266	crypto_xor_cpy(dst, keystream, src, nbytes);
267
268	crypto_inc(ctrblk, DES3_EDE_BLOCK_SIZE);
269}
270
271static unsigned int __ctr_crypt(struct des3_ede_x86_ctx *ctx,
272				struct skcipher_walk *walk)
273{
274	unsigned int bsize = DES3_EDE_BLOCK_SIZE;
275	unsigned int nbytes = walk->nbytes;
276	__be64 *src = (__be64 *)walk->src.virt.addr;
277	__be64 *dst = (__be64 *)walk->dst.virt.addr;
278	u64 ctrblk = be64_to_cpu(*(__be64 *)walk->iv);
279	__be64 ctrblocks[3];
280
281	/* Process four block batch */
282	if (nbytes >= bsize * 3) {
283		do {
284			/* create ctrblks for parallel encrypt */
285			ctrblocks[0] = cpu_to_be64(ctrblk++);
286			ctrblocks[1] = cpu_to_be64(ctrblk++);
287			ctrblocks[2] = cpu_to_be64(ctrblk++);
288
289			des3_ede_enc_blk_3way(ctx, (u8 *)ctrblocks,
290					      (u8 *)ctrblocks);
291
292			dst[0] = src[0] ^ ctrblocks[0];
293			dst[1] = src[1] ^ ctrblocks[1];
294			dst[2] = src[2] ^ ctrblocks[2];
295
296			src += 3;
297			dst += 3;
298		} while ((nbytes -= bsize * 3) >= bsize * 3);
299
300		if (nbytes < bsize)
301			goto done;
302	}
303
304	/* Handle leftovers */
305	do {
306		ctrblocks[0] = cpu_to_be64(ctrblk++);
307
308		des3_ede_enc_blk(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks);
309
310		dst[0] = src[0] ^ ctrblocks[0];
311
312		src += 1;
313		dst += 1;
314	} while ((nbytes -= bsize) >= bsize);
315
316done:
317	*(__be64 *)walk->iv = cpu_to_be64(ctrblk);
318	return nbytes;
319}
320
321static int ctr_crypt(struct skcipher_request *req)
322{
323	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
324	struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm);
325	struct skcipher_walk walk;
326	unsigned int nbytes;
327	int err;
328
329	err = skcipher_walk_virt(&walk, req, false);
330
331	while ((nbytes = walk.nbytes) >= DES3_EDE_BLOCK_SIZE) {
332		nbytes = __ctr_crypt(ctx, &walk);
333		err = skcipher_walk_done(&walk, nbytes);
334	}
335
336	if (nbytes) {
337		ctr_crypt_final(ctx, &walk);
338		err = skcipher_walk_done(&walk, 0);
339	}
340
341	return err;
342}
343
344static int des3_ede_x86_setkey(struct crypto_tfm *tfm, const u8 *key,
345			       unsigned int keylen)
346{
347	struct des3_ede_x86_ctx *ctx = crypto_tfm_ctx(tfm);
348	u32 i, j, tmp;
349	int err;
350
351	err = des3_ede_expand_key(&ctx->enc, key, keylen);
352	if (err == -ENOKEY) {
353		if (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)
354			err = -EINVAL;
355		else
356			err = 0;
357	}
358
359	if (err) {
360		memset(ctx, 0, sizeof(*ctx));
361		return err;
362	}
363
364	/* Fix encryption context for this implementation and form decryption
365	 * context. */
366	j = DES3_EDE_EXPKEY_WORDS - 2;
367	for (i = 0; i < DES3_EDE_EXPKEY_WORDS; i += 2, j -= 2) {
368		tmp = ror32(ctx->enc.expkey[i + 1], 4);
369		ctx->enc.expkey[i + 1] = tmp;
370
371		ctx->dec.expkey[j + 0] = ctx->enc.expkey[i + 0];
372		ctx->dec.expkey[j + 1] = tmp;
373	}
374
375	return 0;
376}
377
378static int des3_ede_x86_setkey_skcipher(struct crypto_skcipher *tfm,
379					const u8 *key,
380					unsigned int keylen)
381{
382	return des3_ede_x86_setkey(&tfm->base, key, keylen);
383}
384
385static struct crypto_alg des3_ede_cipher = {
386	.cra_name		= "des3_ede",
387	.cra_driver_name	= "des3_ede-asm",
388	.cra_priority		= 200,
389	.cra_flags		= CRYPTO_ALG_TYPE_CIPHER,
390	.cra_blocksize		= DES3_EDE_BLOCK_SIZE,
391	.cra_ctxsize		= sizeof(struct des3_ede_x86_ctx),
392	.cra_alignmask		= 0,
393	.cra_module		= THIS_MODULE,
394	.cra_u = {
395		.cipher = {
396			.cia_min_keysize	= DES3_EDE_KEY_SIZE,
397			.cia_max_keysize	= DES3_EDE_KEY_SIZE,
398			.cia_setkey		= des3_ede_x86_setkey,
399			.cia_encrypt		= des3_ede_x86_encrypt,
400			.cia_decrypt		= des3_ede_x86_decrypt,
401		}
402	}
403};
404
405static struct skcipher_alg des3_ede_skciphers[] = {
406	{
407		.base.cra_name		= "ecb(des3_ede)",
408		.base.cra_driver_name	= "ecb-des3_ede-asm",
409		.base.cra_priority	= 300,
410		.base.cra_blocksize	= DES3_EDE_BLOCK_SIZE,
411		.base.cra_ctxsize	= sizeof(struct des3_ede_x86_ctx),
412		.base.cra_module	= THIS_MODULE,
413		.min_keysize		= DES3_EDE_KEY_SIZE,
414		.max_keysize		= DES3_EDE_KEY_SIZE,
415		.setkey			= des3_ede_x86_setkey_skcipher,
416		.encrypt		= ecb_encrypt,
417		.decrypt		= ecb_decrypt,
418	}, {
419		.base.cra_name		= "cbc(des3_ede)",
420		.base.cra_driver_name	= "cbc-des3_ede-asm",
421		.base.cra_priority	= 300,
422		.base.cra_blocksize	= DES3_EDE_BLOCK_SIZE,
423		.base.cra_ctxsize	= sizeof(struct des3_ede_x86_ctx),
424		.base.cra_module	= THIS_MODULE,
425		.min_keysize		= DES3_EDE_KEY_SIZE,
426		.max_keysize		= DES3_EDE_KEY_SIZE,
427		.ivsize			= DES3_EDE_BLOCK_SIZE,
428		.setkey			= des3_ede_x86_setkey_skcipher,
429		.encrypt		= cbc_encrypt,
430		.decrypt		= cbc_decrypt,
431	}, {
432		.base.cra_name		= "ctr(des3_ede)",
433		.base.cra_driver_name	= "ctr-des3_ede-asm",
434		.base.cra_priority	= 300,
435		.base.cra_blocksize	= 1,
436		.base.cra_ctxsize	= sizeof(struct des3_ede_x86_ctx),
437		.base.cra_module	= THIS_MODULE,
438		.min_keysize		= DES3_EDE_KEY_SIZE,
439		.max_keysize		= DES3_EDE_KEY_SIZE,
440		.ivsize			= DES3_EDE_BLOCK_SIZE,
441		.chunksize		= DES3_EDE_BLOCK_SIZE,
442		.setkey			= des3_ede_x86_setkey_skcipher,
443		.encrypt		= ctr_crypt,
444		.decrypt		= ctr_crypt,
445	}
446};
447
448static bool is_blacklisted_cpu(void)
449{
450	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
451		return false;
452
453	if (boot_cpu_data.x86 == 0x0f) {
454		/*
455		 * On Pentium 4, des3_ede-x86_64 is slower than generic C
456		 * implementation because use of 64bit rotates (which are really
457		 * slow on P4). Therefore blacklist P4s.
458		 */
459		return true;
460	}
461
462	return false;
463}
464
465static int force;
466module_param(force, int, 0);
467MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist");
468
469static int __init des3_ede_x86_init(void)
470{
471	int err;
472
473	if (!force && is_blacklisted_cpu()) {
474		pr_info("des3_ede-x86_64: performance on this CPU would be suboptimal: disabling des3_ede-x86_64.\n");
475		return -ENODEV;
476	}
477
478	err = crypto_register_alg(&des3_ede_cipher);
479	if (err)
480		return err;
481
482	err = crypto_register_skciphers(des3_ede_skciphers,
483					ARRAY_SIZE(des3_ede_skciphers));
484	if (err)
485		crypto_unregister_alg(&des3_ede_cipher);
486
487	return err;
488}
489
490static void __exit des3_ede_x86_fini(void)
491{
492	crypto_unregister_alg(&des3_ede_cipher);
493	crypto_unregister_skciphers(des3_ede_skciphers,
494				    ARRAY_SIZE(des3_ede_skciphers));
495}
496
497module_init(des3_ede_x86_init);
498module_exit(des3_ede_x86_fini);
499
500MODULE_LICENSE("GPL");
501MODULE_DESCRIPTION("Triple DES EDE Cipher Algorithm, asm optimized");
502MODULE_ALIAS_CRYPTO("des3_ede");
503MODULE_ALIAS_CRYPTO("des3_ede-asm");
504MODULE_AUTHOR("Jussi Kivilinna <jussi.kivilinna@iki.fi>");