aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/lrw.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2011-11-08 22:50:31 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2011-11-08 22:50:31 -0500
commit6c2205b8ffec035f4925b8ee84b7758afeee58b5 (patch)
tree85c202ee4056deaaddfee2c532eeabe44c02551d /crypto/lrw.c
parent171c02048f50d7187991f251ddeed2d7e5de104f (diff)
crypto: lrw - add interface for parallelized cipher implementions
Export gf128mul table initialization routines and add lrw_crypt() function that can be used by cipher implementations that can benefit from parallelized cipher operations. Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/lrw.c')
-rw-r--r--crypto/lrw.c106
1 files changed, 86 insertions, 20 deletions
diff --git a/crypto/lrw.c b/crypto/lrw.c
index 91c17fa18374..ba42acc4deba 100644
--- a/crypto/lrw.c
+++ b/crypto/lrw.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright (c) 2006 Rik Snel <rsnel@cube.dyndns.org> 4 * Copyright (c) 2006 Rik Snel <rsnel@cube.dyndns.org>
5 * 5 *
6 * Based om ecb.c 6 * Based on ecb.c
7 * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> 7 * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify it 9 * This program is free software; you can redistribute it and/or modify it
@@ -16,6 +16,7 @@
16 * http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html 16 * http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html
17 * 17 *
18 * The test vectors are included in the testing module tcrypt.[ch] */ 18 * The test vectors are included in the testing module tcrypt.[ch] */
19
19#include <crypto/algapi.h> 20#include <crypto/algapi.h>
20#include <linux/err.h> 21#include <linux/err.h>
21#include <linux/init.h> 22#include <linux/init.h>
@@ -26,23 +27,7 @@
26 27
27#include <crypto/b128ops.h> 28#include <crypto/b128ops.h>
28#include <crypto/gf128mul.h> 29#include <crypto/gf128mul.h>
29 30#include <crypto/lrw.h>
30#define LRW_BLOCK_SIZE 16
31
32struct lrw_table_ctx {
33 /* optimizes multiplying a random (non incrementing, as at the
34 * start of a new sector) value with key2, we could also have
35 * used 4k optimization tables or no optimization at all. In the
36 * latter case we would have to store key2 here */
37 struct gf128mul_64k *table;
38 /* stores:
39 * key2*{ 0,0,...0,0,0,0,1 }, key2*{ 0,0,...0,0,0,1,1 },
40 * key2*{ 0,0,...0,0,1,1,1 }, key2*{ 0,0,...0,1,1,1,1 }
41 * key2*{ 0,0,...1,1,1,1,1 }, etc
42 * needed for optimized multiplication of incrementing values
43 * with key2 */
44 be128 mulinc[128];
45};
46 31
47struct priv { 32struct priv {
48 struct crypto_cipher *child; 33 struct crypto_cipher *child;
@@ -60,7 +45,7 @@ static inline void setbit128_bbe(void *b, int bit)
60 ), b); 45 ), b);
61} 46}
62 47
63static int lrw_init_table(struct lrw_table_ctx *ctx, const u8 *tweak) 48int lrw_init_table(struct lrw_table_ctx *ctx, const u8 *tweak)
64{ 49{
65 be128 tmp = { 0 }; 50 be128 tmp = { 0 };
66 int i; 51 int i;
@@ -82,12 +67,14 @@ static int lrw_init_table(struct lrw_table_ctx *ctx, const u8 *tweak)
82 67
83 return 0; 68 return 0;
84} 69}
70EXPORT_SYMBOL_GPL(lrw_init_table);
85 71
86static void lrw_free_table(struct lrw_table_ctx *ctx) 72void lrw_free_table(struct lrw_table_ctx *ctx)
87{ 73{
88 if (ctx->table) 74 if (ctx->table)
89 gf128mul_free_64k(ctx->table); 75 gf128mul_free_64k(ctx->table);
90} 76}
77EXPORT_SYMBOL_GPL(lrw_free_table);
91 78
92static int setkey(struct crypto_tfm *parent, const u8 *key, 79static int setkey(struct crypto_tfm *parent, const u8 *key,
93 unsigned int keylen) 80 unsigned int keylen)
@@ -227,6 +214,85 @@ static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
227 crypto_cipher_alg(ctx->child)->cia_decrypt); 214 crypto_cipher_alg(ctx->child)->cia_decrypt);
228} 215}
229 216
217int lrw_crypt(struct blkcipher_desc *desc, struct scatterlist *sdst,
218 struct scatterlist *ssrc, unsigned int nbytes,
219 struct lrw_crypt_req *req)
220{
221 const unsigned int bsize = LRW_BLOCK_SIZE;
222 const unsigned int max_blks = req->tbuflen / bsize;
223 struct lrw_table_ctx *ctx = req->table_ctx;
224 struct blkcipher_walk walk;
225 unsigned int nblocks;
226 be128 *iv, *src, *dst, *t;
227 be128 *t_buf = req->tbuf;
228 int err, i;
229
230 BUG_ON(max_blks < 1);
231
232 blkcipher_walk_init(&walk, sdst, ssrc, nbytes);
233
234 err = blkcipher_walk_virt(desc, &walk);
235 nbytes = walk.nbytes;
236 if (!nbytes)
237 return err;
238
239 nblocks = min(walk.nbytes / bsize, max_blks);
240 src = (be128 *)walk.src.virt.addr;
241 dst = (be128 *)walk.dst.virt.addr;
242
243 /* calculate first value of T */
244 iv = (be128 *)walk.iv;
245 t_buf[0] = *iv;
246
247 /* T <- I*Key2 */
248 gf128mul_64k_bbe(&t_buf[0], ctx->table);
249
250 i = 0;
251 goto first;
252
253 for (;;) {
254 do {
255 for (i = 0; i < nblocks; i++) {
256 /* T <- I*Key2, using the optimization
257 * discussed in the specification */
258 be128_xor(&t_buf[i], t,
259 &ctx->mulinc[get_index128(iv)]);
260 inc(iv);
261first:
262 t = &t_buf[i];
263
264 /* PP <- T xor P */
265 be128_xor(dst + i, t, src + i);
266 }
267
268 /* CC <- E(Key2,PP) */
269 req->crypt_fn(req->crypt_ctx, (u8 *)dst,
270 nblocks * bsize);
271
272 /* C <- T xor CC */
273 for (i = 0; i < nblocks; i++)
274 be128_xor(dst + i, dst + i, &t_buf[i]);
275
276 src += nblocks;
277 dst += nblocks;
278 nbytes -= nblocks * bsize;
279 nblocks = min(nbytes / bsize, max_blks);
280 } while (nblocks > 0);
281
282 err = blkcipher_walk_done(desc, &walk, nbytes);
283 nbytes = walk.nbytes;
284 if (!nbytes)
285 break;
286
287 nblocks = min(nbytes / bsize, max_blks);
288 src = (be128 *)walk.src.virt.addr;
289 dst = (be128 *)walk.dst.virt.addr;
290 }
291
292 return err;
293}
294EXPORT_SYMBOL_GPL(lrw_crypt);
295
230static int init_tfm(struct crypto_tfm *tfm) 296static int init_tfm(struct crypto_tfm *tfm)
231{ 297{
232 struct crypto_cipher *cipher; 298 struct crypto_cipher *cipher;