Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fscrypt: Switch to sync_skcipher and on-stack requests

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>

+60 -94
+8 -16
fs/crypto/crypto.c
··· 113 113 unsigned int len, unsigned int offs, 114 114 gfp_t gfp_flags) 115 115 { 116 + struct crypto_sync_skcipher *tfm = ci->ci_enc_key.tfm; 117 + SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); 116 118 union fscrypt_iv iv; 117 - struct skcipher_request *req = NULL; 118 119 struct scatterlist dst, src; 119 - struct crypto_skcipher *tfm = ci->ci_enc_key.tfm; 120 - int res = 0; 120 + int err; 121 121 122 122 if (WARN_ON_ONCE(len <= 0)) 123 123 return -EINVAL; ··· 126 126 127 127 fscrypt_generate_iv(&iv, index, ci); 128 128 129 - req = skcipher_request_alloc(tfm, gfp_flags); 130 - if (!req) 131 - return -ENOMEM; 132 - 133 129 skcipher_request_set_callback( 134 130 req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, 135 131 NULL, NULL); 136 - 137 132 sg_init_table(&dst, 1); 138 133 sg_set_page(&dst, dest_page, len, offs); 139 134 sg_init_table(&src, 1); 140 135 sg_set_page(&src, src_page, len, offs); 141 136 skcipher_request_set_crypt(req, &src, &dst, len, &iv); 142 137 if (rw == FS_DECRYPT) 143 - res = crypto_skcipher_decrypt(req); 138 + err = crypto_skcipher_decrypt(req); 144 139 else 145 - res = crypto_skcipher_encrypt(req); 146 - skcipher_request_free(req); 147 - if (res) { 140 + err = crypto_skcipher_encrypt(req); 141 + if (err) 148 142 fscrypt_err(ci->ci_inode, 149 143 "%scryption failed for data unit %llu: %d", 150 - (rw == FS_DECRYPT ? "De" : "En"), index, res); 151 - return res; 152 - } 153 - return 0; 144 + (rw == FS_DECRYPT ? "De" : "En"), index, err); 145 + return err; 154 146 } 155 147 156 148 /**
+17 -36
fs/crypto/fname.c
··· 94 94 int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname, 95 95 u8 *out, unsigned int olen) 96 96 { 97 - struct skcipher_request *req = NULL; 98 97 const struct fscrypt_inode_info *ci = inode->i_crypt_info; 99 - struct crypto_skcipher *tfm = ci->ci_enc_key.tfm; 98 + struct crypto_sync_skcipher *tfm = ci->ci_enc_key.tfm; 99 + SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); 100 100 union fscrypt_iv iv; 101 101 struct scatterlist sg; 102 - int res; 102 + int err; 103 103 104 104 /* 105 105 * Copy the filename to the output buffer for encrypting in-place and ··· 110 110 memcpy(out, iname->name, iname->len); 111 111 memset(out + iname->len, 0, olen - iname->len); 112 112 113 - /* Initialize the IV */ 114 113 fscrypt_generate_iv(&iv, 0, ci); 115 114 116 - /* Set up the encryption request */ 117 - req = skcipher_request_alloc(tfm, GFP_NOFS); 118 - if (!req) 119 - return -ENOMEM; 120 115 skcipher_request_set_callback( 121 116 req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, 122 117 NULL, NULL); 123 118 sg_init_one(&sg, out, olen); 124 119 skcipher_request_set_crypt(req, &sg, &sg, olen, &iv); 125 - 126 - /* Do the encryption */ 127 - res = crypto_skcipher_encrypt(req); 128 - skcipher_request_free(req); 129 - if (res < 0) { 130 - fscrypt_err(inode, "Filename encryption failed: %d", res); 131 - return res; 132 - } 133 - 134 - return 0; 120 + err = crypto_skcipher_encrypt(req); 121 + if (err) 122 + fscrypt_err(inode, "Filename encryption failed: %d", err); 123 + return err; 135 124 } 136 125 EXPORT_SYMBOL_GPL(fscrypt_fname_encrypt); 137 126 ··· 138 149 const struct fscrypt_str *iname, 139 150 struct fscrypt_str *oname) 140 151 { 141 - struct skcipher_request *req = NULL; 142 - struct scatterlist src_sg, dst_sg; 143 152 const struct fscrypt_inode_info *ci = inode->i_crypt_info; 144 - struct crypto_skcipher *tfm = ci->ci_enc_key.tfm; 153 + struct crypto_sync_skcipher *tfm = ci->ci_enc_key.tfm; 154 + SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); 145 155 union fscrypt_iv iv; 146 - int res; 156 + struct scatterlist src_sg, dst_sg; 157 + int err; 147 158 148 - /* Allocate request */ 149 - req = skcipher_request_alloc(tfm, GFP_NOFS); 150 - if (!req) 151 - return -ENOMEM; 159 + fscrypt_generate_iv(&iv, 0, ci); 160 + 152 161 skcipher_request_set_callback( 153 162 req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, 154 163 NULL, NULL); 155 - 156 - /* Initialize IV */ 157 - fscrypt_generate_iv(&iv, 0, ci); 158 - 159 - /* Create decryption request */ 160 164 sg_init_one(&src_sg, iname->name, iname->len); 161 165 sg_init_one(&dst_sg, oname->name, oname->len); 162 166 skcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, &iv); 163 - res = crypto_skcipher_decrypt(req); 164 - skcipher_request_free(req); 165 - if (res < 0) { 166 - fscrypt_err(inode, "Filename decryption failed: %d", res); 167 - return res; 167 + err = crypto_skcipher_decrypt(req); 168 + if (err) { 169 + fscrypt_err(inode, "Filename decryption failed: %d", err); 170 + return err; 168 171 } 169 172 170 173 oname->len = strnlen(oname->name, iname->len);
+1 -1
fs/crypto/fscrypt_private.h
··· 239 239 * Normally only one of the fields will be non-NULL. 240 240 */ 241 241 struct fscrypt_prepared_key { 242 - struct crypto_skcipher *tfm; 242 + struct crypto_sync_skcipher *tfm; 243 243 #ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT 244 244 struct blk_crypto_key *blk_key; 245 245 #endif
+12 -11
fs/crypto/keysetup.c
··· 97 97 } 98 98 99 99 /* Create a symmetric cipher object for the given encryption mode and key */ 100 - static struct crypto_skcipher * 100 + static struct crypto_sync_skcipher * 101 101 fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key, 102 102 const struct inode *inode) 103 103 { 104 - struct crypto_skcipher *tfm; 104 + struct crypto_sync_skcipher *tfm; 105 105 int err; 106 106 107 - tfm = crypto_alloc_skcipher(mode->cipher_str, 0, 108 - FSCRYPT_CRYPTOAPI_MASK); 107 + tfm = crypto_alloc_sync_skcipher(mode->cipher_str, 0, 108 + FSCRYPT_CRYPTOAPI_MASK); 109 109 if (IS_ERR(tfm)) { 110 110 if (PTR_ERR(tfm) == -ENOENT) { 111 111 fscrypt_warn(inode, ··· 125 125 * first time a mode is used. 126 126 */ 127 127 pr_info("fscrypt: %s using implementation \"%s\"\n", 128 - mode->friendly_name, crypto_skcipher_driver_name(tfm)); 128 + mode->friendly_name, 129 + crypto_skcipher_driver_name(&tfm->base)); 129 130 } 130 - if (WARN_ON_ONCE(crypto_skcipher_ivsize(tfm) != mode->ivsize)) { 131 + if (WARN_ON_ONCE(crypto_sync_skcipher_ivsize(tfm) != mode->ivsize)) { 131 132 err = -EINVAL; 132 133 goto err_free_tfm; 133 134 } 134 - crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); 135 - err = crypto_skcipher_setkey(tfm, raw_key, mode->keysize); 135 + crypto_sync_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); 136 + err = crypto_sync_skcipher_setkey(tfm, raw_key, mode->keysize); 136 137 if (err) 137 138 goto err_free_tfm; 138 139 139 140 return tfm; 140 141 141 142 err_free_tfm: 142 - crypto_free_skcipher(tfm); 143 + crypto_free_sync_skcipher(tfm); 143 144 return ERR_PTR(err); 144 145 } 145 146 ··· 153 152 int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key, 154 153 const u8 *raw_key, const struct fscrypt_inode_info *ci) 155 154 { 156 - struct crypto_skcipher *tfm; 155 + struct crypto_sync_skcipher *tfm; 157 156 158 157 if (fscrypt_using_inline_encryption(ci)) 159 158 return fscrypt_prepare_inline_crypt_key(prep_key, raw_key, ··· 177 176 void fscrypt_destroy_prepared_key(struct super_block *sb, 178 177 struct fscrypt_prepared_key *prep_key) 179 178 { 180 - crypto_free_skcipher(prep_key->tfm); 179 + crypto_free_sync_skcipher(prep_key->tfm); 181 180 fscrypt_destroy_inline_crypt_key(sb, prep_key); 182 181 memzero_explicit(prep_key, sizeof(*prep_key)); 183 182 }
+22 -30
fs/crypto/keysetup_v1.c
··· 48 48 const u8 nonce[FSCRYPT_FILE_NONCE_SIZE], 49 49 u8 *derived_key, unsigned int derived_keysize) 50 50 { 51 - int res = 0; 52 - struct skcipher_request *req = NULL; 53 - struct scatterlist src_sg, dst_sg; 54 - struct crypto_skcipher *tfm = 55 - crypto_alloc_skcipher("ecb(aes)", 0, FSCRYPT_CRYPTOAPI_MASK); 51 + struct crypto_sync_skcipher *tfm; 52 + int err; 56 53 57 - if (IS_ERR(tfm)) { 58 - res = PTR_ERR(tfm); 59 - tfm = NULL; 60 - goto out; 61 - } 62 - req = skcipher_request_alloc(tfm, GFP_KERNEL); 63 - if (!req) { 64 - res = -ENOMEM; 65 - goto out; 66 - } 67 - skcipher_request_set_callback( 68 - req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, 69 - NULL, NULL); 70 - res = crypto_skcipher_setkey(tfm, nonce, FSCRYPT_FILE_NONCE_SIZE); 71 - if (res < 0) 72 - goto out; 54 + tfm = crypto_alloc_sync_skcipher("ecb(aes)", 0, FSCRYPT_CRYPTOAPI_MASK); 55 + if (IS_ERR(tfm)) 56 + return PTR_ERR(tfm); 73 57 74 - sg_init_one(&src_sg, master_key, derived_keysize); 75 - sg_init_one(&dst_sg, derived_key, derived_keysize); 76 - skcipher_request_set_crypt(req, &src_sg, &dst_sg, derived_keysize, 77 - NULL); 78 - res = crypto_skcipher_encrypt(req); 79 - out: 80 - skcipher_request_free(req); 81 - crypto_free_skcipher(tfm); 82 - return res; 58 + err = crypto_sync_skcipher_setkey(tfm, nonce, FSCRYPT_FILE_NONCE_SIZE); 59 + if (err == 0) { 60 + SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); 61 + struct scatterlist src_sg, dst_sg; 62 + 63 + skcipher_request_set_callback(req, 64 + CRYPTO_TFM_REQ_MAY_BACKLOG | 65 + CRYPTO_TFM_REQ_MAY_SLEEP, 66 + NULL, NULL); 67 + sg_init_one(&src_sg, master_key, derived_keysize); 68 + sg_init_one(&dst_sg, derived_key, derived_keysize); 69 + skcipher_request_set_crypt(req, &src_sg, &dst_sg, 70 + derived_keysize, NULL); 71 + err = crypto_skcipher_encrypt(req); 72 + } 73 + crypto_free_sync_skcipher(tfm); 74 + return err; 83 75 } 84 76 85 77 /*