[CRYPTO] geode: use consistent IV copy
[powerpc.git] / drivers / crypto / geode-aes.c
index 6d3840e..6c04f13 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/crypto.h>
 #include <linux/spinlock.h>
 #include <crypto/algapi.h>
+#include <crypto/aes.h>
 
 #include <asm/io.h>
 #include <asm/delay.h>
@@ -102,11 +103,15 @@ geode_aes_crypt(struct geode_aes_op *op)
        u32 flags = 0;
        unsigned long iflags;
 
-       if (op->len == 0 || op->src == op->dst)
+       if (op->len == 0)
                return 0;
 
-       if (op->flags & AES_FLAGS_COHERENT)
-               flags |= (AES_CTRL_DCA | AES_CTRL_SCA);
+       /* If the source and destination is the same, then
+        * we need to turn on the coherent flags, otherwise
+        * we don't need to worry
+        */
+
+       flags |= (AES_CTRL_DCA | AES_CTRL_SCA);
 
        if (op->dir == AES_DIR_ENCRYPT)
                flags |= AES_CTRL_ENCRYPT;
@@ -120,7 +125,7 @@ geode_aes_crypt(struct geode_aes_op *op)
                _writefield(AES_WRITEIV0_REG, op->iv);
        }
 
-       if (op->flags & AES_FLAGS_USRKEY) {
+       if (!(op->flags & AES_FLAGS_HIDDENKEY)) {
                flags |= AES_CTRL_WRKEY;
                _writefield(AES_WRITEKEY0_REG, op->key);
        }
@@ -221,6 +226,7 @@ geode_cbc_decrypt(struct blkcipher_desc *desc,
 
        blkcipher_walk_init(&walk, dst, src, nbytes);
        err = blkcipher_walk_virt(desc, &walk);
+       memcpy(op->iv, walk.iv, AES_IV_LENGTH);
 
        while((nbytes = walk.nbytes)) {
                op->src = walk.src.virt.addr,
@@ -229,16 +235,13 @@ geode_cbc_decrypt(struct blkcipher_desc *desc,
                op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
                op->dir = AES_DIR_DECRYPT;
 
-               memcpy(op->iv, walk.iv, AES_IV_LENGTH);
-
                ret = geode_aes_crypt(op);
 
-               memcpy(walk.iv, op->iv, AES_IV_LENGTH);
                nbytes -= ret;
-
                err = blkcipher_walk_done(desc, &walk, nbytes);
        }
 
+       memcpy(walk.iv, op->iv, AES_IV_LENGTH);
        return err;
 }
 
@@ -253,6 +256,7 @@ geode_cbc_encrypt(struct blkcipher_desc *desc,
 
        blkcipher_walk_init(&walk, dst, src, nbytes);
        err = blkcipher_walk_virt(desc, &walk);
+       memcpy(op->iv, walk.iv, AES_IV_LENGTH);
 
        while((nbytes = walk.nbytes)) {
                op->src = walk.src.virt.addr,
@@ -261,13 +265,12 @@ geode_cbc_encrypt(struct blkcipher_desc *desc,
                op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
                op->dir = AES_DIR_ENCRYPT;
 
-               memcpy(op->iv, walk.iv, AES_IV_LENGTH);
-
                ret = geode_aes_crypt(op);
                nbytes -= ret;
                err = blkcipher_walk_done(desc, &walk, nbytes);
        }
 
+       memcpy(walk.iv, op->iv, AES_IV_LENGTH);
        return err;
 }
 
@@ -289,6 +292,7 @@ static struct crypto_alg geode_cbc_alg = {
                        .setkey                 =       geode_setkey,
                        .encrypt                =       geode_cbc_encrypt,
                        .decrypt                =       geode_cbc_decrypt,
+                       .ivsize                 =       AES_IV_LENGTH,
                }
        }
 };