xref: /linux/arch/x86/crypto/twofish_glue_3way.c (revision 251f39fe42dae863bd24e30864e6b66076ba076d)
1 /*
2  * Glue Code for 3-way parallel assembler optimized version of Twofish
3  *
4  * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
5  *
6  * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
7  *   Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
8  * CTR part based on code (crypto/ctr.c) by:
9  *   (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
24  * USA
25  *
26  */
27 
28 #include <linux/crypto.h>
29 #include <linux/init.h>
30 #include <linux/module.h>
31 #include <linux/types.h>
32 #include <crypto/algapi.h>
33 #include <crypto/twofish.h>
34 #include <crypto/b128ops.h>
35 
36 /* regular block cipher functions from twofish_x86_64 module */
37 asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst,
38 				const u8 *src);
39 asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst,
40 				const u8 *src);
41 
42 /* 3-way parallel cipher functions */
43 asmlinkage void __twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
44 				       const u8 *src, bool xor);
45 asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst,
46 				     const u8 *src);
47 
48 static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
49 					const u8 *src)
50 {
51 	__twofish_enc_blk_3way(ctx, dst, src, false);
52 }
53 
54 static inline void twofish_enc_blk_xor_3way(struct twofish_ctx *ctx, u8 *dst,
55 					    const u8 *src)
56 {
57 	__twofish_enc_blk_3way(ctx, dst, src, true);
58 }
59 
60 static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
61 		     void (*fn)(struct twofish_ctx *, u8 *, const u8 *),
62 		     void (*fn_3way)(struct twofish_ctx *, u8 *, const u8 *))
63 {
64 	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
65 	unsigned int bsize = TF_BLOCK_SIZE;
66 	unsigned int nbytes;
67 	int err;
68 
69 	err = blkcipher_walk_virt(desc, walk);
70 
71 	while ((nbytes = walk->nbytes)) {
72 		u8 *wsrc = walk->src.virt.addr;
73 		u8 *wdst = walk->dst.virt.addr;
74 
75 		/* Process three block batch */
76 		if (nbytes >= bsize * 3) {
77 			do {
78 				fn_3way(ctx, wdst, wsrc);
79 
80 				wsrc += bsize * 3;
81 				wdst += bsize * 3;
82 				nbytes -= bsize * 3;
83 			} while (nbytes >= bsize * 3);
84 
85 			if (nbytes < bsize)
86 				goto done;
87 		}
88 
89 		/* Handle leftovers */
90 		do {
91 			fn(ctx, wdst, wsrc);
92 
93 			wsrc += bsize;
94 			wdst += bsize;
95 			nbytes -= bsize;
96 		} while (nbytes >= bsize);
97 
98 done:
99 		err = blkcipher_walk_done(desc, walk, nbytes);
100 	}
101 
102 	return err;
103 }
104 
105 static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
106 		       struct scatterlist *src, unsigned int nbytes)
107 {
108 	struct blkcipher_walk walk;
109 
110 	blkcipher_walk_init(&walk, dst, src, nbytes);
111 	return ecb_crypt(desc, &walk, twofish_enc_blk, twofish_enc_blk_3way);
112 }
113 
114 static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
115 		       struct scatterlist *src, unsigned int nbytes)
116 {
117 	struct blkcipher_walk walk;
118 
119 	blkcipher_walk_init(&walk, dst, src, nbytes);
120 	return ecb_crypt(desc, &walk, twofish_dec_blk, twofish_dec_blk_3way);
121 }
122 
123 static struct crypto_alg blk_ecb_alg = {
124 	.cra_name		= "ecb(twofish)",
125 	.cra_driver_name	= "ecb-twofish-3way",
126 	.cra_priority		= 300,
127 	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
128 	.cra_blocksize		= TF_BLOCK_SIZE,
129 	.cra_ctxsize		= sizeof(struct twofish_ctx),
130 	.cra_alignmask		= 0,
131 	.cra_type		= &crypto_blkcipher_type,
132 	.cra_module		= THIS_MODULE,
133 	.cra_list		= LIST_HEAD_INIT(blk_ecb_alg.cra_list),
134 	.cra_u = {
135 		.blkcipher = {
136 			.min_keysize	= TF_MIN_KEY_SIZE,
137 			.max_keysize	= TF_MAX_KEY_SIZE,
138 			.setkey		= twofish_setkey,
139 			.encrypt	= ecb_encrypt,
140 			.decrypt	= ecb_decrypt,
141 		},
142 	},
143 };
144 
145 static unsigned int __cbc_encrypt(struct blkcipher_desc *desc,
146 				  struct blkcipher_walk *walk)
147 {
148 	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
149 	unsigned int bsize = TF_BLOCK_SIZE;
150 	unsigned int nbytes = walk->nbytes;
151 	u128 *src = (u128 *)walk->src.virt.addr;
152 	u128 *dst = (u128 *)walk->dst.virt.addr;
153 	u128 *iv = (u128 *)walk->iv;
154 
155 	do {
156 		u128_xor(dst, src, iv);
157 		twofish_enc_blk(ctx, (u8 *)dst, (u8 *)dst);
158 		iv = dst;
159 
160 		src += 1;
161 		dst += 1;
162 		nbytes -= bsize;
163 	} while (nbytes >= bsize);
164 
165 	u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv);
166 	return nbytes;
167 }
168 
169 static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
170 		       struct scatterlist *src, unsigned int nbytes)
171 {
172 	struct blkcipher_walk walk;
173 	int err;
174 
175 	blkcipher_walk_init(&walk, dst, src, nbytes);
176 	err = blkcipher_walk_virt(desc, &walk);
177 
178 	while ((nbytes = walk.nbytes)) {
179 		nbytes = __cbc_encrypt(desc, &walk);
180 		err = blkcipher_walk_done(desc, &walk, nbytes);
181 	}
182 
183 	return err;
184 }
185 
186 static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
187 				  struct blkcipher_walk *walk)
188 {
189 	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
190 	unsigned int bsize = TF_BLOCK_SIZE;
191 	unsigned int nbytes = walk->nbytes;
192 	u128 *src = (u128 *)walk->src.virt.addr;
193 	u128 *dst = (u128 *)walk->dst.virt.addr;
194 	u128 ivs[3 - 1];
195 	u128 last_iv;
196 
197 	/* Start of the last block. */
198 	src += nbytes / bsize - 1;
199 	dst += nbytes / bsize - 1;
200 
201 	last_iv = *src;
202 
203 	/* Process three block batch */
204 	if (nbytes >= bsize * 3) {
205 		do {
206 			nbytes -= bsize * (3 - 1);
207 			src -= 3 - 1;
208 			dst -= 3 - 1;
209 
210 			ivs[0] = src[0];
211 			ivs[1] = src[1];
212 
213 			twofish_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src);
214 
215 			u128_xor(dst + 1, dst + 1, ivs + 0);
216 			u128_xor(dst + 2, dst + 2, ivs + 1);
217 
218 			nbytes -= bsize;
219 			if (nbytes < bsize)
220 				goto done;
221 
222 			u128_xor(dst, dst, src - 1);
223 			src -= 1;
224 			dst -= 1;
225 		} while (nbytes >= bsize * 3);
226 
227 		if (nbytes < bsize)
228 			goto done;
229 	}
230 
231 	/* Handle leftovers */
232 	for (;;) {
233 		twofish_dec_blk(ctx, (u8 *)dst, (u8 *)src);
234 
235 		nbytes -= bsize;
236 		if (nbytes < bsize)
237 			break;
238 
239 		u128_xor(dst, dst, src - 1);
240 		src -= 1;
241 		dst -= 1;
242 	}
243 
244 done:
245 	u128_xor(dst, dst, (u128 *)walk->iv);
246 	*(u128 *)walk->iv = last_iv;
247 
248 	return nbytes;
249 }
250 
251 static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
252 		       struct scatterlist *src, unsigned int nbytes)
253 {
254 	struct blkcipher_walk walk;
255 	int err;
256 
257 	blkcipher_walk_init(&walk, dst, src, nbytes);
258 	err = blkcipher_walk_virt(desc, &walk);
259 
260 	while ((nbytes = walk.nbytes)) {
261 		nbytes = __cbc_decrypt(desc, &walk);
262 		err = blkcipher_walk_done(desc, &walk, nbytes);
263 	}
264 
265 	return err;
266 }
267 
268 static struct crypto_alg blk_cbc_alg = {
269 	.cra_name		= "cbc(twofish)",
270 	.cra_driver_name	= "cbc-twofish-3way",
271 	.cra_priority		= 300,
272 	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
273 	.cra_blocksize		= TF_BLOCK_SIZE,
274 	.cra_ctxsize		= sizeof(struct twofish_ctx),
275 	.cra_alignmask		= 0,
276 	.cra_type		= &crypto_blkcipher_type,
277 	.cra_module		= THIS_MODULE,
278 	.cra_list		= LIST_HEAD_INIT(blk_cbc_alg.cra_list),
279 	.cra_u = {
280 		.blkcipher = {
281 			.min_keysize	= TF_MIN_KEY_SIZE,
282 			.max_keysize	= TF_MAX_KEY_SIZE,
283 			.ivsize		= TF_BLOCK_SIZE,
284 			.setkey		= twofish_setkey,
285 			.encrypt	= cbc_encrypt,
286 			.decrypt	= cbc_decrypt,
287 		},
288 	},
289 };
290 
291 static inline void u128_to_be128(be128 *dst, const u128 *src)
292 {
293 	dst->a = cpu_to_be64(src->a);
294 	dst->b = cpu_to_be64(src->b);
295 }
296 
297 static inline void be128_to_u128(u128 *dst, const be128 *src)
298 {
299 	dst->a = be64_to_cpu(src->a);
300 	dst->b = be64_to_cpu(src->b);
301 }
302 
303 static inline void u128_inc(u128 *i)
304 {
305 	i->b++;
306 	if (!i->b)
307 		i->a++;
308 }
309 
310 static void ctr_crypt_final(struct blkcipher_desc *desc,
311 			    struct blkcipher_walk *walk)
312 {
313 	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
314 	u8 *ctrblk = walk->iv;
315 	u8 keystream[TF_BLOCK_SIZE];
316 	u8 *src = walk->src.virt.addr;
317 	u8 *dst = walk->dst.virt.addr;
318 	unsigned int nbytes = walk->nbytes;
319 
320 	twofish_enc_blk(ctx, keystream, ctrblk);
321 	crypto_xor(keystream, src, nbytes);
322 	memcpy(dst, keystream, nbytes);
323 
324 	crypto_inc(ctrblk, TF_BLOCK_SIZE);
325 }
326 
327 static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
328 				struct blkcipher_walk *walk)
329 {
330 	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
331 	unsigned int bsize = TF_BLOCK_SIZE;
332 	unsigned int nbytes = walk->nbytes;
333 	u128 *src = (u128 *)walk->src.virt.addr;
334 	u128 *dst = (u128 *)walk->dst.virt.addr;
335 	u128 ctrblk;
336 	be128 ctrblocks[3];
337 
338 	be128_to_u128(&ctrblk, (be128 *)walk->iv);
339 
340 	/* Process three block batch */
341 	if (nbytes >= bsize * 3) {
342 		do {
343 			if (dst != src) {
344 				dst[0] = src[0];
345 				dst[1] = src[1];
346 				dst[2] = src[2];
347 			}
348 
349 			/* create ctrblks for parallel encrypt */
350 			u128_to_be128(&ctrblocks[0], &ctrblk);
351 			u128_inc(&ctrblk);
352 			u128_to_be128(&ctrblocks[1], &ctrblk);
353 			u128_inc(&ctrblk);
354 			u128_to_be128(&ctrblocks[2], &ctrblk);
355 			u128_inc(&ctrblk);
356 
357 			twofish_enc_blk_xor_3way(ctx, (u8 *)dst,
358 						 (u8 *)ctrblocks);
359 
360 			src += 3;
361 			dst += 3;
362 			nbytes -= bsize * 3;
363 		} while (nbytes >= bsize * 3);
364 
365 		if (nbytes < bsize)
366 			goto done;
367 	}
368 
369 	/* Handle leftovers */
370 	do {
371 		if (dst != src)
372 			*dst = *src;
373 
374 		u128_to_be128(&ctrblocks[0], &ctrblk);
375 		u128_inc(&ctrblk);
376 
377 		twofish_enc_blk(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks);
378 		u128_xor(dst, dst, (u128 *)ctrblocks);
379 
380 		src += 1;
381 		dst += 1;
382 		nbytes -= bsize;
383 	} while (nbytes >= bsize);
384 
385 done:
386 	u128_to_be128((be128 *)walk->iv, &ctrblk);
387 	return nbytes;
388 }
389 
390 static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
391 		     struct scatterlist *src, unsigned int nbytes)
392 {
393 	struct blkcipher_walk walk;
394 	int err;
395 
396 	blkcipher_walk_init(&walk, dst, src, nbytes);
397 	err = blkcipher_walk_virt_block(desc, &walk, TF_BLOCK_SIZE);
398 
399 	while ((nbytes = walk.nbytes) >= TF_BLOCK_SIZE) {
400 		nbytes = __ctr_crypt(desc, &walk);
401 		err = blkcipher_walk_done(desc, &walk, nbytes);
402 	}
403 
404 	if (walk.nbytes) {
405 		ctr_crypt_final(desc, &walk);
406 		err = blkcipher_walk_done(desc, &walk, 0);
407 	}
408 
409 	return err;
410 }
411 
412 static struct crypto_alg blk_ctr_alg = {
413 	.cra_name		= "ctr(twofish)",
414 	.cra_driver_name	= "ctr-twofish-3way",
415 	.cra_priority		= 300,
416 	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
417 	.cra_blocksize		= 1,
418 	.cra_ctxsize		= sizeof(struct twofish_ctx),
419 	.cra_alignmask		= 0,
420 	.cra_type		= &crypto_blkcipher_type,
421 	.cra_module		= THIS_MODULE,
422 	.cra_list		= LIST_HEAD_INIT(blk_ctr_alg.cra_list),
423 	.cra_u = {
424 		.blkcipher = {
425 			.min_keysize	= TF_MIN_KEY_SIZE,
426 			.max_keysize	= TF_MAX_KEY_SIZE,
427 			.ivsize		= TF_BLOCK_SIZE,
428 			.setkey		= twofish_setkey,
429 			.encrypt	= ctr_crypt,
430 			.decrypt	= ctr_crypt,
431 		},
432 	},
433 };
434 
435 int __init init(void)
436 {
437 	int err;
438 
439 	err = crypto_register_alg(&blk_ecb_alg);
440 	if (err)
441 		goto ecb_err;
442 	err = crypto_register_alg(&blk_cbc_alg);
443 	if (err)
444 		goto cbc_err;
445 	err = crypto_register_alg(&blk_ctr_alg);
446 	if (err)
447 		goto ctr_err;
448 
449 	return 0;
450 
451 ctr_err:
452 	crypto_unregister_alg(&blk_cbc_alg);
453 cbc_err:
454 	crypto_unregister_alg(&blk_ecb_alg);
455 ecb_err:
456 	return err;
457 }
458 
459 void __exit fini(void)
460 {
461 	crypto_unregister_alg(&blk_ctr_alg);
462 	crypto_unregister_alg(&blk_cbc_alg);
463 	crypto_unregister_alg(&blk_ecb_alg);
464 }
465 
466 module_init(init);
467 module_exit(fini);
468 
469 MODULE_LICENSE("GPL");
470 MODULE_DESCRIPTION("Twofish Cipher Algorithm, 3-way parallel asm optimized");
471 MODULE_ALIAS("twofish");
472 MODULE_ALIAS("twofish-asm");
473