Re: [PATCH 03/33] lib/crypto: aes: Add CBC and CBC-CTS support
From: Thomas Huth
Date: Thu Jul 09 2026 - 09:07:31 EST
On 07/07/2026 07.34, Eric Biggers wrote:
Add support for AES-CBC and AES-CBC-CTS to the crypto library....
These will be used to provide streamlined implementations of the
"cbc(aes)" and "cts(cbc(aes))" crypto_skcipher algorithms. Most users
of these crypto_skcipher algorithms will also be able to switch to the
library, which as usual will be simpler and faster, e.g.:
- block/blk-crypto-fallback.c (for AES-128-CBC-ESSIV)
- fs/crypto/crypto.c (for AES-128-CBC-ESSIV)
- fs/crypto/fname.c (for AES-256-CTS and AES-128-CBC)
- kernel/bpf/crypto.c
- net/ceph/crypto.c
- security/keys/encrypted-keys/encrypted.c
As usual, the architecture-optimized AES-CBC and AES-CBC-CTS code will
be migrated into the library as well (using the hooks provided in this
commit), eliminating lots of repetitive boilerplate code.
Initial test coverage is provided by the crypto_skcipher support added
in a later commit. I'm planning a KUnit test suite as well.
Signed-off-by: Eric Biggers <ebiggers@xxxxxxxxxx>
---
.../crypto/libcrypto-unauth-encryption.rst | 7 +
include/crypto/aes-cbc.h | 77 ++++++++
lib/crypto/Kconfig | 6 +
lib/crypto/aes.c | 174 ++++++++++++++++++
lib/crypto/tests/Kconfig | 1 +
5 files changed, 265 insertions(+)
create mode 100644 include/crypto/aes-cbc.h
+void aes_cbc_cts_decrypt(u8 *dst, const u8 *src, size_t len,
+ u8 iv[AES_BLOCK_SIZE], const struct aes_key *key)
+{
+ /* Offset to P[n] and C[n] (last plaintext and ciphertext block) */
+ size_t pn_offset = round_down(len - 1, AES_BLOCK_SIZE);
+ /* Length of P[n] and C[n], 1 <= pn_len <= AES_BLOCK_SIZE */
+ size_t pn_len = len - pn_offset;
+ u8 *pad;
+
+ if (WARN_ON_ONCE(len < AES_BLOCK_SIZE))
+ return;
+
+ if (len == AES_BLOCK_SIZE) {
+ aes_cbc_decrypt(dst, src, len, iv, key);
+ return;
+ }
+ if (likely(aes_cbc_cts_decrypt_arch(dst, src, len, iv, key)))
+ return;
+
+ /* Compute P[0]..P[n - 2]. */
+ aes_cbc_decrypt(dst, src, pn_offset - AES_BLOCK_SIZE, iv, key);
+
+ /* Compute P[n] and P[n - 1], considering that src may equal dst. */
+ pad = &dst[pn_offset - AES_BLOCK_SIZE];
+ aes_decrypt(key, pad, &src[pn_offset - AES_BLOCK_SIZE]);
+ crypto_xor_cpy(&dst[pn_offset], &src[pn_offset], pad,
+ pn_len); /* P[n] */
+ crypto_xor(pad, &dst[pn_offset], pn_len);
Took me a while to understand why you'd use the above xor instead of a memcpy(pad, &src[pn_offset], pn_len) here, but that's because src and dst might point to the same buffer, right?
Anyway, patch looks good to me, so:
Reviewed-by: Thomas Huth <thuth@xxxxxxxxxx>
+ aes_decrypt(key, pad, pad);
+ crypto_xor(pad, iv, AES_BLOCK_SIZE); /* P[n - 1] */
+}
+EXPORT_SYMBOL_GPL(aes_cbc_cts_decrypt);
+#endif /* CONFIG_CRYPTO_LIB_AES_CBC */
+