Blame view

crypto/xts.c 11.9 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
60
61
  	err = crypto_cipher_setkey(tweak, key + keylen, keylen);
  	crypto_skcipher_set_flags(parent, crypto_cipher_get_flags(tweak) &
  					  CRYPTO_TFM_RES_MASK);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
62
63
  	if (err)
  		return err;
f1c131b45   Herbert Xu   crypto: xts - Con...
64
  	/* data cipher, uses Key1 i.e. the first half of *key */
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
65
  	child = ctx->child;
f1c131b45   Herbert Xu   crypto: xts - Con...
66
67
68
69
70
71
  	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);
  	crypto_skcipher_set_flags(parent, crypto_skcipher_get_flags(child) &
  					  CRYPTO_TFM_RES_MASK);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
72

f1c131b45   Herbert Xu   crypto: xts - Con...
73
74
  	return err;
  }
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
75

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

78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
92
93
94
95
  	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...
96
  	}
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
97
  	err = skcipher_walk_virt(&w, req, false);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
98

f1c131b45   Herbert Xu   crypto: xts - Con...
99
100
  	while (w.nbytes) {
  		unsigned int avail = w.nbytes;
e55318c84   Ondrej Mosnáček   crypto: gf128mul ...
101
102
  		le128 *wsrc;
  		le128 *wdst;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
103

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

f1c131b45   Herbert Xu   crypto: xts - Con...
107
  		do {
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
108
109
110
111
112
113
114
115
116
117
118
119
120
  			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...
121
122
  			le128_xor(wdst++, &t, wsrc++);
  			gf128mul_x_ble(&t, &t);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
123
  		} while ((avail -= bs) >= bs);
f1c131b45   Herbert Xu   crypto: xts - Con...
124
125
  		err = skcipher_walk_done(&w, avail);
  	}
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
126
127
  	return err;
  }
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
128
129
130
131
132
133
134
135
136
137
138
  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...
139
  {
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
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
184
185
186
187
188
189
  	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...
190
  }
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
191
  static void encrypt_done(struct crypto_async_request *areq, int err)
f1c131b45   Herbert Xu   crypto: xts - Con...
192
  {
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
  	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...
209
  }
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
210
  static void decrypt_done(struct crypto_async_request *areq, int err)
f1c131b45   Herbert Xu   crypto: xts - Con...
211
212
  {
  	struct skcipher_request *req = areq->data;
aa4a829bd   Herbert Xu   crypto: xts - Fix...
213

44427c0fb   Herbert Xu   crypto: xts - Fix...
214
215
216
217
  	if (!err) {
  		struct rctx *rctx = skcipher_request_ctx(req);
  
  		rctx->subreq.base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
218
219
220
221
222
223
224
  		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...
225
  	}
f1c131b45   Herbert Xu   crypto: xts - Con...
226

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

8083b1bf8   Ard Biesheuvel   crypto: xts - add...
235
236
  	if (req->cryptlen < XTS_BLOCK_SIZE)
  		return -EINVAL;
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
237
  	skcipher_request_set_tfm(subreq, ctx->child);
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
238
  	skcipher_request_set_callback(subreq, req->base.flags, compl, req);
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
239
  	skcipher_request_set_crypt(subreq, req->dst, req->dst,
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
240
  				   req->cryptlen & ~(XTS_BLOCK_SIZE - 1), NULL);
f1c131b45   Herbert Xu   crypto: xts - Con...
241

78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
242
243
  	/* calculate first value of T */
  	crypto_cipher_encrypt_one(ctx->tweak, (u8 *)&rctx->t, req->iv);
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
244
245
  
  	return 0;
f1c131b45   Herbert Xu   crypto: xts - Con...
246
  }
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
247
  static int encrypt(struct skcipher_request *req)
f1c131b45   Herbert Xu   crypto: xts - Con...
248
  {
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
249
250
  	struct rctx *rctx = skcipher_request_ctx(req);
  	struct skcipher_request *subreq = &rctx->subreq;
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
251
252
253
254
255
256
  	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...
257

8083b1bf8   Ard Biesheuvel   crypto: xts - add...
258
259
260
261
  	if (err || likely((req->cryptlen % XTS_BLOCK_SIZE) == 0))
  		return err;
  
  	return cts_final(req, crypto_skcipher_encrypt);
f1c131b45   Herbert Xu   crypto: xts - Con...
262
263
264
265
  }
  
  static int decrypt(struct skcipher_request *req)
  {
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
266
267
  	struct rctx *rctx = skcipher_request_ctx(req);
  	struct skcipher_request *subreq = &rctx->subreq;
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
268
269
270
271
272
273
274
275
276
  	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...
277

8083b1bf8   Ard Biesheuvel   crypto: xts - add...
278
  	return cts_final(req, crypto_skcipher_decrypt);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
279
  }
f1c131b45   Herbert Xu   crypto: xts - Con...
280
  static int init_tfm(struct crypto_skcipher *tfm)
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
281
  {
f1c131b45   Herbert Xu   crypto: xts - Con...
282
283
284
285
286
  	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...
287

f1c131b45   Herbert Xu   crypto: xts - Con...
288
289
290
  	child = crypto_spawn_skcipher(&ictx->spawn);
  	if (IS_ERR(child))
  		return PTR_ERR(child);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
291

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

f1c131b45   Herbert Xu   crypto: xts - Con...
294
295
296
297
  	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...
298
  	}
f1c131b45   Herbert Xu   crypto: xts - Con...
299
300
301
302
  	ctx->tweak = tweak;
  
  	crypto_skcipher_set_reqsize(tfm, crypto_skcipher_reqsize(child) +
  					 sizeof(struct rctx));
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
303
304
305
  
  	return 0;
  }
f1c131b45   Herbert Xu   crypto: xts - Con...
306
  static void exit_tfm(struct crypto_skcipher *tfm)
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
307
  {
f1c131b45   Herbert Xu   crypto: xts - Con...
308
309
310
  	struct priv *ctx = crypto_skcipher_ctx(tfm);
  
  	crypto_free_skcipher(ctx->child);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
311
312
  	crypto_free_cipher(ctx->tweak);
  }
f1c131b45   Herbert Xu   crypto: xts - Con...
313
314
315
316
317
318
319
  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...
320
  {
f1c131b45   Herbert Xu   crypto: xts - Con...
321
322
323
324
325
  	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...
326
  	u32 mask;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
327
  	int err;
f1c131b45   Herbert Xu   crypto: xts - Con...
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
  	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);
  
  	crypto_set_skcipher_spawn(&ctx->spawn, skcipher_crypto_instance(inst));
89027579b   Herbert Xu   crypto: xts - Pro...
346
347
348
349
350
351
  
  	mask = crypto_requires_off(algt->type, algt->mask,
  				   CRYPTO_ALG_NEED_FALLBACK |
  				   CRYPTO_ALG_ASYNC);
  
  	err = crypto_grab_skcipher(&ctx->spawn, cipher_name, 0, mask);
f1c131b45   Herbert Xu   crypto: xts - Con...
352
353
354
355
356
  	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;
89027579b   Herbert Xu   crypto: xts - Pro...
357
  		err = crypto_grab_skcipher(&ctx->spawn, ctx->name, 0, mask);
f1c131b45   Herbert Xu   crypto: xts - Con...
358
  	}
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
359
  	if (err)
f1c131b45   Herbert Xu   crypto: xts - Con...
360
  		goto err_free_inst;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
361

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

f1c131b45   Herbert Xu   crypto: xts - Con...
364
365
366
  	err = -EINVAL;
  	if (alg->base.cra_blocksize != XTS_BLOCK_SIZE)
  		goto err_drop_spawn;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
367

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

f1c131b45   Herbert Xu   crypto: xts - Con...
371
372
373
374
  	err = crypto_inst_setname(skcipher_crypto_instance(inst), "xts",
  				  &alg->base);
  	if (err)
  		goto err_drop_spawn;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
375

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

f1c131b45   Herbert Xu   crypto: xts - Con...
379
380
381
382
383
  	/* 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...
384

f1c131b45   Herbert Xu   crypto: xts - Con...
385
386
387
  		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...
388

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

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

f1c131b45   Herbert Xu   crypto: xts - Con...
394
  		if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
5125e4e86   Christophe Jaillet   crypto: xts - Fix...
395
396
397
398
  			     "xts(%s)", ctx->name) >= CRYPTO_MAX_ALG_NAME) {
  			err = -ENAMETOOLONG;
  			goto err_drop_spawn;
  		}
f1c131b45   Herbert Xu   crypto: xts - Con...
399
400
  	} else
  		goto err_drop_spawn;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
401

f1c131b45   Herbert Xu   crypto: xts - Con...
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
  	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...
433
  	kfree(inst);
f1c131b45   Herbert Xu   crypto: xts - Con...
434
  	goto out;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
435
436
437
438
  }
  
  static struct crypto_template crypto_tmpl = {
  	.name = "xts",
f1c131b45   Herbert Xu   crypto: xts - Con...
439
  	.create = create,
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
440
441
442
443
444
445
446
447
448
449
450
451
  	.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...
452
  subsys_initcall(crypto_module_init);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
453
454
455
456
  module_exit(crypto_module_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("XTS block cipher mode");
4943ba16b   Kees Cook   crypto: include c...
457
  MODULE_ALIAS_CRYPTO("xts");