mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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: 900a081f69 ("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>
			
			
This commit is contained in:
		
							parent
							
								
									3af3496395
								
							
						
					
					
						commit
						77568e535a
					
				
					 1 changed files with 7 additions and 7 deletions
				
			
		| 
						 | 
					@ -86,17 +86,17 @@ static int hash_walk_new_entry(struct crypto_hash_walk *walk)
 | 
				
			||||||
int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err)
 | 
					int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int alignmask = walk->alignmask;
 | 
						unsigned int alignmask = walk->alignmask;
 | 
				
			||||||
	unsigned int nbytes = walk->entrylen;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	walk->data -= walk->offset;
 | 
						walk->data -= walk->offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (nbytes && walk->offset & alignmask && !err) {
 | 
						if (walk->entrylen && (walk->offset & alignmask) && !err) {
 | 
				
			||||||
		walk->offset = ALIGN(walk->offset, alignmask + 1);
 | 
							unsigned int nbytes;
 | 
				
			||||||
		nbytes = min(nbytes,
 | 
					 | 
				
			||||||
			     ((unsigned int)(PAGE_SIZE)) - walk->offset);
 | 
					 | 
				
			||||||
		walk->entrylen -= nbytes;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							walk->offset = ALIGN(walk->offset, alignmask + 1);
 | 
				
			||||||
 | 
							nbytes = min(walk->entrylen,
 | 
				
			||||||
 | 
								     (unsigned int)(PAGE_SIZE - walk->offset));
 | 
				
			||||||
		if (nbytes) {
 | 
							if (nbytes) {
 | 
				
			||||||
 | 
								walk->entrylen -= nbytes;
 | 
				
			||||||
			walk->data += walk->offset;
 | 
								walk->data += walk->offset;
 | 
				
			||||||
			return nbytes;
 | 
								return nbytes;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -116,7 +116,7 @@ int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err)
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (nbytes) {
 | 
						if (walk->entrylen) {
 | 
				
			||||||
		walk->offset = 0;
 | 
							walk->offset = 0;
 | 
				
			||||||
		walk->pg++;
 | 
							walk->pg++;
 | 
				
			||||||
		return hash_walk_next(walk);
 | 
							return hash_walk_next(walk);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue