summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/digest.c16
-rw-r--r--crypto/internal.h9
2 files changed, 18 insertions, 7 deletions
diff --git a/crypto/digest.c b/crypto/digest.c
index 0df7f392a56a..19e75563776b 100644
--- a/crypto/digest.c
+++ b/crypto/digest.c
@@ -66,14 +66,18 @@ static void update(struct crypto_tfm *tfm,
static void final(struct crypto_tfm *tfm, u8 *out)
{
unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+ struct digest_alg *digest = &tfm->__crt_alg->cra_digest;
+
if (unlikely((unsigned long)out & alignmask)) {
- unsigned int size = crypto_tfm_alg_digestsize(tfm);
- u8 buffer[size + alignmask];
- u8 *dst = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
- tfm->__crt_alg->cra_digest.dia_final(tfm, dst);
- memcpy(out, dst, size);
+ unsigned long align = alignmask + 1;
+ unsigned long addr = (unsigned long)crypto_tfm_ctx(tfm);
+ u8 *dst = (u8 *)ALIGN(addr, align) +
+ ALIGN(tfm->__crt_alg->cra_ctxsize, align);
+
+ digest->dia_final(tfm, dst);
+ memcpy(out, dst, digest->dia_digestsize);
} else
- tfm->__crt_alg->cra_digest.dia_final(tfm, out);
+ digest->dia_final(tfm, out);
}
static int nosetkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
diff --git a/crypto/internal.h b/crypto/internal.h
index 03c00b0e6b60..b110b979b988 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -99,7 +99,14 @@ static inline void crypto_exit_proc(void)
static inline unsigned int crypto_digest_ctxsize(struct crypto_alg *alg,
int flags)
{
- return alg->cra_ctxsize;
+ unsigned int len = alg->cra_ctxsize;
+
+ if (alg->cra_alignmask) {
+ len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1);
+ len += alg->cra_digest.dia_digestsize;
+ }
+
+ return len;
}
static inline unsigned int crypto_cipher_ctxsize(struct crypto_alg *alg,