]> nv-tegra.nvidia Code Review - linux-3.10.git/blobdiff - crypto/ablkcipher.c
[CRYPTO] api: Allow ablkcipher with no queues
[linux-3.10.git] / crypto / ablkcipher.c
index 9348ddd84a56f8ff6f2b4032767c7668cf23feaa..1c166b47b4cc5b5a627c9ab5a8821d7f4f482779 100644 (file)
 #include <linux/module.h>
 #include <linux/seq_file.h>
 
+static int setkey_unaligned(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int keylen)
+{
+       struct ablkcipher_alg *cipher = crypto_ablkcipher_alg(tfm);
+       unsigned long alignmask = crypto_ablkcipher_alignmask(tfm);
+       int ret;
+       u8 *buffer, *alignbuffer;
+       unsigned long absize;
+
+       absize = keylen + alignmask;
+       buffer = kmalloc(absize, GFP_ATOMIC);
+       if (!buffer)
+               return -ENOMEM;
+
+       alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+       memcpy(alignbuffer, key, keylen);
+       ret = cipher->setkey(tfm, alignbuffer, keylen);
+       memset(alignbuffer, 0, absize);
+       kfree(buffer);
+       return ret;
+}
+
 static int setkey(struct crypto_ablkcipher *tfm, const u8 *key,
                  unsigned int keylen)
 {
        struct ablkcipher_alg *cipher = crypto_ablkcipher_alg(tfm);
+       unsigned long alignmask = crypto_ablkcipher_alignmask(tfm);
 
        if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) {
                crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
                return -EINVAL;
        }
 
+       if ((unsigned long)key & alignmask)
+               return setkey_unaligned(tfm, key, keylen);
+
        return cipher->setkey(tfm, key, keylen);
 }
 
@@ -66,8 +91,10 @@ static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
        seq_printf(m, "min keysize  : %u\n", ablkcipher->min_keysize);
        seq_printf(m, "max keysize  : %u\n", ablkcipher->max_keysize);
        seq_printf(m, "ivsize       : %u\n", ablkcipher->ivsize);
-       seq_printf(m, "qlen         : %u\n", ablkcipher->queue->qlen);
-       seq_printf(m, "max qlen     : %u\n", ablkcipher->queue->max_qlen);
+       if (ablkcipher->queue) {
+               seq_printf(m, "qlen         : %u\n", ablkcipher->queue->qlen);
+               seq_printf(m, "max qlen     : %u\n", ablkcipher->queue->max_qlen);
+       }
 }
 
 const struct crypto_type crypto_ablkcipher_type = {