]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
fscrypt: Switch to sync_skcipher and on-stack requests
authorEric Biggers <ebiggers@kernel.org>
Thu, 10 Jul 2025 06:07:50 +0000 (23:07 -0700)
committerEric Biggers <ebiggers@kernel.org>
Thu, 10 Jul 2025 19:33:08 +0000 (12:33 -0700)
Now that fscrypt uses only synchronous skciphers, switch to the actual
sync_skcipher API and the corresponding on-stack requests.  This
eliminates a heap allocation per en/decryption operation.

Link: https://lore.kernel.org/r/20250710060754.637098-4-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
fs/crypto/crypto.c
fs/crypto/fname.c
fs/crypto/fscrypt_private.h
fs/crypto/keysetup.c
fs/crypto/keysetup_v1.c

index 43d1658e07cec4a72d29b383f92b0e85230f8449..646b1831e683195c9ef4f364a4f88435ee97506c 100644 (file)
@@ -113,11 +113,11 @@ int fscrypt_crypt_data_unit(const struct fscrypt_inode_info *ci,
                            unsigned int len, unsigned int offs,
                            gfp_t gfp_flags)
 {
+       struct crypto_sync_skcipher *tfm = ci->ci_enc_key.tfm;
+       SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm);
        union fscrypt_iv iv;
-       struct skcipher_request *req = NULL;
        struct scatterlist dst, src;
-       struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
-       int res = 0;
+       int err;
 
        if (WARN_ON_ONCE(len <= 0))
                return -EINVAL;
@@ -126,31 +126,23 @@ int fscrypt_crypt_data_unit(const struct fscrypt_inode_info *ci,
 
        fscrypt_generate_iv(&iv, index, ci);
 
-       req = skcipher_request_alloc(tfm, gfp_flags);
-       if (!req)
-               return -ENOMEM;
-
        skcipher_request_set_callback(
                req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
                NULL, NULL);
-
        sg_init_table(&dst, 1);
        sg_set_page(&dst, dest_page, len, offs);
        sg_init_table(&src, 1);
        sg_set_page(&src, src_page, len, offs);
        skcipher_request_set_crypt(req, &src, &dst, len, &iv);
        if (rw == FS_DECRYPT)
-               res = crypto_skcipher_decrypt(req);
+               err = crypto_skcipher_decrypt(req);
        else
-               res = crypto_skcipher_encrypt(req);
-       skcipher_request_free(req);
-       if (res) {
+               err = crypto_skcipher_encrypt(req);
+       if (err)
                fscrypt_err(ci->ci_inode,
                            "%scryption failed for data unit %llu: %d",
-                           (rw == FS_DECRYPT ? "De" : "En"), index, res);
-               return res;
-       }
-       return 0;
+                           (rw == FS_DECRYPT ? "De" : "En"), index, err);
+       return err;
 }
 
 /**
index 17edc24ccd42f688a3cef61cd5d04418b86f2403..f9f6713e144f7a0835c8305dfadd414e285c9184 100644 (file)
@@ -94,12 +94,12 @@ static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
 int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
                          u8 *out, unsigned int olen)
 {
-       struct skcipher_request *req = NULL;
        const struct fscrypt_inode_info *ci = inode->i_crypt_info;
-       struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
+       struct crypto_sync_skcipher *tfm = ci->ci_enc_key.tfm;
+       SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm);
        union fscrypt_iv iv;
        struct scatterlist sg;
-       int res;
+       int err;
 
        /*
         * Copy the filename to the output buffer for encrypting in-place and
@@ -110,28 +110,17 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
        memcpy(out, iname->name, iname->len);
        memset(out + iname->len, 0, olen - iname->len);
 
-       /* Initialize the IV */
        fscrypt_generate_iv(&iv, 0, ci);
 
-       /* Set up the encryption request */
-       req = skcipher_request_alloc(tfm, GFP_NOFS);
-       if (!req)
-               return -ENOMEM;
        skcipher_request_set_callback(
                req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
                NULL, NULL);
        sg_init_one(&sg, out, olen);
        skcipher_request_set_crypt(req, &sg, &sg, olen, &iv);
-
-       /* Do the encryption */
-       res = crypto_skcipher_encrypt(req);
-       skcipher_request_free(req);
-       if (res < 0) {
-               fscrypt_err(inode, "Filename encryption failed: %d", res);
-               return res;
-       }
-
-       return 0;
+       err = crypto_skcipher_encrypt(req);
+       if (err)
+               fscrypt_err(inode, "Filename encryption failed: %d", err);
+       return err;
 }
 EXPORT_SYMBOL_GPL(fscrypt_fname_encrypt);
 
@@ -149,33 +138,25 @@ static int fname_decrypt(const struct inode *inode,
                         const struct fscrypt_str *iname,
                         struct fscrypt_str *oname)
 {
-       struct skcipher_request *req = NULL;
-       struct scatterlist src_sg, dst_sg;
        const struct fscrypt_inode_info *ci = inode->i_crypt_info;
-       struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
+       struct crypto_sync_skcipher *tfm = ci->ci_enc_key.tfm;
+       SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm);
        union fscrypt_iv iv;
-       int res;
+       struct scatterlist src_sg, dst_sg;
+       int err;
+
+       fscrypt_generate_iv(&iv, 0, ci);
 
-       /* Allocate request */
-       req = skcipher_request_alloc(tfm, GFP_NOFS);
-       if (!req)
-               return -ENOMEM;
        skcipher_request_set_callback(
                req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
                NULL, NULL);
-
-       /* Initialize IV */
-       fscrypt_generate_iv(&iv, 0, ci);
-
-       /* Create decryption request */
        sg_init_one(&src_sg, iname->name, iname->len);
        sg_init_one(&dst_sg, oname->name, oname->len);
        skcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, &iv);
-       res = crypto_skcipher_decrypt(req);
-       skcipher_request_free(req);
-       if (res < 0) {
-               fscrypt_err(inode, "Filename decryption failed: %d", res);
-               return res;
+       err = crypto_skcipher_decrypt(req);
+       if (err) {
+               fscrypt_err(inode, "Filename decryption failed: %d", err);
+               return err;
        }
 
        oname->len = strnlen(oname->name, iname->len);
index 06fa8f2b2d0816aefc70f20946fa9a05fdb67b40..bffeb14501fd050a36fe5bd6813edd7cf9aa84bd 100644 (file)
@@ -239,7 +239,7 @@ struct fscrypt_symlink_data {
  * Normally only one of the fields will be non-NULL.
  */
 struct fscrypt_prepared_key {
-       struct crypto_skcipher *tfm;
+       struct crypto_sync_skcipher *tfm;
 #ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
        struct blk_crypto_key *blk_key;
 #endif
index 74d4a2e1ad23aed45b8dc988efc832b8eb03d97e..4f3b9ecbfe4e66415c8ee58128262ccf80238143 100644 (file)
@@ -97,15 +97,15 @@ select_encryption_mode(const union fscrypt_policy *policy,
 }
 
 /* Create a symmetric cipher object for the given encryption mode and key */
-static struct crypto_skcipher *
+static struct crypto_sync_skcipher *
 fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,
                          const struct inode *inode)
 {
-       struct crypto_skcipher *tfm;
+       struct crypto_sync_skcipher *tfm;
        int err;
 
-       tfm = crypto_alloc_skcipher(mode->cipher_str, 0,
-                                   FSCRYPT_CRYPTOAPI_MASK);
+       tfm = crypto_alloc_sync_skcipher(mode->cipher_str, 0,
+                                        FSCRYPT_CRYPTOAPI_MASK);
        if (IS_ERR(tfm)) {
                if (PTR_ERR(tfm) == -ENOENT) {
                        fscrypt_warn(inode,
@@ -125,21 +125,22 @@ fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,
                 * first time a mode is used.
                 */
                pr_info("fscrypt: %s using implementation \"%s\"\n",
-                       mode->friendly_name, crypto_skcipher_driver_name(tfm));
+                       mode->friendly_name,
+                       crypto_skcipher_driver_name(&tfm->base));
        }
-       if (WARN_ON_ONCE(crypto_skcipher_ivsize(tfm) != mode->ivsize)) {
+       if (WARN_ON_ONCE(crypto_sync_skcipher_ivsize(tfm) != mode->ivsize)) {
                err = -EINVAL;
                goto err_free_tfm;
        }
-       crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
-       err = crypto_skcipher_setkey(tfm, raw_key, mode->keysize);
+       crypto_sync_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
+       err = crypto_sync_skcipher_setkey(tfm, raw_key, mode->keysize);
        if (err)
                goto err_free_tfm;
 
        return tfm;
 
 err_free_tfm:
-       crypto_free_skcipher(tfm);
+       crypto_free_sync_skcipher(tfm);
        return ERR_PTR(err);
 }
 
@@ -152,7 +153,7 @@ err_free_tfm:
 int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
                        const u8 *raw_key, const struct fscrypt_inode_info *ci)
 {
-       struct crypto_skcipher *tfm;
+       struct crypto_sync_skcipher *tfm;
 
        if (fscrypt_using_inline_encryption(ci))
                return fscrypt_prepare_inline_crypt_key(prep_key, raw_key,
@@ -176,7 +177,7 @@ int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
 void fscrypt_destroy_prepared_key(struct super_block *sb,
                                  struct fscrypt_prepared_key *prep_key)
 {
-       crypto_free_skcipher(prep_key->tfm);
+       crypto_free_sync_skcipher(prep_key->tfm);
        fscrypt_destroy_inline_crypt_key(sb, prep_key);
        memzero_explicit(prep_key, sizeof(*prep_key));
 }
index 75b0f1211a1e6f3dfe858f954ba6382f13af58a6..c4d05168522b0c60be85dc3c6aad53e393d82705 100644 (file)
@@ -48,38 +48,30 @@ static int derive_key_aes(const u8 *master_key,
                          const u8 nonce[FSCRYPT_FILE_NONCE_SIZE],
                          u8 *derived_key, unsigned int derived_keysize)
 {
-       int res = 0;
-       struct skcipher_request *req = NULL;
-       struct scatterlist src_sg, dst_sg;
-       struct crypto_skcipher *tfm =
-               crypto_alloc_skcipher("ecb(aes)", 0, FSCRYPT_CRYPTOAPI_MASK);
-
-       if (IS_ERR(tfm)) {
-               res = PTR_ERR(tfm);
-               tfm = NULL;
-               goto out;
-       }
-       req = skcipher_request_alloc(tfm, GFP_KERNEL);
-       if (!req) {
-               res = -ENOMEM;
-               goto out;
-       }
-       skcipher_request_set_callback(
-               req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
-               NULL, NULL);
-       res = crypto_skcipher_setkey(tfm, nonce, FSCRYPT_FILE_NONCE_SIZE);
-       if (res < 0)
-               goto out;
+       struct crypto_sync_skcipher *tfm;
+       int err;
 
-       sg_init_one(&src_sg, master_key, derived_keysize);
-       sg_init_one(&dst_sg, derived_key, derived_keysize);
-       skcipher_request_set_crypt(req, &src_sg, &dst_sg, derived_keysize,
-                                  NULL);
-       res = crypto_skcipher_encrypt(req);
-out:
-       skcipher_request_free(req);
-       crypto_free_skcipher(tfm);
-       return res;
+       tfm = crypto_alloc_sync_skcipher("ecb(aes)", 0, FSCRYPT_CRYPTOAPI_MASK);
+       if (IS_ERR(tfm))
+               return PTR_ERR(tfm);
+
+       err = crypto_sync_skcipher_setkey(tfm, nonce, FSCRYPT_FILE_NONCE_SIZE);
+       if (err == 0) {
+               SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm);
+               struct scatterlist src_sg, dst_sg;
+
+               skcipher_request_set_callback(req,
+                                             CRYPTO_TFM_REQ_MAY_BACKLOG |
+                                                     CRYPTO_TFM_REQ_MAY_SLEEP,
+                                             NULL, NULL);
+               sg_init_one(&src_sg, master_key, derived_keysize);
+               sg_init_one(&dst_sg, derived_key, derived_keysize);
+               skcipher_request_set_crypt(req, &src_sg, &dst_sg,
+                                          derived_keysize, NULL);
+               err = crypto_skcipher_encrypt(req);
+       }
+       crypto_free_sync_skcipher(tfm);
+       return err;
 }
 
 /*