|
@@ -32,6 +32,7 @@ struct ahash_request_priv {
|
|
|
crypto_completion_t complete;
|
|
|
void *data;
|
|
|
u8 *result;
|
|
|
+ u32 flags;
|
|
|
void *ubuf[] CRYPTO_MINALIGN_ATTR;
|
|
|
};
|
|
|
|
|
@@ -253,6 +254,8 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt)
|
|
|
priv->result = req->result;
|
|
|
priv->complete = req->base.complete;
|
|
|
priv->data = req->base.data;
|
|
|
+ priv->flags = req->base.flags;
|
|
|
+
|
|
|
/*
|
|
|
* WARNING: We do not backup req->priv here! The req->priv
|
|
|
* is for internal use of the Crypto API and the
|
|
@@ -267,38 +270,44 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void ahash_restore_req(struct ahash_request *req)
|
|
|
+static void ahash_restore_req(struct ahash_request *req, int err)
|
|
|
{
|
|
|
struct ahash_request_priv *priv = req->priv;
|
|
|
|
|
|
+ if (!err)
|
|
|
+ memcpy(priv->result, req->result,
|
|
|
+ crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
|
|
|
+
|
|
|
/* Restore the original crypto request. */
|
|
|
req->result = priv->result;
|
|
|
- req->base.complete = priv->complete;
|
|
|
- req->base.data = priv->data;
|
|
|
+
|
|
|
+ ahash_request_set_callback(req, priv->flags,
|
|
|
+ priv->complete, priv->data);
|
|
|
req->priv = NULL;
|
|
|
|
|
|
/* Free the req->priv.priv from the ADJUSTED request. */
|
|
|
kzfree(priv);
|
|
|
}
|
|
|
|
|
|
-static void ahash_op_unaligned_finish(struct ahash_request *req, int err)
|
|
|
+static void ahash_notify_einprogress(struct ahash_request *req)
|
|
|
{
|
|
|
struct ahash_request_priv *priv = req->priv;
|
|
|
+ struct crypto_async_request oreq;
|
|
|
|
|
|
- if (err == -EINPROGRESS)
|
|
|
- return;
|
|
|
-
|
|
|
- if (!err)
|
|
|
- memcpy(priv->result, req->result,
|
|
|
- crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
|
|
|
+ oreq.data = priv->data;
|
|
|
|
|
|
- ahash_restore_req(req);
|
|
|
+ priv->complete(&oreq, -EINPROGRESS);
|
|
|
}
|
|
|
|
|
|
static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
|
|
|
{
|
|
|
struct ahash_request *areq = req->data;
|
|
|
|
|
|
+ if (err == -EINPROGRESS) {
|
|
|
+ ahash_notify_einprogress(areq);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* Restore the original request, see ahash_op_unaligned() for what
|
|
|
* goes where.
|
|
@@ -309,7 +318,7 @@ static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
|
|
|
*/
|
|
|
|
|
|
/* First copy req->result into req->priv.result */
|
|
|
- ahash_op_unaligned_finish(areq, err);
|
|
|
+ ahash_restore_req(areq, err);
|
|
|
|
|
|
/* Complete the ORIGINAL request. */
|
|
|
areq->base.complete(&areq->base, err);
|
|
@@ -325,7 +334,12 @@ static int ahash_op_unaligned(struct ahash_request *req,
|
|
|
return err;
|
|
|
|
|
|
err = op(req);
|
|
|
- ahash_op_unaligned_finish(req, err);
|
|
|
+ if (err == -EINPROGRESS ||
|
|
|
+ (err == -EBUSY && (ahash_request_flags(req) &
|
|
|
+ CRYPTO_TFM_REQ_MAY_BACKLOG)))
|
|
|
+ return err;
|
|
|
+
|
|
|
+ ahash_restore_req(req, err);
|
|
|
|
|
|
return err;
|
|
|
}
|
|
@@ -360,25 +374,14 @@ int crypto_ahash_digest(struct ahash_request *req)
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(crypto_ahash_digest);
|
|
|
|
|
|
-static void ahash_def_finup_finish2(struct ahash_request *req, int err)
|
|
|
+static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
|
|
|
{
|
|
|
- struct ahash_request_priv *priv = req->priv;
|
|
|
+ struct ahash_request *areq = req->data;
|
|
|
|
|
|
if (err == -EINPROGRESS)
|
|
|
return;
|
|
|
|
|
|
- if (!err)
|
|
|
- memcpy(priv->result, req->result,
|
|
|
- crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
|
|
|
-
|
|
|
- ahash_restore_req(req);
|
|
|
-}
|
|
|
-
|
|
|
-static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
|
|
|
-{
|
|
|
- struct ahash_request *areq = req->data;
|
|
|
-
|
|
|
- ahash_def_finup_finish2(areq, err);
|
|
|
+ ahash_restore_req(areq, err);
|
|
|
|
|
|
areq->base.complete(&areq->base, err);
|
|
|
}
|
|
@@ -389,11 +392,15 @@ static int ahash_def_finup_finish1(struct ahash_request *req, int err)
|
|
|
goto out;
|
|
|
|
|
|
req->base.complete = ahash_def_finup_done2;
|
|
|
- req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
|
|
|
+
|
|
|
err = crypto_ahash_reqtfm(req)->final(req);
|
|
|
+ if (err == -EINPROGRESS ||
|
|
|
+ (err == -EBUSY && (ahash_request_flags(req) &
|
|
|
+ CRYPTO_TFM_REQ_MAY_BACKLOG)))
|
|
|
+ return err;
|
|
|
|
|
|
out:
|
|
|
- ahash_def_finup_finish2(req, err);
|
|
|
+ ahash_restore_req(req, err);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -401,7 +408,16 @@ static void ahash_def_finup_done1(struct crypto_async_request *req, int err)
|
|
|
{
|
|
|
struct ahash_request *areq = req->data;
|
|
|
|
|
|
+ if (err == -EINPROGRESS) {
|
|
|
+ ahash_notify_einprogress(areq);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
|
|
|
+
|
|
|
err = ahash_def_finup_finish1(areq, err);
|
|
|
+ if (areq->priv)
|
|
|
+ return;
|
|
|
|
|
|
areq->base.complete(&areq->base, err);
|
|
|
}
|
|
@@ -416,6 +432,11 @@ static int ahash_def_finup(struct ahash_request *req)
|
|
|
return err;
|
|
|
|
|
|
err = tfm->update(req);
|
|
|
+ if (err == -EINPROGRESS ||
|
|
|
+ (err == -EBUSY && (ahash_request_flags(req) &
|
|
|
+ CRYPTO_TFM_REQ_MAY_BACKLOG)))
|
|
|
+ return err;
|
|
|
+
|
|
|
return ahash_def_finup_finish1(req, err);
|
|
|
}
|
|
|
|