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: 45+ 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-07 5:34 ` [PATCH 04/33] lib/crypto: aes: Add CTR and XCTR support Eric Biggers
2026-07-07 5:34 ` [PATCH 05/33] lib/crypto: aes: Add XTS support 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-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox