Commit 3ad81aa5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull crypto fixes from Herbert Xu:

 - Fix double free in aspeed

 - Fix req->nbytes clobbering in s390/phmac

* tag 'v6.18-p4' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6:
  crypto: aspeed - fix double free caused by devm
  crypto: s390/phmac - Do not modify the req->nbytes value
parents 2d51cb17 3c9bf72c
Loading
Loading
Loading
Loading
+34 −18
Original line number Diff line number Diff line
@@ -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();
+0 −2
Original line number Diff line number Diff line
@@ -787,7 +787,6 @@ static int aspeed_acry_probe(struct platform_device *pdev)
err_engine_rsa_start:
	crypto_engine_exit(acry_dev->crypt_engine_rsa);
clk_exit:
	clk_disable_unprepare(acry_dev->clk);

	return rc;
}
@@ -799,7 +798,6 @@ static void aspeed_acry_remove(struct platform_device *pdev)
	aspeed_acry_unregister(acry_dev);
	crypto_engine_exit(acry_dev->crypt_engine_rsa);
	tasklet_kill(&acry_dev->done_task);
	clk_disable_unprepare(acry_dev->clk);
}

MODULE_DEVICE_TABLE(of, aspeed_acry_of_matches);