Merge branch 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa...
[firefly-linux-kernel-4.4.55.git] / drivers / md / dm-crypt.c
index 0fce0bc1a9572f70167cc66d0524186e9e5abece..81b0fa66045204604a979fdc929e723f6c914a5c 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) 2003 Christophe Saout <christophe@saout.de>
  * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
  * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2013 Milan Broz <gmazyland@gmail.com>
  *
  * This file is released under the GPL.
  */
@@ -98,6 +99,13 @@ struct iv_lmk_private {
        u8 *seed;
 };
 
+#define TCW_WHITENING_SIZE 16
+struct iv_tcw_private {
+       struct crypto_shash *crc32_tfm;
+       u8 *iv_seed;
+       u8 *whitening;
+};
+
 /*
  * Crypt: maps a linear range of a block device
  * and encrypts / decrypts at the same time.
@@ -139,6 +147,7 @@ struct crypt_config {
                struct iv_essiv_private essiv;
                struct iv_benbi_private benbi;
                struct iv_lmk_private lmk;
+               struct iv_tcw_private tcw;
        } iv_gen_private;
        sector_t iv_offset;
        unsigned int iv_size;
@@ -171,7 +180,8 @@ struct crypt_config {
 
        unsigned long flags;
        unsigned int key_size;
-       unsigned int key_parts;
+       unsigned int key_parts;      /* independent parts in key buffer */
+       unsigned int key_extra_size; /* additional keys length */
        u8 key[0];
 };
 
@@ -230,6 +240,16 @@ static struct crypto_ablkcipher *any_tfm(struct crypt_config *cc)
  *         version 3: the same as version 2 with additional IV seed
  *                   (it uses 65 keys, last key is used as IV seed)
  *
+ * tcw:  Compatible implementation of the block chaining mode used
+ *       by the TrueCrypt device encryption system (prior to version 4.1).
+ *       For more info see: http://www.truecrypt.org
+ *       It operates on full 512 byte sectors and uses CBC
+ *       with an IV derived from initial key and the sector number.
+ *       In addition, whitening value is applied on every sector, whitening
+ *       is calculated from initial key, sector number and mixed using CRC32.
+ *       Note that this encryption scheme is vulnerable to watermarking attacks
+ *       and should be used for old compatible containers access only.
+ *
  * plumb: unimplemented, see:
  * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454
  */
@@ -530,7 +550,7 @@ static int crypt_iv_lmk_one(struct crypt_config *cc, u8 *iv,
                char ctx[crypto_shash_descsize(lmk->hash_tfm)];
        } sdesc;
        struct md5_state md5state;
-       u32 buf[4];
+       __le32 buf[4];
        int i, r;
 
        sdesc.desc.tfm = lmk->hash_tfm;
@@ -608,6 +628,153 @@ static int crypt_iv_lmk_post(struct crypt_config *cc, u8 *iv,
        return r;
 }
 
+static void crypt_iv_tcw_dtr(struct crypt_config *cc)
+{
+       struct iv_tcw_private *tcw = &cc->iv_gen_private.tcw;
+
+       kzfree(tcw->iv_seed);
+       tcw->iv_seed = NULL;
+       kzfree(tcw->whitening);
+       tcw->whitening = NULL;
+
+       if (tcw->crc32_tfm && !IS_ERR(tcw->crc32_tfm))
+               crypto_free_shash(tcw->crc32_tfm);
+       tcw->crc32_tfm = NULL;
+}
+
+static int crypt_iv_tcw_ctr(struct crypt_config *cc, struct dm_target *ti,
+                           const char *opts)
+{
+       struct iv_tcw_private *tcw = &cc->iv_gen_private.tcw;
+
+       if (cc->key_size <= (cc->iv_size + TCW_WHITENING_SIZE)) {
+               ti->error = "Wrong key size for TCW";
+               return -EINVAL;
+       }
+
+       tcw->crc32_tfm = crypto_alloc_shash("crc32", 0, 0);
+       if (IS_ERR(tcw->crc32_tfm)) {
+               ti->error = "Error initializing CRC32 in TCW";
+               return PTR_ERR(tcw->crc32_tfm);
+       }
+
+       tcw->iv_seed = kzalloc(cc->iv_size, GFP_KERNEL);
+       tcw->whitening = kzalloc(TCW_WHITENING_SIZE, GFP_KERNEL);
+       if (!tcw->iv_seed || !tcw->whitening) {
+               crypt_iv_tcw_dtr(cc);
+               ti->error = "Error allocating seed storage in TCW";
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static int crypt_iv_tcw_init(struct crypt_config *cc)
+{
+       struct iv_tcw_private *tcw = &cc->iv_gen_private.tcw;
+       int key_offset = cc->key_size - cc->iv_size - TCW_WHITENING_SIZE;
+
+       memcpy(tcw->iv_seed, &cc->key[key_offset], cc->iv_size);
+       memcpy(tcw->whitening, &cc->key[key_offset + cc->iv_size],
+              TCW_WHITENING_SIZE);
+
+       return 0;
+}
+
+static int crypt_iv_tcw_wipe(struct crypt_config *cc)
+{
+       struct iv_tcw_private *tcw = &cc->iv_gen_private.tcw;
+
+       memset(tcw->iv_seed, 0, cc->iv_size);
+       memset(tcw->whitening, 0, TCW_WHITENING_SIZE);
+
+       return 0;
+}
+
+static int crypt_iv_tcw_whitening(struct crypt_config *cc,
+                                 struct dm_crypt_request *dmreq,
+                                 u8 *data)
+{
+       struct iv_tcw_private *tcw = &cc->iv_gen_private.tcw;
+       u64 sector = cpu_to_le64((u64)dmreq->iv_sector);
+       u8 buf[TCW_WHITENING_SIZE];
+       struct {
+               struct shash_desc desc;
+               char ctx[crypto_shash_descsize(tcw->crc32_tfm)];
+       } sdesc;
+       int i, r;
+
+       /* xor whitening with sector number */
+       memcpy(buf, tcw->whitening, TCW_WHITENING_SIZE);
+       crypto_xor(buf, (u8 *)&sector, 8);
+       crypto_xor(&buf[8], (u8 *)&sector, 8);
+
+       /* calculate crc32 for every 32bit part and xor it */
+       sdesc.desc.tfm = tcw->crc32_tfm;
+       sdesc.desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+       for (i = 0; i < 4; i++) {
+               r = crypto_shash_init(&sdesc.desc);
+               if (r)
+                       goto out;
+               r = crypto_shash_update(&sdesc.desc, &buf[i * 4], 4);
+               if (r)
+                       goto out;
+               r = crypto_shash_final(&sdesc.desc, &buf[i * 4]);
+               if (r)
+                       goto out;
+       }
+       crypto_xor(&buf[0], &buf[12], 4);
+       crypto_xor(&buf[4], &buf[8], 4);
+
+       /* apply whitening (8 bytes) to whole sector */
+       for (i = 0; i < ((1 << SECTOR_SHIFT) / 8); i++)
+               crypto_xor(data + i * 8, buf, 8);
+out:
+       memset(buf, 0, sizeof(buf));
+       return r;
+}
+
+static int crypt_iv_tcw_gen(struct crypt_config *cc, u8 *iv,
+                           struct dm_crypt_request *dmreq)
+{
+       struct iv_tcw_private *tcw = &cc->iv_gen_private.tcw;
+       u64 sector = cpu_to_le64((u64)dmreq->iv_sector);
+       u8 *src;
+       int r = 0;
+
+       /* Remove whitening from ciphertext */
+       if (bio_data_dir(dmreq->ctx->bio_in) != WRITE) {
+               src = kmap_atomic(sg_page(&dmreq->sg_in));
+               r = crypt_iv_tcw_whitening(cc, dmreq, src + dmreq->sg_in.offset);
+               kunmap_atomic(src);
+       }
+
+       /* Calculate IV */
+       memcpy(iv, tcw->iv_seed, cc->iv_size);
+       crypto_xor(iv, (u8 *)&sector, 8);
+       if (cc->iv_size > 8)
+               crypto_xor(&iv[8], (u8 *)&sector, cc->iv_size - 8);
+
+       return r;
+}
+
+static int crypt_iv_tcw_post(struct crypt_config *cc, u8 *iv,
+                            struct dm_crypt_request *dmreq)
+{
+       u8 *dst;
+       int r;
+
+       if (bio_data_dir(dmreq->ctx->bio_in) != WRITE)
+               return 0;
+
+       /* Apply whitening on ciphertext */
+       dst = kmap_atomic(sg_page(&dmreq->sg_out));
+       r = crypt_iv_tcw_whitening(cc, dmreq, dst + dmreq->sg_out.offset);
+       kunmap_atomic(dst);
+
+       return r;
+}
+
 static struct crypt_iv_operations crypt_iv_plain_ops = {
        .generator = crypt_iv_plain_gen
 };
@@ -643,6 +810,15 @@ static struct crypt_iv_operations crypt_iv_lmk_ops = {
        .post      = crypt_iv_lmk_post
 };
 
+static struct crypt_iv_operations crypt_iv_tcw_ops = {
+       .ctr       = crypt_iv_tcw_ctr,
+       .dtr       = crypt_iv_tcw_dtr,
+       .init      = crypt_iv_tcw_init,
+       .wipe      = crypt_iv_tcw_wipe,
+       .generator = crypt_iv_tcw_gen,
+       .post      = crypt_iv_tcw_post
+};
+
 static void crypt_convert_init(struct crypt_config *cc,
                               struct convert_context *ctx,
                               struct bio *bio_out, struct bio *bio_in,
@@ -774,7 +950,7 @@ static int crypt_convert(struct crypt_config *cc,
                /* async */
                case -EBUSY:
                        wait_for_completion(&ctx->restart);
-                       INIT_COMPLETION(ctx->restart);
+                       reinit_completion(&ctx->restart);
                        /* fall through*/
                case -EINPROGRESS:
                        this_cc->req = NULL;
@@ -1274,9 +1450,12 @@ static int crypt_alloc_tfms(struct crypt_config *cc, char *ciphermode)
 
 static int crypt_setkey_allcpus(struct crypt_config *cc)
 {
-       unsigned subkey_size = cc->key_size >> ilog2(cc->tfms_count);
+       unsigned subkey_size;
        int err = 0, i, r;
 
+       /* Ignore extra keys (which are used for IV etc) */
+       subkey_size = (cc->key_size - cc->key_extra_size) >> ilog2(cc->tfms_count);
+
        for (i = 0; i < cc->tfms_count; i++) {
                r = crypto_ablkcipher_setkey(cc->tfms[i],
                                             cc->key + (i * subkey_size),
@@ -1409,6 +1588,7 @@ static int crypt_ctr_cipher(struct dm_target *ti,
                return -EINVAL;
        }
        cc->key_parts = cc->tfms_count;
+       cc->key_extra_size = 0;
 
        cc->cipher = kstrdup(cipher, GFP_KERNEL);
        if (!cc->cipher)
@@ -1460,13 +1640,6 @@ static int crypt_ctr_cipher(struct dm_target *ti,
                goto bad;
        }
 
-       /* Initialize and set key */
-       ret = crypt_set_key(cc, key);
-       if (ret < 0) {
-               ti->error = "Error decoding and setting key";
-               goto bad;
-       }
-
        /* Initialize IV */
        cc->iv_size = crypto_ablkcipher_ivsize(any_tfm(cc));
        if (cc->iv_size)
@@ -1493,18 +1666,33 @@ static int crypt_ctr_cipher(struct dm_target *ti,
                cc->iv_gen_ops = &crypt_iv_null_ops;
        else if (strcmp(ivmode, "lmk") == 0) {
                cc->iv_gen_ops = &crypt_iv_lmk_ops;
-               /* Version 2 and 3 is recognised according
+               /*
+                * Version 2 and 3 is recognised according
                 * to length of provided multi-key string.
                 * If present (version 3), last key is used as IV seed.
+                * All keys (including IV seed) are always the same size.
                 */
-               if (cc->key_size % cc->key_parts)
+               if (cc->key_size % cc->key_parts) {
                        cc->key_parts++;
+                       cc->key_extra_size = cc->key_size / cc->key_parts;
+               }
+       } else if (strcmp(ivmode, "tcw") == 0) {
+               cc->iv_gen_ops = &crypt_iv_tcw_ops;
+               cc->key_parts += 2; /* IV + whitening */
+               cc->key_extra_size = cc->iv_size + TCW_WHITENING_SIZE;
        } else {
                ret = -EINVAL;
                ti->error = "Invalid IV mode";
                goto bad;
        }
 
+       /* Initialize and set key */
+       ret = crypt_set_key(cc, key);
+       if (ret < 0) {
+               ti->error = "Error decoding and setting key";
+               goto bad;
+       }
+
        /* Allocate IV */
        if (cc->iv_gen_ops && cc->iv_gen_ops->ctr) {
                ret = cc->iv_gen_ops->ctr(cc, ti, ivopts);
@@ -1817,7 +2005,7 @@ static int crypt_iterate_devices(struct dm_target *ti,
 
 static struct target_type crypt_target = {
        .name   = "crypt",
-       .version = {1, 12, 1},
+       .version = {1, 13, 0},
        .module = THIS_MODULE,
        .ctr    = crypt_ctr,
        .dtr    = crypt_dtr,