fscrypt: Switch to sync_skcipher and on-stack requests
Subsystems (2)
Eric Biggers
maintainercover fscrypt: Switch to sync_skcipher and on-stack requests
Simplify the code and eliminate per-encryption-op dynamic memory allocations by switching from crypto_skcipher to crypto_sync_skcipher, and from dynamic request allocation to SYNC_SKCIPHER_REQUEST_ON_STACK.
Previously, this change would have made the x86 accelerated AES code no longer be used, which would have been very bad. However, I fixed that in 6.16. So we can make this simplification now.
This patchset applies to fscrypt/for-next. The base-commit (listed below) can be found in next-20250708
Eric Biggers (3):
fscrypt: Don't use asynchronous CryptoAPI algorithms
fscrypt: Drop FORBID_WEAK_KEYS flag for AES-ECB
fscrypt: Switch to sync_skcipher and on-stack requests
fs/crypto/crypto.c | 27 ++++++---------- fs/crypto/fname.c | 63 +++++++++++++------------------------ fs/crypto/fscrypt_private.h | 7 +++-- fs/crypto/keysetup.c | 23 +++++++------- fs/crypto/keysetup_v1.c | 56 +++++++++++++++------------------ 5 files changed, 71 insertions(+), 105 deletions(-)
base-commit: b41c1d8d07906786c60893980d52688f31d114a6
Signature · 1 line
2.50.0
Eric Biggers
maintainerPATCH 1/3 fscrypt: Don't use asynchronous CryptoAPI algorithms
Now that fscrypt has disabled support for non-inline crypto engines, and none of the CPU-based algorithms have the CRYPTO_ALG_ASYNC flag set anymore, there is no need to "support" asynchronous algorithms. Therefore, remove the code that handled asynchronous returns, and allocate only algorithms without CRYPTO_ALG_ASYNC set.
This commit should *not* be backported to kernels that lack commit 0ba6ec5b2972 ("crypto: x86/aes - stop using the SIMD helper"), as then it would disable the use of the optimized AES code on x86.
--- fs/crypto/crypto.c | 7 +++---- fs/crypto/fname.c | 18 ++++++++---------- fs/crypto/fscrypt_private.h | 5 +++-- fs/crypto/keysetup_v1.c | 9 ++++----- 4 files changed, 18 insertions(+), 21 deletions(-)
fs/crypto/crypto.c +3 -4
@@ -113,11 +113,10 @@ int fscrypt_crypt_data_unit(const struct fscrypt_inode_info *ci, unsigned int len, unsigned int offs, gfp_t gfp_flags) { union fscrypt_iv iv;struct skcipher_request *req =NULL ; -DECLARE_CRYPTO_WAIT (wait);struct scatterlist dst, src;struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;int res =0 ;if (WARN_ON_ONCE (len <=0 ))
@@ -131,21 +130,21 @@ int fscrypt_crypt_data_unit(const struct fscrypt_inode_info *ci,if (!req)return -ENOMEM ;skcipher_request_set_callback ( req,CRYPTO_TFM_REQ_MAY_BACKLOG |CRYPTO_TFM_REQ_MAY_SLEEP , - crypto_req_done, &wait); +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_wait_req (crypto_skcipher_decrypt (req), &wait); + res =crypto_skcipher_decrypt (req);else - res =crypto_wait_req (crypto_skcipher_encrypt (req), &wait); + res =crypto_skcipher_encrypt (req);skcipher_request_free (req);if (res) {fscrypt_err (ci->ci_inode,"%scryption failed for data unit %llu: %d" , (rw ==FS_DECRYPT ?"De" :"En" ), index, res);
fs/crypto/fname.c +8 -10
@@ -93,11 +93,10 @@ 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 ; -DECLARE_CRYPTO_WAIT (wait);const struct fscrypt_inode_info *ci = inode->i_crypt_info;struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;union fscrypt_iv iv;struct scatterlist sg;int res;
@@ -116,18 +115,18 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,/* 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 , - crypto_req_done, &wait); +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_wait_req (crypto_skcipher_encrypt (req), &wait); + res =crypto_skcipher_encrypt (req);skcipher_request_free (req);if (res <0 ) {fscrypt_err (inode,"Filename encryption failed: %d" , res);return res; }
@@ -149,33 +148,32 @@ EXPORT_SYMBOL_GPL(fscrypt_fname_encrypt);static int fname_decrypt (const struct inode *inode,const struct fscrypt_str *iname,struct fscrypt_str *oname) {struct skcipher_request *req =NULL ; -DECLARE_CRYPTO_WAIT (wait);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;union fscrypt_iv iv;int res;/* 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 , - crypto_req_done, &wait); +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_wait_req (crypto_skcipher_decrypt (req), &wait); + res =crypto_skcipher_decrypt (req);skcipher_request_free (req);if (res <0 ) {fscrypt_err (inode,"Filename decryption failed: %d" , res);return res; }
fs/crypto/fscrypt_private.h +3 -2
@@ -57,12 +57,13 @@* Adiantum is faster still, and is the recommended option on such platforms...) * * Note that fscrypt also supports inline crypto engines. Those don't use the * Crypto API and work much better than the old-style (non-inline) engines. */ -#define FSCRYPT_CRYPTOAPI_MASK \ - (CRYPTO_ALG_ALLOCATES_MEMORY | CRYPTO_ALG_KERN_DRIVER_ONLY) +#define FSCRYPT_CRYPTOAPI_MASK \ + (CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY | \ + CRYPTO_ALG_KERN_DRIVER_ONLY)#define FSCRYPT_CONTEXT_V1 1#define FSCRYPT_CONTEXT_V2 2/* Keep this in sync with include/uapi/linux/fscrypt.h */
fs/crypto/keysetup_v1.c +4 -5
@@ -48,11 +48,10 @@ 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 ; -DECLARE_CRYPTO_WAIT (wait);struct scatterlist src_sg, dst_sg;struct crypto_skcipher *tfm =crypto_alloc_skcipher ("ecb(aes)" ,0 ,FSCRYPT_CRYPTOAPI_MASK );if (IS_ERR (tfm)) {
@@ -64,22 +63,22 @@ static int derive_key_aes(const u8 *master_key, 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 , - crypto_req_done, &wait); +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;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_wait_req (crypto_skcipher_encrypt (req), &wait); + res =crypto_skcipher_encrypt (req); out:skcipher_request_free (req);crypto_free_skcipher (tfm);return res; }
Signature · 1 line
2.50.0
Eric Biggers
maintainerPATCH 2/3 fscrypt: Drop FORBID_WEAK_KEYS flag for AES-ECB
In reply to Eric BiggersThis flag does nothing for AES-ECB.
--- fs/crypto/keysetup_v1.c | 1 - 1 file changed, 1 deletion(-)
fs/crypto/keysetup_v1.c +0 -1
@@ -57,11 +57,10 @@ static int derive_key_aes(const u8 *master_key,if (IS_ERR (tfm)) { res =PTR_ERR (tfm); tfm =NULL ; goto out; } -crypto_skcipher_set_flags (tfm,CRYPTO_TFM_REQ_FORBID_WEAK_KEYS ); req =skcipher_request_alloc (tfm,GFP_KERNEL );if (!req) { res = -ENOMEM ; goto out; }
Signature · 1 line
2.50.0
Eric Biggers
maintainerPATCH 3/3 fscrypt: Switch to sync_skcipher and on-stack requests
In reply to Eric BiggersNow 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.
--- fs/crypto/crypto.c | 24 ++++++----------- fs/crypto/fname.c | 53 ++++++++++++------------------------ fs/crypto/fscrypt_private.h | 2 +- fs/crypto/keysetup.c | 23 ++++++++-------- fs/crypto/keysetup_v1.c | 54 +++++++++++++++++-------------------- 5 files changed, 63 insertions(+), 93 deletions(-)
fs/crypto/crypto.c +8 -16
@@ -111,48 +111,40 @@ int fscrypt_crypt_data_unit(const struct fscrypt_inode_info *ci, fscrypt_direction_t rw, u64 index, struct page *src_page, struct page *dest_page, 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 ;if (WARN_ON_ONCE (len %FSCRYPT_CONTENTS_ALIGNMENT !=0 ))return -EINVAL ;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; }/** * fscrypt_encrypt_pagecache_blocks() - Encrypt data from a pagecache folio * @folio: the locked pagecache folio containing the data to encrypt
fs/crypto/fname.c +17 -36
102 lines not on this page · raw message
fs/crypto/fscrypt_private.h +1 -1
@@ -237,11 +237,11 @@ struct fscrypt_symlink_data {* @blk_key: key for blk-crypto * * 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 };
fs/crypto/keysetup.c +12 -11
@@ -95,19 +95,19 @@ select_encryption_mode(const union fscrypt_policy *policy, inode->i_ino, (inode->i_mode & S_IFMT));return ERR_PTR (-EINVAL ); }/* 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,"Missing crypto API support for %s (API name: \"%s\")" , mode->friendly_name, mode->cipher_str);
@@ -123,25 +123,26 @@ fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,* crypto algorithm implementation is used. Help people debug * performance problems by logging the ->cra_driver_name the * 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); }/* * Prepare the crypto transform object or blk-crypto key in @prep_key, given the
@@ -150,11 +151,11 @@ fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,* and IV generation method (@ci->ci_policy.flags). */ 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, ci->ci_mode->keysize, false, ci);
@@ -174,11 +175,11 @@ int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,/* Destroy a crypto transform object and/or blk-crypto 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)); }/* Given a per-file encryption key, set up the file's crypto transform object */
fs/crypto/keysetup_v1.c +25 -29
67 lines not on this page · raw message
Signature · 1 line
2.50.0