|
@@ -71,11 +71,9 @@ static inline u8 *ablkcipher_get_spot(u8 *start, unsigned int len)
|
|
|
return max(start, end_page);
|
|
|
}
|
|
|
|
|
|
-static inline unsigned int ablkcipher_done_slow(struct ablkcipher_walk *walk,
|
|
|
- unsigned int bsize)
|
|
|
+static inline void ablkcipher_done_slow(struct ablkcipher_walk *walk,
|
|
|
+ unsigned int n)
|
|
|
{
|
|
|
- unsigned int n = bsize;
|
|
|
-
|
|
|
for (;;) {
|
|
|
unsigned int len_this_page = scatterwalk_pagelen(&walk->out);
|
|
|
|
|
@@ -87,17 +85,13 @@ static inline unsigned int ablkcipher_done_slow(struct ablkcipher_walk *walk,
|
|
|
n -= len_this_page;
|
|
|
scatterwalk_start(&walk->out, sg_next(walk->out.sg));
|
|
|
}
|
|
|
-
|
|
|
- return bsize;
|
|
|
}
|
|
|
|
|
|
-static inline unsigned int ablkcipher_done_fast(struct ablkcipher_walk *walk,
|
|
|
- unsigned int n)
|
|
|
+static inline void ablkcipher_done_fast(struct ablkcipher_walk *walk,
|
|
|
+ unsigned int n)
|
|
|
{
|
|
|
scatterwalk_advance(&walk->in, n);
|
|
|
scatterwalk_advance(&walk->out, n);
|
|
|
-
|
|
|
- return n;
|
|
|
}
|
|
|
|
|
|
static int ablkcipher_walk_next(struct ablkcipher_request *req,
|
|
@@ -107,39 +101,40 @@ int ablkcipher_walk_done(struct ablkcipher_request *req,
|
|
|
struct ablkcipher_walk *walk, int err)
|
|
|
{
|
|
|
struct crypto_tfm *tfm = req->base.tfm;
|
|
|
- unsigned int nbytes = 0;
|
|
|
+ unsigned int n; /* bytes processed */
|
|
|
+ bool more;
|
|
|
|
|
|
- if (likely(err >= 0)) {
|
|
|
- unsigned int n = walk->nbytes - err;
|
|
|
+ if (unlikely(err < 0))
|
|
|
+ goto finish;
|
|
|
|
|
|
- if (likely(!(walk->flags & ABLKCIPHER_WALK_SLOW)))
|
|
|
- n = ablkcipher_done_fast(walk, n);
|
|
|
- else if (WARN_ON(err)) {
|
|
|
- err = -EINVAL;
|
|
|
- goto err;
|
|
|
- } else
|
|
|
- n = ablkcipher_done_slow(walk, n);
|
|
|
+ n = walk->nbytes - err;
|
|
|
+ walk->total -= n;
|
|
|
+ more = (walk->total != 0);
|
|
|
|
|
|
- nbytes = walk->total - n;
|
|
|
- err = 0;
|
|
|
+ if (likely(!(walk->flags & ABLKCIPHER_WALK_SLOW))) {
|
|
|
+ ablkcipher_done_fast(walk, n);
|
|
|
+ } else {
|
|
|
+ if (WARN_ON(err)) {
|
|
|
+ /* unexpected case; didn't process all bytes */
|
|
|
+ err = -EINVAL;
|
|
|
+ goto finish;
|
|
|
+ }
|
|
|
+ ablkcipher_done_slow(walk, n);
|
|
|
}
|
|
|
|
|
|
- scatterwalk_done(&walk->in, 0, nbytes);
|
|
|
- scatterwalk_done(&walk->out, 1, nbytes);
|
|
|
-
|
|
|
-err:
|
|
|
- walk->total = nbytes;
|
|
|
- walk->nbytes = nbytes;
|
|
|
+ scatterwalk_done(&walk->in, 0, more);
|
|
|
+ scatterwalk_done(&walk->out, 1, more);
|
|
|
|
|
|
- if (nbytes) {
|
|
|
+ if (more) {
|
|
|
crypto_yield(req->base.flags);
|
|
|
return ablkcipher_walk_next(req, walk);
|
|
|
}
|
|
|
-
|
|
|
+ err = 0;
|
|
|
+finish:
|
|
|
+ walk->nbytes = 0;
|
|
|
if (walk->iv != req->info)
|
|
|
memcpy(req->info, walk->iv, tfm->crt_ablkcipher.ivsize);
|
|
|
kfree(walk->iv_buffer);
|
|
|
-
|
|
|
return err;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(ablkcipher_walk_done);
|