|
|
@@ -95,7 +95,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;
|
|
|
|
|
|
@@ -103,19 +103,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 |
|
|
|
@@ -131,7 +133,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
|
|
|
@@ -139,27 +141,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;
|