Blame view

crypto/xts.c 11.7 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
2
3
  /* XTS: as defined in IEEE1619/D16
   *	http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
4
5
6
   *
   * Copyright (c) 2007 Rik Snel <rsnel@cube.dyndns.org>
   *
ddbc73616   Corentin LABBE   crypto: xts - fix...
7
   * Based on ecb.c
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
8
   * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
9
   */
f1c131b45   Herbert Xu   crypto: xts - Con...
10
11
  #include <crypto/internal/skcipher.h>
  #include <crypto/scatterwalk.h>
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
12
13
14
15
16
17
  #include <linux/err.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/scatterlist.h>
  #include <linux/slab.h>
ce0045561   Jussi Kivilinna   crypto: xts: add ...
18
  #include <crypto/xts.h>
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
19
20
21
22
  #include <crypto/b128ops.h>
  #include <crypto/gf128mul.h>
  
  struct priv {
f1c131b45   Herbert Xu   crypto: xts - Con...
23
  	struct crypto_skcipher *child;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
24
25
  	struct crypto_cipher *tweak;
  };
f1c131b45   Herbert Xu   crypto: xts - Con...
26
27
28
29
30
31
  struct xts_instance_ctx {
  	struct crypto_skcipher_spawn spawn;
  	char name[CRYPTO_MAX_ALG_NAME];
  };
  
  struct rctx {
e55318c84   Ondrej Mosnáček   crypto: gf128mul ...
32
  	le128 t;
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
33
34
  	struct scatterlist *tail;
  	struct scatterlist sg[2];
f1c131b45   Herbert Xu   crypto: xts - Con...
35
36
37
38
  	struct skcipher_request subreq;
  };
  
  static int setkey(struct crypto_skcipher *parent, const u8 *key,
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
39
40
  		  unsigned int keylen)
  {
f1c131b45   Herbert Xu   crypto: xts - Con...
41
42
43
  	struct priv *ctx = crypto_skcipher_ctx(parent);
  	struct crypto_skcipher *child;
  	struct crypto_cipher *tweak;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
44
  	int err;
f1c131b45   Herbert Xu   crypto: xts - Con...
45
  	err = xts_verify_key(parent, key, keylen);
28856a9e5   Stephan Mueller   crypto: xts - con...
46
47
  	if (err)
  		return err;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
48

f1c131b45   Herbert Xu   crypto: xts - Con...
49
  	keylen /= 2;
25985edce   Lucas De Marchi   Fix common misspe...
50
  	/* we need two cipher instances: one to compute the initial 'tweak'
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
51
52
53
54
  	 * by encrypting the IV (usually the 'plain' iv) and the other
  	 * one to encrypt and decrypt the data */
  
  	/* tweak cipher, uses Key2 i.e. the second half of *key */
f1c131b45   Herbert Xu   crypto: xts - Con...
55
56
57
  	tweak = ctx->tweak;
  	crypto_cipher_clear_flags(tweak, CRYPTO_TFM_REQ_MASK);
  	crypto_cipher_set_flags(tweak, crypto_skcipher_get_flags(parent) &
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
58
  				       CRYPTO_TFM_REQ_MASK);
f1c131b45   Herbert Xu   crypto: xts - Con...
59
  	err = crypto_cipher_setkey(tweak, key + keylen, keylen);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
60
61
  	if (err)
  		return err;
f1c131b45   Herbert Xu   crypto: xts - Con...
62
  	/* data cipher, uses Key1 i.e. the first half of *key */
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
63
  	child = ctx->child;
f1c131b45   Herbert Xu   crypto: xts - Con...
64
65
66
  	crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
  	crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(parent) &
  					 CRYPTO_TFM_REQ_MASK);
af5034e8e   Eric Biggers   crypto: remove pr...
67
  	return crypto_skcipher_setkey(child, key, keylen);
f1c131b45   Herbert Xu   crypto: xts - Con...
68
  }
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
69

78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
70
71
72
73
74
75
  /*
   * 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 gf128mul_x_ble() calls again.
   */
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
76
  static int xor_tweak(struct skcipher_request *req, bool second_pass, bool enc)
f1c131b45   Herbert Xu   crypto: xts - Con...
77
78
  {
  	struct rctx *rctx = skcipher_request_ctx(req);
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
79
  	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
80
  	const bool cts = (req->cryptlen % XTS_BLOCK_SIZE);
f1c131b45   Herbert Xu   crypto: xts - Con...
81
82
  	const int bs = XTS_BLOCK_SIZE;
  	struct skcipher_walk w;
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
83
  	le128 t = rctx->t;
f1c131b45   Herbert Xu   crypto: xts - Con...
84
  	int err;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
85

78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
86
87
88
89
  	if (second_pass) {
  		req = &rctx->subreq;
  		/* set to our TFM to enforce correct alignment: */
  		skcipher_request_set_tfm(req, tfm);
f1c131b45   Herbert Xu   crypto: xts - Con...
90
  	}
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
91
  	err = skcipher_walk_virt(&w, req, false);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
92

f1c131b45   Herbert Xu   crypto: xts - Con...
93
94
  	while (w.nbytes) {
  		unsigned int avail = w.nbytes;
e55318c84   Ondrej Mosnáček   crypto: gf128mul ...
95
96
  		le128 *wsrc;
  		le128 *wdst;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
97

f1c131b45   Herbert Xu   crypto: xts - Con...
98
99
  		wsrc = w.src.virt.addr;
  		wdst = w.dst.virt.addr;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
100

f1c131b45   Herbert Xu   crypto: xts - Con...
101
  		do {
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
102
103
104
105
106
107
108
109
110
111
112
113
114
  			if (unlikely(cts) &&
  			    w.total - w.nbytes + avail < 2 * XTS_BLOCK_SIZE) {
  				if (!enc) {
  					if (second_pass)
  						rctx->t = t;
  					gf128mul_x_ble(&t, &t);
  				}
  				le128_xor(wdst, &t, wsrc);
  				if (enc && second_pass)
  					gf128mul_x_ble(&rctx->t, &t);
  				skcipher_walk_done(&w, avail - bs);
  				return 0;
  			}
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
115
116
  			le128_xor(wdst++, &t, wsrc++);
  			gf128mul_x_ble(&t, &t);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
117
  		} while ((avail -= bs) >= bs);
f1c131b45   Herbert Xu   crypto: xts - Con...
118
119
  		err = skcipher_walk_done(&w, avail);
  	}
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
120
121
  	return err;
  }
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
122
123
124
125
126
127
128
129
130
131
132
  static int xor_tweak_pre(struct skcipher_request *req, bool enc)
  {
  	return xor_tweak(req, false, enc);
  }
  
  static int xor_tweak_post(struct skcipher_request *req, bool enc)
  {
  	return xor_tweak(req, true, enc);
  }
  
  static void cts_done(struct crypto_async_request *areq, int err)
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
133
  {
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
  	struct skcipher_request *req = areq->data;
  	le128 b;
  
  	if (!err) {
  		struct rctx *rctx = skcipher_request_ctx(req);
  
  		scatterwalk_map_and_copy(&b, rctx->tail, 0, XTS_BLOCK_SIZE, 0);
  		le128_xor(&b, &rctx->t, &b);
  		scatterwalk_map_and_copy(&b, rctx->tail, 0, XTS_BLOCK_SIZE, 1);
  	}
  
  	skcipher_request_complete(req, err);
  }
  
  static int cts_final(struct skcipher_request *req,
  		     int (*crypt)(struct skcipher_request *req))
  {
  	struct priv *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
  	int offset = req->cryptlen & ~(XTS_BLOCK_SIZE - 1);
  	struct rctx *rctx = skcipher_request_ctx(req);
  	struct skcipher_request *subreq = &rctx->subreq;
  	int tail = req->cryptlen % XTS_BLOCK_SIZE;
  	le128 b[2];
  	int err;
  
  	rctx->tail = scatterwalk_ffwd(rctx->sg, req->dst,
  				      offset - XTS_BLOCK_SIZE);
  
  	scatterwalk_map_and_copy(b, rctx->tail, 0, XTS_BLOCK_SIZE, 0);
  	memcpy(b + 1, b, tail);
  	scatterwalk_map_and_copy(b, req->src, offset, tail, 0);
  
  	le128_xor(b, &rctx->t, b);
  
  	scatterwalk_map_and_copy(b, rctx->tail, 0, XTS_BLOCK_SIZE + tail, 1);
  
  	skcipher_request_set_tfm(subreq, ctx->child);
  	skcipher_request_set_callback(subreq, req->base.flags, cts_done, req);
  	skcipher_request_set_crypt(subreq, rctx->tail, rctx->tail,
  				   XTS_BLOCK_SIZE, NULL);
  
  	err = crypt(subreq);
  	if (err)
  		return err;
  
  	scatterwalk_map_and_copy(b, rctx->tail, 0, XTS_BLOCK_SIZE, 0);
  	le128_xor(b, &rctx->t, b);
  	scatterwalk_map_and_copy(b, rctx->tail, 0, XTS_BLOCK_SIZE, 1);
  
  	return 0;
f1c131b45   Herbert Xu   crypto: xts - Con...
184
  }
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
185
  static void encrypt_done(struct crypto_async_request *areq, int err)
f1c131b45   Herbert Xu   crypto: xts - Con...
186
  {
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
  	struct skcipher_request *req = areq->data;
  
  	if (!err) {
  		struct rctx *rctx = skcipher_request_ctx(req);
  
  		rctx->subreq.base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
  		err = xor_tweak_post(req, true);
  
  		if (!err && unlikely(req->cryptlen % XTS_BLOCK_SIZE)) {
  			err = cts_final(req, crypto_skcipher_encrypt);
  			if (err == -EINPROGRESS)
  				return;
  		}
  	}
  
  	skcipher_request_complete(req, err);
f1c131b45   Herbert Xu   crypto: xts - Con...
203
  }
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
204
  static void decrypt_done(struct crypto_async_request *areq, int err)
f1c131b45   Herbert Xu   crypto: xts - Con...
205
206
  {
  	struct skcipher_request *req = areq->data;
aa4a829bd   Herbert Xu   crypto: xts - Fix...
207

44427c0fb   Herbert Xu   crypto: xts - Fix...
208
209
210
211
  	if (!err) {
  		struct rctx *rctx = skcipher_request_ctx(req);
  
  		rctx->subreq.base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
212
213
214
215
216
217
218
  		err = xor_tweak_post(req, false);
  
  		if (!err && unlikely(req->cryptlen % XTS_BLOCK_SIZE)) {
  			err = cts_final(req, crypto_skcipher_decrypt);
  			if (err == -EINPROGRESS)
  				return;
  		}
44427c0fb   Herbert Xu   crypto: xts - Fix...
219
  	}
f1c131b45   Herbert Xu   crypto: xts - Con...
220

f1c131b45   Herbert Xu   crypto: xts - Con...
221
222
  	skcipher_request_complete(req, err);
  }
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
223
  static int init_crypt(struct skcipher_request *req, crypto_completion_t compl)
f1c131b45   Herbert Xu   crypto: xts - Con...
224
  {
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
225
  	struct priv *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
f1c131b45   Herbert Xu   crypto: xts - Con...
226
  	struct rctx *rctx = skcipher_request_ctx(req);
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
227
  	struct skcipher_request *subreq = &rctx->subreq;
f1c131b45   Herbert Xu   crypto: xts - Con...
228

8083b1bf8   Ard Biesheuvel   crypto: xts - add...
229
230
  	if (req->cryptlen < XTS_BLOCK_SIZE)
  		return -EINVAL;
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
231
  	skcipher_request_set_tfm(subreq, ctx->child);
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
232
  	skcipher_request_set_callback(subreq, req->base.flags, compl, req);
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
233
  	skcipher_request_set_crypt(subreq, req->dst, req->dst,
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
234
  				   req->cryptlen & ~(XTS_BLOCK_SIZE - 1), NULL);
f1c131b45   Herbert Xu   crypto: xts - Con...
235

78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
236
237
  	/* calculate first value of T */
  	crypto_cipher_encrypt_one(ctx->tweak, (u8 *)&rctx->t, req->iv);
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
238
239
  
  	return 0;
f1c131b45   Herbert Xu   crypto: xts - Con...
240
  }
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
241
  static int encrypt(struct skcipher_request *req)
f1c131b45   Herbert Xu   crypto: xts - Con...
242
  {
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
243
244
  	struct rctx *rctx = skcipher_request_ctx(req);
  	struct skcipher_request *subreq = &rctx->subreq;
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
245
246
247
248
249
250
  	int err;
  
  	err = init_crypt(req, encrypt_done) ?:
  	      xor_tweak_pre(req, true) ?:
  	      crypto_skcipher_encrypt(subreq) ?:
  	      xor_tweak_post(req, true);
f1c131b45   Herbert Xu   crypto: xts - Con...
251

8083b1bf8   Ard Biesheuvel   crypto: xts - add...
252
253
254
255
  	if (err || likely((req->cryptlen % XTS_BLOCK_SIZE) == 0))
  		return err;
  
  	return cts_final(req, crypto_skcipher_encrypt);
f1c131b45   Herbert Xu   crypto: xts - Con...
256
257
258
259
  }
  
  static int decrypt(struct skcipher_request *req)
  {
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
260
261
  	struct rctx *rctx = skcipher_request_ctx(req);
  	struct skcipher_request *subreq = &rctx->subreq;
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
262
263
264
265
266
267
268
269
270
  	int err;
  
  	err = init_crypt(req, decrypt_done) ?:
  	      xor_tweak_pre(req, false) ?:
  	      crypto_skcipher_decrypt(subreq) ?:
  	      xor_tweak_post(req, false);
  
  	if (err || likely((req->cryptlen % XTS_BLOCK_SIZE) == 0))
  		return err;
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
271

8083b1bf8   Ard Biesheuvel   crypto: xts - add...
272
  	return cts_final(req, crypto_skcipher_decrypt);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
273
  }
f1c131b45   Herbert Xu   crypto: xts - Con...
274
  static int init_tfm(struct crypto_skcipher *tfm)
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
275
  {
f1c131b45   Herbert Xu   crypto: xts - Con...
276
277
278
279
280
  	struct skcipher_instance *inst = skcipher_alg_instance(tfm);
  	struct xts_instance_ctx *ictx = skcipher_instance_ctx(inst);
  	struct priv *ctx = crypto_skcipher_ctx(tfm);
  	struct crypto_skcipher *child;
  	struct crypto_cipher *tweak;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
281

f1c131b45   Herbert Xu   crypto: xts - Con...
282
283
284
  	child = crypto_spawn_skcipher(&ictx->spawn);
  	if (IS_ERR(child))
  		return PTR_ERR(child);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
285

f1c131b45   Herbert Xu   crypto: xts - Con...
286
  	ctx->child = child;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
287

f1c131b45   Herbert Xu   crypto: xts - Con...
288
289
290
291
  	tweak = crypto_alloc_cipher(ictx->name, 0, 0);
  	if (IS_ERR(tweak)) {
  		crypto_free_skcipher(ctx->child);
  		return PTR_ERR(tweak);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
292
  	}
f1c131b45   Herbert Xu   crypto: xts - Con...
293
294
295
296
  	ctx->tweak = tweak;
  
  	crypto_skcipher_set_reqsize(tfm, crypto_skcipher_reqsize(child) +
  					 sizeof(struct rctx));
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
297
298
299
  
  	return 0;
  }
f1c131b45   Herbert Xu   crypto: xts - Con...
300
  static void exit_tfm(struct crypto_skcipher *tfm)
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
301
  {
f1c131b45   Herbert Xu   crypto: xts - Con...
302
303
304
  	struct priv *ctx = crypto_skcipher_ctx(tfm);
  
  	crypto_free_skcipher(ctx->child);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
305
306
  	crypto_free_cipher(ctx->tweak);
  }
f1c131b45   Herbert Xu   crypto: xts - Con...
307
308
309
310
311
312
313
  static void free(struct skcipher_instance *inst)
  {
  	crypto_drop_skcipher(skcipher_instance_ctx(inst));
  	kfree(inst);
  }
  
  static int create(struct crypto_template *tmpl, struct rtattr **tb)
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
314
  {
f1c131b45   Herbert Xu   crypto: xts - Con...
315
316
317
318
319
  	struct skcipher_instance *inst;
  	struct crypto_attr_type *algt;
  	struct xts_instance_ctx *ctx;
  	struct skcipher_alg *alg;
  	const char *cipher_name;
89027579b   Herbert Xu   crypto: xts - Pro...
320
  	u32 mask;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
321
  	int err;
f1c131b45   Herbert Xu   crypto: xts - Con...
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
  	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(*ctx), GFP_KERNEL);
  	if (!inst)
  		return -ENOMEM;
  
  	ctx = skcipher_instance_ctx(inst);
89027579b   Herbert Xu   crypto: xts - Pro...
338
339
340
  	mask = crypto_requires_off(algt->type, algt->mask,
  				   CRYPTO_ALG_NEED_FALLBACK |
  				   CRYPTO_ALG_ASYNC);
b9f76dddb   Eric Biggers   crypto: skcipher ...
341
342
  	err = crypto_grab_skcipher(&ctx->spawn, skcipher_crypto_instance(inst),
  				   cipher_name, 0, mask);
f1c131b45   Herbert Xu   crypto: xts - Con...
343
344
345
346
347
  	if (err == -ENOENT) {
  		err = -ENAMETOOLONG;
  		if (snprintf(ctx->name, CRYPTO_MAX_ALG_NAME, "ecb(%s)",
  			     cipher_name) >= CRYPTO_MAX_ALG_NAME)
  			goto err_free_inst;
b9f76dddb   Eric Biggers   crypto: skcipher ...
348
349
350
  		err = crypto_grab_skcipher(&ctx->spawn,
  					   skcipher_crypto_instance(inst),
  					   ctx->name, 0, mask);
f1c131b45   Herbert Xu   crypto: xts - Con...
351
  	}
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
352
  	if (err)
f1c131b45   Herbert Xu   crypto: xts - Con...
353
  		goto err_free_inst;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
354

f1c131b45   Herbert Xu   crypto: xts - Con...
355
  	alg = crypto_skcipher_spawn_alg(&ctx->spawn);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
356

f1c131b45   Herbert Xu   crypto: xts - Con...
357
358
359
  	err = -EINVAL;
  	if (alg->base.cra_blocksize != XTS_BLOCK_SIZE)
  		goto err_drop_spawn;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
360

f1c131b45   Herbert Xu   crypto: xts - Con...
361
362
  	if (crypto_skcipher_alg_ivsize(alg))
  		goto err_drop_spawn;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
363

f1c131b45   Herbert Xu   crypto: xts - Con...
364
365
366
367
  	err = crypto_inst_setname(skcipher_crypto_instance(inst), "xts",
  				  &alg->base);
  	if (err)
  		goto err_drop_spawn;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
368

f1c131b45   Herbert Xu   crypto: xts - Con...
369
370
  	err = -EINVAL;
  	cipher_name = alg->base.cra_name;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
371

f1c131b45   Herbert Xu   crypto: xts - Con...
372
373
374
375
376
  	/* Alas we screwed up the naming so we have to mangle the
  	 * cipher name.
  	 */
  	if (!strncmp(cipher_name, "ecb(", 4)) {
  		unsigned len;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
377

f1c131b45   Herbert Xu   crypto: xts - Con...
378
379
380
  		len = strlcpy(ctx->name, cipher_name + 4, sizeof(ctx->name));
  		if (len < 2 || len >= sizeof(ctx->name))
  			goto err_drop_spawn;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
381

f1c131b45   Herbert Xu   crypto: xts - Con...
382
383
  		if (ctx->name[len - 1] != ')')
  			goto err_drop_spawn;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
384

f1c131b45   Herbert Xu   crypto: xts - Con...
385
  		ctx->name[len - 1] = 0;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
386

f1c131b45   Herbert Xu   crypto: xts - Con...
387
  		if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
5125e4e86   Christophe Jaillet   crypto: xts - Fix...
388
389
390
391
  			     "xts(%s)", ctx->name) >= CRYPTO_MAX_ALG_NAME) {
  			err = -ENAMETOOLONG;
  			goto err_drop_spawn;
  		}
f1c131b45   Herbert Xu   crypto: xts - Con...
392
393
  	} else
  		goto err_drop_spawn;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
394

f1c131b45   Herbert Xu   crypto: xts - Con...
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
  	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 = XTS_BLOCK_SIZE;
  	inst->alg.base.cra_alignmask = alg->base.cra_alignmask |
  				       (__alignof__(u64) - 1);
  
  	inst->alg.ivsize = XTS_BLOCK_SIZE;
  	inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg) * 2;
  	inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(alg) * 2;
  
  	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;
  
  	inst->free = free;
  
  	err = skcipher_register_instance(tmpl, inst);
  	if (err)
  		goto err_drop_spawn;
  
  out:
  	return err;
  
  err_drop_spawn:
  	crypto_drop_skcipher(&ctx->spawn);
  err_free_inst:
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
426
  	kfree(inst);
f1c131b45   Herbert Xu   crypto: xts - Con...
427
  	goto out;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
428
429
430
431
  }
  
  static struct crypto_template crypto_tmpl = {
  	.name = "xts",
f1c131b45   Herbert Xu   crypto: xts - Con...
432
  	.create = create,
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
433
434
435
436
437
438
439
440
441
442
443
444
  	.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...
445
  subsys_initcall(crypto_module_init);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
446
447
448
449
  module_exit(crypto_module_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("XTS block cipher mode");
4943ba16b   Kees Cook   crypto: include c...
450
  MODULE_ALIAS_CRYPTO("xts");