|
@@ -21,11 +21,10 @@
|
|
|
#include <linux/scatterlist.h>
|
|
|
#include <linux/slab.h>
|
|
|
|
|
|
+#include <crypto/xts.h>
|
|
|
#include <crypto/b128ops.h>
|
|
|
#include <crypto/gf128mul.h>
|
|
|
|
|
|
-#define XTS_BLOCK_SIZE 16
|
|
|
-
|
|
|
struct priv {
|
|
|
struct crypto_cipher *child;
|
|
|
struct crypto_cipher *tweak;
|
|
@@ -167,6 +166,78 @@ static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
|
|
crypto_cipher_alg(ctx->child)->cia_decrypt);
|
|
|
}
|
|
|
|
|
|
+int xts_crypt(struct blkcipher_desc *desc, struct scatterlist *sdst,
|
|
|
+ struct scatterlist *ssrc, unsigned int nbytes,
|
|
|
+ struct xts_crypt_req *req)
|
|
|
+{
|
|
|
+ const unsigned int bsize = XTS_BLOCK_SIZE;
|
|
|
+ const unsigned int max_blks = req->tbuflen / bsize;
|
|
|
+ struct blkcipher_walk walk;
|
|
|
+ unsigned int nblocks;
|
|
|
+ be128 *src, *dst, *t;
|
|
|
+ be128 *t_buf = req->tbuf;
|
|
|
+ int err, i;
|
|
|
+
|
|
|
+ BUG_ON(max_blks < 1);
|
|
|
+
|
|
|
+ blkcipher_walk_init(&walk, sdst, ssrc, nbytes);
|
|
|
+
|
|
|
+ err = blkcipher_walk_virt(desc, &walk);
|
|
|
+ nbytes = walk.nbytes;
|
|
|
+ if (!nbytes)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ nblocks = min(nbytes / bsize, max_blks);
|
|
|
+ src = (be128 *)walk.src.virt.addr;
|
|
|
+ dst = (be128 *)walk.dst.virt.addr;
|
|
|
+
|
|
|
+ /* calculate first value of T */
|
|
|
+ req->tweak_fn(req->tweak_ctx, (u8 *)&t_buf[0], walk.iv);
|
|
|
+
|
|
|
+ i = 0;
|
|
|
+ goto first;
|
|
|
+
|
|
|
+ for (;;) {
|
|
|
+ do {
|
|
|
+ for (i = 0; i < nblocks; i++) {
|
|
|
+ gf128mul_x_ble(&t_buf[i], t);
|
|
|
+first:
|
|
|
+ t = &t_buf[i];
|
|
|
+
|
|
|
+ /* PP <- T xor P */
|
|
|
+ be128_xor(dst + i, t, src + i);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* CC <- E(Key2,PP) */
|
|
|
+ req->crypt_fn(req->crypt_ctx, (u8 *)dst,
|
|
|
+ nblocks * bsize);
|
|
|
+
|
|
|
+ /* C <- T xor CC */
|
|
|
+ for (i = 0; i < nblocks; i++)
|
|
|
+ be128_xor(dst + i, dst + i, &t_buf[i]);
|
|
|
+
|
|
|
+ src += nblocks;
|
|
|
+ dst += nblocks;
|
|
|
+ nbytes -= nblocks * bsize;
|
|
|
+ nblocks = min(nbytes / bsize, max_blks);
|
|
|
+ } while (nblocks > 0);
|
|
|
+
|
|
|
+ *(be128 *)walk.iv = *t;
|
|
|
+
|
|
|
+ err = blkcipher_walk_done(desc, &walk, nbytes);
|
|
|
+ nbytes = walk.nbytes;
|
|
|
+ if (!nbytes)
|
|
|
+ break;
|
|
|
+
|
|
|
+ nblocks = min(nbytes / bsize, max_blks);
|
|
|
+ src = (be128 *)walk.src.virt.addr;
|
|
|
+ dst = (be128 *)walk.dst.virt.addr;
|
|
|
+ }
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(xts_crypt);
|
|
|
+
|
|
|
static int init_tfm(struct crypto_tfm *tfm)
|
|
|
{
|
|
|
struct crypto_cipher *cipher;
|