The Linux Kernel Mailing List
 help / color / mirror / Atom feed
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


  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