[PATCH 07/29] crypto: skcipher - optimize initializing skcipher_walk fields

Eric Biggers
2024-12-21T09:11:32Z

The helper functions like crypto_skcipher_blocksize() take in a pointer
to a tfm object, but they actually return properties of the algorithm.
As the Linux kernel is compiled with -fno-strict-aliasing, the compiler
has to assume that the writes to struct skcipher_walk could clobber the
tfm's pointer to its algorithm. Thus it gets repeatedly reloaded in the
generated code. Therefore, replace the use of these helper functions
with staightforward accesses to the struct fields.

Signed-off-by: Eric Biggers <ebiggers@google.com>
---
crypto/skcipher.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/crypto/skcipher.c b/crypto/skcipher.c
index e54d1ad46566..7ef2e4ddf07a 100644
--- a/crypto/skcipher.c
+++ b/crypto/skcipher.c
@@ -306,12 +306,12 @@ static int skcipher_walk_first(struct skcipher_walk *walk)
}

int skcipher_walk_virt(struct skcipher_walk *walk,
struct skcipher_request *req, bool atomic)
{
- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
- struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
+ const struct skcipher_alg *alg =
+ crypto_skcipher_alg(crypto_skcipher_reqtfm(req));

might_sleep_if(req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP);

walk->total = req->cryptlen;
walk->nbytes = 0;
@@ -326,13 +326,13 @@ int skcipher_walk_virt(struct skcipher_walk *walk,
return 0;

scatterwalk_start(&walk->in, req->src);
scatterwalk_start(&walk->out, req->dst);

- walk->blocksize = crypto_skcipher_blocksize(tfm);
- walk->ivsize = crypto_skcipher_ivsize(tfm);
- walk->alignmask = crypto_skcipher_alignmask(tfm);
+ walk->blocksize = alg->base.cra_blocksize;
+ walk->ivsize = alg->co.ivsize;
+ walk->alignmask = alg->base.cra_alignmask;

if (alg->co.base.cra_type != &crypto_skcipher_type)
walk->stride = alg->co.chunksize;
else
walk->stride = alg->walksize;
@@ -342,11 +342,11 @@ int skcipher_walk_virt(struct skcipher_walk *walk,
EXPORT_SYMBOL_GPL(skcipher_walk_virt);

static int skcipher_walk_aead_common(struct skcipher_walk *walk,
struct aead_request *req, bool atomic)
{
- struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+ const struct aead_alg *alg = crypto_aead_alg(crypto_aead_reqtfm(req));

walk->nbytes = 0;
walk->iv = req->iv;
walk->oiv = req->iv;
if ((req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) && !atomic)
@@ -364,14 +364,14 @@ static int skcipher_walk_aead_common(struct skcipher_walk *walk,
scatterwalk_copychunks(NULL, &walk->out, req->assoclen, 2);

scatterwalk_done(&walk->in, 0, walk->total);
scatterwalk_done(&walk->out, 0, walk->total);

- walk->blocksize = crypto_aead_blocksize(tfm);
- walk->stride = crypto_aead_chunksize(tfm);
- walk->ivsize = crypto_aead_ivsize(tfm);
- walk->alignmask = crypto_aead_alignmask(tfm);
+ walk->blocksize = alg->base.cra_blocksize;
+ walk->stride = alg->chunksize;
+ walk->ivsize = alg->ivsize;
+ walk->alignmask = alg->base.cra_alignmask;

return skcipher_walk_first(walk);
}

int skcipher_walk_aead_encrypt(struct skcipher_walk *walk,
--
2.47.1