diff options
Diffstat (limited to 'crypto/skcipher.c')
| -rw-r--r-- | crypto/skcipher.c | 42 | 
1 files changed, 23 insertions, 19 deletions
diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 5d836fc3df3e..22753c1c7202 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -90,7 +90,7 @@ static inline u8 *skcipher_get_spot(u8 *start, unsigned int len)  	return max(start, end_page);  } -static void skcipher_done_slow(struct skcipher_walk *walk, unsigned int bsize) +static int skcipher_done_slow(struct skcipher_walk *walk, unsigned int bsize)  {  	u8 *addr; @@ -98,19 +98,21 @@ static void skcipher_done_slow(struct skcipher_walk *walk, unsigned int bsize)  	addr = skcipher_get_spot(addr, bsize);  	scatterwalk_copychunks(addr, &walk->out, bsize,  			       (walk->flags & SKCIPHER_WALK_PHYS) ? 2 : 1); +	return 0;  }  int skcipher_walk_done(struct skcipher_walk *walk, int err)  { -	unsigned int n; /* bytes processed */ -	bool more; +	unsigned int n = walk->nbytes; +	unsigned int nbytes = 0; -	if (unlikely(err < 0)) +	if (!n)  		goto finish; -	n = walk->nbytes - err; -	walk->total -= n; -	more = (walk->total != 0); +	if (likely(err >= 0)) { +		n -= err; +		nbytes = walk->total - n; +	}  	if (likely(!(walk->flags & (SKCIPHER_WALK_PHYS |  				    SKCIPHER_WALK_SLOW | @@ -126,7 +128,7 @@ unmap_src:  		memcpy(walk->dst.virt.addr, walk->page, n);  		skcipher_unmap_dst(walk);  	} else if (unlikely(walk->flags & SKCIPHER_WALK_SLOW)) { -		if (err) { +		if (err > 0) {  			/*  			 * Didn't process all bytes.  Either the algorithm is  			 * broken, or this was the last step and it turned out @@ -134,27 +136,29 @@ unmap_src:  			 * the algorithm requires it.  			 */  			err = -EINVAL; -			goto finish; -		} -		skcipher_done_slow(walk, n); -		goto already_advanced; +			nbytes = 0; +		} else +			n = skcipher_done_slow(walk, n);  	} +	if (err > 0) +		err = 0; + +	walk->total = nbytes; +	walk->nbytes = 0; +  	scatterwalk_advance(&walk->in, n);  	scatterwalk_advance(&walk->out, n); -already_advanced: -	scatterwalk_done(&walk->in, 0, more); -	scatterwalk_done(&walk->out, 1, more); +	scatterwalk_done(&walk->in, 0, nbytes); +	scatterwalk_done(&walk->out, 1, nbytes); -	if (more) { +	if (nbytes) {  		crypto_yield(walk->flags & SKCIPHER_WALK_SLEEP ?  			     CRYPTO_TFM_REQ_MAY_SLEEP : 0);  		return skcipher_walk_next(walk);  	} -	err = 0; -finish: -	walk->nbytes = 0; +finish:  	/* Short-circuit for the common/fast path. */  	if (!((unsigned long)walk->buffer | (unsigned long)walk->page))  		goto out;  |