aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/xts.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/xts.c')
-rw-r--r--crypto/xts.c79
1 files changed, 76 insertions, 3 deletions
diff --git a/crypto/xts.c b/crypto/xts.c
index 851705446c82..ca1608f44cb5 100644
--- a/crypto/xts.c
+++ b/crypto/xts.c
@@ -21,6 +21,7 @@
21#include <linux/scatterlist.h> 21#include <linux/scatterlist.h>
22#include <linux/slab.h> 22#include <linux/slab.h>
23 23
24#include <crypto/xts.h>
24#include <crypto/b128ops.h> 25#include <crypto/b128ops.h>
25#include <crypto/gf128mul.h> 26#include <crypto/gf128mul.h>
26 27
@@ -96,7 +97,7 @@ static int crypt(struct blkcipher_desc *d,
96{ 97{
97 int err; 98 int err;
98 unsigned int avail; 99 unsigned int avail;
99 const int bs = crypto_cipher_blocksize(ctx->child); 100 const int bs = XTS_BLOCK_SIZE;
100 struct sinfo s = { 101 struct sinfo s = {
101 .tfm = crypto_cipher_tfm(ctx->child), 102 .tfm = crypto_cipher_tfm(ctx->child),
102 .fn = fn 103 .fn = fn
@@ -165,6 +166,78 @@ static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
165 crypto_cipher_alg(ctx->child)->cia_decrypt); 166 crypto_cipher_alg(ctx->child)->cia_decrypt);
166} 167}
167 168
169int xts_crypt(struct blkcipher_desc *desc, struct scatterlist *sdst,
170 struct scatterlist *ssrc, unsigned int nbytes,
171 struct xts_crypt_req *req)
172{
173 const unsigned int bsize = XTS_BLOCK_SIZE;
174 const unsigned int max_blks = req->tbuflen / bsize;
175 struct blkcipher_walk walk;
176 unsigned int nblocks;
177 be128 *src, *dst, *t;
178 be128 *t_buf = req->tbuf;
179 int err, i;
180
181 BUG_ON(max_blks < 1);
182
183 blkcipher_walk_init(&walk, sdst, ssrc, nbytes);
184
185 err = blkcipher_walk_virt(desc, &walk);
186 nbytes = walk.nbytes;
187 if (!nbytes)
188 return err;
189
190 nblocks = min(nbytes / bsize, max_blks);
191 src = (be128 *)walk.src.virt.addr;
192 dst = (be128 *)walk.dst.virt.addr;
193
194 /* calculate first value of T */
195 req->tweak_fn(req->tweak_ctx, (u8 *)&t_buf[0], walk.iv);
196
197 i = 0;
198 goto first;
199
200 for (;;) {
201 do {
202 for (i = 0; i < nblocks; i++) {
203 gf128mul_x_ble(&t_buf[i], t);
204first:
205 t = &t_buf[i];
206
207 /* PP <- T xor P */
208 be128_xor(dst + i, t, src + i);
209 }
210
211 /* CC <- E(Key2,PP) */
212 req->crypt_fn(req->crypt_ctx, (u8 *)dst,
213 nblocks * bsize);
214
215 /* C <- T xor CC */
216 for (i = 0; i < nblocks; i++)
217 be128_xor(dst + i, dst + i, &t_buf[i]);
218
219 src += nblocks;
220 dst += nblocks;
221 nbytes -= nblocks * bsize;
222 nblocks = min(nbytes / bsize, max_blks);
223 } while (nblocks > 0);
224
225 *(be128 *)walk.iv = *t;
226
227 err = blkcipher_walk_done(desc, &walk, nbytes);
228 nbytes = walk.nbytes;
229 if (!nbytes)
230 break;
231
232 nblocks = min(nbytes / bsize, max_blks);
233 src = (be128 *)walk.src.virt.addr;
234 dst = (be128 *)walk.dst.virt.addr;
235 }
236
237 return err;
238}
239EXPORT_SYMBOL_GPL(xts_crypt);
240
168static int init_tfm(struct crypto_tfm *tfm) 241static int init_tfm(struct crypto_tfm *tfm)
169{ 242{
170 struct crypto_cipher *cipher; 243 struct crypto_cipher *cipher;
@@ -177,7 +250,7 @@ static int init_tfm(struct crypto_tfm *tfm)
177 if (IS_ERR(cipher)) 250 if (IS_ERR(cipher))
178 return PTR_ERR(cipher); 251 return PTR_ERR(cipher);
179 252
180 if (crypto_cipher_blocksize(cipher) != 16) { 253 if (crypto_cipher_blocksize(cipher) != XTS_BLOCK_SIZE) {
181 *flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; 254 *flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
182 crypto_free_cipher(cipher); 255 crypto_free_cipher(cipher);
183 return -EINVAL; 256 return -EINVAL;
@@ -192,7 +265,7 @@ static int init_tfm(struct crypto_tfm *tfm)
192 } 265 }
193 266
194 /* this check isn't really needed, leave it here just in case */ 267 /* this check isn't really needed, leave it here just in case */
195 if (crypto_cipher_blocksize(cipher) != 16) { 268 if (crypto_cipher_blocksize(cipher) != XTS_BLOCK_SIZE) {
196 crypto_free_cipher(cipher); 269 crypto_free_cipher(cipher);
197 crypto_free_cipher(ctx->child); 270 crypto_free_cipher(ctx->child);
198 *flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; 271 *flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;