Skip to content

Commit 52e7e0d

Browse files
author
Eric Biggers
committed
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>
1 parent 53d9218 commit 52e7e0d

5 files changed

Lines changed: 61 additions & 95 deletions

File tree

fs/crypto/crypto.c

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,11 @@ int fscrypt_crypt_data_unit(const struct fscrypt_inode_info *ci,
113113
unsigned int len, unsigned int offs,
114114
gfp_t gfp_flags)
115115
{
116+
struct crypto_sync_skcipher *tfm = ci->ci_enc_key.tfm;
117+
SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm);
116118
union fscrypt_iv iv;
117-
struct skcipher_request *req = NULL;
118119
struct scatterlist dst, src;
119-
struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
120-
int res = 0;
120+
int err;
121121

122122
if (WARN_ON_ONCE(len <= 0))
123123
return -EINVAL;
@@ -126,31 +126,23 @@ int fscrypt_crypt_data_unit(const struct fscrypt_inode_info *ci,
126126

127127
fscrypt_generate_iv(&iv, index, ci);
128128

129-
req = skcipher_request_alloc(tfm, gfp_flags);
130-
if (!req)
131-
return -ENOMEM;
132-
133129
skcipher_request_set_callback(
134130
req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
135131
NULL, NULL);
136-
137132
sg_init_table(&dst, 1);
138133
sg_set_page(&dst, dest_page, len, offs);
139134
sg_init_table(&src, 1);
140135
sg_set_page(&src, src_page, len, offs);
141136
skcipher_request_set_crypt(req, &src, &dst, len, &iv);
142137
if (rw == FS_DECRYPT)
143-
res = crypto_skcipher_decrypt(req);
138+
err = crypto_skcipher_decrypt(req);
144139
else
145-
res = crypto_skcipher_encrypt(req);
146-
skcipher_request_free(req);
147-
if (res) {
140+
err = crypto_skcipher_encrypt(req);
141+
if (err)
148142
fscrypt_err(ci->ci_inode,
149143
"%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;
154146
}
155147

156148
/**

fs/crypto/fname.c

Lines changed: 17 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,12 @@ static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
9494
int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
9595
u8 *out, unsigned int olen)
9696
{
97-
struct skcipher_request *req = NULL;
9897
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);
100100
union fscrypt_iv iv;
101101
struct scatterlist sg;
102-
int res;
102+
int err;
103103

104104
/*
105105
* 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,
110110
memcpy(out, iname->name, iname->len);
111111
memset(out + iname->len, 0, olen - iname->len);
112112

113-
/* Initialize the IV */
114113
fscrypt_generate_iv(&iv, 0, ci);
115114

116-
/* Set up the encryption request */
117-
req = skcipher_request_alloc(tfm, GFP_NOFS);
118-
if (!req)
119-
return -ENOMEM;
120115
skcipher_request_set_callback(
121116
req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
122117
NULL, NULL);
123118
sg_init_one(&sg, out, olen);
124119
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;
135124
}
136125
EXPORT_SYMBOL_GPL(fscrypt_fname_encrypt);
137126

@@ -149,33 +138,25 @@ static int fname_decrypt(const struct inode *inode,
149138
const struct fscrypt_str *iname,
150139
struct fscrypt_str *oname)
151140
{
152-
struct skcipher_request *req = NULL;
153-
struct scatterlist src_sg, dst_sg;
154141
const struct fscrypt_inode_info *ci = inode->i_crypt_info;
155-
struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
142+
struct crypto_sync_skcipher *tfm = ci->ci_enc_key.tfm;
143+
SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm);
156144
union fscrypt_iv iv;
157-
int res;
145+
struct scatterlist src_sg, dst_sg;
146+
int err;
147+
148+
fscrypt_generate_iv(&iv, 0, ci);
158149

159-
/* Allocate request */
160-
req = skcipher_request_alloc(tfm, GFP_NOFS);
161-
if (!req)
162-
return -ENOMEM;
163150
skcipher_request_set_callback(
164151
req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
165152
NULL, NULL);
166-
167-
/* Initialize IV */
168-
fscrypt_generate_iv(&iv, 0, ci);
169-
170-
/* Create decryption request */
171153
sg_init_one(&src_sg, iname->name, iname->len);
172154
sg_init_one(&dst_sg, oname->name, oname->len);
173155
skcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, &iv);
174-
res = crypto_skcipher_decrypt(req);
175-
skcipher_request_free(req);
176-
if (res < 0) {
177-
fscrypt_err(inode, "Filename decryption failed: %d", res);
178-
return res;
156+
err = crypto_skcipher_decrypt(req);
157+
if (err) {
158+
fscrypt_err(inode, "Filename decryption failed: %d", err);
159+
return err;
179160
}
180161

181162
oname->len = strnlen(oname->name, iname->len);

fs/crypto/fscrypt_private.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ struct fscrypt_symlink_data {
239239
* Normally only one of the fields will be non-NULL.
240240
*/
241241
struct fscrypt_prepared_key {
242-
struct crypto_skcipher *tfm;
242+
struct crypto_sync_skcipher *tfm;
243243
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
244244
struct blk_crypto_key *blk_key;
245245
#endif

fs/crypto/keysetup.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,15 @@ select_encryption_mode(const union fscrypt_policy *policy,
9797
}
9898

9999
/* Create a symmetric cipher object for the given encryption mode and key */
100-
static struct crypto_skcipher *
100+
static struct crypto_sync_skcipher *
101101
fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,
102102
const struct inode *inode)
103103
{
104-
struct crypto_skcipher *tfm;
104+
struct crypto_sync_skcipher *tfm;
105105
int err;
106106

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);
109109
if (IS_ERR(tfm)) {
110110
if (PTR_ERR(tfm) == -ENOENT) {
111111
fscrypt_warn(inode,
@@ -125,21 +125,22 @@ fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,
125125
* first time a mode is used.
126126
*/
127127
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));
129130
}
130-
if (WARN_ON_ONCE(crypto_skcipher_ivsize(tfm) != mode->ivsize)) {
131+
if (WARN_ON_ONCE(crypto_sync_skcipher_ivsize(tfm) != mode->ivsize)) {
131132
err = -EINVAL;
132133
goto err_free_tfm;
133134
}
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);
136137
if (err)
137138
goto err_free_tfm;
138139

139140
return tfm;
140141

141142
err_free_tfm:
142-
crypto_free_skcipher(tfm);
143+
crypto_free_sync_skcipher(tfm);
143144
return ERR_PTR(err);
144145
}
145146

@@ -152,7 +153,7 @@ fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,
152153
int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
153154
const u8 *raw_key, const struct fscrypt_inode_info *ci)
154155
{
155-
struct crypto_skcipher *tfm;
156+
struct crypto_sync_skcipher *tfm;
156157

157158
if (fscrypt_using_inline_encryption(ci))
158159
return fscrypt_prepare_inline_crypt_key(prep_key, raw_key,
@@ -176,7 +177,7 @@ int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
176177
void fscrypt_destroy_prepared_key(struct super_block *sb,
177178
struct fscrypt_prepared_key *prep_key)
178179
{
179-
crypto_free_skcipher(prep_key->tfm);
180+
crypto_free_sync_skcipher(prep_key->tfm);
180181
fscrypt_destroy_inline_crypt_key(sb, prep_key);
181182
memzero_explicit(prep_key, sizeof(*prep_key));
182183
}

fs/crypto/keysetup_v1.c

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -48,38 +48,30 @@ static int derive_key_aes(const u8 *master_key,
4848
const u8 nonce[FSCRYPT_FILE_NONCE_SIZE],
4949
u8 *derived_key, unsigned int derived_keysize)
5050
{
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);
56-
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;
51+
struct crypto_sync_skcipher *tfm;
52+
int err;
7353

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;
54+
tfm = crypto_alloc_sync_skcipher("ecb(aes)", 0, FSCRYPT_CRYPTOAPI_MASK);
55+
if (IS_ERR(tfm))
56+
return PTR_ERR(tfm);
57+
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;
8375
}
8476

8577
/*

0 commit comments

Comments
 (0)