From: Eric Biggers <ebiggers@kernel.org>
To: linux-crypto@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, Eric Biggers <ebiggers@kernel.org>
Subject: [PATCH 19/33] KEYS: encrypted: Use AES-CBC library instead of crypto_skcipher
Date: Mon, 6 Jul 2026 22:34:49 -0700 [thread overview]
Message-ID: <20260707053503.209874-20-ebiggers@kernel.org> (raw)
In-Reply-To: <20260707053503.209874-1-ebiggers@kernel.org>
Now that there's a library API for AES-CBC, use it instead of a
"cbc(aes)" crypto_skcipher. This significantly simplifies the code.
Note that this use of AES-CBC remains questionable (an AEAD should be
used instead), but it remains for backwards compatibility.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
security/keys/Kconfig | 4 +-
security/keys/encrypted-keys/encrypted.c | 194 +++++++----------------
2 files changed, 62 insertions(+), 136 deletions(-)
diff --git a/security/keys/Kconfig b/security/keys/Kconfig
index f4510d8cb485..d482f632791a 100644
--- a/security/keys/Kconfig
+++ b/security/keys/Kconfig
@@ -83,9 +83,7 @@ endif
config ENCRYPTED_KEYS
tristate "ENCRYPTED KEYS"
- select CRYPTO
- select CRYPTO_AES
- select CRYPTO_CBC
+ select CRYPTO_LIB_AES_CBC
select CRYPTO_LIB_SHA256
help
This option provides support for create/encrypting/decrypting keys
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index 59cb77b237b3..3dae2c29496b 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -25,11 +25,9 @@
#include <linux/key-type.h>
#include <linux/random.h>
#include <linux/rcupdate.h>
-#include <linux/scatterlist.h>
#include <linux/ctype.h>
-#include <crypto/aes.h>
+#include <crypto/aes-cbc.h>
#include <crypto/sha2.h>
-#include <crypto/skcipher.h>
#include <crypto/utils.h>
#include "encrypted.h"
@@ -37,17 +35,15 @@
static const char KEY_TRUSTED_PREFIX[] = "trusted:";
static const char KEY_USER_PREFIX[] = "user:";
-static const char blkcipher_alg[] = "cbc(aes)";
static const char key_format_default[] = "default";
static const char key_format_ecryptfs[] = "ecryptfs";
static const char key_format_enc32[] = "enc32";
-static unsigned int ivsize;
-static int blksize;
#define KEY_TRUSTED_PREFIX_LEN (sizeof (KEY_TRUSTED_PREFIX) - 1)
#define KEY_USER_PREFIX_LEN (sizeof (KEY_USER_PREFIX) - 1)
#define KEY_ECRYPTFS_DESC_LEN 16
#define HASH_SIZE SHA256_DIGEST_SIZE
+#define IV_SIZE AES_BLOCK_SIZE /* AES-CBC initialization vector size in bytes */
#define MAX_DATA_SIZE 4096
#define MIN_DATA_SIZE 20
#define KEY_ENC32_PAYLOAD_LEN 32
@@ -79,22 +75,6 @@ module_param(user_decrypted_data, bool, 0);
MODULE_PARM_DESC(user_decrypted_data,
"Allow instantiation of encrypted keys using provided decrypted data");
-static int aes_get_sizes(void)
-{
- struct crypto_skcipher *tfm;
-
- tfm = crypto_alloc_skcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC);
- if (IS_ERR(tfm)) {
- pr_err("encrypted_key: failed to alloc_cipher (%ld)\n",
- PTR_ERR(tfm));
- return PTR_ERR(tfm);
- }
- ivsize = crypto_skcipher_ivsize(tfm);
- blksize = crypto_skcipher_blocksize(tfm);
- crypto_free_skcipher(tfm);
- return 0;
-}
-
/*
* valid_ecryptfs_desc - verify the description of a new/loaded encrypted key
*
@@ -354,39 +334,6 @@ static int get_derived_key(u8 *derived_key, enum derived_key_type key_type,
return 0;
}
-static struct skcipher_request *init_skcipher_req(const u8 *key,
- unsigned int key_len)
-{
- struct skcipher_request *req;
- struct crypto_skcipher *tfm;
- int ret;
-
- tfm = crypto_alloc_skcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC);
- if (IS_ERR(tfm)) {
- pr_err("encrypted_key: failed to load %s transform (%ld)\n",
- blkcipher_alg, PTR_ERR(tfm));
- return ERR_CAST(tfm);
- }
-
- ret = crypto_skcipher_setkey(tfm, key, key_len);
- if (ret < 0) {
- pr_err("encrypted_key: failed to setkey (%d)\n", ret);
- crypto_free_skcipher(tfm);
- return ERR_PTR(ret);
- }
-
- req = skcipher_request_alloc(tfm, GFP_KERNEL);
- if (!req) {
- pr_err("encrypted_key: failed to allocate request for %s\n",
- blkcipher_alg);
- crypto_free_skcipher(tfm);
- return ERR_PTR(-ENOMEM);
- }
-
- skcipher_request_set_callback(req, 0, NULL, NULL);
- return req;
-}
-
static struct key *request_master_key(struct encrypted_key_payload *epayload,
const u8 **master_key, size_t *master_keylen)
{
@@ -427,42 +374,35 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload,
const u8 *derived_key,
unsigned int derived_keylen)
{
- struct scatterlist sg_in[2];
- struct scatterlist sg_out[1];
- struct crypto_skcipher *tfm;
- struct skcipher_request *req;
+ struct aes_enckey key;
unsigned int encrypted_datalen;
- u8 iv[AES_BLOCK_SIZE];
+ u8 iv[IV_SIZE];
int ret;
- encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
+ ret = aes_prepareenckey(&key, derived_key, derived_keylen);
+ if (ret < 0) /* Should never fail here, since a valid length was used */
+ return ret;
- req = init_skcipher_req(derived_key, derived_keylen);
- ret = PTR_ERR(req);
- if (IS_ERR(req))
- goto out;
dump_decrypted_data(epayload);
- sg_init_table(sg_in, 2);
- sg_set_buf(&sg_in[0], epayload->decrypted_data,
- epayload->decrypted_datalen);
- sg_set_page(&sg_in[1], ZERO_PAGE(0), AES_BLOCK_SIZE, 0);
-
- sg_init_table(sg_out, 1);
- sg_set_buf(sg_out, epayload->encrypted_data, encrypted_datalen);
-
+ /*
+ * Pad the plaintext with zeros up to the next multiple of
+ * AES_BLOCK_SIZE, to make it have a valid length for AES-CBC.
+ * To do this without needing a temporary buffer, copy the plaintext
+ * into ->encrypted_data, pad it, and encrypt it in-place.
+ */
+ encrypted_datalen =
+ roundup(epayload->decrypted_datalen, AES_BLOCK_SIZE);
+ memset(epayload->encrypted_data, 0, encrypted_datalen);
+ memcpy(epayload->encrypted_data, epayload->decrypted_data,
+ epayload->decrypted_datalen);
memcpy(iv, epayload->iv, sizeof(iv));
- skcipher_request_set_crypt(req, sg_in, sg_out, encrypted_datalen, iv);
- ret = crypto_skcipher_encrypt(req);
- tfm = crypto_skcipher_reqtfm(req);
- skcipher_request_free(req);
- crypto_free_skcipher(tfm);
- if (ret < 0)
- pr_err("encrypted_key: failed to encrypt (%d)\n", ret);
- else
- dump_encrypted_data(epayload, encrypted_datalen);
-out:
- return ret;
+ aes_cbc_encrypt(epayload->encrypted_data, epayload->encrypted_data,
+ encrypted_datalen, iv, &key);
+ dump_encrypted_data(epayload, encrypted_datalen);
+
+ memzero_explicit(&key, sizeof(key));
+ return 0;
}
static int datablob_hmac_append(struct encrypted_key_payload *epayload,
@@ -528,45 +468,37 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload,
const u8 *derived_key,
unsigned int derived_keylen)
{
- struct scatterlist sg_in[1];
- struct scatterlist sg_out[2];
- struct crypto_skcipher *tfm;
- struct skcipher_request *req;
+ struct aes_key key;
unsigned int encrypted_datalen;
- u8 iv[AES_BLOCK_SIZE];
- u8 *pad;
+ u8 iv[IV_SIZE];
+ u8 *tmp;
int ret;
- /* Throwaway buffer to hold the unused zero padding at the end */
- pad = kmalloc(AES_BLOCK_SIZE, GFP_KERNEL);
- if (!pad)
- return -ENOMEM;
+ ret = aes_preparekey(&key, derived_key, derived_keylen);
+ if (ret < 0) /* Should never fail here, since a valid length was used */
+ return ret;
- encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
- req = init_skcipher_req(derived_key, derived_keylen);
- ret = PTR_ERR(req);
- if (IS_ERR(req))
+ /*
+ * The plaintext was padded before encryption, so decrypt it into a
+ * temporary buffer that has space for the padding.
+ */
+ encrypted_datalen =
+ roundup(epayload->decrypted_datalen, AES_BLOCK_SIZE);
+ tmp = kmalloc(encrypted_datalen, GFP_KERNEL);
+ if (!tmp) {
+ ret = -ENOMEM;
goto out;
+ }
dump_encrypted_data(epayload, encrypted_datalen);
-
- sg_init_table(sg_in, 1);
- sg_init_table(sg_out, 2);
- sg_set_buf(sg_in, epayload->encrypted_data, encrypted_datalen);
- sg_set_buf(&sg_out[0], epayload->decrypted_data,
- epayload->decrypted_datalen);
- sg_set_buf(&sg_out[1], pad, AES_BLOCK_SIZE);
-
memcpy(iv, epayload->iv, sizeof(iv));
- skcipher_request_set_crypt(req, sg_in, sg_out, encrypted_datalen, iv);
- ret = crypto_skcipher_decrypt(req);
- tfm = crypto_skcipher_reqtfm(req);
- skcipher_request_free(req);
- crypto_free_skcipher(tfm);
- if (ret < 0)
- goto out;
+ aes_cbc_decrypt(tmp, epayload->encrypted_data, encrypted_datalen, iv,
+ &key);
+ memcpy(epayload->decrypted_data, tmp, epayload->decrypted_datalen);
dump_decrypted_data(epayload);
+ ret = 0;
out:
- kfree(pad);
+ kfree_sensitive(tmp);
+ memzero_explicit(&key, sizeof(key));
return ret;
}
@@ -630,10 +562,10 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key,
}
}
- encrypted_datalen = roundup(decrypted_datalen, blksize);
+ encrypted_datalen = roundup(decrypted_datalen, AES_BLOCK_SIZE);
- datablob_len = format_len + 1 + strlen(master_desc) + 1
- + strlen(datalen) + 1 + ivsize + 1 + encrypted_datalen;
+ datablob_len = format_len + 1 + strlen(master_desc) + 1 +
+ strlen(datalen) + 1 + IV_SIZE + 1 + encrypted_datalen;
ret = key_payload_reserve(key, payload_datalen + datablob_len
+ HASH_SIZE + 1);
@@ -664,13 +596,14 @@ static int encrypted_key_decrypt(struct encrypted_key_payload *epayload,
size_t asciilen;
int ret;
- encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
- asciilen = (ivsize + 1 + encrypted_datalen + HASH_SIZE) * 2;
+ encrypted_datalen =
+ roundup(epayload->decrypted_datalen, AES_BLOCK_SIZE);
+ asciilen = (IV_SIZE + 1 + encrypted_datalen + HASH_SIZE) * 2;
if (strlen(hex_encoded_iv) != asciilen)
return -EINVAL;
- hex_encoded_data = hex_encoded_iv + (2 * ivsize) + 2;
- ret = hex2bin(epayload->iv, hex_encoded_iv, ivsize);
+ hex_encoded_data = hex_encoded_iv + (2 * IV_SIZE) + 2;
+ ret = hex2bin(epayload->iv, hex_encoded_iv, IV_SIZE);
if (ret < 0)
return -EINVAL;
ret = hex2bin(epayload->encrypted_data, hex_encoded_data,
@@ -719,7 +652,7 @@ static void __ekey_init(struct encrypted_key_payload *epayload,
epayload->master_desc = epayload->format + format_len + 1;
epayload->datalen = epayload->master_desc + strlen(master_desc) + 1;
epayload->iv = epayload->datalen + strlen(datalen) + 1;
- epayload->encrypted_data = epayload->iv + ivsize + 1;
+ epayload->encrypted_data = epayload->iv + IV_SIZE + 1;
epayload->decrypted_data = epayload->payload_data;
if (!format)
@@ -763,11 +696,11 @@ static int encrypted_init(struct encrypted_key_payload *epayload,
if (hex_encoded_iv) {
ret = encrypted_key_decrypt(epayload, format, hex_encoded_iv);
} else if (decrypted_data) {
- get_random_bytes(epayload->iv, ivsize);
+ get_random_bytes(epayload->iv, IV_SIZE);
ret = hex2bin(epayload->decrypted_data, decrypted_data,
epayload->decrypted_datalen);
} else {
- get_random_bytes(epayload->iv, ivsize);
+ get_random_bytes(epayload->iv, IV_SIZE);
get_random_bytes(epayload->decrypted_data, epayload->decrypted_datalen);
}
return ret;
@@ -884,7 +817,7 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep)
__ekey_init(new_epayload, epayload->format, new_master_desc,
epayload->datalen);
- memcpy(new_epayload->iv, epayload->iv, ivsize);
+ memcpy(new_epayload->iv, epayload->iv, IV_SIZE);
memcpy(new_epayload->payload_data, epayload->payload_data,
epayload->payload_datalen);
@@ -918,9 +851,9 @@ static long encrypted_read(const struct key *key, char *buffer,
epayload = dereference_key_locked(key);
/* returns the hex encoded iv, encrypted-data, and hmac as ascii */
- asciiblob_len = epayload->datablob_len + ivsize + 1
- + roundup(epayload->decrypted_datalen, blksize)
- + (HASH_SIZE * 2);
+ asciiblob_len = epayload->datablob_len + IV_SIZE + 1 +
+ roundup(epayload->decrypted_datalen, AES_BLOCK_SIZE) +
+ (HASH_SIZE * 2);
if (!buffer || buflen < asciiblob_len)
return asciiblob_len;
@@ -982,11 +915,6 @@ EXPORT_SYMBOL_GPL(key_type_encrypted);
static int __init init_encrypted(void)
{
- int ret;
-
- ret = aes_get_sizes();
- if (ret < 0)
- return ret;
return register_key_type(&key_type_encrypted);
}
--
2.54.0
next prev parent reply other threads:[~2026-07-07 5:37 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-07 5:34 [PATCH 00/33] Library APIs for AES encryption modes Eric Biggers
2026-07-07 5:34 ` [PATCH 01/33] crypto: xts - Split out __xts_verify_key() helper Eric Biggers
2026-07-07 13:20 ` Thomas Huth
2026-07-07 5:34 ` [PATCH 02/33] lib/crypto: aes: Add ECB support Eric Biggers
2026-07-07 13:59 ` Thomas Huth
2026-07-07 19:22 ` Eric Biggers
2026-07-08 5:29 ` Thomas Huth
2026-07-07 5:34 ` [PATCH 03/33] lib/crypto: aes: Add CBC and CBC-CTS support Eric Biggers
2026-07-09 13:06 ` Thomas Huth
2026-07-13 23:37 ` Eric Biggers
2026-07-07 5:34 ` [PATCH 04/33] lib/crypto: aes: Add CTR and XCTR support Eric Biggers
2026-07-13 8:39 ` Thomas Huth
2026-07-13 23:54 ` Eric Biggers
2026-07-14 4:53 ` Thomas Huth
2026-07-07 5:34 ` [PATCH 05/33] lib/crypto: aes: Add XTS support Eric Biggers
2026-07-13 12:15 ` Thomas Huth
2026-07-14 0:23 ` Eric Biggers
2026-07-07 5:34 ` [PATCH 06/33] lib/crypto: aes: Add GCM support Eric Biggers
2026-07-07 5:34 ` [PATCH 07/33] lib/crypto: aes: Add CCM support Eric Biggers
2026-07-07 5:34 ` [PATCH 08/33] crypto: aes - Add ECB support using library Eric Biggers
2026-07-07 5:34 ` [PATCH 09/33] crypto: aes - Add CBC and CBC-CTS " Eric Biggers
2026-07-07 5:34 ` [PATCH 10/33] crypto: aes - Add CTR and XCTR " Eric Biggers
2026-07-07 5:34 ` [PATCH 11/33] crypto: aes - Add XTS " Eric Biggers
2026-07-07 5:34 ` [PATCH 12/33] crypto: aes - Add GCM " Eric Biggers
2026-07-07 5:34 ` [PATCH 13/33] crypto: aes - Add CCM " Eric Biggers
2026-07-07 5:34 ` [PATCH 14/33] x86/sev: Use new AES-GCM library Eric Biggers
2026-07-07 5:34 ` [PATCH 15/33] lib/crypto: aesgcm: Remove old " Eric Biggers
2026-07-07 5:34 ` [PATCH 16/33] crypto: aes - Remove AES-CBC-MAC support Eric Biggers
2026-07-07 5:34 ` [PATCH 17/33] lib/crypto: aes: Remove aes_cbcmac_* functions Eric Biggers
2026-07-07 5:34 ` [PATCH 18/33] fscrypt: Use aes_ecb_encrypt() for v1 key derivation Eric Biggers
2026-07-07 5:34 ` Eric Biggers [this message]
2026-07-07 5:34 ` [PATCH 20/33] KEYS: trusted: dcp: Use AES-GCM library instead of crypto_aead Eric Biggers
2026-07-07 5:34 ` [PATCH 21/33] libceph: Use AES-CBC library in ceph_aes_crypt() Eric Biggers
2026-07-07 5:34 ` [PATCH 22/33] libceph: Reimplement messenger v2 encryption using AES-GCM library Eric Biggers
2026-07-07 5:34 ` [PATCH 23/33] wifi: mac80211: Use AES-CTR library in fils_aead.c Eric Biggers
2026-07-07 5:34 ` [PATCH 24/33] wifi: mac80211: Use AES-GCM library for GMAC suite Eric Biggers
2026-07-07 5:34 ` [PATCH 25/33] wifi: mac80211: Use crypto libraries for GCMP and CCMP suites Eric Biggers
2026-07-07 5:34 ` [PATCH 26/33] macsec: Use AES-GCM library instead of crypto_aead Eric Biggers
2026-07-07 5:34 ` [PATCH 27/33] wifi: ipw2x00: Use AES-CCM library Eric Biggers
2026-07-07 5:34 ` [PATCH 28/33] mac802154: Use AES-CCM and AES-CTR libraries Eric Biggers
2026-07-07 5:34 ` [PATCH 29/33] bpf: crypto: Use AES-CBC and AES-ECB libraries Eric Biggers
2026-07-07 15:01 ` Vadim Fedorenko
2026-07-07 18:20 ` Eric Biggers
2026-07-07 22:50 ` Vadim Fedorenko
2026-07-07 23:16 ` Eric Biggers
2026-07-08 11:47 ` Vadim Fedorenko
2026-07-09 15:47 ` Eric Biggers
2026-07-09 16:46 ` Vadim Fedorenko
2026-07-07 5:35 ` [PATCH 30/33] bpf: crypto: Add AES-GCM support Eric Biggers
2026-07-07 15:02 ` Vadim Fedorenko
2026-07-07 5:35 ` [PATCH 31/33] smb: client: Use AES-GCM and AES-CCM libraries Eric Biggers
2026-07-07 5:35 ` [PATCH 32/33] ksmbd: " Eric Biggers
2026-07-07 10:51 ` Namjae Jeon
2026-07-07 5:35 ` [PATCH 33/33] net: tipc: Use AES-GCM library instead of crypto_aead Eric Biggers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260707053503.209874-20-ebiggers@kernel.org \
--to=ebiggers@kernel.org \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.