Blame view

crypto/lrw.c 10.7 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
2
3
4
5
6
  /* LRW: as defined by Cyril Guyot in
   *	http://grouper.ieee.org/groups/1619/email/pdf00017.pdf
   *
   * Copyright (c) 2006 Rik Snel <rsnel@cube.dyndns.org>
   *
6c2205b8f   Jussi Kivilinna   crypto: lrw - add...
7
   * Based on ecb.c
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
8
   * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
9
10
11
12
13
14
   */
  /* This implementation is checked against the test vectors in the above
   * document and by a test vector provided by Ken Buchanan at
   * http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html
   *
   * The test vectors are included in the testing module tcrypt.[ch] */
6c2205b8f   Jussi Kivilinna   crypto: lrw - add...
15

700cb3f5f   Herbert Xu   crypto: lrw - Con...
16
17
  #include <crypto/internal/skcipher.h>
  #include <crypto/scatterwalk.h>
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
18
19
20
21
22
23
24
25
26
  #include <linux/err.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/scatterlist.h>
  #include <linux/slab.h>
  
  #include <crypto/b128ops.h>
  #include <crypto/gf128mul.h>
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
27

217afccf6   Eric Biggers   crypto: lrw - rem...
28
  #define LRW_BLOCK_SIZE 16
171c02048   Jussi Kivilinna   crypto: lrw - spl...
29
  struct priv {
700cb3f5f   Herbert Xu   crypto: lrw - Con...
30
  	struct crypto_skcipher *child;
217afccf6   Eric Biggers   crypto: lrw - rem...
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  
  	/*
  	 * optimizes multiplying a random (non incrementing, as at the
  	 * start of a new sector) value with key2, we could also have
  	 * used 4k optimization tables or no optimization at all. In the
  	 * latter case we would have to store key2 here
  	 */
  	struct gf128mul_64k *table;
  
  	/*
  	 * stores:
  	 *  key2*{ 0,0,...0,0,0,0,1 }, key2*{ 0,0,...0,0,0,1,1 },
  	 *  key2*{ 0,0,...0,0,1,1,1 }, key2*{ 0,0,...0,1,1,1,1 }
  	 *  key2*{ 0,0,...1,1,1,1,1 }, etc
  	 * needed for optimized multiplication of incrementing values
  	 * with key2
  	 */
  	be128 mulinc[128];
171c02048   Jussi Kivilinna   crypto: lrw - spl...
49
  };
700cb3f5f   Herbert Xu   crypto: lrw - Con...
50
  struct rctx {
700cb3f5f   Herbert Xu   crypto: lrw - Con...
51
  	be128 t;
700cb3f5f   Herbert Xu   crypto: lrw - Con...
52
53
  	struct skcipher_request subreq;
  };
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
54
55
  static inline void setbit128_bbe(void *b, int bit)
  {
8eb2dfac4   Herbert Xu   crypto: lrw - Fix...
56
57
58
59
60
61
62
  	__set_bit(bit ^ (0x80 -
  #ifdef __BIG_ENDIAN
  			 BITS_PER_LONG
  #else
  			 BITS_PER_BYTE
  #endif
  			), b);
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
63
  }
217afccf6   Eric Biggers   crypto: lrw - rem...
64
65
  static int setkey(struct crypto_skcipher *parent, const u8 *key,
  		  unsigned int keylen)
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
66
  {
217afccf6   Eric Biggers   crypto: lrw - rem...
67
68
69
70
  	struct priv *ctx = crypto_skcipher_ctx(parent);
  	struct crypto_skcipher *child = ctx->child;
  	int err, bsize = LRW_BLOCK_SIZE;
  	const u8 *tweak = key + keylen - bsize;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
71
  	be128 tmp = { 0 };
171c02048   Jussi Kivilinna   crypto: lrw - spl...
72
  	int i;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
73

217afccf6   Eric Biggers   crypto: lrw - rem...
74
75
76
77
78
79
80
81
  	crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
  	crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(parent) &
  					 CRYPTO_TFM_REQ_MASK);
  	err = crypto_skcipher_setkey(child, key, keylen - bsize);
  	crypto_skcipher_set_flags(parent, crypto_skcipher_get_flags(child) &
  					  CRYPTO_TFM_RES_MASK);
  	if (err)
  		return err;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
82
83
84
85
  	if (ctx->table)
  		gf128mul_free_64k(ctx->table);
  
  	/* initialize multiplication table for Key2 */
171c02048   Jussi Kivilinna   crypto: lrw - spl...
86
  	ctx->table = gf128mul_init_64k_bbe((be128 *)tweak);
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
87
88
89
90
91
92
93
94
95
96
97
98
  	if (!ctx->table)
  		return -ENOMEM;
  
  	/* initialize optimization table */
  	for (i = 0; i < 128; i++) {
  		setbit128_bbe(&tmp, i);
  		ctx->mulinc[i] = tmp;
  		gf128mul_64k_bbe(&ctx->mulinc[i], ctx->table);
  	}
  
  	return 0;
  }
171c02048   Jussi Kivilinna   crypto: lrw - spl...
99

c778f96bf   Ondrej Mosnacek   crypto: lrw - Opt...
100
101
102
103
104
105
106
107
108
109
110
111
  /*
   * Returns the number of trailing '1' bits in the words of the counter, which is
   * represented by 4 32-bit words, arranged from least to most significant.
   * At the same time, increments the counter by one.
   *
   * For example:
   *
   * u32 counter[4] = { 0xFFFFFFFF, 0x1, 0x0, 0x0 };
   * int i = next_index(&counter);
   * // i == 33, counter == { 0x0, 0x2, 0x0, 0x0 }
   */
  static int next_index(u32 *counter)
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
112
  {
c778f96bf   Ondrej Mosnacek   crypto: lrw - Opt...
113
  	int i, res = 0;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
114

c778f96bf   Ondrej Mosnacek   crypto: lrw - Opt...
115
  	for (i = 0; i < 4; i++) {
fd27b571c   Ard Biesheuvel   crypto: lrw - fix...
116
117
  		if (counter[i] + 1 != 0)
  			return res + ffz(counter[i]++);
c778f96bf   Ondrej Mosnacek   crypto: lrw - Opt...
118
119
  		counter[i] = 0;
  		res += 32;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
120
  	}
fbe1a850b   Ondrej Mosnacek   crypto: lrw - Fix...
121
122
123
124
125
126
  	/*
  	 * If we get here, then x == 128 and we are incrementing the counter
  	 * from all ones to all zeros. This means we must return index 127, i.e.
  	 * the one corresponding to key2*{ 1,...,1 }.
  	 */
  	return 127;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
127
  }
ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
128
129
130
131
132
133
134
  /*
   * We compute the tweak masks twice (both before and after the ECB encryption or
   * decryption) to avoid having to allocate a temporary buffer and/or make
   * mutliple calls to the 'ecb(..)' instance, which usually would be slower than
   * just doing the next_index() calls again.
   */
  static int xor_tweak(struct skcipher_request *req, bool second_pass)
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
135
  {
700cb3f5f   Herbert Xu   crypto: lrw - Con...
136
  	const int bs = LRW_BLOCK_SIZE;
700cb3f5f   Herbert Xu   crypto: lrw - Con...
137
  	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
700cb3f5f   Herbert Xu   crypto: lrw - Con...
138
  	struct priv *ctx = crypto_skcipher_ctx(tfm);
ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
139
140
  	struct rctx *rctx = skcipher_request_ctx(req);
  	be128 t = rctx->t;
700cb3f5f   Herbert Xu   crypto: lrw - Con...
141
  	struct skcipher_walk w;
c778f96bf   Ondrej Mosnacek   crypto: lrw - Opt...
142
143
  	__be32 *iv;
  	u32 counter[4];
700cb3f5f   Herbert Xu   crypto: lrw - Con...
144
  	int err;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
145

ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
146
147
148
149
150
  	if (second_pass) {
  		req = &rctx->subreq;
  		/* set to our TFM to enforce correct alignment: */
  		skcipher_request_set_tfm(req, tfm);
  	}
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
151

ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
152
  	err = skcipher_walk_virt(&w, req, false);
aec286cd3   Eric Biggers   crypto: lrw - don...
153
154
  	if (err)
  		return err;
c778f96bf   Ondrej Mosnacek   crypto: lrw - Opt...
155

aec286cd3   Eric Biggers   crypto: lrw - don...
156
  	iv = (__be32 *)w.iv;
c778f96bf   Ondrej Mosnacek   crypto: lrw - Opt...
157
158
159
160
  	counter[0] = be32_to_cpu(iv[3]);
  	counter[1] = be32_to_cpu(iv[2]);
  	counter[2] = be32_to_cpu(iv[1]);
  	counter[3] = be32_to_cpu(iv[0]);
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
161

700cb3f5f   Herbert Xu   crypto: lrw - Con...
162
163
164
165
166
167
168
  	while (w.nbytes) {
  		unsigned int avail = w.nbytes;
  		be128 *wsrc;
  		be128 *wdst;
  
  		wsrc = w.src.virt.addr;
  		wdst = w.dst.virt.addr;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
169

64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
170
  		do {
ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
171
  			be128_xor(wdst++, &t, wsrc++);
700cb3f5f   Herbert Xu   crypto: lrw - Con...
172

64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
173
174
  			/* T <- I*Key2, using the optimization
  			 * discussed in the specification */
ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
175
  			be128_xor(&t, &t, &ctx->mulinc[next_index(counter)]);
700cb3f5f   Herbert Xu   crypto: lrw - Con...
176
  		} while ((avail -= bs) >= bs);
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
177

ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
178
  		if (second_pass && w.nbytes == w.total) {
c778f96bf   Ondrej Mosnacek   crypto: lrw - Opt...
179
180
181
182
183
  			iv[0] = cpu_to_be32(counter[3]);
  			iv[1] = cpu_to_be32(counter[2]);
  			iv[2] = cpu_to_be32(counter[1]);
  			iv[3] = cpu_to_be32(counter[0]);
  		}
700cb3f5f   Herbert Xu   crypto: lrw - Con...
184
185
  		err = skcipher_walk_done(&w, avail);
  	}
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
186

700cb3f5f   Herbert Xu   crypto: lrw - Con...
187
188
  	return err;
  }
ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
189
  static int xor_tweak_pre(struct skcipher_request *req)
700cb3f5f   Herbert Xu   crypto: lrw - Con...
190
  {
ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
191
  	return xor_tweak(req, false);
700cb3f5f   Herbert Xu   crypto: lrw - Con...
192
  }
ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
193
  static int xor_tweak_post(struct skcipher_request *req)
700cb3f5f   Herbert Xu   crypto: lrw - Con...
194
  {
ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
195
  	return xor_tweak(req, true);
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
196
  }
ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
197
  static void crypt_done(struct crypto_async_request *areq, int err)
700cb3f5f   Herbert Xu   crypto: lrw - Con...
198
199
  {
  	struct skcipher_request *req = areq->data;
700cb3f5f   Herbert Xu   crypto: lrw - Con...
200

b257b48cd   Herbert Xu   crypto: lrw - Fix...
201
202
203
204
  	if (!err) {
  		struct rctx *rctx = skcipher_request_ctx(req);
  
  		rctx->subreq.base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
205
  		err = xor_tweak_post(req);
b257b48cd   Herbert Xu   crypto: lrw - Fix...
206
  	}
700cb3f5f   Herbert Xu   crypto: lrw - Con...
207
208
209
  
  	skcipher_request_complete(req, err);
  }
ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
210
  static void init_crypt(struct skcipher_request *req)
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
211
  {
ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
212
  	struct priv *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
700cb3f5f   Herbert Xu   crypto: lrw - Con...
213
  	struct rctx *rctx = skcipher_request_ctx(req);
ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
214
  	struct skcipher_request *subreq = &rctx->subreq;
700cb3f5f   Herbert Xu   crypto: lrw - Con...
215

ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
216
217
218
219
220
  	skcipher_request_set_tfm(subreq, ctx->child);
  	skcipher_request_set_callback(subreq, req->base.flags, crypt_done, req);
  	/* pass req->iv as IV (will be used by xor_tweak, ECB will ignore it) */
  	skcipher_request_set_crypt(subreq, req->dst, req->dst,
  				   req->cryptlen, req->iv);
700cb3f5f   Herbert Xu   crypto: lrw - Con...
221

ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
222
223
  	/* calculate first value of T */
  	memcpy(&rctx->t, req->iv, sizeof(rctx->t));
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
224

ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
225
226
  	/* T <- I*Key2 */
  	gf128mul_64k_bbe(&rctx->t, ctx->table);
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
227
  }
ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
228
  static int encrypt(struct skcipher_request *req)
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
229
  {
ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
230
231
  	struct rctx *rctx = skcipher_request_ctx(req);
  	struct skcipher_request *subreq = &rctx->subreq;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
232

ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
233
234
235
236
  	init_crypt(req);
  	return xor_tweak_pre(req) ?:
  		crypto_skcipher_encrypt(subreq) ?:
  		xor_tweak_post(req);
700cb3f5f   Herbert Xu   crypto: lrw - Con...
237
238
239
240
  }
  
  static int decrypt(struct skcipher_request *req)
  {
ac3c8f36c   Ondrej Mosnacek   crypto: lrw - Do ...
241
242
243
244
245
246
247
  	struct rctx *rctx = skcipher_request_ctx(req);
  	struct skcipher_request *subreq = &rctx->subreq;
  
  	init_crypt(req);
  	return xor_tweak_pre(req) ?:
  		crypto_skcipher_decrypt(subreq) ?:
  		xor_tweak_post(req);
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
248
  }
700cb3f5f   Herbert Xu   crypto: lrw - Con...
249
  static int init_tfm(struct crypto_skcipher *tfm)
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
250
  {
700cb3f5f   Herbert Xu   crypto: lrw - Con...
251
252
253
254
  	struct skcipher_instance *inst = skcipher_alg_instance(tfm);
  	struct crypto_skcipher_spawn *spawn = skcipher_instance_ctx(inst);
  	struct priv *ctx = crypto_skcipher_ctx(tfm);
  	struct crypto_skcipher *cipher;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
255

700cb3f5f   Herbert Xu   crypto: lrw - Con...
256
  	cipher = crypto_spawn_skcipher(spawn);
2e306ee01   Herbert Xu   [CRYPTO] api: Add...
257
258
  	if (IS_ERR(cipher))
  		return PTR_ERR(cipher);
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
259

2e306ee01   Herbert Xu   [CRYPTO] api: Add...
260
  	ctx->child = cipher;
700cb3f5f   Herbert Xu   crypto: lrw - Con...
261
262
263
  
  	crypto_skcipher_set_reqsize(tfm, crypto_skcipher_reqsize(cipher) +
  					 sizeof(struct rctx));
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
264
265
  	return 0;
  }
700cb3f5f   Herbert Xu   crypto: lrw - Con...
266
  static void exit_tfm(struct crypto_skcipher *tfm)
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
267
  {
700cb3f5f   Herbert Xu   crypto: lrw - Con...
268
  	struct priv *ctx = crypto_skcipher_ctx(tfm);
171c02048   Jussi Kivilinna   crypto: lrw - spl...
269

217afccf6   Eric Biggers   crypto: lrw - rem...
270
271
  	if (ctx->table)
  		gf128mul_free_64k(ctx->table);
700cb3f5f   Herbert Xu   crypto: lrw - Con...
272
273
  	crypto_free_skcipher(ctx->child);
  }
dca0ae390   Linus Torvalds   gcc-10: avoid sha...
274
  static void free_inst(struct skcipher_instance *inst)
700cb3f5f   Herbert Xu   crypto: lrw - Con...
275
276
277
  {
  	crypto_drop_skcipher(skcipher_instance_ctx(inst));
  	kfree(inst);
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
278
  }
700cb3f5f   Herbert Xu   crypto: lrw - Con...
279
  static int create(struct crypto_template *tmpl, struct rtattr **tb)
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
280
  {
700cb3f5f   Herbert Xu   crypto: lrw - Con...
281
282
283
284
285
286
  	struct crypto_skcipher_spawn *spawn;
  	struct skcipher_instance *inst;
  	struct crypto_attr_type *algt;
  	struct skcipher_alg *alg;
  	const char *cipher_name;
  	char ecb_name[CRYPTO_MAX_ALG_NAME];
ebc610e5b   Herbert Xu   [CRYPTO] template...
287
  	int err;
700cb3f5f   Herbert Xu   crypto: lrw - Con...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
  	algt = crypto_get_attr_type(tb);
  	if (IS_ERR(algt))
  		return PTR_ERR(algt);
  
  	if ((algt->type ^ CRYPTO_ALG_TYPE_SKCIPHER) & algt->mask)
  		return -EINVAL;
  
  	cipher_name = crypto_attr_alg_name(tb[1]);
  	if (IS_ERR(cipher_name))
  		return PTR_ERR(cipher_name);
  
  	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
  	if (!inst)
  		return -ENOMEM;
  
  	spawn = skcipher_instance_ctx(inst);
  
  	crypto_set_skcipher_spawn(spawn, skcipher_crypto_instance(inst));
  	err = crypto_grab_skcipher(spawn, cipher_name, 0,
  				   crypto_requires_sync(algt->type,
  							algt->mask));
  	if (err == -ENOENT) {
  		err = -ENAMETOOLONG;
  		if (snprintf(ecb_name, CRYPTO_MAX_ALG_NAME, "ecb(%s)",
  			     cipher_name) >= CRYPTO_MAX_ALG_NAME)
  			goto err_free_inst;
  
  		err = crypto_grab_skcipher(spawn, ecb_name, 0,
  					   crypto_requires_sync(algt->type,
  								algt->mask));
  	}
ebc610e5b   Herbert Xu   [CRYPTO] template...
319
  	if (err)
700cb3f5f   Herbert Xu   crypto: lrw - Con...
320
  		goto err_free_inst;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
321

700cb3f5f   Herbert Xu   crypto: lrw - Con...
322
  	alg = crypto_skcipher_spawn_alg(spawn);
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
323

700cb3f5f   Herbert Xu   crypto: lrw - Con...
324
325
326
  	err = -EINVAL;
  	if (alg->base.cra_blocksize != LRW_BLOCK_SIZE)
  		goto err_drop_spawn;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
327

700cb3f5f   Herbert Xu   crypto: lrw - Con...
328
329
  	if (crypto_skcipher_alg_ivsize(alg))
  		goto err_drop_spawn;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
330

700cb3f5f   Herbert Xu   crypto: lrw - Con...
331
332
333
334
  	err = crypto_inst_setname(skcipher_crypto_instance(inst), "lrw",
  				  &alg->base);
  	if (err)
  		goto err_drop_spawn;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
335

700cb3f5f   Herbert Xu   crypto: lrw - Con...
336
337
  	err = -EINVAL;
  	cipher_name = alg->base.cra_name;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
338

700cb3f5f   Herbert Xu   crypto: lrw - Con...
339
340
341
342
343
  	/* Alas we screwed up the naming so we have to mangle the
  	 * cipher name.
  	 */
  	if (!strncmp(cipher_name, "ecb(", 4)) {
  		unsigned len;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
344

700cb3f5f   Herbert Xu   crypto: lrw - Con...
345
346
347
  		len = strlcpy(ecb_name, cipher_name + 4, sizeof(ecb_name));
  		if (len < 2 || len >= sizeof(ecb_name))
  			goto err_drop_spawn;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
348

700cb3f5f   Herbert Xu   crypto: lrw - Con...
349
350
  		if (ecb_name[len - 1] != ')')
  			goto err_drop_spawn;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
351

700cb3f5f   Herbert Xu   crypto: lrw - Con...
352
  		ecb_name[len - 1] = 0;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
353

700cb3f5f   Herbert Xu   crypto: lrw - Con...
354
  		if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
616129cc6   Christophe Jaillet   crypto: lrw - Fix...
355
356
357
358
  			     "lrw(%s)", ecb_name) >= CRYPTO_MAX_ALG_NAME) {
  			err = -ENAMETOOLONG;
  			goto err_drop_spawn;
  		}
d38efad2b   Christophe Jaillet   crypto: lrw - Che...
359
360
  	} else
  		goto err_drop_spawn;
700cb3f5f   Herbert Xu   crypto: lrw - Con...
361
362
363
364
365
  
  	inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC;
  	inst->alg.base.cra_priority = alg->base.cra_priority;
  	inst->alg.base.cra_blocksize = LRW_BLOCK_SIZE;
  	inst->alg.base.cra_alignmask = alg->base.cra_alignmask |
20a0f9761   Eric Biggers   crypto: lrw - use...
366
  				       (__alignof__(be128) - 1);
700cb3f5f   Herbert Xu   crypto: lrw - Con...
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
  
  	inst->alg.ivsize = LRW_BLOCK_SIZE;
  	inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg) +
  				LRW_BLOCK_SIZE;
  	inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(alg) +
  				LRW_BLOCK_SIZE;
  
  	inst->alg.base.cra_ctxsize = sizeof(struct priv);
  
  	inst->alg.init = init_tfm;
  	inst->alg.exit = exit_tfm;
  
  	inst->alg.setkey = setkey;
  	inst->alg.encrypt = encrypt;
  	inst->alg.decrypt = decrypt;
dca0ae390   Linus Torvalds   gcc-10: avoid sha...
382
  	inst->free = free_inst;
700cb3f5f   Herbert Xu   crypto: lrw - Con...
383
384
385
386
387
388
389
390
391
392
393
  
  	err = skcipher_register_instance(tmpl, inst);
  	if (err)
  		goto err_drop_spawn;
  
  out:
  	return err;
  
  err_drop_spawn:
  	crypto_drop_skcipher(spawn);
  err_free_inst:
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
394
  	kfree(inst);
700cb3f5f   Herbert Xu   crypto: lrw - Con...
395
  	goto out;
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
396
397
398
399
  }
  
  static struct crypto_template crypto_tmpl = {
  	.name = "lrw",
700cb3f5f   Herbert Xu   crypto: lrw - Con...
400
  	.create = create,
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
401
402
403
404
405
406
407
408
409
410
411
412
  	.module = THIS_MODULE,
  };
  
  static int __init crypto_module_init(void)
  {
  	return crypto_register_template(&crypto_tmpl);
  }
  
  static void __exit crypto_module_exit(void)
  {
  	crypto_unregister_template(&crypto_tmpl);
  }
c4741b230   Eric Biggers   crypto: run initc...
413
  subsys_initcall(crypto_module_init);
64470f1b8   Rik Snel   [CRYPTO] lrw: Lis...
414
415
416
417
  module_exit(crypto_module_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("LRW block cipher mode");
4943ba16b   Kees Cook   crypto: include c...
418
  MODULE_ALIAS_CRYPTO("lrw");