Commit 075db214 authored by Herbert Xu's avatar Herbert Xu
Browse files

crypto: ahash - Only save callback and data in ahash_save_req



As unaligned operations are supported by the underlying algorithm,
ahash_save_req and ahash_restore_req can be greatly simplified to
only preserve the callback and data.

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 21746054
Loading
Loading
Loading
Loading
+35 −62
Original line number Diff line number Diff line
@@ -41,6 +41,12 @@ struct crypto_hash_walk {
	struct scatterlist *sg;
};

struct ahash_save_req_state {
	struct ahash_request *req;
	crypto_completion_t compl;
	void *data;
};

static int hash_walk_next(struct crypto_hash_walk *walk)
{
	unsigned int offset = walk->offset;
@@ -279,67 +285,34 @@ int crypto_ahash_init(struct ahash_request *req)
}
EXPORT_SYMBOL_GPL(crypto_ahash_init);

static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt,
			  bool has_state)
static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt)
{
	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
	unsigned int ds = crypto_ahash_digestsize(tfm);
	struct ahash_request *subreq;
	unsigned int subreq_size;
	unsigned int reqsize;
	u8 *result;
	struct ahash_save_req_state *state;
	gfp_t gfp;
	u32 flags;

	subreq_size = sizeof(*subreq);
	reqsize = crypto_ahash_reqsize(tfm);
	reqsize = ALIGN(reqsize, crypto_tfm_ctx_alignment());
	subreq_size += reqsize;
	subreq_size += ds;

	flags = ahash_request_flags(req);
	gfp = (flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?  GFP_KERNEL : GFP_ATOMIC;
	subreq = kmalloc(subreq_size, gfp);
	if (!subreq)
	state = kmalloc(sizeof(*state), gfp);
	if (!state)
		return -ENOMEM;

	ahash_request_set_tfm(subreq, tfm);
	ahash_request_set_callback(subreq, flags, cplt, req);

	result = (u8 *)(subreq + 1) + reqsize;

	ahash_request_set_crypt(subreq, req->src, result, req->nbytes);

	if (has_state) {
		void *state;

		state = kmalloc(crypto_ahash_statesize(tfm), gfp);
		if (!state) {
			kfree(subreq);
			return -ENOMEM;
		}

		crypto_ahash_export(req, state);
		crypto_ahash_import(subreq, state);
		kfree_sensitive(state);
	}

	req->priv = subreq;
	state->compl = req->base.complete;
	state->data = req->base.data;
	req->base.complete = cplt;
	req->base.data = state;
	state->req = req;

	return 0;
}

static void ahash_restore_req(struct ahash_request *req, int err)
static void ahash_restore_req(struct ahash_request *req)
{
	struct ahash_request *subreq = req->priv;

	if (!err)
		memcpy(req->result, subreq->result,
		       crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
	struct ahash_save_req_state *state = req->base.data;

	req->priv = NULL;

	kfree_sensitive(subreq);
	req->base.complete = state->compl;
	req->base.data = state->data;
	kfree(state);
}

int crypto_ahash_update(struct ahash_request *req)
@@ -391,51 +364,51 @@ EXPORT_SYMBOL_GPL(crypto_ahash_digest);

static void ahash_def_finup_done2(void *data, int err)
{
	struct ahash_request *areq = data;
	struct ahash_save_req_state *state = data;
	struct ahash_request *areq = state->req;

	if (err == -EINPROGRESS)
		return;

	ahash_restore_req(areq, err);

	ahash_restore_req(areq);
	ahash_request_complete(areq, err);
}

static int ahash_def_finup_finish1(struct ahash_request *req, int err)
{
	struct ahash_request *subreq = req->priv;

	if (err)
		goto out;

	subreq->base.complete = ahash_def_finup_done2;
	req->base.complete = ahash_def_finup_done2;

	err = crypto_ahash_alg(crypto_ahash_reqtfm(req))->final(subreq);
	err = crypto_ahash_alg(crypto_ahash_reqtfm(req))->final(req);
	if (err == -EINPROGRESS || err == -EBUSY)
		return err;

out:
	ahash_restore_req(req, err);
	ahash_restore_req(req);
	return err;
}

static void ahash_def_finup_done1(void *data, int err)
{
	struct ahash_request *areq = data;
	struct ahash_request *subreq;
	struct ahash_save_req_state *state0 = data;
	struct ahash_save_req_state state;
	struct ahash_request *areq;

	state = *state0;
	areq = state.req;
	if (err == -EINPROGRESS)
		goto out;

	subreq = areq->priv;
	subreq->base.flags &= CRYPTO_TFM_REQ_MAY_BACKLOG;
	areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;

	err = ahash_def_finup_finish1(areq, err);
	if (err == -EINPROGRESS || err == -EBUSY)
		return;

out:
	ahash_request_complete(areq, err);
	state.compl(state.data, err);
}

static int ahash_def_finup(struct ahash_request *req)
@@ -443,11 +416,11 @@ static int ahash_def_finup(struct ahash_request *req)
	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
	int err;

	err = ahash_save_req(req, ahash_def_finup_done1, true);
	err = ahash_save_req(req, ahash_def_finup_done1);
	if (err)
		return err;

	err = crypto_ahash_alg(tfm)->update(req->priv);
	err = crypto_ahash_alg(tfm)->update(req);
	if (err == -EINPROGRESS || err == -EBUSY)
		return err;

+0 −3
Original line number Diff line number Diff line
@@ -55,9 +55,6 @@ struct ahash_request {
	struct scatterlist *src;
	u8 *result;

	/* This field may only be used by the ahash API code. */
	void *priv;

	void *__ctx[] CRYPTO_MINALIGN_ATTR;
};