diff options
-rw-r--r-- | crypto/digest.c | 16 | ||||
-rw-r--r-- | crypto/internal.h | 9 |
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, |