X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=crypto%2Fcipher.c;h=dfd4bcfc59758332d8ae82fc1d0db2e009c9b26a;hb=0481990b758628e12f4b0a9e15094e70cefc7cd1;hp=d3295ce14a575790b27fd549acbec3ac2b210879;hpb=fbdae9f3e7fb57c07cb0d973f113eb25da2e8ff2;p=linux-2.6 diff --git a/crypto/cipher.c b/crypto/cipher.c index d3295ce14a..dfd4bcfc59 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -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) @@ -166,6 +191,8 @@ static unsigned int cbc_process_encrypt(const struct cipher_desc *desc, u8 *iv = desc->info; unsigned int done = 0; + nbytes -= bsize; + do { xor(iv, src); fn(crypto_tfm_ctx(tfm), dst, iv); @@ -173,7 +200,7 @@ static unsigned int cbc_process_encrypt(const struct cipher_desc *desc, src += bsize; dst += bsize; - } while ((done += bsize) < nbytes); + } while ((done += bsize) <= nbytes); return done; } @@ -194,6 +221,8 @@ static unsigned int cbc_process_decrypt(const struct cipher_desc *desc, u8 *iv = desc->info; unsigned int done = 0; + nbytes -= bsize; + do { u8 *tmp_dst = *dst_p; @@ -205,7 +234,7 @@ static unsigned int cbc_process_decrypt(const struct cipher_desc *desc, src += bsize; dst += bsize; - } while ((done += bsize) < nbytes); + } while ((done += bsize) <= nbytes); return done; } @@ -218,12 +247,14 @@ static unsigned int ecb_process(const struct cipher_desc *desc, u8 *dst, void (*fn)(void *, u8 *, const u8 *) = desc->crfn; unsigned int done = 0; + nbytes -= bsize; + do { fn(crypto_tfm_ctx(tfm), dst, src); src += bsize; dst += bsize; - } while ((done += bsize) < nbytes); + } while ((done += bsize) <= nbytes); return done; } @@ -298,7 +329,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 +361,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, @@ -352,11 +383,7 @@ static int nocrypt_iv(struct crypto_tfm *tfm, int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags) { u32 mode = flags & CRYPTO_TFM_MODE_MASK; - tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB; - if (flags & CRYPTO_TFM_REQ_WEAK_KEY) - tfm->crt_flags = CRYPTO_TFM_REQ_WEAK_KEY; - return 0; } @@ -399,7 +426,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)) {