summaryrefslogtreecommitdiffstats
path: root/crypto/ahash.c
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2019-02-01 02:51:41 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2019-02-08 02:30:08 -0500
commit77568e535af7c4f97eaef1e555bf0af83772456c (patch)
tree5ad037fe1e2edc8dee2d44c36afb2ea86f062280 /crypto/ahash.c
parent3af349639597fea582a93604734d717e59a0e223 (diff)
crypto: ahash - fix another early termination in hash walk
Hash algorithms with an alignmask set, e.g. "xcbc(aes-aesni)" and "michael_mic", fail the improved hash tests because they sometimes produce the wrong digest. The bug is that in the case where a scatterlist element crosses pages, not all the data is actually hashed because the scatterlist walk terminates too early. This happens because the 'nbytes' variable in crypto_hash_walk_done() is assigned the number of bytes remaining in the page, then later interpreted as the number of bytes remaining in the scatterlist element. Fix it. Fixes: 900a081f6912 ("crypto: ahash - Fix early termination in hash walk") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/ahash.c')
-rw-r--r--crypto/ahash.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/crypto/ahash.c b/crypto/ahash.c
index ca0d3e281fef..81e2767e2164 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -86,17 +86,17 @@ static int hash_walk_new_entry(struct crypto_hash_walk *walk)
86int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err) 86int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err)
87{ 87{
88 unsigned int alignmask = walk->alignmask; 88 unsigned int alignmask = walk->alignmask;
89 unsigned int nbytes = walk->entrylen;
90 89
91 walk->data -= walk->offset; 90 walk->data -= walk->offset;
92 91
93 if (nbytes && walk->offset & alignmask && !err) { 92 if (walk->entrylen && (walk->offset & alignmask) && !err) {
94 walk->offset = ALIGN(walk->offset, alignmask + 1); 93 unsigned int nbytes;
95 nbytes = min(nbytes,
96 ((unsigned int)(PAGE_SIZE)) - walk->offset);
97 walk->entrylen -= nbytes;
98 94
95 walk->offset = ALIGN(walk->offset, alignmask + 1);
96 nbytes = min(walk->entrylen,
97 (unsigned int)(PAGE_SIZE - walk->offset));
99 if (nbytes) { 98 if (nbytes) {
99 walk->entrylen -= nbytes;
100 walk->data += walk->offset; 100 walk->data += walk->offset;
101 return nbytes; 101 return nbytes;
102 } 102 }
@@ -116,7 +116,7 @@ int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err)
116 if (err) 116 if (err)
117 return err; 117 return err;
118 118
119 if (nbytes) { 119 if (walk->entrylen) {
120 walk->offset = 0; 120 walk->offset = 0;
121 walk->pg++; 121 walk->pg++;
122 return hash_walk_next(walk); 122 return hash_walk_next(walk);