]> git.karo-electronics.de Git - karo-tx-linux.git/blob - arch/x86/crypto/serpent_sse2_glue.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac
[karo-tx-linux.git] / arch / x86 / crypto / serpent_sse2_glue.c
1 /*
2  * Glue Code for SSE2 assembler versions of Serpent Cipher
3  *
4  * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
5  *
6  * Glue code based on aesni-intel_glue.c by:
7  *  Copyright (C) 2008, Intel Corp.
8  *    Author: Huang Ying <ying.huang@intel.com>
9  *
10  * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
11  *   Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
12  * CTR part based on code (crypto/ctr.c) by:
13  *   (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
14  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
28  * USA
29  *
30  */
31
32 #include <linux/module.h>
33 #include <linux/hardirq.h>
34 #include <linux/types.h>
35 #include <linux/crypto.h>
36 #include <linux/err.h>
37 #include <crypto/algapi.h>
38 #include <crypto/serpent.h>
39 #include <crypto/cryptd.h>
40 #include <crypto/b128ops.h>
41 #include <crypto/ctr.h>
42 #include <crypto/lrw.h>
43 #include <crypto/xts.h>
44 #include <asm/i387.h>
45 #include <asm/serpent.h>
46 #include <crypto/scatterwalk.h>
47 #include <linux/workqueue.h>
48 #include <linux/spinlock.h>
49
50 struct async_serpent_ctx {
51         struct cryptd_ablkcipher *cryptd_tfm;
52 };
53
54 static inline bool serpent_fpu_begin(bool fpu_enabled, unsigned int nbytes)
55 {
56         if (fpu_enabled)
57                 return true;
58
59         /* SSE2 is only used when chunk to be processed is large enough, so
60          * do not enable FPU until it is necessary.
61          */
62         if (nbytes < SERPENT_BLOCK_SIZE * SERPENT_PARALLEL_BLOCKS)
63                 return false;
64
65         kernel_fpu_begin();
66         return true;
67 }
68
69 static inline void serpent_fpu_end(bool fpu_enabled)
70 {
71         if (fpu_enabled)
72                 kernel_fpu_end();
73 }
74
75 static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
76                      bool enc)
77 {
78         bool fpu_enabled = false;
79         struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
80         const unsigned int bsize = SERPENT_BLOCK_SIZE;
81         unsigned int nbytes;
82         int err;
83
84         err = blkcipher_walk_virt(desc, walk);
85         desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
86
87         while ((nbytes = walk->nbytes)) {
88                 u8 *wsrc = walk->src.virt.addr;
89                 u8 *wdst = walk->dst.virt.addr;
90
91                 fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes);
92
93                 /* Process multi-block batch */
94                 if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) {
95                         do {
96                                 if (enc)
97                                         serpent_enc_blk_xway(ctx, wdst, wsrc);
98                                 else
99                                         serpent_dec_blk_xway(ctx, wdst, wsrc);
100
101                                 wsrc += bsize * SERPENT_PARALLEL_BLOCKS;
102                                 wdst += bsize * SERPENT_PARALLEL_BLOCKS;
103                                 nbytes -= bsize * SERPENT_PARALLEL_BLOCKS;
104                         } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS);
105
106                         if (nbytes < bsize)
107                                 goto done;
108                 }
109
110                 /* Handle leftovers */
111                 do {
112                         if (enc)
113                                 __serpent_encrypt(ctx, wdst, wsrc);
114                         else
115                                 __serpent_decrypt(ctx, wdst, wsrc);
116
117                         wsrc += bsize;
118                         wdst += bsize;
119                         nbytes -= bsize;
120                 } while (nbytes >= bsize);
121
122 done:
123                 err = blkcipher_walk_done(desc, walk, nbytes);
124         }
125
126         serpent_fpu_end(fpu_enabled);
127         return err;
128 }
129
130 static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
131                        struct scatterlist *src, unsigned int nbytes)
132 {
133         struct blkcipher_walk walk;
134
135         blkcipher_walk_init(&walk, dst, src, nbytes);
136         return ecb_crypt(desc, &walk, true);
137 }
138
139 static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
140                        struct scatterlist *src, unsigned int nbytes)
141 {
142         struct blkcipher_walk walk;
143
144         blkcipher_walk_init(&walk, dst, src, nbytes);
145         return ecb_crypt(desc, &walk, false);
146 }
147
148 static unsigned int __cbc_encrypt(struct blkcipher_desc *desc,
149                                   struct blkcipher_walk *walk)
150 {
151         struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
152         const unsigned int bsize = SERPENT_BLOCK_SIZE;
153         unsigned int nbytes = walk->nbytes;
154         u128 *src = (u128 *)walk->src.virt.addr;
155         u128 *dst = (u128 *)walk->dst.virt.addr;
156         u128 *iv = (u128 *)walk->iv;
157
158         do {
159                 u128_xor(dst, src, iv);
160                 __serpent_encrypt(ctx, (u8 *)dst, (u8 *)dst);
161                 iv = dst;
162
163                 src += 1;
164                 dst += 1;
165                 nbytes -= bsize;
166         } while (nbytes >= bsize);
167
168         u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv);
169         return nbytes;
170 }
171
172 static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
173                        struct scatterlist *src, unsigned int nbytes)
174 {
175         struct blkcipher_walk walk;
176         int err;
177
178         blkcipher_walk_init(&walk, dst, src, nbytes);
179         err = blkcipher_walk_virt(desc, &walk);
180
181         while ((nbytes = walk.nbytes)) {
182                 nbytes = __cbc_encrypt(desc, &walk);
183                 err = blkcipher_walk_done(desc, &walk, nbytes);
184         }
185
186         return err;
187 }
188
189 static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
190                                   struct blkcipher_walk *walk)
191 {
192         struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
193         const unsigned int bsize = SERPENT_BLOCK_SIZE;
194         unsigned int nbytes = walk->nbytes;
195         u128 *src = (u128 *)walk->src.virt.addr;
196         u128 *dst = (u128 *)walk->dst.virt.addr;
197         u128 ivs[SERPENT_PARALLEL_BLOCKS - 1];
198         u128 last_iv;
199         int i;
200
201         /* Start of the last block. */
202         src += nbytes / bsize - 1;
203         dst += nbytes / bsize - 1;
204
205         last_iv = *src;
206
207         /* Process multi-block batch */
208         if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) {
209                 do {
210                         nbytes -= bsize * (SERPENT_PARALLEL_BLOCKS - 1);
211                         src -= SERPENT_PARALLEL_BLOCKS - 1;
212                         dst -= SERPENT_PARALLEL_BLOCKS - 1;
213
214                         for (i = 0; i < SERPENT_PARALLEL_BLOCKS - 1; i++)
215                                 ivs[i] = src[i];
216
217                         serpent_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src);
218
219                         for (i = 0; i < SERPENT_PARALLEL_BLOCKS - 1; i++)
220                                 u128_xor(dst + (i + 1), dst + (i + 1), ivs + i);
221
222                         nbytes -= bsize;
223                         if (nbytes < bsize)
224                                 goto done;
225
226                         u128_xor(dst, dst, src - 1);
227                         src -= 1;
228                         dst -= 1;
229                 } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS);
230
231                 if (nbytes < bsize)
232                         goto done;
233         }
234
235         /* Handle leftovers */
236         for (;;) {
237                 __serpent_decrypt(ctx, (u8 *)dst, (u8 *)src);
238
239                 nbytes -= bsize;
240                 if (nbytes < bsize)
241                         break;
242
243                 u128_xor(dst, dst, src - 1);
244                 src -= 1;
245                 dst -= 1;
246         }
247
248 done:
249         u128_xor(dst, dst, (u128 *)walk->iv);
250         *(u128 *)walk->iv = last_iv;
251
252         return nbytes;
253 }
254
255 static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
256                        struct scatterlist *src, unsigned int nbytes)
257 {
258         bool fpu_enabled = false;
259         struct blkcipher_walk walk;
260         int err;
261
262         blkcipher_walk_init(&walk, dst, src, nbytes);
263         err = blkcipher_walk_virt(desc, &walk);
264         desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
265
266         while ((nbytes = walk.nbytes)) {
267                 fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes);
268                 nbytes = __cbc_decrypt(desc, &walk);
269                 err = blkcipher_walk_done(desc, &walk, nbytes);
270         }
271
272         serpent_fpu_end(fpu_enabled);
273         return err;
274 }
275
276 static inline void u128_to_be128(be128 *dst, const u128 *src)
277 {
278         dst->a = cpu_to_be64(src->a);
279         dst->b = cpu_to_be64(src->b);
280 }
281
282 static inline void be128_to_u128(u128 *dst, const be128 *src)
283 {
284         dst->a = be64_to_cpu(src->a);
285         dst->b = be64_to_cpu(src->b);
286 }
287
288 static inline void u128_inc(u128 *i)
289 {
290         i->b++;
291         if (!i->b)
292                 i->a++;
293 }
294
295 static void ctr_crypt_final(struct blkcipher_desc *desc,
296                             struct blkcipher_walk *walk)
297 {
298         struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
299         u8 *ctrblk = walk->iv;
300         u8 keystream[SERPENT_BLOCK_SIZE];
301         u8 *src = walk->src.virt.addr;
302         u8 *dst = walk->dst.virt.addr;
303         unsigned int nbytes = walk->nbytes;
304
305         __serpent_encrypt(ctx, keystream, ctrblk);
306         crypto_xor(keystream, src, nbytes);
307         memcpy(dst, keystream, nbytes);
308
309         crypto_inc(ctrblk, SERPENT_BLOCK_SIZE);
310 }
311
312 static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
313                                 struct blkcipher_walk *walk)
314 {
315         struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
316         const unsigned int bsize = SERPENT_BLOCK_SIZE;
317         unsigned int nbytes = walk->nbytes;
318         u128 *src = (u128 *)walk->src.virt.addr;
319         u128 *dst = (u128 *)walk->dst.virt.addr;
320         u128 ctrblk;
321         be128 ctrblocks[SERPENT_PARALLEL_BLOCKS];
322         int i;
323
324         be128_to_u128(&ctrblk, (be128 *)walk->iv);
325
326         /* Process multi-block batch */
327         if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) {
328                 do {
329                         /* create ctrblks for parallel encrypt */
330                         for (i = 0; i < SERPENT_PARALLEL_BLOCKS; i++) {
331                                 if (dst != src)
332                                         dst[i] = src[i];
333
334                                 u128_to_be128(&ctrblocks[i], &ctrblk);
335                                 u128_inc(&ctrblk);
336                         }
337
338                         serpent_enc_blk_xway_xor(ctx, (u8 *)dst,
339                                                  (u8 *)ctrblocks);
340
341                         src += SERPENT_PARALLEL_BLOCKS;
342                         dst += SERPENT_PARALLEL_BLOCKS;
343                         nbytes -= bsize * SERPENT_PARALLEL_BLOCKS;
344                 } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS);
345
346                 if (nbytes < bsize)
347                         goto done;
348         }
349
350         /* Handle leftovers */
351         do {
352                 if (dst != src)
353                         *dst = *src;
354
355                 u128_to_be128(&ctrblocks[0], &ctrblk);
356                 u128_inc(&ctrblk);
357
358                 __serpent_encrypt(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks);
359                 u128_xor(dst, dst, (u128 *)ctrblocks);
360
361                 src += 1;
362                 dst += 1;
363                 nbytes -= bsize;
364         } while (nbytes >= bsize);
365
366 done:
367         u128_to_be128((be128 *)walk->iv, &ctrblk);
368         return nbytes;
369 }
370
371 static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
372                      struct scatterlist *src, unsigned int nbytes)
373 {
374         bool fpu_enabled = false;
375         struct blkcipher_walk walk;
376         int err;
377
378         blkcipher_walk_init(&walk, dst, src, nbytes);
379         err = blkcipher_walk_virt_block(desc, &walk, SERPENT_BLOCK_SIZE);
380         desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
381
382         while ((nbytes = walk.nbytes) >= SERPENT_BLOCK_SIZE) {
383                 fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes);
384                 nbytes = __ctr_crypt(desc, &walk);
385                 err = blkcipher_walk_done(desc, &walk, nbytes);
386         }
387
388         serpent_fpu_end(fpu_enabled);
389
390         if (walk.nbytes) {
391                 ctr_crypt_final(desc, &walk);
392                 err = blkcipher_walk_done(desc, &walk, 0);
393         }
394
395         return err;
396 }
397
398 struct crypt_priv {
399         struct serpent_ctx *ctx;
400         bool fpu_enabled;
401 };
402
403 static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
404 {
405         const unsigned int bsize = SERPENT_BLOCK_SIZE;
406         struct crypt_priv *ctx = priv;
407         int i;
408
409         ctx->fpu_enabled = serpent_fpu_begin(ctx->fpu_enabled, nbytes);
410
411         if (nbytes == bsize * SERPENT_PARALLEL_BLOCKS) {
412                 serpent_enc_blk_xway(ctx->ctx, srcdst, srcdst);
413                 return;
414         }
415
416         for (i = 0; i < nbytes / bsize; i++, srcdst += bsize)
417                 __serpent_encrypt(ctx->ctx, srcdst, srcdst);
418 }
419
420 static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
421 {
422         const unsigned int bsize = SERPENT_BLOCK_SIZE;
423         struct crypt_priv *ctx = priv;
424         int i;
425
426         ctx->fpu_enabled = serpent_fpu_begin(ctx->fpu_enabled, nbytes);
427
428         if (nbytes == bsize * SERPENT_PARALLEL_BLOCKS) {
429                 serpent_dec_blk_xway(ctx->ctx, srcdst, srcdst);
430                 return;
431         }
432
433         for (i = 0; i < nbytes / bsize; i++, srcdst += bsize)
434                 __serpent_decrypt(ctx->ctx, srcdst, srcdst);
435 }
436
437 struct serpent_lrw_ctx {
438         struct lrw_table_ctx lrw_table;
439         struct serpent_ctx serpent_ctx;
440 };
441
442 static int lrw_serpent_setkey(struct crypto_tfm *tfm, const u8 *key,
443                               unsigned int keylen)
444 {
445         struct serpent_lrw_ctx *ctx = crypto_tfm_ctx(tfm);
446         int err;
447
448         err = __serpent_setkey(&ctx->serpent_ctx, key, keylen -
449                                                         SERPENT_BLOCK_SIZE);
450         if (err)
451                 return err;
452
453         return lrw_init_table(&ctx->lrw_table, key + keylen -
454                                                 SERPENT_BLOCK_SIZE);
455 }
456
457 static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
458                        struct scatterlist *src, unsigned int nbytes)
459 {
460         struct serpent_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
461         be128 buf[SERPENT_PARALLEL_BLOCKS];
462         struct crypt_priv crypt_ctx = {
463                 .ctx = &ctx->serpent_ctx,
464                 .fpu_enabled = false,
465         };
466         struct lrw_crypt_req req = {
467                 .tbuf = buf,
468                 .tbuflen = sizeof(buf),
469
470                 .table_ctx = &ctx->lrw_table,
471                 .crypt_ctx = &crypt_ctx,
472                 .crypt_fn = encrypt_callback,
473         };
474         int ret;
475
476         desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
477         ret = lrw_crypt(desc, dst, src, nbytes, &req);
478         serpent_fpu_end(crypt_ctx.fpu_enabled);
479
480         return ret;
481 }
482
483 static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
484                        struct scatterlist *src, unsigned int nbytes)
485 {
486         struct serpent_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
487         be128 buf[SERPENT_PARALLEL_BLOCKS];
488         struct crypt_priv crypt_ctx = {
489                 .ctx = &ctx->serpent_ctx,
490                 .fpu_enabled = false,
491         };
492         struct lrw_crypt_req req = {
493                 .tbuf = buf,
494                 .tbuflen = sizeof(buf),
495
496                 .table_ctx = &ctx->lrw_table,
497                 .crypt_ctx = &crypt_ctx,
498                 .crypt_fn = decrypt_callback,
499         };
500         int ret;
501
502         desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
503         ret = lrw_crypt(desc, dst, src, nbytes, &req);
504         serpent_fpu_end(crypt_ctx.fpu_enabled);
505
506         return ret;
507 }
508
509 static void lrw_exit_tfm(struct crypto_tfm *tfm)
510 {
511         struct serpent_lrw_ctx *ctx = crypto_tfm_ctx(tfm);
512
513         lrw_free_table(&ctx->lrw_table);
514 }
515
516 struct serpent_xts_ctx {
517         struct serpent_ctx tweak_ctx;
518         struct serpent_ctx crypt_ctx;
519 };
520
521 static int xts_serpent_setkey(struct crypto_tfm *tfm, const u8 *key,
522                               unsigned int keylen)
523 {
524         struct serpent_xts_ctx *ctx = crypto_tfm_ctx(tfm);
525         u32 *flags = &tfm->crt_flags;
526         int err;
527
528         /* key consists of keys of equal size concatenated, therefore
529          * the length must be even
530          */
531         if (keylen % 2) {
532                 *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
533                 return -EINVAL;
534         }
535
536         /* first half of xts-key is for crypt */
537         err = __serpent_setkey(&ctx->crypt_ctx, key, keylen / 2);
538         if (err)
539                 return err;
540
541         /* second half of xts-key is for tweak */
542         return __serpent_setkey(&ctx->tweak_ctx, key + keylen / 2, keylen / 2);
543 }
544
545 static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
546                        struct scatterlist *src, unsigned int nbytes)
547 {
548         struct serpent_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
549         be128 buf[SERPENT_PARALLEL_BLOCKS];
550         struct crypt_priv crypt_ctx = {
551                 .ctx = &ctx->crypt_ctx,
552                 .fpu_enabled = false,
553         };
554         struct xts_crypt_req req = {
555                 .tbuf = buf,
556                 .tbuflen = sizeof(buf),
557
558                 .tweak_ctx = &ctx->tweak_ctx,
559                 .tweak_fn = XTS_TWEAK_CAST(__serpent_encrypt),
560                 .crypt_ctx = &crypt_ctx,
561                 .crypt_fn = encrypt_callback,
562         };
563         int ret;
564
565         desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
566         ret = xts_crypt(desc, dst, src, nbytes, &req);
567         serpent_fpu_end(crypt_ctx.fpu_enabled);
568
569         return ret;
570 }
571
572 static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
573                        struct scatterlist *src, unsigned int nbytes)
574 {
575         struct serpent_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
576         be128 buf[SERPENT_PARALLEL_BLOCKS];
577         struct crypt_priv crypt_ctx = {
578                 .ctx = &ctx->crypt_ctx,
579                 .fpu_enabled = false,
580         };
581         struct xts_crypt_req req = {
582                 .tbuf = buf,
583                 .tbuflen = sizeof(buf),
584
585                 .tweak_ctx = &ctx->tweak_ctx,
586                 .tweak_fn = XTS_TWEAK_CAST(__serpent_encrypt),
587                 .crypt_ctx = &crypt_ctx,
588                 .crypt_fn = decrypt_callback,
589         };
590         int ret;
591
592         desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
593         ret = xts_crypt(desc, dst, src, nbytes, &req);
594         serpent_fpu_end(crypt_ctx.fpu_enabled);
595
596         return ret;
597 }
598
599 static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key,
600                         unsigned int key_len)
601 {
602         struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm);
603         struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base;
604         int err;
605
606         crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
607         crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm)
608                                     & CRYPTO_TFM_REQ_MASK);
609         err = crypto_ablkcipher_setkey(child, key, key_len);
610         crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child)
611                                     & CRYPTO_TFM_RES_MASK);
612         return err;
613 }
614
615 static int __ablk_encrypt(struct ablkcipher_request *req)
616 {
617         struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
618         struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm);
619         struct blkcipher_desc desc;
620
621         desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm);
622         desc.info = req->info;
623         desc.flags = 0;
624
625         return crypto_blkcipher_crt(desc.tfm)->encrypt(
626                 &desc, req->dst, req->src, req->nbytes);
627 }
628
629 static int ablk_encrypt(struct ablkcipher_request *req)
630 {
631         struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
632         struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm);
633
634         if (!irq_fpu_usable()) {
635                 struct ablkcipher_request *cryptd_req =
636                         ablkcipher_request_ctx(req);
637
638                 memcpy(cryptd_req, req, sizeof(*req));
639                 ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
640
641                 return crypto_ablkcipher_encrypt(cryptd_req);
642         } else {
643                 return __ablk_encrypt(req);
644         }
645 }
646
647 static int ablk_decrypt(struct ablkcipher_request *req)
648 {
649         struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
650         struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm);
651
652         if (!irq_fpu_usable()) {
653                 struct ablkcipher_request *cryptd_req =
654                         ablkcipher_request_ctx(req);
655
656                 memcpy(cryptd_req, req, sizeof(*req));
657                 ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
658
659                 return crypto_ablkcipher_decrypt(cryptd_req);
660         } else {
661                 struct blkcipher_desc desc;
662
663                 desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm);
664                 desc.info = req->info;
665                 desc.flags = 0;
666
667                 return crypto_blkcipher_crt(desc.tfm)->decrypt(
668                         &desc, req->dst, req->src, req->nbytes);
669         }
670 }
671
672 static void ablk_exit(struct crypto_tfm *tfm)
673 {
674         struct async_serpent_ctx *ctx = crypto_tfm_ctx(tfm);
675
676         cryptd_free_ablkcipher(ctx->cryptd_tfm);
677 }
678
679 static int ablk_init(struct crypto_tfm *tfm)
680 {
681         struct async_serpent_ctx *ctx = crypto_tfm_ctx(tfm);
682         struct cryptd_ablkcipher *cryptd_tfm;
683         char drv_name[CRYPTO_MAX_ALG_NAME];
684
685         snprintf(drv_name, sizeof(drv_name), "__driver-%s",
686                                         crypto_tfm_alg_driver_name(tfm));
687
688         cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, 0, 0);
689         if (IS_ERR(cryptd_tfm))
690                 return PTR_ERR(cryptd_tfm);
691
692         ctx->cryptd_tfm = cryptd_tfm;
693         tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) +
694                 crypto_ablkcipher_reqsize(&cryptd_tfm->base);
695
696         return 0;
697 }
698
699 static struct crypto_alg serpent_algs[10] = { {
700         .cra_name               = "__ecb-serpent-sse2",
701         .cra_driver_name        = "__driver-ecb-serpent-sse2",
702         .cra_priority           = 0,
703         .cra_flags              = CRYPTO_ALG_TYPE_BLKCIPHER,
704         .cra_blocksize          = SERPENT_BLOCK_SIZE,
705         .cra_ctxsize            = sizeof(struct serpent_ctx),
706         .cra_alignmask          = 0,
707         .cra_type               = &crypto_blkcipher_type,
708         .cra_module             = THIS_MODULE,
709         .cra_list               = LIST_HEAD_INIT(serpent_algs[0].cra_list),
710         .cra_u = {
711                 .blkcipher = {
712                         .min_keysize    = SERPENT_MIN_KEY_SIZE,
713                         .max_keysize    = SERPENT_MAX_KEY_SIZE,
714                         .setkey         = serpent_setkey,
715                         .encrypt        = ecb_encrypt,
716                         .decrypt        = ecb_decrypt,
717                 },
718         },
719 }, {
720         .cra_name               = "__cbc-serpent-sse2",
721         .cra_driver_name        = "__driver-cbc-serpent-sse2",
722         .cra_priority           = 0,
723         .cra_flags              = CRYPTO_ALG_TYPE_BLKCIPHER,
724         .cra_blocksize          = SERPENT_BLOCK_SIZE,
725         .cra_ctxsize            = sizeof(struct serpent_ctx),
726         .cra_alignmask          = 0,
727         .cra_type               = &crypto_blkcipher_type,
728         .cra_module             = THIS_MODULE,
729         .cra_list               = LIST_HEAD_INIT(serpent_algs[1].cra_list),
730         .cra_u = {
731                 .blkcipher = {
732                         .min_keysize    = SERPENT_MIN_KEY_SIZE,
733                         .max_keysize    = SERPENT_MAX_KEY_SIZE,
734                         .setkey         = serpent_setkey,
735                         .encrypt        = cbc_encrypt,
736                         .decrypt        = cbc_decrypt,
737                 },
738         },
739 }, {
740         .cra_name               = "__ctr-serpent-sse2",
741         .cra_driver_name        = "__driver-ctr-serpent-sse2",
742         .cra_priority           = 0,
743         .cra_flags              = CRYPTO_ALG_TYPE_BLKCIPHER,
744         .cra_blocksize          = 1,
745         .cra_ctxsize            = sizeof(struct serpent_ctx),
746         .cra_alignmask          = 0,
747         .cra_type               = &crypto_blkcipher_type,
748         .cra_module             = THIS_MODULE,
749         .cra_list               = LIST_HEAD_INIT(serpent_algs[2].cra_list),
750         .cra_u = {
751                 .blkcipher = {
752                         .min_keysize    = SERPENT_MIN_KEY_SIZE,
753                         .max_keysize    = SERPENT_MAX_KEY_SIZE,
754                         .ivsize         = SERPENT_BLOCK_SIZE,
755                         .setkey         = serpent_setkey,
756                         .encrypt        = ctr_crypt,
757                         .decrypt        = ctr_crypt,
758                 },
759         },
760 }, {
761         .cra_name               = "__lrw-serpent-sse2",
762         .cra_driver_name        = "__driver-lrw-serpent-sse2",
763         .cra_priority           = 0,
764         .cra_flags              = CRYPTO_ALG_TYPE_BLKCIPHER,
765         .cra_blocksize          = SERPENT_BLOCK_SIZE,
766         .cra_ctxsize            = sizeof(struct serpent_lrw_ctx),
767         .cra_alignmask          = 0,
768         .cra_type               = &crypto_blkcipher_type,
769         .cra_module             = THIS_MODULE,
770         .cra_list               = LIST_HEAD_INIT(serpent_algs[3].cra_list),
771         .cra_exit               = lrw_exit_tfm,
772         .cra_u = {
773                 .blkcipher = {
774                         .min_keysize    = SERPENT_MIN_KEY_SIZE +
775                                           SERPENT_BLOCK_SIZE,
776                         .max_keysize    = SERPENT_MAX_KEY_SIZE +
777                                           SERPENT_BLOCK_SIZE,
778                         .ivsize         = SERPENT_BLOCK_SIZE,
779                         .setkey         = lrw_serpent_setkey,
780                         .encrypt        = lrw_encrypt,
781                         .decrypt        = lrw_decrypt,
782                 },
783         },
784 }, {
785         .cra_name               = "__xts-serpent-sse2",
786         .cra_driver_name        = "__driver-xts-serpent-sse2",
787         .cra_priority           = 0,
788         .cra_flags              = CRYPTO_ALG_TYPE_BLKCIPHER,
789         .cra_blocksize          = SERPENT_BLOCK_SIZE,
790         .cra_ctxsize            = sizeof(struct serpent_xts_ctx),
791         .cra_alignmask          = 0,
792         .cra_type               = &crypto_blkcipher_type,
793         .cra_module             = THIS_MODULE,
794         .cra_list               = LIST_HEAD_INIT(serpent_algs[4].cra_list),
795         .cra_u = {
796                 .blkcipher = {
797                         .min_keysize    = SERPENT_MIN_KEY_SIZE * 2,
798                         .max_keysize    = SERPENT_MAX_KEY_SIZE * 2,
799                         .ivsize         = SERPENT_BLOCK_SIZE,
800                         .setkey         = xts_serpent_setkey,
801                         .encrypt        = xts_encrypt,
802                         .decrypt        = xts_decrypt,
803                 },
804         },
805 }, {
806         .cra_name               = "ecb(serpent)",
807         .cra_driver_name        = "ecb-serpent-sse2",
808         .cra_priority           = 400,
809         .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
810         .cra_blocksize          = SERPENT_BLOCK_SIZE,
811         .cra_ctxsize            = sizeof(struct async_serpent_ctx),
812         .cra_alignmask          = 0,
813         .cra_type               = &crypto_ablkcipher_type,
814         .cra_module             = THIS_MODULE,
815         .cra_list               = LIST_HEAD_INIT(serpent_algs[5].cra_list),
816         .cra_init               = ablk_init,
817         .cra_exit               = ablk_exit,
818         .cra_u = {
819                 .ablkcipher = {
820                         .min_keysize    = SERPENT_MIN_KEY_SIZE,
821                         .max_keysize    = SERPENT_MAX_KEY_SIZE,
822                         .setkey         = ablk_set_key,
823                         .encrypt        = ablk_encrypt,
824                         .decrypt        = ablk_decrypt,
825                 },
826         },
827 }, {
828         .cra_name               = "cbc(serpent)",
829         .cra_driver_name        = "cbc-serpent-sse2",
830         .cra_priority           = 400,
831         .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
832         .cra_blocksize          = SERPENT_BLOCK_SIZE,
833         .cra_ctxsize            = sizeof(struct async_serpent_ctx),
834         .cra_alignmask          = 0,
835         .cra_type               = &crypto_ablkcipher_type,
836         .cra_module             = THIS_MODULE,
837         .cra_list               = LIST_HEAD_INIT(serpent_algs[6].cra_list),
838         .cra_init               = ablk_init,
839         .cra_exit               = ablk_exit,
840         .cra_u = {
841                 .ablkcipher = {
842                         .min_keysize    = SERPENT_MIN_KEY_SIZE,
843                         .max_keysize    = SERPENT_MAX_KEY_SIZE,
844                         .ivsize         = SERPENT_BLOCK_SIZE,
845                         .setkey         = ablk_set_key,
846                         .encrypt        = __ablk_encrypt,
847                         .decrypt        = ablk_decrypt,
848                 },
849         },
850 }, {
851         .cra_name               = "ctr(serpent)",
852         .cra_driver_name        = "ctr-serpent-sse2",
853         .cra_priority           = 400,
854         .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
855         .cra_blocksize          = 1,
856         .cra_ctxsize            = sizeof(struct async_serpent_ctx),
857         .cra_alignmask          = 0,
858         .cra_type               = &crypto_ablkcipher_type,
859         .cra_module             = THIS_MODULE,
860         .cra_list               = LIST_HEAD_INIT(serpent_algs[7].cra_list),
861         .cra_init               = ablk_init,
862         .cra_exit               = ablk_exit,
863         .cra_u = {
864                 .ablkcipher = {
865                         .min_keysize    = SERPENT_MIN_KEY_SIZE,
866                         .max_keysize    = SERPENT_MAX_KEY_SIZE,
867                         .ivsize         = SERPENT_BLOCK_SIZE,
868                         .setkey         = ablk_set_key,
869                         .encrypt        = ablk_encrypt,
870                         .decrypt        = ablk_encrypt,
871                         .geniv          = "chainiv",
872                 },
873         },
874 }, {
875         .cra_name               = "lrw(serpent)",
876         .cra_driver_name        = "lrw-serpent-sse2",
877         .cra_priority           = 400,
878         .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
879         .cra_blocksize          = SERPENT_BLOCK_SIZE,
880         .cra_ctxsize            = sizeof(struct async_serpent_ctx),
881         .cra_alignmask          = 0,
882         .cra_type               = &crypto_ablkcipher_type,
883         .cra_module             = THIS_MODULE,
884         .cra_list               = LIST_HEAD_INIT(serpent_algs[8].cra_list),
885         .cra_init               = ablk_init,
886         .cra_exit               = ablk_exit,
887         .cra_u = {
888                 .ablkcipher = {
889                         .min_keysize    = SERPENT_MIN_KEY_SIZE +
890                                           SERPENT_BLOCK_SIZE,
891                         .max_keysize    = SERPENT_MAX_KEY_SIZE +
892                                           SERPENT_BLOCK_SIZE,
893                         .ivsize         = SERPENT_BLOCK_SIZE,
894                         .setkey         = ablk_set_key,
895                         .encrypt        = ablk_encrypt,
896                         .decrypt        = ablk_decrypt,
897                 },
898         },
899 }, {
900         .cra_name               = "xts(serpent)",
901         .cra_driver_name        = "xts-serpent-sse2",
902         .cra_priority           = 400,
903         .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
904         .cra_blocksize          = SERPENT_BLOCK_SIZE,
905         .cra_ctxsize            = sizeof(struct async_serpent_ctx),
906         .cra_alignmask          = 0,
907         .cra_type               = &crypto_ablkcipher_type,
908         .cra_module             = THIS_MODULE,
909         .cra_list               = LIST_HEAD_INIT(serpent_algs[9].cra_list),
910         .cra_init               = ablk_init,
911         .cra_exit               = ablk_exit,
912         .cra_u = {
913                 .ablkcipher = {
914                         .min_keysize    = SERPENT_MIN_KEY_SIZE * 2,
915                         .max_keysize    = SERPENT_MAX_KEY_SIZE * 2,
916                         .ivsize         = SERPENT_BLOCK_SIZE,
917                         .setkey         = ablk_set_key,
918                         .encrypt        = ablk_encrypt,
919                         .decrypt        = ablk_decrypt,
920                 },
921         },
922 } };
923
924 static int __init serpent_sse2_init(void)
925 {
926         if (!cpu_has_xmm2) {
927                 printk(KERN_INFO "SSE2 instructions are not detected.\n");
928                 return -ENODEV;
929         }
930
931         return crypto_register_algs(serpent_algs, ARRAY_SIZE(serpent_algs));
932 }
933
934 static void __exit serpent_sse2_exit(void)
935 {
936         crypto_unregister_algs(serpent_algs, ARRAY_SIZE(serpent_algs));
937 }
938
939 module_init(serpent_sse2_init);
940 module_exit(serpent_sse2_exit);
941
942 MODULE_DESCRIPTION("Serpent Cipher Algorithm, SSE2 optimized");
943 MODULE_LICENSE("GPL");
944 MODULE_ALIAS("serpent");