]> err.no Git - linux-2.6/blobdiff - crypto/cipher.c
/home/lenb/src/to-linus branch 'acpi-2.6.12'
[linux-2.6] / crypto / cipher.c
index d3295ce14a575790b27fd549acbec3ac2b210879..8da644364cb4225824575ec4813741b9d46d7041 100644 (file)
@@ -41,7 +41,7 @@ static unsigned int crypt_slow(const struct cipher_desc *desc,
                               struct scatter_walk *in,
                               struct scatter_walk *out, unsigned int bsize)
 {
-       unsigned int alignmask = crypto_tfm_alg_alignmask(desc->tfm);
+       unsigned long alignmask = crypto_tfm_alg_alignmask(desc->tfm);
        u8 buffer[bsize * 2 + alignmask];
        u8 *src = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
        u8 *dst = src + bsize;
@@ -154,6 +154,31 @@ static int crypt(const struct cipher_desc *desc,
        return 0;
 }
 
+static int crypt_iv_unaligned(struct cipher_desc *desc,
+                             struct scatterlist *dst,
+                             struct scatterlist *src,
+                             unsigned int nbytes)
+{
+       struct crypto_tfm *tfm = desc->tfm;
+       unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+       u8 *iv = desc->info;
+
+       if (unlikely(((unsigned long)iv & alignmask))) {
+               unsigned int ivsize = tfm->crt_cipher.cit_ivsize;
+               u8 buffer[ivsize + alignmask];
+               u8 *tmp = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+               int err;
+
+               desc->info = memcpy(tmp, iv, ivsize);
+               err = crypt(desc, dst, src, nbytes);
+               memcpy(iv, tmp, ivsize);
+
+               return err;
+       }
+
+       return crypt(desc, dst, src, nbytes);
+}
+
 static unsigned int cbc_process_encrypt(const struct cipher_desc *desc,
                                        u8 *dst, const u8 *src,
                                        unsigned int nbytes)
@@ -298,7 +323,7 @@ static int cbc_encrypt_iv(struct crypto_tfm *tfm,
        desc.prfn = cipher->cia_encrypt_cbc ?: cbc_process_encrypt;
        desc.info = iv;
 
-       return crypt(&desc, dst, src, nbytes);
+       return crypt_iv_unaligned(&desc, dst, src, nbytes);
 }
 
 static int cbc_decrypt(struct crypto_tfm *tfm,
@@ -330,7 +355,7 @@ static int cbc_decrypt_iv(struct crypto_tfm *tfm,
        desc.prfn = cipher->cia_decrypt_cbc ?: cbc_process_decrypt;
        desc.info = iv;
 
-       return crypt(&desc, dst, src, nbytes);
+       return crypt_iv_unaligned(&desc, dst, src, nbytes);
 }
 
 static int nocrypt(struct crypto_tfm *tfm,
@@ -399,7 +424,7 @@ int crypto_init_cipher_ops(struct crypto_tfm *tfm)
        }
        
        if (ops->cit_mode == CRYPTO_TFM_MODE_CBC) {
-               unsigned int align;
+               unsigned long align;
                unsigned long addr;
                
                switch (crypto_tfm_alg_blocksize(tfm)) {