summaryrefslogtreecommitdiff
path: root/arch/s390/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/crypto')
-rw-r--r--arch/s390/crypto/phmac_s390.c52
1 files changed, 34 insertions, 18 deletions
diff --git a/arch/s390/crypto/phmac_s390.c b/arch/s390/crypto/phmac_s390.c
index 7ecfdc4fba2d..89f3e6d8fd89 100644
--- a/arch/s390/crypto/phmac_s390.c
+++ b/arch/s390/crypto/phmac_s390.c
@@ -169,11 +169,18 @@ struct kmac_sha2_ctx {
u64 buflen[2];
};
+enum async_op {
+ OP_NOP = 0,
+ OP_UPDATE,
+ OP_FINAL,
+ OP_FINUP,
+};
+
/* phmac request context */
struct phmac_req_ctx {
struct hash_walk_helper hwh;
struct kmac_sha2_ctx kmac_ctx;
- bool final;
+ enum async_op async_op;
};
/*
@@ -610,6 +617,7 @@ static int phmac_update(struct ahash_request *req)
* using engine to serialize requests.
*/
if (rc == 0 || rc == -EKEYEXPIRED) {
+ req_ctx->async_op = OP_UPDATE;
atomic_inc(&tfm_ctx->via_engine_ctr);
rc = crypto_transfer_hash_request_to_engine(phmac_crypto_engine, req);
if (rc != -EINPROGRESS)
@@ -647,8 +655,7 @@ static int phmac_final(struct ahash_request *req)
* using engine to serialize requests.
*/
if (rc == 0 || rc == -EKEYEXPIRED) {
- req->nbytes = 0;
- req_ctx->final = true;
+ req_ctx->async_op = OP_FINAL;
atomic_inc(&tfm_ctx->via_engine_ctr);
rc = crypto_transfer_hash_request_to_engine(phmac_crypto_engine, req);
if (rc != -EINPROGRESS)
@@ -676,13 +683,16 @@ static int phmac_finup(struct ahash_request *req)
if (rc)
goto out;
+ req_ctx->async_op = OP_FINUP;
+
/* Try synchronous operations if no active engine usage */
if (!atomic_read(&tfm_ctx->via_engine_ctr)) {
rc = phmac_kmac_update(req, false);
if (rc == 0)
- req->nbytes = 0;
+ req_ctx->async_op = OP_FINAL;
}
- if (!rc && !req->nbytes && !atomic_read(&tfm_ctx->via_engine_ctr)) {
+ if (!rc && req_ctx->async_op == OP_FINAL &&
+ !atomic_read(&tfm_ctx->via_engine_ctr)) {
rc = phmac_kmac_final(req, false);
if (rc == 0)
goto out;
@@ -694,7 +704,7 @@ static int phmac_finup(struct ahash_request *req)
* using engine to serialize requests.
*/
if (rc == 0 || rc == -EKEYEXPIRED) {
- req_ctx->final = true;
+ /* req->async_op has been set to either OP_FINUP or OP_FINAL */
atomic_inc(&tfm_ctx->via_engine_ctr);
rc = crypto_transfer_hash_request_to_engine(phmac_crypto_engine, req);
if (rc != -EINPROGRESS)
@@ -855,15 +865,16 @@ static int phmac_do_one_request(struct crypto_engine *engine, void *areq)
/*
* Three kinds of requests come in here:
- * update when req->nbytes > 0 and req_ctx->final is false
- * final when req->nbytes = 0 and req_ctx->final is true
- * finup when req->nbytes > 0 and req_ctx->final is true
- * For update and finup the hwh walk needs to be prepared and
- * up to date but the actual nr of bytes in req->nbytes may be
- * any non zero number. For final there is no hwh walk needed.
+ * 1. req->async_op == OP_UPDATE with req->nbytes > 0
+ * 2. req->async_op == OP_FINUP with req->nbytes > 0
+ * 3. req->async_op == OP_FINAL
+ * For update and finup the hwh walk has already been prepared
+ * by the caller. For final there is no hwh walk needed.
*/
- if (req->nbytes) {
+ switch (req_ctx->async_op) {
+ case OP_UPDATE:
+ case OP_FINUP:
rc = phmac_kmac_update(req, true);
if (rc == -EKEYEXPIRED) {
/*
@@ -880,10 +891,11 @@ static int phmac_do_one_request(struct crypto_engine *engine, void *areq)
hwh_advance(hwh, rc);
goto out;
}
- req->nbytes = 0;
- }
-
- if (req_ctx->final) {
+ if (req_ctx->async_op == OP_UPDATE)
+ break;
+ req_ctx->async_op = OP_FINAL;
+ fallthrough;
+ case OP_FINAL:
rc = phmac_kmac_final(req, true);
if (rc == -EKEYEXPIRED) {
/*
@@ -897,10 +909,14 @@ static int phmac_do_one_request(struct crypto_engine *engine, void *areq)
cond_resched();
return -ENOSPC;
}
+ break;
+ default:
+ /* unknown/unsupported/unimplemented asynch op */
+ return -EOPNOTSUPP;
}
out:
- if (rc || req_ctx->final)
+ if (rc || req_ctx->async_op == OP_FINAL)
memzero_explicit(kmac_ctx, sizeof(*kmac_ctx));
pr_debug("request complete with rc=%d\n", rc);
local_bh_disable();