Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19fa7752 authored by Herbert Xu's avatar Herbert Xu
Browse files

crypto: algif_aead - Switch to new AEAD interface



This patch makes use of the new AEAD interface which uses a single
SG list instead of separate lists for the AD and plain text.

Note that the user-space interface now requires both input and
output to be of the same length, and both must include space for
the AD as well as the authentication tag.

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent a3f2185a
Loading
Loading
Loading
Loading
+8 −58
Original line number Diff line number Diff line
@@ -72,7 +72,7 @@ static inline bool aead_sufficient_data(struct aead_ctx *ctx)
{
	unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req));

	return (ctx->used >= (ctx->aead_assoclen + (ctx->enc ? 0 : as)));
	return ctx->used >= ctx->aead_assoclen + as;
}

static void aead_put_sgl(struct sock *sk)
@@ -353,12 +353,8 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored,
	struct sock *sk = sock->sk;
	struct alg_sock *ask = alg_sk(sk);
	struct aead_ctx *ctx = ask->private;
	unsigned bs = crypto_aead_blocksize(crypto_aead_reqtfm(&ctx->aead_req));
	unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req));
	struct aead_sg_list *sgl = &ctx->tsgl;
	struct scatterlist *sg = NULL;
	struct scatterlist assoc[ALG_MAX_PAGES];
	size_t assoclen = 0;
	unsigned int i = 0;
	int err = -EINVAL;
	unsigned long used = 0;
@@ -407,23 +403,13 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored,
	if (!aead_sufficient_data(ctx))
		goto unlock;

	outlen = used;

	/*
	 * The cipher operation input data is reduced by the associated data
	 * length as this data is processed separately later on.
	 */
	used -= ctx->aead_assoclen;

	if (ctx->enc) {
		/* round up output buffer to multiple of block size */
		outlen = ((used + bs - 1) / bs * bs);
		/* add the size needed for the auth tag to be created */
		outlen += as;
	} else {
		/* output data size is input without the authentication tag */
		outlen = used - as;
		/* round up output buffer to multiple of block size */
		outlen = ((outlen + bs - 1) / bs * bs);
	}
	used -= ctx->aead_assoclen + (ctx->enc ? as : 0);

	/* convert iovecs of output buffers into scatterlists */
	while (iov_iter_count(&msg->msg_iter)) {
@@ -452,47 +438,11 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored,
	if (usedpages < outlen)
		goto unlock;

	sg_init_table(assoc, ALG_MAX_PAGES);
	assoclen = ctx->aead_assoclen;
	/*
	 * Split scatterlist into two: first part becomes AD, second part
	 * is plaintext / ciphertext. The first part is assigned to assoc
	 * scatterlist. When this loop finishes, sg points to the start of the
	 * plaintext / ciphertext.
	 */
	for (i = 0; i < ctx->tsgl.cur; i++) {
		sg = sgl->sg + i;
		if (sg->length <= assoclen) {
			/* AD is larger than one page */
			sg_set_page(assoc + i, sg_page(sg),
				    sg->length, sg->offset);
			assoclen -= sg->length;
			if (i >= ctx->tsgl.cur)
				goto unlock;
		} else if (!assoclen) {
			/* current page is to start of plaintext / ciphertext */
			if (i)
				/* AD terminates at page boundary */
				sg_mark_end(assoc + i - 1);
			else
				/* AD size is zero */
				sg_mark_end(assoc);
			break;
		} else {
			/* AD does not terminate at page boundary */
			sg_set_page(assoc + i, sg_page(sg),
				    assoclen, sg->offset);
			sg_mark_end(assoc + i);
			/* plaintext / ciphertext starts after AD */
			sg->length -= assoclen;
			sg->offset += assoclen;
			break;
		}
	}
	sg_mark_end(sgl->sg + sgl->cur - 1);

	aead_request_set_assoc(&ctx->aead_req, assoc, ctx->aead_assoclen);
	aead_request_set_crypt(&ctx->aead_req, sg, ctx->rsgl[0].sg, used,
			       ctx->iv);
	aead_request_set_crypt(&ctx->aead_req, sgl->sg, ctx->rsgl[0].sg,
			       used, ctx->iv);
	aead_request_set_ad(&ctx->aead_req, ctx->aead_assoclen);

	err = af_alg_wait_for_completion(ctx->enc ?
					 crypto_aead_encrypt(&ctx->aead_req) :