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>pull/1309/head
parent
53d9218d8d
commit
52e7e0d889
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
struct crypto_sync_skcipher *tfm;
|
||||
int err;
|
||||
|
||||
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;
|
||||
tfm = crypto_alloc_sync_skcipher("ecb(aes)", 0, FSCRYPT_CRYPTOAPI_MASK);
|
||||
if (IS_ERR(tfm))
|
||||
return PTR_ERR(tfm);
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue