3
0
Fork 0
forked from mirrors/linux

crypto: algif_aead - use memcpy_sglist() instead of null skcipher

For copying data between two scatterlists, just use memcpy_sglist()
instead of the so-called "null skcipher".  This is much simpler.

Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
Eric Biggers 2025-05-05 12:10:38 -07:00 committed by Herbert Xu
parent bdc2a55687
commit f2804d0eee
2 changed files with 18 additions and 84 deletions

View file

@ -1392,7 +1392,6 @@ config CRYPTO_USER_API_AEAD
depends on NET depends on NET
select CRYPTO_AEAD select CRYPTO_AEAD
select CRYPTO_SKCIPHER select CRYPTO_SKCIPHER
select CRYPTO_NULL
select CRYPTO_USER_API select CRYPTO_USER_API
help help
Enable the userspace interface for AEAD cipher algorithms. Enable the userspace interface for AEAD cipher algorithms.

View file

@ -27,7 +27,6 @@
#include <crypto/scatterwalk.h> #include <crypto/scatterwalk.h>
#include <crypto/if_alg.h> #include <crypto/if_alg.h>
#include <crypto/skcipher.h> #include <crypto/skcipher.h>
#include <crypto/null.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/kernel.h> #include <linux/kernel.h>
@ -36,19 +35,13 @@
#include <linux/net.h> #include <linux/net.h>
#include <net/sock.h> #include <net/sock.h>
struct aead_tfm {
struct crypto_aead *aead;
struct crypto_sync_skcipher *null_tfm;
};
static inline bool aead_sufficient_data(struct sock *sk) static inline bool aead_sufficient_data(struct sock *sk)
{ {
struct alg_sock *ask = alg_sk(sk); struct alg_sock *ask = alg_sk(sk);
struct sock *psk = ask->parent; struct sock *psk = ask->parent;
struct alg_sock *pask = alg_sk(psk); struct alg_sock *pask = alg_sk(psk);
struct af_alg_ctx *ctx = ask->private; struct af_alg_ctx *ctx = ask->private;
struct aead_tfm *aeadc = pask->private; struct crypto_aead *tfm = pask->private;
struct crypto_aead *tfm = aeadc->aead;
unsigned int as = crypto_aead_authsize(tfm); unsigned int as = crypto_aead_authsize(tfm);
/* /*
@ -64,27 +57,12 @@ static int aead_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
struct alg_sock *ask = alg_sk(sk); struct alg_sock *ask = alg_sk(sk);
struct sock *psk = ask->parent; struct sock *psk = ask->parent;
struct alg_sock *pask = alg_sk(psk); struct alg_sock *pask = alg_sk(psk);
struct aead_tfm *aeadc = pask->private; struct crypto_aead *tfm = pask->private;
struct crypto_aead *tfm = aeadc->aead;
unsigned int ivsize = crypto_aead_ivsize(tfm); unsigned int ivsize = crypto_aead_ivsize(tfm);
return af_alg_sendmsg(sock, msg, size, ivsize); return af_alg_sendmsg(sock, msg, size, ivsize);
} }
static int crypto_aead_copy_sgl(struct crypto_sync_skcipher *null_tfm,
struct scatterlist *src,
struct scatterlist *dst, unsigned int len)
{
SYNC_SKCIPHER_REQUEST_ON_STACK(skreq, null_tfm);
skcipher_request_set_sync_tfm(skreq, null_tfm);
skcipher_request_set_callback(skreq, CRYPTO_TFM_REQ_MAY_SLEEP,
NULL, NULL);
skcipher_request_set_crypt(skreq, src, dst, len, NULL);
return crypto_skcipher_encrypt(skreq);
}
static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
size_t ignored, int flags) size_t ignored, int flags)
{ {
@ -93,9 +71,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
struct sock *psk = ask->parent; struct sock *psk = ask->parent;
struct alg_sock *pask = alg_sk(psk); struct alg_sock *pask = alg_sk(psk);
struct af_alg_ctx *ctx = ask->private; struct af_alg_ctx *ctx = ask->private;
struct aead_tfm *aeadc = pask->private; struct crypto_aead *tfm = pask->private;
struct crypto_aead *tfm = aeadc->aead;
struct crypto_sync_skcipher *null_tfm = aeadc->null_tfm;
unsigned int i, as = crypto_aead_authsize(tfm); unsigned int i, as = crypto_aead_authsize(tfm);
struct af_alg_async_req *areq; struct af_alg_async_req *areq;
struct af_alg_tsgl *tsgl, *tmp; struct af_alg_tsgl *tsgl, *tmp;
@ -223,11 +199,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
* v v * v v
* RX SGL: AAD || PT || Tag * RX SGL: AAD || PT || Tag
*/ */
err = crypto_aead_copy_sgl(null_tfm, tsgl_src, memcpy_sglist(areq->first_rsgl.sgl.sgt.sgl, tsgl_src,
areq->first_rsgl.sgl.sgt.sgl, processed);
processed);
if (err)
goto free;
af_alg_pull_tsgl(sk, processed, NULL, 0); af_alg_pull_tsgl(sk, processed, NULL, 0);
} else { } else {
/* /*
@ -241,12 +214,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
* RX SGL: AAD || CT ----+ * RX SGL: AAD || CT ----+
*/ */
/* Copy AAD || CT to RX SGL buffer for in-place operation. */ /* Copy AAD || CT to RX SGL buffer for in-place operation. */
err = crypto_aead_copy_sgl(null_tfm, tsgl_src, memcpy_sglist(areq->first_rsgl.sgl.sgt.sgl, tsgl_src, outlen);
areq->first_rsgl.sgl.sgt.sgl,
outlen);
if (err)
goto free;
/* Create TX SGL for tag and chain it to RX SGL. */ /* Create TX SGL for tag and chain it to RX SGL. */
areq->tsgl_entries = af_alg_count_tsgl(sk, processed, areq->tsgl_entries = af_alg_count_tsgl(sk, processed,
@ -379,7 +348,7 @@ static int aead_check_key(struct socket *sock)
int err = 0; int err = 0;
struct sock *psk; struct sock *psk;
struct alg_sock *pask; struct alg_sock *pask;
struct aead_tfm *tfm; struct crypto_aead *tfm;
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk); struct alg_sock *ask = alg_sk(sk);
@ -393,7 +362,7 @@ static int aead_check_key(struct socket *sock)
err = -ENOKEY; err = -ENOKEY;
lock_sock_nested(psk, SINGLE_DEPTH_NESTING); lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY) if (crypto_aead_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
goto unlock; goto unlock;
atomic_dec(&pask->nokey_refcnt); atomic_dec(&pask->nokey_refcnt);
@ -454,54 +423,22 @@ static struct proto_ops algif_aead_ops_nokey = {
static void *aead_bind(const char *name, u32 type, u32 mask) static void *aead_bind(const char *name, u32 type, u32 mask)
{ {
struct aead_tfm *tfm; return crypto_alloc_aead(name, type, mask);
struct crypto_aead *aead;
struct crypto_sync_skcipher *null_tfm;
tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
if (!tfm)
return ERR_PTR(-ENOMEM);
aead = crypto_alloc_aead(name, type, mask);
if (IS_ERR(aead)) {
kfree(tfm);
return ERR_CAST(aead);
}
null_tfm = crypto_get_default_null_skcipher();
if (IS_ERR(null_tfm)) {
crypto_free_aead(aead);
kfree(tfm);
return ERR_CAST(null_tfm);
}
tfm->aead = aead;
tfm->null_tfm = null_tfm;
return tfm;
} }
static void aead_release(void *private) static void aead_release(void *private)
{ {
struct aead_tfm *tfm = private; crypto_free_aead(private);
crypto_free_aead(tfm->aead);
crypto_put_default_null_skcipher();
kfree(tfm);
} }
static int aead_setauthsize(void *private, unsigned int authsize) static int aead_setauthsize(void *private, unsigned int authsize)
{ {
struct aead_tfm *tfm = private; return crypto_aead_setauthsize(private, authsize);
return crypto_aead_setauthsize(tfm->aead, authsize);
} }
static int aead_setkey(void *private, const u8 *key, unsigned int keylen) static int aead_setkey(void *private, const u8 *key, unsigned int keylen)
{ {
struct aead_tfm *tfm = private; return crypto_aead_setkey(private, key, keylen);
return crypto_aead_setkey(tfm->aead, key, keylen);
} }
static void aead_sock_destruct(struct sock *sk) static void aead_sock_destruct(struct sock *sk)
@ -510,8 +447,7 @@ static void aead_sock_destruct(struct sock *sk)
struct af_alg_ctx *ctx = ask->private; struct af_alg_ctx *ctx = ask->private;
struct sock *psk = ask->parent; struct sock *psk = ask->parent;
struct alg_sock *pask = alg_sk(psk); struct alg_sock *pask = alg_sk(psk);
struct aead_tfm *aeadc = pask->private; struct crypto_aead *tfm = pask->private;
struct crypto_aead *tfm = aeadc->aead;
unsigned int ivlen = crypto_aead_ivsize(tfm); unsigned int ivlen = crypto_aead_ivsize(tfm);
af_alg_pull_tsgl(sk, ctx->used, NULL, 0); af_alg_pull_tsgl(sk, ctx->used, NULL, 0);
@ -524,10 +460,9 @@ static int aead_accept_parent_nokey(void *private, struct sock *sk)
{ {
struct af_alg_ctx *ctx; struct af_alg_ctx *ctx;
struct alg_sock *ask = alg_sk(sk); struct alg_sock *ask = alg_sk(sk);
struct aead_tfm *tfm = private; struct crypto_aead *tfm = private;
struct crypto_aead *aead = tfm->aead;
unsigned int len = sizeof(*ctx); unsigned int len = sizeof(*ctx);
unsigned int ivlen = crypto_aead_ivsize(aead); unsigned int ivlen = crypto_aead_ivsize(tfm);
ctx = sock_kmalloc(sk, len, GFP_KERNEL); ctx = sock_kmalloc(sk, len, GFP_KERNEL);
if (!ctx) if (!ctx)
@ -554,9 +489,9 @@ static int aead_accept_parent_nokey(void *private, struct sock *sk)
static int aead_accept_parent(void *private, struct sock *sk) static int aead_accept_parent(void *private, struct sock *sk)
{ {
struct aead_tfm *tfm = private; struct crypto_aead *tfm = private;
if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY) if (crypto_aead_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
return -ENOKEY; return -ENOKEY;
return aead_accept_parent_nokey(private, sk); return aead_accept_parent_nokey(private, sk);