Blame view

crypto/xts.c 11.8 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
   */
0eb76ba29   Ard Biesheuvel   crypto: remove ci...
10
  #include <crypto/internal/cipher.h>
f1c131b45   Herbert Xu   crypto: xts - Con...
11
12
  #include <crypto/internal/skcipher.h>
  #include <crypto/scatterwalk.h>
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
13
14
15
16
17
18
  #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 ...
19
  #include <crypto/xts.h>
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
20
21
  #include <crypto/b128ops.h>
  #include <crypto/gf128mul.h>
a874f5910   Eric Biggers   crypto: xts - pre...
22
  struct xts_tfm_ctx {
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
  struct xts_instance_ctx {
  	struct crypto_skcipher_spawn spawn;
  	char name[CRYPTO_MAX_ALG_NAME];
  };
a874f5910   Eric Biggers   crypto: xts - pre...
30
  struct xts_request_ctx {
e55318c84   Ondrej Mosnáček   crypto: gf128mul ...
31
  	le128 t;
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
32
33
  	struct scatterlist *tail;
  	struct scatterlist sg[2];
f1c131b45   Herbert Xu   crypto: xts - Con...
34
35
  	struct skcipher_request subreq;
  };
a874f5910   Eric Biggers   crypto: xts - pre...
36
37
  static int xts_setkey(struct crypto_skcipher *parent, const u8 *key,
  		      unsigned int keylen)
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
38
  {
a874f5910   Eric Biggers   crypto: xts - pre...
39
  	struct xts_tfm_ctx *ctx = crypto_skcipher_ctx(parent);
f1c131b45   Herbert Xu   crypto: xts - Con...
40
41
  	struct crypto_skcipher *child;
  	struct crypto_cipher *tweak;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
42
  	int err;
f1c131b45   Herbert Xu   crypto: xts - Con...
43
  	err = xts_verify_key(parent, key, keylen);
28856a9e5   Stephan Mueller   crypto: xts - con...
44
45
  	if (err)
  		return err;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
46

f1c131b45   Herbert Xu   crypto: xts - Con...
47
  	keylen /= 2;
25985edce   Lucas De Marchi   Fix common misspe...
48
  	/* we need two cipher instances: one to compute the initial 'tweak'
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
49
50
51
52
  	 * 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...
53
54
55
  	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...
56
  				       CRYPTO_TFM_REQ_MASK);
f1c131b45   Herbert Xu   crypto: xts - Con...
57
  	err = crypto_cipher_setkey(tweak, key + keylen, keylen);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
58
59
  	if (err)
  		return err;
f1c131b45   Herbert Xu   crypto: xts - Con...
60
  	/* data cipher, uses Key1 i.e. the first half of *key */
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
61
  	child = ctx->child;
f1c131b45   Herbert Xu   crypto: xts - Con...
62
63
64
  	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...
65
  	return crypto_skcipher_setkey(child, key, keylen);
f1c131b45   Herbert Xu   crypto: xts - Con...
66
  }
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
67

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

78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
85
86
87
88
  	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...
89
  	}
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
90
  	err = skcipher_walk_virt(&w, req, false);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
91

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

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

f1c131b45   Herbert Xu   crypto: xts - Con...
100
  		do {
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
101
102
103
104
105
106
107
108
109
110
111
112
113
  			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...
114
115
  			le128_xor(wdst++, &t, wsrc++);
  			gf128mul_x_ble(&t, &t);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
116
  		} while ((avail -= bs) >= bs);
f1c131b45   Herbert Xu   crypto: xts - Con...
117
118
  		err = skcipher_walk_done(&w, avail);
  	}
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
119
120
  	return err;
  }
a874f5910   Eric Biggers   crypto: xts - pre...
121
  static int xts_xor_tweak_pre(struct skcipher_request *req, bool enc)
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
122
  {
a874f5910   Eric Biggers   crypto: xts - pre...
123
  	return xts_xor_tweak(req, false, enc);
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
124
  }
a874f5910   Eric Biggers   crypto: xts - pre...
125
  static int xts_xor_tweak_post(struct skcipher_request *req, bool enc)
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
126
  {
a874f5910   Eric Biggers   crypto: xts - pre...
127
  	return xts_xor_tweak(req, true, enc);
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
128
  }
a874f5910   Eric Biggers   crypto: xts - pre...
129
  static void xts_cts_done(struct crypto_async_request *areq, int err)
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
130
  {
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
131
132
133
134
  	struct skcipher_request *req = areq->data;
  	le128 b;
  
  	if (!err) {
a874f5910   Eric Biggers   crypto: xts - pre...
135
  		struct xts_request_ctx *rctx = skcipher_request_ctx(req);
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
136
137
138
139
140
141
142
143
  
  		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);
  }
a874f5910   Eric Biggers   crypto: xts - pre...
144
145
  static int xts_cts_final(struct skcipher_request *req,
  			 int (*crypt)(struct skcipher_request *req))
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
146
  {
a874f5910   Eric Biggers   crypto: xts - pre...
147
148
  	const struct xts_tfm_ctx *ctx =
  		crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
149
  	int offset = req->cryptlen & ~(XTS_BLOCK_SIZE - 1);
a874f5910   Eric Biggers   crypto: xts - pre...
150
  	struct xts_request_ctx *rctx = skcipher_request_ctx(req);
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
151
152
153
154
155
156
157
158
159
  	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);
958ea4e0d   Ard Biesheuvel   crypto: xts - Rep...
160
  	b[1] = b[0];
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
161
162
163
164
165
166
167
  	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);
a874f5910   Eric Biggers   crypto: xts - pre...
168
169
  	skcipher_request_set_callback(subreq, req->base.flags, xts_cts_done,
  				      req);
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
170
171
172
173
174
175
176
177
178
179
180
181
  	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...
182
  }
a874f5910   Eric Biggers   crypto: xts - pre...
183
  static void xts_encrypt_done(struct crypto_async_request *areq, int err)
f1c131b45   Herbert Xu   crypto: xts - Con...
184
  {
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
185
186
187
  	struct skcipher_request *req = areq->data;
  
  	if (!err) {
a874f5910   Eric Biggers   crypto: xts - pre...
188
  		struct xts_request_ctx *rctx = skcipher_request_ctx(req);
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
189
190
  
  		rctx->subreq.base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
a874f5910   Eric Biggers   crypto: xts - pre...
191
  		err = xts_xor_tweak_post(req, true);
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
192
193
  
  		if (!err && unlikely(req->cryptlen % XTS_BLOCK_SIZE)) {
a874f5910   Eric Biggers   crypto: xts - pre...
194
  			err = xts_cts_final(req, crypto_skcipher_encrypt);
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
195
196
197
198
199
200
  			if (err == -EINPROGRESS)
  				return;
  		}
  	}
  
  	skcipher_request_complete(req, err);
f1c131b45   Herbert Xu   crypto: xts - Con...
201
  }
a874f5910   Eric Biggers   crypto: xts - pre...
202
  static void xts_decrypt_done(struct crypto_async_request *areq, int err)
f1c131b45   Herbert Xu   crypto: xts - Con...
203
204
  {
  	struct skcipher_request *req = areq->data;
aa4a829bd   Herbert Xu   crypto: xts - Fix...
205

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

f1c131b45   Herbert Xu   crypto: xts - Con...
219
220
  	skcipher_request_complete(req, err);
  }
a874f5910   Eric Biggers   crypto: xts - pre...
221
222
  static int xts_init_crypt(struct skcipher_request *req,
  			  crypto_completion_t compl)
f1c131b45   Herbert Xu   crypto: xts - Con...
223
  {
a874f5910   Eric Biggers   crypto: xts - pre...
224
225
226
  	const struct xts_tfm_ctx *ctx =
  		crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
  	struct xts_request_ctx *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
  }
a874f5910   Eric Biggers   crypto: xts - pre...
241
  static int xts_encrypt(struct skcipher_request *req)
f1c131b45   Herbert Xu   crypto: xts - Con...
242
  {
a874f5910   Eric Biggers   crypto: xts - pre...
243
  	struct xts_request_ctx *rctx = skcipher_request_ctx(req);
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
244
  	struct skcipher_request *subreq = &rctx->subreq;
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
245
  	int err;
a874f5910   Eric Biggers   crypto: xts - pre...
246
247
  	err = xts_init_crypt(req, xts_encrypt_done) ?:
  	      xts_xor_tweak_pre(req, true) ?:
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
248
  	      crypto_skcipher_encrypt(subreq) ?:
a874f5910   Eric Biggers   crypto: xts - pre...
249
  	      xts_xor_tweak_post(req, true);
f1c131b45   Herbert Xu   crypto: xts - Con...
250

8083b1bf8   Ard Biesheuvel   crypto: xts - add...
251
252
  	if (err || likely((req->cryptlen % XTS_BLOCK_SIZE) == 0))
  		return err;
a874f5910   Eric Biggers   crypto: xts - pre...
253
  	return xts_cts_final(req, crypto_skcipher_encrypt);
f1c131b45   Herbert Xu   crypto: xts - Con...
254
  }
a874f5910   Eric Biggers   crypto: xts - pre...
255
  static int xts_decrypt(struct skcipher_request *req)
f1c131b45   Herbert Xu   crypto: xts - Con...
256
  {
a874f5910   Eric Biggers   crypto: xts - pre...
257
  	struct xts_request_ctx *rctx = skcipher_request_ctx(req);
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
258
  	struct skcipher_request *subreq = &rctx->subreq;
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
259
  	int err;
a874f5910   Eric Biggers   crypto: xts - pre...
260
261
  	err = xts_init_crypt(req, xts_decrypt_done) ?:
  	      xts_xor_tweak_pre(req, false) ?:
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
262
  	      crypto_skcipher_decrypt(subreq) ?:
a874f5910   Eric Biggers   crypto: xts - pre...
263
  	      xts_xor_tweak_post(req, false);
8083b1bf8   Ard Biesheuvel   crypto: xts - add...
264
265
266
  
  	if (err || likely((req->cryptlen % XTS_BLOCK_SIZE) == 0))
  		return err;
78105c7e7   Ondrej Mosnacek   crypto: xts - Dro...
267

a874f5910   Eric Biggers   crypto: xts - pre...
268
  	return xts_cts_final(req, crypto_skcipher_decrypt);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
269
  }
a874f5910   Eric Biggers   crypto: xts - pre...
270
  static int xts_init_tfm(struct crypto_skcipher *tfm)
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
271
  {
f1c131b45   Herbert Xu   crypto: xts - Con...
272
273
  	struct skcipher_instance *inst = skcipher_alg_instance(tfm);
  	struct xts_instance_ctx *ictx = skcipher_instance_ctx(inst);
a874f5910   Eric Biggers   crypto: xts - pre...
274
  	struct xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm);
f1c131b45   Herbert Xu   crypto: xts - Con...
275
276
  	struct crypto_skcipher *child;
  	struct crypto_cipher *tweak;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
277

f1c131b45   Herbert Xu   crypto: xts - Con...
278
279
280
  	child = crypto_spawn_skcipher(&ictx->spawn);
  	if (IS_ERR(child))
  		return PTR_ERR(child);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
281

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

f1c131b45   Herbert Xu   crypto: xts - Con...
284
285
286
287
  	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...
288
  	}
f1c131b45   Herbert Xu   crypto: xts - Con...
289
290
291
  	ctx->tweak = tweak;
  
  	crypto_skcipher_set_reqsize(tfm, crypto_skcipher_reqsize(child) +
a874f5910   Eric Biggers   crypto: xts - pre...
292
  					 sizeof(struct xts_request_ctx));
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
293
294
295
  
  	return 0;
  }
a874f5910   Eric Biggers   crypto: xts - pre...
296
  static void xts_exit_tfm(struct crypto_skcipher *tfm)
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
297
  {
a874f5910   Eric Biggers   crypto: xts - pre...
298
  	struct xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm);
f1c131b45   Herbert Xu   crypto: xts - Con...
299
300
  
  	crypto_free_skcipher(ctx->child);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
301
302
  	crypto_free_cipher(ctx->tweak);
  }
a874f5910   Eric Biggers   crypto: xts - pre...
303
  static void xts_free_instance(struct skcipher_instance *inst)
f1c131b45   Herbert Xu   crypto: xts - Con...
304
  {
a874f5910   Eric Biggers   crypto: xts - pre...
305
306
307
  	struct xts_instance_ctx *ictx = skcipher_instance_ctx(inst);
  
  	crypto_drop_skcipher(&ictx->spawn);
f1c131b45   Herbert Xu   crypto: xts - Con...
308
309
  	kfree(inst);
  }
a874f5910   Eric Biggers   crypto: xts - pre...
310
  static int xts_create(struct crypto_template *tmpl, struct rtattr **tb)
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
311
  {
f1c131b45   Herbert Xu   crypto: xts - Con...
312
  	struct skcipher_instance *inst;
f1c131b45   Herbert Xu   crypto: xts - Con...
313
314
315
  	struct xts_instance_ctx *ctx;
  	struct skcipher_alg *alg;
  	const char *cipher_name;
89027579b   Herbert Xu   crypto: xts - Pro...
316
  	u32 mask;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
317
  	int err;
7bcb2c99f   Eric Biggers   crypto: algapi - ...
318
319
320
  	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SKCIPHER, &mask);
  	if (err)
  		return err;
f1c131b45   Herbert Xu   crypto: xts - Con...
321
322
323
324
325
326
327
328
329
330
  
  	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);
b9f76dddb   Eric Biggers   crypto: skcipher ...
331
332
  	err = crypto_grab_skcipher(&ctx->spawn, skcipher_crypto_instance(inst),
  				   cipher_name, 0, mask);
f1c131b45   Herbert Xu   crypto: xts - Con...
333
334
335
336
337
  	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 ...
338
339
340
  		err = crypto_grab_skcipher(&ctx->spawn,
  					   skcipher_crypto_instance(inst),
  					   ctx->name, 0, mask);
f1c131b45   Herbert Xu   crypto: xts - Con...
341
  	}
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
342
  	if (err)
f1c131b45   Herbert Xu   crypto: xts - Con...
343
  		goto err_free_inst;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
344

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

f1c131b45   Herbert Xu   crypto: xts - Con...
347
348
  	err = -EINVAL;
  	if (alg->base.cra_blocksize != XTS_BLOCK_SIZE)
732e54095   Eric Biggers   crypto: xts - sim...
349
  		goto err_free_inst;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
350

f1c131b45   Herbert Xu   crypto: xts - Con...
351
  	if (crypto_skcipher_alg_ivsize(alg))
732e54095   Eric Biggers   crypto: xts - sim...
352
  		goto err_free_inst;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
353

f1c131b45   Herbert Xu   crypto: xts - Con...
354
355
356
  	err = crypto_inst_setname(skcipher_crypto_instance(inst), "xts",
  				  &alg->base);
  	if (err)
732e54095   Eric Biggers   crypto: xts - sim...
357
  		goto err_free_inst;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
358

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

f1c131b45   Herbert Xu   crypto: xts - Con...
362
363
364
365
366
  	/* 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...
367

f1c131b45   Herbert Xu   crypto: xts - Con...
368
369
  		len = strlcpy(ctx->name, cipher_name + 4, sizeof(ctx->name));
  		if (len < 2 || len >= sizeof(ctx->name))
732e54095   Eric Biggers   crypto: xts - sim...
370
  			goto err_free_inst;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
371

f1c131b45   Herbert Xu   crypto: xts - Con...
372
  		if (ctx->name[len - 1] != ')')
732e54095   Eric Biggers   crypto: xts - sim...
373
  			goto err_free_inst;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
374

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

f1c131b45   Herbert Xu   crypto: xts - Con...
377
  		if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
5125e4e86   Christophe Jaillet   crypto: xts - Fix...
378
379
  			     "xts(%s)", ctx->name) >= CRYPTO_MAX_ALG_NAME) {
  			err = -ENAMETOOLONG;
732e54095   Eric Biggers   crypto: xts - sim...
380
  			goto err_free_inst;
5125e4e86   Christophe Jaillet   crypto: xts - Fix...
381
  		}
f1c131b45   Herbert Xu   crypto: xts - Con...
382
  	} else
732e54095   Eric Biggers   crypto: xts - sim...
383
  		goto err_free_inst;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
384

f1c131b45   Herbert Xu   crypto: xts - Con...
385
386
387
388
389
390
391
392
  	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;
a874f5910   Eric Biggers   crypto: xts - pre...
393
  	inst->alg.base.cra_ctxsize = sizeof(struct xts_tfm_ctx);
f1c131b45   Herbert Xu   crypto: xts - Con...
394

a874f5910   Eric Biggers   crypto: xts - pre...
395
396
  	inst->alg.init = xts_init_tfm;
  	inst->alg.exit = xts_exit_tfm;
f1c131b45   Herbert Xu   crypto: xts - Con...
397

a874f5910   Eric Biggers   crypto: xts - pre...
398
399
400
  	inst->alg.setkey = xts_setkey;
  	inst->alg.encrypt = xts_encrypt;
  	inst->alg.decrypt = xts_decrypt;
f1c131b45   Herbert Xu   crypto: xts - Con...
401

a874f5910   Eric Biggers   crypto: xts - pre...
402
  	inst->free = xts_free_instance;
f1c131b45   Herbert Xu   crypto: xts - Con...
403
404
  
  	err = skcipher_register_instance(tmpl, inst);
732e54095   Eric Biggers   crypto: xts - sim...
405
  	if (err) {
f1c131b45   Herbert Xu   crypto: xts - Con...
406
  err_free_inst:
a874f5910   Eric Biggers   crypto: xts - pre...
407
  		xts_free_instance(inst);
732e54095   Eric Biggers   crypto: xts - sim...
408
409
  	}
  	return err;
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
410
  }
a874f5910   Eric Biggers   crypto: xts - pre...
411
  static struct crypto_template xts_tmpl = {
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
412
  	.name = "xts",
a874f5910   Eric Biggers   crypto: xts - pre...
413
  	.create = xts_create,
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
414
415
  	.module = THIS_MODULE,
  };
a874f5910   Eric Biggers   crypto: xts - pre...
416
  static int __init xts_module_init(void)
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
417
  {
a874f5910   Eric Biggers   crypto: xts - pre...
418
  	return crypto_register_template(&xts_tmpl);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
419
  }
a874f5910   Eric Biggers   crypto: xts - pre...
420
  static void __exit xts_module_exit(void)
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
421
  {
a874f5910   Eric Biggers   crypto: xts - pre...
422
  	crypto_unregister_template(&xts_tmpl);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
423
  }
a874f5910   Eric Biggers   crypto: xts - pre...
424
425
  subsys_initcall(xts_module_init);
  module_exit(xts_module_exit);
f19f5111c   Rik Snel   [CRYPTO] xts: XTS...
426
427
428
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("XTS block cipher mode");
4943ba16b   Kees Cook   crypto: include c...
429
  MODULE_ALIAS_CRYPTO("xts");
0eb76ba29   Ard Biesheuvel   crypto: remove ci...
430
  MODULE_IMPORT_NS(CRYPTO_INTERNAL);
f84b16330   Herbert Xu   crypto: xts - Add...
431
  MODULE_SOFTDEP("pre: ecb");