USB: serial: option: add Quectel BG96 id
[pandora-kernel.git] / drivers / md / dm-crypt.c
index 58d8c6d..acdad2d 100644 (file)
@@ -1262,20 +1262,6 @@ static int crypt_decode_key(u8 *key, char *hex, unsigned int size)
        return 0;
 }
 
-/*
- * Encode key into its hex representation
- */
-static void crypt_encode_key(char *hex, u8 *key, unsigned int size)
-{
-       unsigned int i;
-
-       for (i = 0; i < size; i++) {
-               sprintf(hex, "%02x", *key);
-               hex += 2;
-               key++;
-       }
-}
-
 static void crypt_free_tfms(struct crypt_config *cc, int cpu)
 {
        struct crypt_cpu *cpu_cc = per_cpu_ptr(cc->cpu, cpu);
@@ -1336,12 +1322,15 @@ static int crypt_set_key(struct crypt_config *cc, char *key)
        if (!cc->key_size && strcmp(key, "-"))
                goto out;
 
+       /* clear the flag since following operations may invalidate previously valid key */
+       clear_bit(DM_CRYPT_KEY_VALID, &cc->flags);
+
        if (cc->key_size && crypt_decode_key(cc->key, key, cc->key_size) < 0)
                goto out;
 
-       set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
-
        r = crypt_setkey_allcpus(cc);
+       if (!r)
+               set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
 
 out:
        /* Hex key string not needed after here, so wipe it. */
@@ -1579,6 +1568,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        unsigned int key_size, opt_params;
        unsigned long long tmpll;
        int ret;
+       size_t iv_size_padding;
        struct dm_arg_set as;
        const char *opt_string;
 
@@ -1614,12 +1604,23 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
        cc->dmreq_start = sizeof(struct ablkcipher_request);
        cc->dmreq_start += crypto_ablkcipher_reqsize(any_tfm(cc));
-       cc->dmreq_start = ALIGN(cc->dmreq_start, crypto_tfm_ctx_alignment());
-       cc->dmreq_start += crypto_ablkcipher_alignmask(any_tfm(cc)) &
-                          ~(crypto_tfm_ctx_alignment() - 1);
+       cc->dmreq_start = ALIGN(cc->dmreq_start, __alignof__(struct dm_crypt_request));
+
+       if (crypto_ablkcipher_alignmask(any_tfm(cc)) < CRYPTO_MINALIGN) {
+               /* Allocate the padding exactly */
+               iv_size_padding = -(cc->dmreq_start + sizeof(struct dm_crypt_request))
+                               & crypto_ablkcipher_alignmask(any_tfm(cc));
+       } else {
+               /*
+                * If the cipher requires greater alignment than kmalloc
+                * alignment, we don't know the exact position of the
+                * initialization vector. We must assume worst case.
+                */
+               iv_size_padding = crypto_ablkcipher_alignmask(any_tfm(cc));
+       }
 
        cc->req_pool = mempool_create_kmalloc_pool(MIN_IOS, cc->dmreq_start +
-                       sizeof(struct dm_crypt_request) + cc->iv_size);
+                       sizeof(struct dm_crypt_request) + iv_size_padding + cc->iv_size);
        if (!cc->req_pool) {
                ti->error = "Cannot allocate crypt request mempool";
                goto bad;
@@ -1739,11 +1740,11 @@ static int crypt_map(struct dm_target *ti, struct bio *bio,
        return DM_MAPIO_SUBMITTED;
 }
 
-static int crypt_status(struct dm_target *ti, status_type_t type,
-                       char *result, unsigned int maxlen)
+static void crypt_status(struct dm_target *ti, status_type_t type,
+                        char *result, unsigned maxlen)
 {
        struct crypt_config *cc = ti->private;
-       unsigned int sz = 0;
+       unsigned i, sz = 0;
 
        switch (type) {
        case STATUSTYPE_INFO:
@@ -1753,17 +1754,11 @@ static int crypt_status(struct dm_target *ti, status_type_t type,
        case STATUSTYPE_TABLE:
                DMEMIT("%s ", cc->cipher_string);
 
-               if (cc->key_size > 0) {
-                       if ((maxlen - sz) < ((cc->key_size << 1) + 1))
-                               return -ENOMEM;
-
-                       crypt_encode_key(result + sz, cc->key, cc->key_size);
-                       sz += cc->key_size << 1;
-               } else {
-                       if (sz >= maxlen)
-                               return -ENOMEM;
-                       result[sz++] = '-';
-               }
+               if (cc->key_size > 0)
+                       for (i = 0; i < cc->key_size; i++)
+                               DMEMIT("%02x", cc->key[i]);
+               else
+                       DMEMIT("-");
 
                DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset,
                                cc->dev->name, (unsigned long long)cc->start);
@@ -1773,7 +1768,6 @@ static int crypt_status(struct dm_target *ti, status_type_t type,
 
                break;
        }
-       return 0;
 }
 
 static void crypt_postsuspend(struct dm_target *ti)
@@ -1867,7 +1861,7 @@ static int crypt_iterate_devices(struct dm_target *ti,
 
 static struct target_type crypt_target = {
        .name   = "crypt",
-       .version = {1, 11, 0},
+       .version = {1, 11, 1},
        .module = THIS_MODULE,
        .ctr    = crypt_ctr,
        .dtr    = crypt_dtr,