AES-CMAC library
Subsystems (10)
Eric Biggers
maintainercover AES-CMAC library
This series can also be retrieved from:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git aes-cmac-v1
This series adds support for AES CBC-based MACs to the crypto library, specifically AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC. The implementation is fully optimized with the existing architecture-optimized AES code, either single-block AES en/decryption or arm64's neon_aes_mac_update() and ce_aes_mac_update(). As usual, optimizations are now enabled by default as well.
AES-CMAC support will be useful for at least the SMB client and server, and the bluetooth and mac80211 drivers. Patches 8-15 convert these users to use the crypto library API instead of crypto_shash, though these patches will likely go in via subsystem trees later. They result in some significant simplifications and performance improvements.
As usual, a KUnit test suite, FIPS self-test, and traditional crypto API wrapper algorithms are included as well.
Note that I'm also planning to add additional AES modes to the library. This is just an initial set of AES modes to get things started. Notably, with the SMB client and server already using the SHA* and MD5 libraries, "cmac(aes)" was the only remaining use of crypto_shash there. So it makes sense to take care of that.
Eric Biggers (15):
lib/crypto: aes: Add support for CBC-based MACs
crypto: aes - Add cmac, xcbc, and cbcmac algorithms using library
crypto: arm64/aes - Fix 32-bit aes_mac_update() arg treated as 64-bit lib/crypto: arm64/aes: Move assembly code for AES modes into libaes lib/crypto: arm64/aes: Migrate optimized CBC-based MACs into library lib/crypto: tests: Add KUnit tests for CBC-based MACs lib/crypto: aes: Add FIPS self-test for CMAC
smb: client: Use AES-CMAC library for SMB3 signature calculation
smb: client: Remove obsolete cmac(aes) allocation
smb: client: Make generate_key() return void
smb: client: Drop 'allocate_crypto' arg from smb*_calc_signature()
ksmbd: Use AES-CMAC library for SMB3 signature calculation
Bluetooth: SMP: Use AES-CMAC library API
wifi: mac80211: Use AES-CMAC library in ieee80211_aes_cmac()
wifi: mac80211: Use AES-CMAC library in aes_s2v()
arch/arm64/crypto/Kconfig | 2 +-
arch/arm64/crypto/Makefile | 4 +-
arch/arm64/crypto/aes-ce-ccm-glue.c | 4 -
arch/arm64/crypto/aes-glue.c | 260 +-----------------
arch/arm64/crypto/aes-neonbs-glue.c | 15 +-
crypto/Kconfig | 2 +
crypto/aes.c | 183 +++++++++++-
crypto/testmgr.c | 10 +-
drivers/crypto/starfive/jh7110-aes.c | 2 +-
fs/smb/client/Kconfig | 2 +-
fs/smb/client/cifs_unicode.c | 1 +
fs/smb/client/cifsencrypt.c | 62 ++---
fs/smb/client/cifsfs.c | 1 -
fs/smb/client/cifsglob.h | 7 +-
fs/smb/client/cifsproto.h | 3 -
fs/smb/client/misc.c | 57 ----
fs/smb/client/sess.c | 11 -
fs/smb/client/smb2proto.h | 1 -
fs/smb/client/smb2transport.c | 113 ++------
fs/smb/server/Kconfig | 2 +-
fs/smb/server/auth.c | 51 +---
fs/smb/server/auth.h | 4 +-
fs/smb/server/crypto_ctx.c | 58 ----
fs/smb/server/crypto_ctx.h | 12 -
fs/smb/server/server.c | 1 -
fs/smb/server/smb2pdu.c | 8 +-
include/crypto/aes-cbc-macs.h | 154 +++++++++++
include/crypto/aes.h | 66 +++++
lib/crypto/Kconfig | 10 +
lib/crypto/Makefile | 4 +-
lib/crypto/aes.c | 231 +++++++++++++++-
.../crypto => lib/crypto/arm64}/aes-ce.S | 0
.../crypto => lib/crypto/arm64}/aes-modes.S | 23 +-
.../crypto => lib/crypto/arm64}/aes-neon.S | 0
lib/crypto/arm64/aes.h | 76 ++++-
lib/crypto/fips.h | 5 +
lib/crypto/tests/Kconfig | 10 +
lib/crypto/tests/Makefile | 1 +
lib/crypto/tests/aes-cmac-testvecs.h | 181 ++++++++++++
lib/crypto/tests/aes_cbc_macs_kunit.c | 228 +++++++++++++++
net/bluetooth/Kconfig | 3 +-
net/bluetooth/smp.c | 180 +++++-------
net/mac80211/Kconfig | 2 +-
net/mac80211/aes_cmac.c | 65 +----
net/mac80211/aes_cmac.h | 12 +-
net/mac80211/fils_aead.c | 48 ++--
net/mac80211/key.c | 11 +-
net/mac80211/key.h | 3 +-
net/mac80211/wpa.c | 13 +-
scripts/crypto/gen-fips-testvecs.py | 10 +
scripts/crypto/gen-hash-testvecs.py | 31 ++-
51 files changed, 1388 insertions(+), 855 deletions(-)
create mode 100644 include/crypto/aes-cbc-macs.h
rename {arch/arm64/crypto => lib/crypto/arm64}/aes-ce.S (100%)
rename {arch/arm64/crypto => lib/crypto/arm64}/aes-modes.S (98%)
rename {arch/arm64/crypto => lib/crypto/arm64}/aes-neon.S (100%)
create mode 100644 lib/crypto/tests/aes-cmac-testvecs.h
create mode 100644 lib/crypto/tests/aes_cbc_macs_kunit.cbase-commit: 2961f841b025fb234860bac26dfb7fa7cb0fb122
prerequisite-patch-id: 8eccdd31739fb317dfda9dddbfc5c3cd64e77331
prerequisite-patch-id: ca782470cef2467042fbe8f0166933d7fa292628
Signature · 1 line
2.53.0
Eric Biggers
maintainerPATCH 1/15 lib/crypto: aes: Add support for CBC-based MACs
Add support for CBC-based MACs to the AES library, specifically AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC.
Of these three algorithms, AES-CMAC is the most modern and the most commonly used. Use cases for the AES-CMAC library include the kernel's SMB client and server, and the bluetooth and mac80211 drivers.
Support for AES-XCBC-MAC and AES-CBC-MAC is included so that there will be no performance regression in the "xcbc(aes)" and "ccm(aes)" support in the traditional crypto API once the arm64-optimized code is migrated into the library. AES-XCBC-MAC is given its own key preparation function but is otherwise identical to AES-CMAC and just reuses the AES-CMAC structs and functions.
The implementation automatically uses the optimized AES key expansion and single block en/decryption functions. It also allows architectures to provide an optimized implementation of aes_cbcmac_blocks(), which allows the existing arm64-optimized code for these modes to be used.
Just put the code for these modes directly in the libaes module rather than in a separate module. This is simpler, it makes it easier to share code between AES modes, and it increases the amount of inlining that is possible. (Indeed, for these reasons, most of the architecture-optimized AES code already provides multiple modes per module. x86 for example has only a single aesni-intel module. So to a large extent, this design choice just reflects the status quo.)
However, since there are a lot of AES modes, there's still some value in omitting modes that are not needed at all in a given kernel. Therefore, make these modes an optional feature of libaes, controlled by CONFIG_CRYPTO_LIB_AES_CBC_MACS. This seems like a good middle ground.
--- include/crypto/aes-cbc-macs.h | 154 ++++++++++++++++++++++++++ lib/crypto/Kconfig | 10 ++ lib/crypto/aes.c | 198 ++++++++++++++++++++++++++++++++++ 3 files changed, 362 insertions(+) create mode 100644 include/crypto/aes-cbc-macs.h
include/crypto/aes-cbc-macs.h new file +154 -0
@@ -0,0 +1,154 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Support for AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC +* +* Copyright 2026 Google LLC +*/ +#ifndef _CRYPTO_AES_CBC_MACS_H +#define _CRYPTO_AES_CBC_MACS_H + +#include <crypto/aes.h> + +/** +* struct aes_cmac_key - Prepared key for AES-CMAC or AES-XCBC-MAC +* @aes: The AES key for cipher block chaining +* @k_final: Finalization subkeys for the final block. +* k_final[0] (CMAC K1, XCBC-MAC K2) is used if it's a full block. +* k_final[1] (CMAC K2, XCBC-MAC K3) is used if it's a partial block. +*/ +struct aes_cmac_key { +struct aes_enckey aes; +union { +u8 b[AES_BLOCK_SIZE ]; +__be64 w[2 ]; + } k_final[2 ]; +}; + +/** +* struct aes_cmac_ctx - Context for computing an AES-CMAC or AES-XCBC-MAC value +* @key: Pointer to the key struct. A pointer is used rather than a copy of the +* struct, since the key struct size may be large. It is assumed that the +* key lives at least as long as the context. +* @partial_len: Number of bytes that have been XOR'ed into @h since the last +* AES encryption. This is 0 if no data has been processed yet, +* or between 1 and AES_BLOCK_SIZE inclusive otherwise. +* @h: The current chaining value +*/ +struct aes_cmac_ctx { +const struct aes_cmac_key *key; +size_t partial_len; +u8 h[AES_BLOCK_SIZE ]; +}; + +/** +* aes_cmac_preparekey() - Prepare a key for AES-CMAC +* @key: (output) The key struct to initialize +* @in_key: The raw AES key +* @key_len: Length of the raw key in bytes. The supported values are +* AES_KEYSIZE_128, AES_KEYSIZE_192, and AES_KEYSIZE_256. +* +* Context: Any context. +* Return: 0 on success or -EINVAL if the given key length is invalid. No other +* errors are possible, so callers that always pass a valid key length +* don't need to check for errors. +*/ +int aes_cmac_preparekey (struct aes_cmac_key *key,const u8 *in_key, +size_t key_len); + +/** +* aes_xcbcmac_preparekey() - Prepare a key for AES-XCBC-MAC +* @key: (output) The key struct to initialize +* @in_key: The raw key. As per the AES-XCBC-MAC specification (RFC 3566), this +* is 128 bits, matching the internal use of AES-128. +* +* AES-XCBC-MAC and AES-CMAC are the same except for the key preparation. After +* that step, AES-XCBC-MAC is supported via the aes_cmac_* functions. +* +* New users should use AES-CMAC instead of AES-XCBC-MAC. +* +* Context: Any context. +*/ +void aes_xcbcmac_preparekey (struct aes_cmac_key *key, + const u8 in_key[at_least AES_KEYSIZE_128]); + +/** +* aes_cmac_init() - Start computing an AES-CMAC or AES-XCBC-MAC value +* @ctx: (output) The context to initialize +* @key: The key to use. Note that a pointer to the key is saved in the +* context, so the key must live at least as long as the context. +* +* This supports both AES-CMAC and AES-XCBC-MAC. Which one is done depends on +* whether aes_cmac_preparekey() or aes_xcbcmac_preparekey() was called. +*/ +static inline void aes_cmac_init (struct aes_cmac_ctx *ctx, +const struct aes_cmac_key *key) +{ + *ctx = (struct aes_cmac_ctx ){ .key = key }; +} + +/** +* aes_cmac_update() - Update an AES-CMAC or AES-XCBC-MAC context with more data +* @ctx: The context to update; must have been initialized +* @data: The message data +* @data_len: The data length in bytes. Doesn't need to be block-aligned. +* +* This can be called any number of times. +* +* Context: Any context. +*/ +void aes_cmac_update (struct aes_cmac_ctx *ctx,const u8 *data,size_t data_len); + +/** +* aes_cmac_final() - Finish computing an AES-CMAC or AES-XCBC-MAC value +* @ctx: The context to finalize; must have been initialized +* @out: (output) The resulting MAC +* +* After finishing, this zeroizes @ctx. So the caller does not need to do it. +* +* Context: Any context. +*/ +void aes_cmac_final(struct aes_cmac_ctx *ctx, u8 out[at_least AES_BLOCK_SIZE]); + +/** +* aes_cmac() - Compute AES-CMAC or AES-XCBC-MAC in one shot +* @key: The key to use +* @data: The message data +* @data_len: The data length in bytes +* @out: (output) The resulting AES-CMAC or AES-XCBC-MAC value +* +* This supports both AES-CMAC and AES-XCBC-MAC. Which one is done depends on +* whether aes_cmac_preparekey() or aes_xcbcmac_preparekey() was called. +* +* Context: Any context. +*/ +static inline void aes_cmac (const struct aes_cmac_key *key,const u8 *data, + size_t data_len, u8 out[at_least AES_BLOCK_SIZE]) +{ +struct aes_cmac_ctx ctx; + +aes_cmac_init (&ctx, key); +aes_cmac_update (&ctx, data, data_len); +aes_cmac_final (&ctx, out); +} + +/* +* AES-CBC-MAC support. This is provided only for use by the implementation of +* AES-CCM. It should have no other users. Warning: unlike AES-CMAC and +* AES-XCBC-MAC, AES-CBC-MAC isn't a secure MAC for variable-length messages. +*/ +struct aes_cbcmac_ctx { +const struct aes_enckey *key; +size_t partial_len; +u8 h[AES_BLOCK_SIZE ]; +}; +static inline void aes_cbcmac_init (struct aes_cbcmac_ctx *ctx, +const struct aes_enckey *key) +{ + *ctx = (struct aes_cbcmac_ctx ){ .key = key }; +} +void aes_cbcmac_update (struct aes_cbcmac_ctx *ctx,const u8 *data, +size_t data_len); +void aes_cbcmac_final (struct aes_cbcmac_ctx *ctx, + u8 out[at_least AES_BLOCK_SIZE]); + +#endif /* _CRYPTO_AES_CBC_MACS_H */
lib/crypto/Kconfig +10 -0
@@ -8,10 +8,12 @@ config CRYPTO_HASH_INFO config CRYPTO_LIB_UTILS tristate config CRYPTO_LIB_AES tristate + # Select dependencies of modes that are part of libaes. + select CRYPTO_LIB_UTILS if CRYPTO_LIB_AES_CBC_MACS config CRYPTO_LIB_AES_ARCH bool depends on CRYPTO_LIB_AES && !UML && !KMSAN default y if ARM
@@ -26,10 +28,18 @@ config CRYPTO_LIB_AES_ARCH config CRYPTO_LIB_AESCFB tristate select CRYPTO_LIB_AES select CRYPTO_LIB_UTILS +config CRYPTO_LIB_AES_CBC_MACS + tristate + select CRYPTO_LIB_AES + help + The AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC library functions. Select + this if your module uses any of the functions from + <crypto/aes-cbc-macs.h>. + config CRYPTO_LIB_AESGCM tristate select CRYPTO_LIB_AES select CRYPTO_LIB_GF128MUL select CRYPTO_LIB_UTILS
lib/crypto/aes.c +198 -0
219 lines not on this page · raw message
Signature · 1 line
2.53.0
Eric Biggers
maintainerPATCH 2/15 crypto: aes - Add cmac, xcbc, and cbcmac algorithms using library
In reply to Eric BiggersUpdate the "aes" module to implement "cmac(aes)", "xcbc(aes)", and "cbcmac(aes)" algorithms using the corresponding library functions, and register these with the crypto_shash API. Each algorithm is included only if the corresponding existing kconfig option is enabled.
This allows the architecture-optimized implementations of these algorithms to continue to be accessible via the crypto_shash API once they are migrated into the library.
For "xcbc(aes)", I also fixed the bug where AES key lengths other than 128 bits were allowed, so that this bug didn't have to be implemented in the library. The AES-XCBC-MAC specification (RFC 3566) is clear that key lengths other than 128 bits MUST NOT be supported. AES-XCBC-MAC derives a 128-bit subkey internally, so the nonstandard support for longer AES keys didn't really work: AES-128 was still used internally.
In the unlikely event that someone is actually relying on the broken and nonstandard support for longer AES-XCBC-MAC keys, we can fairly easily reintroduce it. But it seems unnecessary: the only user of "xcbc(aes)" seems to be IPsec, which uses 128-bit keys with it.
--- crypto/Kconfig | 2 + crypto/aes.c | 183 ++++++++++++++++++++++++++- crypto/testmgr.c | 10 +- drivers/crypto/starfive/jh7110-aes.c | 2 +- 4 files changed, 190 insertions(+), 7 deletions(-)
crypto/Kconfig +2 -0
@@ -359,10 +359,12 @@ menu "Block ciphers" config CRYPTO_AES tristate "AES (Advanced Encryption Standard)" select CRYPTO_ALGAPI select CRYPTO_LIB_AES + select CRYPTO_LIB_AES_CBC_MACS if CRYPTO_CMAC || CRYPTO_XCBC || CRYPTO_CCM + select CRYPTO_HASH if CRYPTO_CMAC || CRYPTO_XCBC || CRYPTO_CCM help AES cipher algorithms (Rijndael)(FIPS-197, ISO/IEC 18033-3) Rijndael appears to be consistently a very good performer in both hardware and software across a wide range of computing
crypto/aes.c +182 -1
225 lines not on this page · raw message
crypto/testmgr.c +5 -5
@@ -4386,11 +4386,11 @@ static const struct alg_test_desc alg_test_descs[] = { .cipher = __VECS(aes_cbc_tv_template) } }, {#endif .alg = "cbcmac(aes)", - .generic_driver = "cbcmac(aes-lib)", + .generic_driver = "cbcmac-aes-lib", .test = alg_test_hash, .suite = { .hash = __VECS(aes_cbcmac_tv_template) } }, {
@@ -4399,11 +4399,11 @@ static const struct alg_test_desc alg_test_descs[] = { .suite = { .hash = __VECS(sm4_cbcmac_tv_template) } }, { .alg = "ccm(aes)", - .generic_driver = "ccm_base(ctr(aes-lib),cbcmac(aes-lib))", + .generic_driver = "ccm_base(ctr(aes-lib),cbcmac-aes-lib)", .test = alg_test_aead, .fips_allowed = 1, .suite = { .aead = { ____VECS(aes_ccm_tv_template),
@@ -4427,11 +4427,11 @@ static const struct alg_test_desc alg_test_descs[] = { .suite = { .cipher =__VECS (chacha20_tv_template) }, }, { .alg = "cmac(aes)", - .generic_driver = "cmac(aes-lib)", + .generic_driver = "cmac-aes-lib", .fips_allowed = 1, .test = alg_test_hash, .suite = { .hash =__VECS (aes_cmac128_tv_template) }
@@ -5324,11 +5324,11 @@ static const struct alg_test_desc alg_test_descs[] = { .aad_iv = 1, } } }, { .alg = "rfc4309(ccm(aes))", - .generic_driver = "rfc4309(ccm_base(ctr(aes-lib),cbcmac(aes-lib)))", + .generic_driver = "rfc4309(ccm_base(ctr(aes-lib),cbcmac-aes-lib))", .test = alg_test_aead, .fips_allowed = 1, .suite = { .aead = { ____VECS(aes_ccm_rfc4309_tv_template),
@@ -5513,11 +5513,11 @@ static const struct alg_test_desc alg_test_descs[] = { .suite = { .sig = __VECS(x962_ecdsa_nist_p521_tv_template) } }, { .alg = "xcbc(aes)", - .generic_driver = "xcbc(aes-lib)", + .generic_driver = "xcbc-aes-lib", .test = alg_test_hash, .suite = { .hash = __VECS(aes_xcbc128_tv_template) } }, {
drivers/crypto/starfive/jh7110-aes.c +1 -1
@@ -1001,11 +1001,11 @@ static int starfive_aes_ctr_init_tfm(struct crypto_skcipher *tfm)return starfive_aes_init_tfm (tfm,"ctr(aes-lib)" ); }static int starfive_aes_ccm_init_tfm (struct crypto_aead *tfm) { -return starfive_aes_aead_init_tfm (tfm,"ccm_base(ctr(aes-lib),cbcmac(aes-lib))" ); +return starfive_aes_aead_init_tfm (tfm,"ccm_base(ctr(aes-lib),cbcmac-aes-lib)" ); }static int starfive_aes_gcm_init_tfm (struct crypto_aead *tfm) {return starfive_aes_aead_init_tfm (tfm,"gcm_base(ctr(aes-lib),ghash-generic)" );
Signature · 1 line
2.53.0
Eric Biggers
maintainerPATCH 3/15 crypto: arm64/aes - Fix 32-bit aes_mac_update() arg treated as 64-bit
In reply to Eric BiggersSince the 'enc_after' argument to neon_aes_mac_update() and ce_aes_mac_update() has type 'int', it needs to be accessed using the corresponding 32-bit register, not the 64-bit register. The upper half of the corresponding 64-bit register may contain garbage.
--- arch/arm64/crypto/aes-modes.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/crypto/aes-modes.S +2 -2
@@ -836,11 +836,11 @@ AES_FUNC_START(aes_mac_update) encrypt_block v0, w2, x1, x7, w8 eor v0.16b, v0.16b, v3.16b encrypt_block v0, w2, x1, x7, w8 eor v0.16b, v0.16b, v4.16b cmp w3, wzr - csinv x5, x6, xzr, eq + csinv w5, w6, wzr, eq cbz w5, .Lmacout encrypt_block v0, w2, x1, x7, w8 st1 {v0.16b}, [x4] /* return dg */ cond_yield .Lmacout, x7, x8 b .Lmacloop4x
@@ -850,11 +850,11 @@ AES_FUNC_START(aes_mac_update) cbz w3, .Lmacout ld1 {v1.16b}, [x0], #16 /* get next pt block */ eor v0.16b, v0.16b, v1.16b /* ..and xor with dg */ subs w3, w3, #1 - csinv x5, x6, xzr, eq + csinv w5, w6, wzr, eq cbz w5, .Lmacout .Lmacenc: encrypt_block v0, w2, x1, x7, w8 b .Lmacloop
Signature · 1 line
2.53.0
Ard Biesheuvel
maintainerRe: [PATCH 03/15] crypto: arm64/aes - Fix 32-bit aes_mac_update() arg treated as 64-bit
Quoted 5 lines · Eric Biggers
Since the '
enc_after' argument toneon_aes_mac_update()andce_aes_mac_update()has type 'int', it needs to be accessed using the corresponding 32-bit register, not the 64-bit register. The upper half of the corresponding 64-bit register may contain garbage.
How could that happen? Setting the 32-bit alias of a GPR clears the upper half.
Quoted 4 lines
Fixes 4860620da7e5 ("crypto: arm64/aes - add NEON/Crypto ExtensionsCBCMAC/CMAC/XCBC driver")
Signed-off-by Eric Biggers <[email protected]>
Agree with the change but I don't think this needs a cc:stable (or a fixes tag)
Quoted 36 lines
--- arch/arm64/crypto/aes-modes.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)arch/arm64/crypto/aes-modes.S +2
-2@@ -836,11 +836,11 @@ AES_FUNC_START(aes_mac_update) encrypt_block v0, w2, x1, x7, w8 eor v0.16b, v0.16b, v3.16b encrypt_block v0, w2, x1, x7, w8 eor v0.16b, v0.16b, v4.16b cmp w3, wzr - csinv x5, x6, xzr, eq + csinv w5, w6, wzr, eq cbz w5, .Lmacout encrypt_block v0, w2, x1, x7, w8 st1 {v0.16b}, [x4] /* return dg */ cond_yield .Lmacout, x7, x8 b .Lmacloop4x@@ -850,11 +850,11 @@ AES_FUNC_START(aes_mac_update) cbz w3, .Lmacout ld1 {v1.16b}, [x0], #16 /* get next pt block */ eor v0.16b, v0.16b, v1.16b /* ..and xor with dg */ subs w3, w3, #1 - csinv x5, x6, xzr, eq + csinv w5, w6, wzr, eq cbz w5, .Lmacout .Lmacenc: encrypt_block v0, w2, x1, x7, w8 b .LmacloopSignature · 1 line
2.53.0
Eric Biggers
maintainerRe: [PATCH 03/15] crypto: arm64/aes - Fix 32-bit aes_mac_update() arg treated as 64-bit
Quoted 7 lines · Ard Biesheuvel
Quoted 4 lines · Eric Biggers
Since the '
enc_after' argument toneon_aes_mac_update()andce_aes_mac_update()has type 'int', it needs to be accessed using the corresponding 32-bit register, not the 64-bit register. The upper half of the corresponding 64-bit register may contain garbage.How could that happen? Setting the 32-bit alias of a GPR clears the upper half.
The ABI doesn't guarantee that the upper 32 bits are cleared. Try the following:
void g(unsigned int a);
void f(unsigned long long a)
{
g((unsigned int)a);
}Both gcc and clang generate code that simply tail-calls g(), leaving the upper 32 bits unchanged rather than zeroing them as per the cast:
0000000000000000 <f>:
0: 14000000 b 0x0 <f>
So it's possible. Now, it's certainly unlikely to happen in practice, as the real code doesn't use truncating casts like that, and the instructions that write to the 32-bit registers clear the upper 64 bits -- as you noted and as I've noted before in similar fixes (e.g.
https://lore.kernel.org/r/[email protected]/).
So does it really matter? Probably not. However, given that the correct behavior wasn't *guaranteed*, I think that to be safe we should continue to consider patches like this to be bugfixes.
- Eric
Eric Biggers
maintainerPATCH 4/15 lib/crypto: arm64/aes: Move assembly code for AES modes into libaes
In reply to Eric BiggersTo migrate the support for CBC-based MACs into libaes, the corresponding arm64 assembly code needs to be moved there. However, the arm64 AES assembly code groups many AES modes together; individual modes aren't easily separable. (This isn't unique to arm64; other architectures organize their AES modes similarly.)
Since the other AES modes will be migrated into the library eventually too, just move the full assembly files for the AES modes into the library. (This is similar to what I already did for PowerPC and SPARC.)
Specifically: move the assembly files aes-ce.S, aes-modes.S, and aes-neon.S and their build rules; declare the assembly functions in <crypto/aes.h>; and export the assembly functions from libaes.
Note that the exports and public declarations of the assembly functions are temporary. They exist only to keep arch/arm64/crypto/ working until the AES modes are fully moved into the library.
---
arch/arm64/crypto/Makefile | 4 +-
arch/arm64/crypto/aes-ce-ccm-glue.c | 4 --
arch/arm64/crypto/aes-glue.c | 47 +------------
arch/arm64/crypto/aes-neonbs-glue.c | 15 +---
include/crypto/aes.h | 69 +++++++++++++++++++
lib/crypto/Makefile | 4 +-
.../crypto => lib/crypto/arm64}/aes-ce.S | 0
.../crypto => lib/crypto/arm64}/aes-modes.S | 0
.../crypto => lib/crypto/arm64}/aes-neon.S | 0
lib/crypto/arm64/aes.h | 30 ++++++++
10 files changed, 106 insertions(+), 67 deletions(-)
rename {arch/arm64/crypto => lib/crypto/arm64}/aes-ce.S (100%)
rename {arch/arm64/crypto => lib/crypto/arm64}/aes-modes.S (100%)
rename {arch/arm64/crypto => lib/crypto/arm64}/aes-neon.S (100%)arch/arm64/crypto/Makefile +2 -2
@@ -31,12 +31,12 @@ ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o obj-$(CONFIG_CRYPTO_AES_ARM64_CE_CCM) += aes-ce-ccm.o aes-ce-ccm-y := aes-ce-ccm-glue.o aes-ce-ccm-core.o obj-$(CONFIG_CRYPTO_AES_ARM64_CE_BLK) += aes-ce-blk.o -aes-ce-blk-y := aes-glue-ce.o aes-ce.o +aes-ce-blk-y := aes-glue-ce.o obj-$(CONFIG_CRYPTO_AES_ARM64_NEON_BLK) += aes-neon-blk.o -aes-neon-blk-y := aes-glue-neon.o aes-neon.o +aes-neon-blk-y := aes-glue-neon.o obj-$(CONFIG_CRYPTO_AES_ARM64_BS) += aes-neon-bs.o aes-neon-bs-y := aes-neonbs-core.o aes-neonbs-glue.o
arch/arm64/crypto/aes-ce-ccm-glue.c +0 -4
@@ -29,14 +29,10 @@ static int num_rounds(struct crypto_aes_ctx *ctx)* => n byte key => 6 + (n/4) rounds */ return 6 + ctx->key_length /4 ; } -asmlinkage u32 ce_aes_mac_update(u8 const in[], u32 const rk[], int rounds, -int blocks,u8 dg[],int enc_before, -int enc_after); - asmlinkage void ce_aes_ccm_encrypt(u8 out[], u8 const in[], u32 cbytes,u32 const rk[],u32 rounds,u8 mac[],u8 ctr[],u8 const final_iv[]); asmlinkage void ce_aes_ccm_decrypt(u8 out[], u8 const in[], u32 cbytes,
arch/arm64/crypto/aes-glue.c +1 -46
68 lines not on this page · raw message
arch/arm64/crypto/aes-neonbs-glue.c +1 -14
@@ -15,10 +15,11 @@#include <crypto/xts.h> #include <linux/module.h> MODULE_AUTHOR ("Ard Biesheuvel <[email protected]>" );MODULE_DESCRIPTION ("Bit sliced AES using NEON instructions" ); +MODULE_IMPORT_NS ("CRYPTO_INTERNAL" );MODULE_LICENSE ("GPL v2" );MODULE_ALIAS_CRYPTO ("ecb(aes)" );MODULE_ALIAS_CRYPTO ("cbc(aes)" );MODULE_ALIAS_CRYPTO ("ctr(aes)" );
@@ -40,24 +41,10 @@ asmlinkage void aesbs_ctr_encrypt(u8 out[], u8 const in[], u8 const rk[], asmlinkage void aesbs_xts_encrypt(u8 out[], u8 const in[], u8 const rk[],int rounds,int blocks,u8 iv[]); asmlinkage void aesbs_xts_decrypt(u8 out[], u8 const in[], u8 const rk[],int rounds,int blocks,u8 iv[]); -/* borrowed from aes-neon-blk.ko */ -asmlinkage void neon_aes_ecb_encrypt(u8 out[], u8 const in[], u32 const rk[], -int rounds,int blocks); -asmlinkage void neon_aes_cbc_encrypt(u8 out[], u8 const in[], u32 const rk[], -int rounds,int blocks,u8 iv[]); -asmlinkage void neon_aes_ctr_encrypt(u8 out[], u8 const in[], u32 const rk[], -int rounds,int bytes,u8 ctr[]); -asmlinkage void neon_aes_xts_encrypt(u8 out[], u8 const in[], -u32 const rk1[],int rounds,int bytes, -u32 const rk2[],u8 iv[],int first); -asmlinkage void neon_aes_xts_decrypt(u8 out[], u8 const in[], -u32 const rk1[],int rounds,int bytes, -u32 const rk2[],u8 iv[],int first); -struct aesbs_ctx {u8 rk[13 * (8 *AES_BLOCK_SIZE ) +32 ];int rounds; }__aligned(AES_BLOCK_SIZE) ;
include/crypto/aes.h +69 -0
79 lines not on this page · raw message
lib/crypto/Makefile +3 -1
@@ -24,11 +24,13 @@ CFLAGS_aes.o += -I$(src)/$(SRCARCH) libaes-$(CONFIG_ARM) += arm/aes-cipher-core.o ifeq ($(CONFIG_ARM64),y) libaes-y += arm64/aes-cipher-core.o -libaes-$(CONFIG_KERNEL_MODE_NEON) += arm64/aes-ce-core.o +libaes-$(CONFIG_KERNEL_MODE_NEON) += arm64/aes-ce-core.o \ + arm64/aes-ce.o \ + arm64/aes-neon.o endif ifeq ($(CONFIG_PPC),y) ifeq ($(CONFIG_SPE),y) libaes-y += powerpc/aes-spe-core.o \
lib/crypto/arm64/aes-ce.S renamed from arch/arm64/crypto/aes-ce.S +0 -0
lib/crypto/arm64/aes-modes.S renamed from arch/arm64/crypto/aes-modes.S +0 -0
lib/crypto/arm64/aes-neon.S renamed from arch/arm64/crypto/aes-neon.S +0 -0
lib/crypto/arm64/aes.h +30 -0
@@ -124,10 +124,40 @@ int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, 6 + key_len / 4);return 0 ; }EXPORT_SYMBOL (ce_aes_expandkey); +#if IS_ENABLED (CONFIG_KERNEL_MODE_NEON ) +EXPORT_SYMBOL_NS_GPL (neon_aes_ecb_encrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (neon_aes_ecb_decrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (neon_aes_cbc_encrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (neon_aes_cbc_decrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (neon_aes_cbc_cts_encrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (neon_aes_cbc_cts_decrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (neon_aes_ctr_encrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (neon_aes_xctr_encrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (neon_aes_xts_encrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (neon_aes_xts_decrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (neon_aes_essiv_cbc_encrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (neon_aes_essiv_cbc_decrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (neon_aes_mac_update,"CRYPTO_INTERNAL" ); + +EXPORT_SYMBOL_NS_GPL (ce_aes_ecb_encrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (ce_aes_ecb_decrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (ce_aes_cbc_encrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (ce_aes_cbc_decrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (ce_aes_cbc_cts_encrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (ce_aes_cbc_cts_decrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (ce_aes_ctr_encrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (ce_aes_xctr_encrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (ce_aes_xts_encrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (ce_aes_xts_decrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (ce_aes_essiv_cbc_encrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (ce_aes_essiv_cbc_decrypt,"CRYPTO_INTERNAL" ); +EXPORT_SYMBOL_NS_GPL (ce_aes_mac_update,"CRYPTO_INTERNAL" ); +#endif +static void aes_encrypt_arch (const struct aes_enckey *key,u8 out[AES_BLOCK_SIZE ],const u8 in[AES_BLOCK_SIZE ]) { if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
Signature · 1 line
2.53.0
Eric Biggers
maintainerPATCH 5/15 lib/crypto: arm64/aes: Migrate optimized CBC-based MACs into library
In reply to Eric BiggersInstead of exposing the arm64-optimized CMAC, XCBC-MAC, and CBC-MAC code via arm64-specific crypto_shash algorithms, instead just implement the aes_cbcmac_blocks_arch() library function. This is much simpler, it makes the corresponding library functions be arm64-optimized, and it fixes the longstanding issue where this optimized code was disabled by default. The corresponding algorithms still remain available through crypto_shash, but individual architectures no longer need to handle it.
Note that to be compatible with the library using 'size_t' lengths, the type of the return value and 'blocks' parameter to the assembly functions had to be changed to 'size_t', and the assembly code had to be updated accordingly to use the corresponding 64-bit registers.
--- arch/arm64/crypto/Kconfig | 2 +- arch/arm64/crypto/aes-glue.c | 213 +---------------------------------- include/crypto/aes.h | 9 +- lib/crypto/arm64/aes-modes.S | 19 ++-- lib/crypto/arm64/aes.h | 48 +++++++- 5 files changed, 61 insertions(+), 230 deletions(-)
arch/arm64/crypto/Kconfig +1 -1
@@ -142,11 +142,11 @@ config CRYPTO_AES_ARM64_CE_CCM tristate "AEAD cipher: AES in CCM mode (ARMv8 Crypto Extensions)" depends on KERNEL_MODE_NEON select CRYPTO_ALGAPI select CRYPTO_AES_ARM64_CE_BLK select CRYPTO_AEAD - select CRYPTO_LIB_AES + select CRYPTO_LIB_AES_CBC_MACS help AEAD cipher: AES cipher algorithms (FIPS-197) with CCM (Counter with Cipher Block Chaining-Message Authentication Code) authenticated encryption mode (NIST SP800-38C)
arch/arm64/crypto/aes-glue.c +1 -212
270 lines not on this page · raw message
include/crypto/aes.h +3 -6
@@ -198,13 +198,10 @@ asmlinkage void neon_aes_essiv_cbc_encrypt(u8 out[], u8 const in[], u32 const rk2[]); asmlinkage void neon_aes_essiv_cbc_decrypt(u8 out[], u8 const in[],u32 const rk1[],int rounds,int blocks,u8 iv[],u32 const rk2[]); -asmlinkage int neon_aes_mac_update(u8 const in[], u32 const rk[], int rounds, -int blocks,u8 dg[],int enc_before, -int enc_after); asmlinkage void ce_aes_ecb_encrypt(u8 out[], u8 const in[], u32 const rk[],int rounds,int blocks); asmlinkage void ce_aes_ecb_decrypt(u8 out[], u8 const in[], u32 const rk[],int rounds,int blocks);
@@ -231,13 +228,13 @@ asmlinkage void ce_aes_essiv_cbc_encrypt(u8 out[], u8 const in[], u32 const rk1[], int rounds, int blocks, u8 iv[], u32 const rk2[]); asmlinkage void ce_aes_essiv_cbc_decrypt(u8 out[], u8 const in[],u32 const rk1[],int rounds,int blocks,u8 iv[],u32 const rk2[]); -asmlinkage int ce_aes_mac_update(u8 const in[], u32 const rk[], int rounds, -int blocks,u8 dg[],int enc_before, -int enc_after); +asmlinkage size_t ce_aes_mac_update(u8 const in[], u32 const rk[], int rounds, +size_t blocks,u8 dg[],int enc_before, +int enc_after);#elif defined(CONFIG_PPC )void ppc_expand_key_128 (u32 *key_enc,const u8 *key);void ppc_expand_key_192 (u32 *key_enc,const u8 *key);void ppc_expand_key_256 (u32 *key_enc,const u8 *key);void ppc_generate_decrypt_key (u32 *key_dec,u32 *key_enc,unsigned int key_len);
lib/crypto/arm64/aes-modes.S +11 -8
@@ -813,54 +813,57 @@ AES_FUNC_START(aes_xts_decrypt) st1 {v2.16b}, [x4] /* overlapping stores */ mov w4, wzr b .Lxtsdecctsout AES_FUNC_END(aes_xts_decrypt) +#if IS_ENABLED(CONFIG_CRYPTO_LIB_AES_CBC_MACS) /* - * aes_mac_update(u8 const in[], u32 const rk[], int rounds, - * int blocks, u8 dg[], int enc_before, int enc_after) + * size_t aes_mac_update(u8 const in[], u32 const rk[], int rounds, + * size_t blocks, u8 dg[], int enc_before, + * int enc_after); */ AES_FUNC_START(aes_mac_update) ld1 {v0.16b}, [x4] /* get dg */ enc_prepare w2, x1, x7 cbz w5, .Lmacloop4x encrypt_block v0, w2, x1, x7, w8 .Lmacloop4x: - subs w3, w3, #4 + subs x3, x3, #4 bmi .Lmac1x ld1 {v1.16b-v4.16b}, [x0], #64 /* get next pt block */ eor v0.16b, v0.16b, v1.16b /* ..and xor with dg */ encrypt_block v0, w2, x1, x7, w8 eor v0.16b, v0.16b, v2.16b encrypt_block v0, w2, x1, x7, w8 eor v0.16b, v0.16b, v3.16b encrypt_block v0, w2, x1, x7, w8 eor v0.16b, v0.16b, v4.16b - cmp w3, wzr + cmp x3, xzr csinv w5, w6, wzr, eq cbz w5, .Lmacout encrypt_block v0, w2, x1, x7, w8 st1 {v0.16b}, [x4] /* return dg */ cond_yield .Lmacout, x7, x8 b .Lmacloop4x .Lmac1x: - add w3, w3, #4 + add x3, x3, #4 .Lmacloop: - cbz w3, .Lmacout + cbz x3, .Lmacout ld1 {v1.16b}, [x0], #16 /* get next pt block */ eor v0.16b, v0.16b, v1.16b /* ..and xor with dg */ - subs w3, w3, #1 + subs x3, x3, #1 csinv w5, w6, wzr, eq cbz w5, .Lmacout .Lmacenc: encrypt_block v0, w2, x1, x7, w8 b .Lmacloop .Lmacout: st1 {v0.16b}, [x4] /* return dg */ - mov w0, w3 + mov x0, x3 ret AES_FUNC_END(aes_mac_update) +#endif /* CONFIG_CRYPTO_LIB_AES_CBC_MACS */
lib/crypto/arm64/aes.h +45 -3
99 lines not on this page · raw message
Signature · 1 line
2.53.0
Eric Biggers
maintainerPATCH 6/15 lib/crypto: tests: Add KUnit tests for CBC-based MACs
In reply to Eric BiggersAdd a KUnit test suite for the AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC library functions.
--- lib/crypto/tests/Kconfig | 10 ++ lib/crypto/tests/Makefile | 1 + lib/crypto/tests/aes-cmac-testvecs.h | 181 ++++++++++++++++++++ lib/crypto/tests/aes_cbc_macs_kunit.c | 228 ++++++++++++++++++++++++++ scripts/crypto/gen-hash-testvecs.py | 31 +++- 5 files changed, 448 insertions(+), 3 deletions(-) create mode 100644 lib/crypto/tests/aes-cmac-testvecs.h create mode 100644 lib/crypto/tests/aes_cbc_macs_kunit.c
lib/crypto/tests/Kconfig +10 -0
@@ -1,7 +1,17 @@ # SPDX-License-Identifier: GPL-2.0-or-later +config CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST + tristate "KUnit tests for AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS || CRYPTO_SELFTESTS + select CRYPTO_LIB_BENCHMARK_VISIBLE + select CRYPTO_LIB_AES_CBC_MACS + help + KUnit tests for the AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC message + authentication codes. + config CRYPTO_LIB_BLAKE2B_KUNIT_TEST tristate "KUnit tests for BLAKE2b" if !KUNIT_ALL_TESTS depends on KUNIT default KUNIT_ALL_TESTS || CRYPTO_SELFTESTS select CRYPTO_LIB_BENCHMARK_VISIBLE
lib/crypto/tests/Makefile +1 -0
@@ -1,7 +1,8 @@ # SPDX-License-Identifier: GPL-2.0-or-later +obj-$(CONFIG_CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST) += aes_cbc_macs_kunit.o obj-$(CONFIG_CRYPTO_LIB_BLAKE2B_KUNIT_TEST) += blake2b_kunit.o obj-$(CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST) += blake2s_kunit.o obj-$(CONFIG_CRYPTO_LIB_CURVE25519_KUNIT_TEST) += curve25519_kunit.o obj-$(CONFIG_CRYPTO_LIB_MD5_KUNIT_TEST) += md5_kunit.o obj-$(CONFIG_CRYPTO_LIB_MLDSA_KUNIT_TEST) += mldsa_kunit.o
lib/crypto/tests/aes-cmac-testvecs.h new file +181 -0
181 lines not on this page · raw message
lib/crypto/tests/aes_cbc_macs_kunit.c new file +228 -0
228 lines not on this page · raw message
scripts/crypto/gen-hash-testvecs.py +28 -3
@@ -1,12 +1,16 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0-or-later # # Script that generates test vectors for the given hash function. # +# Requires that python-cryptography be installed. +# # Copyright 2025 Google LLC +import cryptography.hazmat.primitives.ciphers +import cryptography.hazmat.primitives.cmac import hashlib import hmac import sys DATA_LENS = [0, 1, 2, 3, 16, 32, 48, 49, 63, 64, 65, 127, 128, 129, 256, 511,
@@ -22,10 +26,24 @@ def rand_bytes(length): for _ in range(length): seed = (seed * 25214903917 + 11) % 2**48 out.append((seed >> 16) % 256) return bytes(out) +AES_256_KEY_SIZE = 32 + +# AES-CMAC. Just wraps the implementation from python-cryptography. +class AesCmac: + def __init__(self, key): + aes = cryptography.hazmat.primitives.ciphers.algorithms.AES(key) + self.cmac = cryptography.hazmat.primitives.cmac.CMAC(aes) + + def update(self, data): + self.cmac.update(data) + + def digest(self): + return self.cmac.finalize() + POLY1305_KEY_SIZE = 32 # A straightforward, unoptimized implementation of Poly1305. # Reference: https://cr.yp.to/mac/poly1305-20050329.pdf class Poly1305:
@@ -78,13 +96,16 @@ class Polyval: def digest(self): return self.acc.to_bytes(16, byteorder='little') def hash_init(alg): + # The keyed hash functions are assigned a fixed random key here, to present + # them as unkeyed hash functions. This allows all the test cases for + # unkeyed hash functions to work on them. + if alg == 'aes-cmac': + return AesCmac(rand_bytes(AES_256_KEY_SIZE)) if alg == 'poly1305': - # Use a fixed random key here, to present Poly1305 as an unkeyed hash. - # This allows all the test cases for unkeyed hashes to work on Poly1305. return Poly1305(rand_bytes(POLY1305_KEY_SIZE)) if alg == 'polyval': return Polyval(rand_bytes(POLYVAL_BLOCK_SIZE)) return hashlib.new(alg)
@@ -114,10 +135,12 @@ def print_c_struct_u8_array_field(name, value): print(f'\t\t.{name} = {{') print_bytes('\t\t\t', value, 8) print('\t\t},') def alg_digest_size_const(alg): + if alg == 'aes-cmac': + return 'AES_BLOCK_SIZE' if alg.startswith('blake2'): return f'{alg.upper()}_HASH_SIZE' return f"{alg.upper().replace('-', '_')}_DIGEST_SIZE" def gen_unkeyed_testvecs(alg):
@@ -250,11 +273,13 @@ if len(sys.argv) != 2: sys.exit(1) alg = sys.argv[1] print('/* SPDX-License-Identifier: GPL-2.0-or-later */') print(f'/* This file was generated by: {sys.argv[0]} {" ".join(sys.argv[1:])} */') -if alg.startswith('blake2'): +if alg == 'aes-cmac': + gen_unkeyed_testvecs(alg) +elif alg.startswith('blake2'): gen_unkeyed_testvecs(alg) gen_additional_blake2_testvecs(alg) elif alg == 'nh': gen_nh_testvecs() elif alg == 'poly1305':
Signature · 1 line
2.53.0
Eric Biggers
maintainerPATCH 7/15 lib/crypto: aes: Add FIPS self-test for CMAC
In reply to Eric BiggersAdd a FIPS cryptographic algorithm self-test for AES-CMAC to fulfill the self-test requirement when this code is built into a FIPS 140 cryptographic module. This provides parity with the traditional crypto API, which uses crypto/testmgr.c to meet the FIPS self-test requirement.
--- lib/crypto/aes.c | 35 ++++++++++++++++++++++++++--- lib/crypto/fips.h | 5 +++++ scripts/crypto/gen-fips-testvecs.py | 10 +++++++++ 3 files changed, 47 insertions(+), 3 deletions(-)
lib/crypto/aes.c +32 -3
@@ -10,10 +10,11 @@#include <linux/cache.h> #include <linux/crypto.h> #include <linux/export.h> #include <linux/module.h> #include <linux/unaligned.h> +#include "fips.h" static const u8 ____cacheline_aligned aes_sbox[] = {0x63 ,0x7c ,0x77 ,0x7b ,0xf2 ,0x6b ,0x6f ,0xc5 ,0x30 ,0x01 ,0x67 ,0x2b ,0xfe ,0xd7 ,0xab ,0x76 ,0xca ,0x82 ,0xc9 ,0x7d ,0xfa ,0x59 ,0x47 ,0xf0 ,
@@ -706,25 +707,53 @@ void aes_cbcmac_final(struct aes_cbcmac_ctx *ctx, u8 out[AES_BLOCK_SIZE]) else memcpy(out, ctx->h, AES_BLOCK_SIZE);memzero_explicit (ctx,sizeof (*ctx)); }EXPORT_SYMBOL_NS_GPL (aes_cbcmac_final,"CRYPTO_INTERNAL" ); -#endif /* CONFIG_CRYPTO_LIB_AES_CBC_MACS */ -#ifdef aes_mod_init_arch +/* +* FIPS cryptographic algorithm self-test for AES-CMAC. As per the FIPS 140-3 +* Implementation Guidance, a cryptographic algorithm self-test for at least one +* of AES-GCM, AES-CCM, AES-CMAC, or AES-GMAC is required if any of those modes +* is implemented. This fulfills that requirement via AES-CMAC. +* +* This is just for FIPS. The full tests are in the KUnit test suite. +*/ +static void __init aes_cmac_fips_test (void ) +{ +struct aes_cmac_key key; +u8 mac[AES_BLOCK_SIZE ]; + +if (aes_cmac_preparekey (&key, fips_test_key,sizeof (fips_test_key)) != +0 ) +panic ("aes: CMAC FIPS self-test failed (preparekey)\n" ); +aes_cmac (&key, fips_test_data,sizeof (fips_test_data), mac); +if (memcmp (fips_test_aes_cmac_value, mac,sizeof (mac)) !=0 ) +panic ("aes: CMAC FIPS self-test failed (wrong MAC)\n" ); +memzero_explicit (&key,sizeof (key)); +} +#else /* CONFIG_CRYPTO_LIB_AES_CBC_MACS */ +static inline void aes_cmac_fips_test (void ) +{ +} +#endif /* !CONFIG_CRYPTO_LIB_AES_CBC_MACS */ +static int __init aes_mod_init (void ) { +#ifdef aes_mod_init_archaes_mod_init_arch (); +#endif +if (fips_enabled) +aes_cmac_fips_test ();return 0 ; }subsys_initcall (aes_mod_init); static void __exit aes_mod_exit(void) { }module_exit (aes_mod_exit); -#endif MODULE_DESCRIPTION ("AES block cipher" );MODULE_AUTHOR ("Ard Biesheuvel <[email protected]>" );MODULE_AUTHOR ("Eric Biggers <[email protected]>" );MODULE_LICENSE ("GPL v2" );
lib/crypto/fips.h +5 -0
@@ -41,5 +41,10 @@ static const u8 fips_test_sha3_256_value[] __initconst __maybe_unused = {0x77 ,0xc4 ,0x8b ,0x69 ,0x70 ,0x5f ,0x0a ,0xb1 ,0xb1 ,0xa5 ,0x82 ,0x0a ,0x22 ,0x2b ,0x49 ,0x31 ,0xba ,0x9b ,0xb6 ,0xaa ,0x32 ,0xa7 ,0x97 ,0x00 , 0x98, 0xdb, 0xff, 0xe7, 0xc6, 0xde, 0xb5, 0x82, }; + +static const u8 fips_test_aes_cmac_value[]__initconst __maybe_unused = { +0xc5 ,0x88 ,0x28 ,0x55 ,0xd7 ,0x2c ,0x00 ,0xb6 , +0x6a ,0xa7 ,0xfc ,0x82 ,0x90 ,0x81 ,0xcf ,0x18 , +};
scripts/crypto/gen-fips-testvecs.py +10 -0
@@ -1,12 +1,16 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0-or-later # # Script that generates lib/crypto/fips.h # +# Requires that python-cryptography be installed. +# # Copyright 2025 Google LLC +import cryptography.hazmat.primitives.ciphers +import cryptography.hazmat.primitives.cmac import hashlib import hmac fips_test_data = b"fips test data\0\0" fips_test_key = b"fips test key\0\0\0"
@@ -32,5 +36,11 @@ for alg in 'sha1', 'sha256', 'sha512': ctx.update(fips_test_data) print_static_u8_array_definition(f'fips_test_hmac_{alg}_value', ctx.digest()) print_static_u8_array_definition(f'fips_test_sha3_256_value', hashlib.sha3_256(fips_test_data).digest()) + +aes = cryptography.hazmat.primitives.ciphers.algorithms.AES(fips_test_key) +aes_cmac = cryptography.hazmat.primitives.cmac.CMAC(aes) +aes_cmac.update(fips_test_data) +print_static_u8_array_definition('fips_test_aes_cmac_value', + aes_cmac.finalize())
Signature · 1 line
2.53.0
Eric Biggers
maintainerPATCH 8/15 smb: client: Use AES-CMAC library for SMB3 signature calculation
In reply to Eric BiggersConvert smb3_calc_signature() to use the AES-CMAC library instead of a "cmac(aes)" crypto_shash.
The result is simpler and faster code. With the library there's no need to allocate memory, no need to handle errors except for key preparation, and the AES-CMAC code is accessed directly without inefficient indirect calls and other unnecessary API overhead.
For now a "cmac(aes)" crypto_shash is still being allocated in 'struct cifs_secmech'. Later commits will remove that, simplifying the code even further.
--- fs/smb/client/Kconfig | 1 + fs/smb/client/cifsencrypt.c | 60 ++++++++++++----------------------- fs/smb/client/cifsglob.h | 2 +- fs/smb/client/smb2transport.c | 41 +++++------------------- 4 files changed, 30 insertions(+), 74 deletions(-)
fs/smb/client/Kconfig +1 -0
@@ -9,10 +9,11 @@ config CIFS select CRYPTO_AEAD2 select CRYPTO_CCM select CRYPTO_GCM select CRYPTO_ECB select CRYPTO_AES + select CRYPTO_LIB_AES_CBC_MACS select CRYPTO_LIB_ARC4 select CRYPTO_LIB_MD5 select CRYPTO_LIB_SHA256 select CRYPTO_LIB_SHA512 select KEYS
fs/smb/client/cifsencrypt.c +20 -40
101 lines not on this page · raw message
fs/smb/client/cifsglob.h +1 -1
@@ -2285,11 +2285,11 @@ static inline void mid_execute_callback(struct TCP_Server_Info *server, FILE_SUPPORTS_REPARSE_POINTS))struct cifs_calc_sig_ctx {struct md5_ctx *md5;struct hmac_sha256_ctx *hmac; -struct shash_desc *shash; +struct aes_cmac_ctx *cmac; };#define CIFS_RECONN_DELAY_SECS 30#define CIFS_MAX_RECONN_DELAY (4 * CIFS_RECONN_DELAY_SECS)
fs/smb/client/smb2transport.c +8 -33
96 lines not on this page · raw message
Signature · 1 line
2.53.0
Eric Biggers
maintainerPATCH 9/15 smb: client: Remove obsolete cmac(aes) allocation
In reply to Eric BiggersSince the crypto library API is now being used instead of crypto_shash, the "cmac(aes)" crypto_shash that is being allocated and stored in 'struct cifs_secmech' is no longer used. Remove it.
That makes the kconfig selection of CRYPTO_CMAC and the module softdep on "cmac" unnecessary. So remove those too.
Finally, since this removes the last use of crypto_shash from the smb client, also remove the remaining crypto_shash-related helper functions.
Note: cifs_unicode.c was relying on <linux/unaligned.h> being included transitively via <crypto/internal/hash.h>. Since the latter include is removed, make cifs_unicode.c include <linux/unaligned.h> explicitly.
--- fs/smb/client/Kconfig | 1 - fs/smb/client/cifs_unicode.c | 1 + fs/smb/client/cifsencrypt.c | 2 -- fs/smb/client/cifsfs.c | 1 - fs/smb/client/cifsglob.h | 5 +-- fs/smb/client/cifsproto.h | 3 -- fs/smb/client/misc.c | 57 ----------------------------------- fs/smb/client/sess.c | 11 ------- fs/smb/client/smb2proto.h | 1 - fs/smb/client/smb2transport.c | 15 --------- 10 files changed, 2 insertions(+), 95 deletions(-)
fs/smb/client/Kconfig +0 -1
@@ -3,11 +3,10 @@ config CIFS tristate "SMB3 and CIFS support (advanced network filesystem)" depends on INET select NLS select NLS_UCS2_UTILS select CRYPTO - select CRYPTO_CMAC select CRYPTO_AEAD2 select CRYPTO_CCM select CRYPTO_GCM select CRYPTO_ECB select CRYPTO_AES
fs/smb/client/cifs_unicode.c +1 -0
@@ -4,10 +4,11 @@* Copyright (c) International Business Machines Corp., 2000,2009 * Modified by Steve French ([email protected]) */ #include <linux/fs.h> #include <linux/slab.h> +#include <linux/unaligned.h> #include "cifs_fs_sb.h" #include "cifs_unicode.h" #include "cifsglob.h" #include "cifs_debug.h"
fs/smb/client/cifsencrypt.c +0 -2
@@ -501,12 +501,10 @@ calc_seckey(struct cifs_ses *ses) }void cifs_crypto_secmech_release (struct TCP_Server_Info *server) { -cifs_free_hash (&server->secmech.aes_cmac); -if (server->secmech.enc) {crypto_free_aead (server->secmech.enc); server->secmech.enc =NULL ; }if (server->secmech.dec) {
fs/smb/client/cifsfs.c +0 -1
@@ -2142,11 +2142,10 @@ MODULE_DESCRIPTION "also older servers complying with the SNIA CIFS Specification)");MODULE_VERSION (CIFS_VERSION );MODULE_SOFTDEP ("ecb" );MODULE_SOFTDEP ("nls" );MODULE_SOFTDEP ("aes" ); -MODULE_SOFTDEP ("cmac" );MODULE_SOFTDEP ("aead2" );MODULE_SOFTDEP ("ccm" );MODULE_SOFTDEP ("gcm" );module_init (init_cifs)module_exit (exit_cifs)
fs/smb/client/cifsglob.h +1 -4
@@ -20,11 +20,10 @@#include <linux/utsname.h> #include <linux/sched/mm.h> #include <linux/netfs.h> #include "cifs_fs_sb.h" #include "cifsacl.h" -#include <crypto/internal/hash.h> #include <uapi/linux/cifs/cifs_mount.h> #include "../common/smbglob.h" #include "../common/smb2pdu.h" #include "../common/fscc.h" #include "smb2pdu.h"
@@ -218,14 +217,12 @@ static inline const char *cifs_symlink_type_str(enum cifs_symlink_type type)struct session_key {unsigned int len;char *response; }; -/* crypto hashing related structure/fields, not specific to a sec mech */ +/* encryption related structure/fields, not specific to a sec mech */ struct cifs_secmech { -struct shash_desc *aes_cmac;/* block-cipher based MAC function, for SMB3 signatures */ -struct crypto_aead *enc;/* smb3 encryption AEAD TFM (AES-CCM and AES-GCM) */ struct crypto_aead *dec;/* smb3 decryption AEAD TFM (AES-CCM and AES-GCM) */ };/* per smb session structure/fields */
fs/smb/client/cifsproto.h +0 -3
@@ -345,13 +345,10 @@ int __cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, char *signature, struct cifs_calc_sig_ctx *ctx);enum securityEnum cifs_select_sectype (struct TCP_Server_Info *server,enum securityEnum requested); -int cifs_alloc_hash (const char *name,struct shash_desc **sdesc); -void cifs_free_hash (struct shash_desc **sdesc); -int cifs_try_adding_channels (struct cifs_ses *ses);int smb3_update_ses_channels (struct cifs_ses *ses,struct TCP_Server_Info *server,bool from_reconnect,bool disable_mchan);bool is_ses_using_iface (struct cifs_ses *ses,struct cifs_server_iface *iface);
fs/smb/client/misc.c +0 -57
67 lines not on this page · raw message
fs/smb/client/sess.c +0 -11
@@ -593,21 +593,10 @@ cifs_ses_add_channel(struct cifs_ses *ses,cifs_chan_set_need_reconnect (ses, chan->server);spin_unlock (&ses->chan_lock);mutex_lock (&ses->session_mutex); -/* -* We need to allocate the server crypto now as we will need -* to sign packets before we generate the channel signing key -* (we sign with the session key) -*/ - rc =smb3_crypto_shash_allocate (chan->server); -if (rc) { -cifs_dbg (VFS ,"%s: crypto alloc failed\n" , __func__); -mutex_unlock (&ses->session_mutex); - goto out; - } rc =cifs_negotiate_protocol (xid, ses, chan->server);if (!rc) rc =cifs_setup_session (xid, ses, chan->server, ses->local_nls);
fs/smb/client/smb2proto.h +0 -1
@@ -253,11 +253,10 @@ int smb2_validate_iov(unsigned int offset, unsigned int buffer_length,int smb2_validate_and_copy_iov (unsigned int offset,unsigned int buffer_length,struct kvec *iov,unsigned int minbufsize,char *data);void smb2_copy_fs_info_to_kstatfs (struct smb2_fs_full_size_info *pfs_inf,struct kstatfs *kst); -int smb3_crypto_shash_allocate (struct TCP_Server_Info *server);void smb311_update_preauth_hash (struct cifs_ses *ses,struct TCP_Server_Info *server,struct kvec *iov,int nvec); int smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, const char *path, u32 desired_access, u32 class,
fs/smb/client/smb2transport.c +0 -15
@@ -27,18 +27,10 @@#include "smb2proto.h" #include "cifs_debug.h" #include "../common/smb2status.h" #include "smb2glob.h" -int -smb3_crypto_shash_allocate (struct TCP_Server_Info *server) -{ -struct cifs_secmech *p = &server->secmech; - -return cifs_alloc_hash ("cmac(aes)" , &p->aes_cmac); -} -static int smb3_get_sign_key (__u64 ses_id,struct TCP_Server_Info *server,u8 *key) {struct cifs_chan *chan;struct TCP_Server_Info *pserver;
@@ -264,24 +256,17 @@ static int generate_key(struct cifs_ses *ses, struct kvec label, {unsigned char zero =0x0 ;__u8 i[4 ] = {0 ,0 ,0 ,1 };__u8 L128 [4 ] = {0 ,0 ,0 ,128 };__u8 L256 [4 ] = {0 ,0 ,1 ,0 }; -int rc =0 ;unsigned char prfhash[SMB2_HMACSHA256_SIZE ];struct TCP_Server_Info *server = ses->server;struct hmac_sha256_ctx hmac_ctx;memset (prfhash,0x0 ,SMB2_HMACSHA256_SIZE );memset (key,0x0 , key_size); - rc =smb3_crypto_shash_allocate (server); -if (rc) { -cifs_server_dbg (VFS ,"%s: crypto alloc failed\n" , __func__); -return rc; - } -hmac_sha256_init_usingrawkey (&hmac_ctx, ses->auth_key.response,SMB2_NTLMV2_SESSKEY_SIZE );hmac_sha256_update (&hmac_ctx, i,4 );hmac_sha256_update (&hmac_ctx, label.iov_base, label.iov_len);hmac_sha256_update (&hmac_ctx, &zero,1 );
Signature · 1 line
2.53.0
Eric Biggers
maintainerPATCH 10/15 smb: client: Make generate_key() return void
In reply to Eric BiggersSince the crypto library API is now being used instead of crypto_shash, generate_key() can no longer fail. Make it return void and simplify the callers accordingly.
--- fs/smb/client/smb2transport.c | 45 +++++++++++++---------------------- 1 file changed, 16 insertions(+), 29 deletions(-)
fs/smb/client/smb2transport.c +16 -29
@@ -249,12 +249,12 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,memcpy (shdr->Signature, smb2_signature,SMB2_SIGNATURE_SIZE );return rc; } -static int generate_key (struct cifs_ses *ses,struct kvec label, -struct kvec context,__u8 *key,unsigned int key_size) +static void generate_key (struct cifs_ses *ses,struct kvec label, +struct kvec context,__u8 *key,unsigned int key_size) {unsigned char zero =0x0 ;__u8 i[4 ] = {0 ,0 ,0 ,1 };__u8 L128 [4 ] = {0 ,0 ,0 ,128 };__u8 L256 [4 ] = {0 ,0 ,1 ,0 };
@@ -279,11 +279,10 @@ static int generate_key(struct cifs_ses *ses, struct kvec label,hmac_sha256_update (&hmac_ctx,L128 ,4 ); }hmac_sha256_final (&hmac_ctx, prfhash);memcpy (key, prfhash, key_size); -return 0 ; }struct derivation {struct kvec label;struct kvec context;
@@ -298,11 +297,10 @@ struct derivation_triplet {static int generate_smb3signingkey (struct cifs_ses *ses,struct TCP_Server_Info *server,const struct derivation_triplet *ptriplet) { -int rc;bool is_binding = false;int chan_index =0 ;spin_lock (&ses->ses_lock);spin_lock (&ses->chan_lock);
@@ -329,42 +327,31 @@ generate_smb3signingkey(struct cifs_ses *ses,* key and store it in the channel as to not overwrite the * master connection signing key stored in the session */ if (is_binding) { - rc =generate_key (ses, ptriplet->signing.label, - ptriplet->signing.context, - ses->chans[chan_index].signkey, -SMB3_SIGN_KEY_SIZE ); -if (rc) -return rc; +generate_key (ses, ptriplet->signing.label, + ptriplet->signing.context, + ses->chans[chan_index].signkey, +SMB3_SIGN_KEY_SIZE ); }else { - rc =generate_key (ses, ptriplet->signing.label, - ptriplet->signing.context, - ses->smb3signingkey, -SMB3_SIGN_KEY_SIZE ); -if (rc) -return rc; +generate_key (ses, ptriplet->signing.label, + ptriplet->signing.context, + ses->smb3signingkey,SMB3_SIGN_KEY_SIZE );/* safe to access primary channel, since it will never go away */ spin_lock (&ses->chan_lock);memcpy (ses->chans[chan_index].signkey, ses->smb3signingkey,SMB3_SIGN_KEY_SIZE );spin_unlock (&ses->chan_lock); - rc =generate_key (ses, ptriplet->encryption.label, - ptriplet->encryption.context, - ses->smb3encryptionkey, -SMB3_ENC_DEC_KEY_SIZE ); -if (rc) -return rc; - rc =generate_key (ses, ptriplet->decryption.label, - ptriplet->decryption.context, - ses->smb3decryptionkey, -SMB3_ENC_DEC_KEY_SIZE ); -if (rc) -return rc; +generate_key (ses, ptriplet->encryption.label, + ptriplet->encryption.context, + ses->smb3encryptionkey,SMB3_ENC_DEC_KEY_SIZE ); +generate_key (ses, ptriplet->decryption.label, + ptriplet->decryption.context, + ses->smb3decryptionkey,SMB3_ENC_DEC_KEY_SIZE ); }#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS cifs_dbg (VFS ,"%s: dumping generated AES session keys\n" , __func__);/*
@@ -389,11 +376,11 @@ generate_smb3signingkey(struct cifs_ses *ses, SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3encryptionkey);cifs_dbg (VFS ,"ServerOut Key %*ph\n" , SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3decryptionkey); }#endif -return rc; +return 0 ; }int generate_smb30signingkey (struct cifs_ses *ses,struct TCP_Server_Info *server)
Signature · 1 line
2.53.0
Eric Biggers
maintainerPATCH 11/15 smb: client: Drop 'allocate_crypto' arg from smb*_calc_signature()
In reply to Eric BiggersSince the crypto library API is now being used instead of crypto_shash, all structs for MAC computation are now just fixed-size structs allocated on the stack; no dynamic allocations are ever required. Besides being much more efficient, this also means that the 'allocate_crypto' argument to smb2_calc_signature() and smb3_calc_signature() is no longer used. Remove this unused argument.
--- fs/smb/client/smb2transport.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
fs/smb/client/smb2transport.c +5 -7
@@ -202,12 +202,11 @@ smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid)return tcon; }static int -smb2_calc_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server, -bool allocate_crypto) +smb2_calc_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server) {int rc;unsigned char smb2_signature[SMB2_HMACSHA256_SIZE ];struct kvec *iov = rqst->rq_iov;struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0 ].iov_base;
@@ -438,12 +437,11 @@ generate_smb311signingkey(struct cifs_ses *ses,return generate_smb3signingkey (ses, server, &triplet); }static int -smb3_calc_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server, -bool allocate_crypto) +smb3_calc_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server) {int rc;unsigned char smb3_signature[SMB2_CMACAES_SIZE ];struct kvec *iov = rqst->rq_iov;struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0 ].iov_base;
@@ -451,11 +449,11 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,struct aes_cmac_ctx cmac_ctx;struct smb_rqst drqst;u8 key[SMB3_SIGN_KEY_SIZE ];if (server->vals->protocol_id <=SMB21_PROT_ID ) -return smb2_calc_signature (rqst, server, allocate_crypto); +return smb2_calc_signature (rqst, server); rc =smb3_get_sign_key (le64_to_cpu (shdr->SessionId), server, key);if (unlikely (rc)) {cifs_server_dbg (FYI ,"%s: Could not get signing key\n" , __func__);return rc;
@@ -522,11 +520,11 @@ smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)if (!is_binding && !server->session_estab) {strscpy (shdr->Signature,"BSRSPYL" );return 0 ; } -return smb3_calc_signature (rqst, server, false); +return smb3_calc_signature (rqst, server); }int smb2_verify_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server) {
@@ -558,11 +556,11 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)*/ memcpy (server_response_sig, shdr->Signature,SMB2_SIGNATURE_SIZE );memset (shdr->Signature,0 ,SMB2_SIGNATURE_SIZE ); - rc =smb3_calc_signature (rqst, server, true); + rc =smb3_calc_signature (rqst, server);if (rc)return rc; if (crypto_memneq(server_response_sig, shdr->Signature,
Signature · 1 line
2.53.0
Re: [PATCH 11/15] smb: client: Drop 'allocate_crypto' arg from smb*_calc_signature()
Quoted 88 lines · Eric Biggers
Since the crypto library API is now being used instead of
crypto_shash, all structs for MAC computation are now just fixed-size structs allocated on the stack; no dynamic allocations are ever required. Besides being much more efficient, this also means that the 'allocate_crypto' argument tosmb2_calc_signature()andsmb3_calc_signature()is no longer used. Remove this unused argument.Signed-off-by Eric Biggers <[email protected]>--- fs/smb/client/smb2transport.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)fs/smb/client/smb2transport.c +5
-8@@ -202,12 +202,11 @@ smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid)return tcon; }static int -smb2_calc_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server, -bool allocate_crypto) +smb2_calc_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server) {int rc;unsigned char smb2_signature[SMB2_HMACSHA256_SIZE ];struct kvec *iov = rqst->rq_iov;struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0 ].iov_base;@@ -438,12 +437,11 @@ generate_smb311signingkey(struct cifs_ses *ses,return generate_smb3signingkey (ses, server, &triplet); }static int -smb3_calc_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server, -bool allocate_crypto) +smb3_calc_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server) {int rc;unsigned char smb3_signature[SMB2_CMACAES_SIZE ];struct kvec *iov = rqst->rq_iov;struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0 ].iov_base;@@ -451,11 +449,11 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,struct aes_cmac_ctx cmac_ctx;struct smb_rqst drqst;u8 key[SMB3_SIGN_KEY_SIZE ];if (server->vals->protocol_id <=SMB21_PROT_ID ) -return smb2_calc_signature (rqst, server, allocate_crypto); +return smb2_calc_signature (rqst, server); rc =smb3_get_sign_key (le64_to_cpu (shdr->SessionId), server, key);if (unlikely (rc)) {cifs_server_dbg (FYI ,"%s: Could not get signing key\n" , __func__);return rc;@@ -522,11 +520,11 @@ smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)if (!is_binding && !server->session_estab) {strscpy (shdr->Signature,"BSRSPYL" );return 0 ; } -return smb3_calc_signature (rqst, server, false); +return smb3_calc_signature (rqst, server); }int smb2_verify_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server) {@@ -558,11 +556,11 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)*/ memcpy (server_response_sig, shdr->Signature,SMB2_SIGNATURE_SIZE );memset (shdr->Signature,0 ,SMB2_SIGNATURE_SIZE ); - rc =smb3_calc_signature (rqst, server, true); + rc =smb3_calc_signature (rqst, server);if (rc)return rc; if (crypto_memneq(server_response_sig, shdr->Signature, --2.53.0
Signature · 3 lines
Thanks, Steve
Eric Biggers
maintainerPATCH 12/15 ksmbd: Use AES-CMAC library for SMB3 signature calculation
In reply to Eric BiggersNow that AES-CMAC has a library API, convert ksmbd_sign_smb3_pdu() to use it instead of a "cmac(aes)" crypto_shash.
The result is simpler and faster code. With the library there's no need to dynamically allocate memory, no need to handle errors, and the AES-CMAC code is accessed directly without inefficient indirect calls and other unnecessary API overhead.
--- fs/smb/server/Kconfig | 2 +- fs/smb/server/auth.c | 51 +++++++++------------------------ fs/smb/server/auth.h | 4 +-- fs/smb/server/crypto_ctx.c | 58 -------------------------------------- fs/smb/server/crypto_ctx.h | 12 -------- fs/smb/server/server.c | 1 - fs/smb/server/smb2pdu.c | 8 ++---- 7 files changed, 19 insertions(+), 117 deletions(-)
fs/smb/server/Kconfig +1 -1
@@ -6,17 +6,17 @@ config SMB_SERVER select NLS select NLS_UTF8 select NLS_UCS2_UTILS select CRYPTO select CRYPTO_ECB + select CRYPTO_LIB_AES_CBC_MACS select CRYPTO_LIB_ARC4 select CRYPTO_LIB_DES select CRYPTO_LIB_MD5 select CRYPTO_LIB_SHA256 select CRYPTO_LIB_SHA512 select CRYPTO_LIB_UTILS - select CRYPTO_CMAC select CRYPTO_AEAD2 select CRYPTO_CCM select CRYPTO_GCM select ASN1 select OID_REGISTRY
fs/smb/server/auth.c +13 -38
75 lines not on this page · raw message
fs/smb/server/auth.h +2 -2
@@ -52,12 +52,12 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob, struct ksmbd_conn *conn);int ksmbd_krb5_authenticate (struct ksmbd_session *sess,char *in_blob,int in_len,char *out_blob,int *out_len);void ksmbd_sign_smb2_pdu (struct ksmbd_conn *conn,char *key,struct kvec *iov,int n_vec,char *sig); -int ksmbd_sign_smb3_pdu (struct ksmbd_conn *conn,char *key,struct kvec *iov, -int n_vec,char *sig); +void ksmbd_sign_smb3_pdu (struct ksmbd_conn *conn,char *key,struct kvec *iov, +int n_vec,char *sig);int ksmbd_gen_smb30_signingkey (struct ksmbd_session *sess,struct ksmbd_conn *conn);int ksmbd_gen_smb311_signingkey (struct ksmbd_session *sess,struct ksmbd_conn *conn); void ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
fs/smb/server/crypto_ctx.c +0 -58
92 lines not on this page · raw message
fs/smb/server/crypto_ctx.h +0 -12
@@ -4,18 +4,12 @@*/ #ifndef __CRYPTO_CTX_H__#define __CRYPTO_CTX_H__ -#include <crypto/hash.h> #include <crypto/aead.h> -enum { -CRYPTO_SHASH_CMACAES =0 , -CRYPTO_SHASH_MAX , -}; -enum {CRYPTO_AEAD_AES_GCM =16 ,CRYPTO_AEAD_AES_CCM ,CRYPTO_AEAD_MAX , };
@@ -26,23 +20,17 @@ enum { };struct ksmbd_crypto_ctx {struct list_head list; -struct shash_desc *desc[CRYPTO_SHASH_MAX ];struct crypto_aead *ccmaes[CRYPTO_AEAD_MAX ]; }; -#define CRYPTO_CMACAES (c) ((c)->desc[CRYPTO_SHASH_CMACAES]) - -#define CRYPTO_CMACAES_TFM (c) ((c)->desc[CRYPTO_SHASH_CMACAES]->tfm) -#define CRYPTO_GCM (c) ((c)->ccmaes[CRYPTO_AEAD_AES_GCM])#define CRYPTO_CCM (c) ((c)->ccmaes[CRYPTO_AEAD_AES_CCM])void ksmbd_release_crypto_ctx (struct ksmbd_crypto_ctx *ctx); -struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes (void );struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm (void );struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm (void );void ksmbd_crypto_destroy (void );int ksmbd_crypto_create (void );
fs/smb/server/server.c +0 -1
@@ -631,11 +631,10 @@ MODULE_AUTHOR("Namjae Jeon <[email protected]>");MODULE_DESCRIPTION ("Linux kernel CIFS/SMB SERVER" );MODULE_LICENSE ("GPL" );MODULE_SOFTDEP ("pre: ecb" );MODULE_SOFTDEP ("pre: nls" );MODULE_SOFTDEP ("pre: aes" ); -MODULE_SOFTDEP ("pre: cmac" );MODULE_SOFTDEP ("pre: aead2" );MODULE_SOFTDEP ("pre: ccm" );MODULE_SOFTDEP ("pre: gcm" );module_init (ksmbd_server_init)module_exit (ksmbd_server_exit)
fs/smb/server/smb2pdu.c +3 -5
@@ -8964,12 +8964,11 @@ int smb3_check_sign_req(struct ksmbd_work *work)memcpy (signature_req, hdr->Signature,SMB2_SIGNATURE_SIZE );memset (hdr->Signature,0 ,SMB2_SIGNATURE_SIZE ); iov[0 ].iov_base = (char *)&hdr->ProtocolId; iov[0 ].iov_len = len; -if (ksmbd_sign_smb3_pdu (conn, signing_key, iov,1 , signature)) -return 0 ; +ksmbd_sign_smb3_pdu (conn, signing_key, iov,1 , signature);if (crypto_memneq (signature, signature_req,SMB2_SIGNATURE_SIZE )) {pr_err ("bad smb2 signature\n" );return 0 ; }
@@ -9016,13 +9015,12 @@ void smb3_set_sign_rsp(struct ksmbd_work *work) n_vec++; }else { iov = &work->iov[work->iov_idx]; } -if (!ksmbd_sign_smb3_pdu (conn, signing_key, iov, n_vec, - signature)) -memcpy (hdr->Signature, signature,SMB2_SIGNATURE_SIZE ); +ksmbd_sign_smb3_pdu (conn, signing_key, iov, n_vec, signature); +memcpy (hdr->Signature, signature,SMB2_SIGNATURE_SIZE ); }/** * smb3_preauth_hash_rsp() - handler for computing preauth hash on response * @work: smb work containing response buffer
Signature · 1 line
2.53.0
Re: [PATCH 12/15] ksmbd: Use AES-CMAC library for SMB3 signature calculation
Quoted 10 lines · Eric Biggers
Now that AES-CMAC has a library API, convert
ksmbd_sign_smb3_pdu()to use it instead of a "cmac(aes)"crypto_shash.The result is simpler and faster code. With the library there's no need to dynamically allocate memory, no need to handle errors, and the AES-CMAC code is accessed directly without inefficient indirect calls and other unnecessary API overhead.
Signed-off-by Eric Biggers <[email protected]>
Thanks!
Eric Biggers
maintainerPATCH 13/15 Bluetooth: SMP: Use AES-CMAC library API
In reply to Eric BiggersNow that AES-CMAC has a library API, convert net/bluetooth/smp.c to use it instead of the "cmac(aes)" crypto_shash. Since the library API doesn't require dynamic memory allocation, we no longer need to pass a crypto_shash object down the call stack and can simply allocate the aes_cmac_key on the stack in smp_aes_cmac() (renamed from aes_cmac()).
The result is simpler and faster code that no longer relies on the error-prone loading of algorithms by name.
Note that the maximum stack usage actually decreases slightly, despite the expanded AES key being moved to the stack. This is because the old code called crypto_shash_tfm_digest(), which allocates 384 bytes on the stack for a maximally-sized hash descriptor for any algorithm. The new code instead declares a 288-byte aes_cmac_key, then calls aes_cmac() which declares a 32-byte aes_cmac_ctx. Since 288 + 32 < 384, the maximum stack usage decreases. I.e. the entire expanded AES key easily fits in the space that the generic crypto API was wasting before.
I didn't add zeroization of the aes_cmac_key, since smp_aes_cmac() already copies the raw key to the stack without zeroizing it.
--- net/bluetooth/Kconfig | 3 +- net/bluetooth/smp.c | 180 +++++++++++++++--------------------------- 2 files changed, 65 insertions(+), 118 deletions(-)
net/bluetooth/Kconfig +1 -2
@@ -9,12 +9,11 @@ menuconfig BT depends on RFKILL || !RFKILL select CRC16 select CRYPTO select CRYPTO_SKCIPHER select CRYPTO_LIB_AES - imply CRYPTO_AES - select CRYPTO_CMAC + select CRYPTO_LIB_AES_CBC_MACS select CRYPTO_ECB select CRYPTO_SHA256 select CRYPTO_ECDH help Bluetooth is low-cost, low-power, short-range wireless technology.
net/bluetooth/smp.c +64 -116
739 lines not on this page · raw message
Signature · 1 line
2.53.0
Eric Biggers
maintainerPATCH 14/15 wifi: mac80211: Use AES-CMAC library in ieee80211_aes_cmac()
In reply to Eric BiggersNow that AES-CMAC has a library API, convert the mac80211 AES-CMAC packet authentication code to use it instead of a "cmac(aes)" crypto_shash. This has multiple benefits, such as:
- It's faster. The AES-CMAC code is now called directly, without unnecessary overhead such as indirect calls.
- MAC calculation can no longer fail.
- The AES-CMAC key struct is now a fixed size, allowing it to be embedded directly into 'struct ieee80211_key' rather than using a separate allocation. Note that although this increases the size of the 'u.cmac' field of 'struct ieee80211_key', it doesn't cause it to exceed the size of the largest variant of the union 'u'. Therefore, the size of 'struct ieee80211_key' itself is unchanged.
--- net/mac80211/Kconfig | 1 + net/mac80211/aes_cmac.c | 65 ++++++++--------------------------------- net/mac80211/aes_cmac.h | 12 +++----- net/mac80211/key.c | 11 ++----- net/mac80211/key.h | 3 +- net/mac80211/wpa.c | 13 +++------ 6 files changed, 26 insertions(+), 79 deletions(-)
net/mac80211/Kconfig +1 -0
@@ -1,10 +1,11 @@ # SPDX-License-Identifier: GPL-2.0-only config MAC80211 tristate "Generic IEEE 802.11 Networking Stack (mac80211)" depends on CFG80211 select CRYPTO + select CRYPTO_LIB_AES_CBC_MACS select CRYPTO_LIB_ARC4 select CRYPTO_AES select CRYPTO_CCM select CRYPTO_GCM select CRYPTO_CMAC
net/mac80211/aes_cmac.c +12 -53
92 lines not on this page · raw message
net/mac80211/aes_cmac.h +4 -8
@@ -4,16 +4,12 @@*/ #ifndef AES_CMAC_H #define AES_CMAC_H -#include <linux/crypto.h> -#include <crypto/hash.h> +#include <crypto/aes-cbc-macs.h> -struct crypto_shash *ieee80211_aes_cmac_key_setup (const u8 key[], -size_t key_len); -int ieee80211_aes_cmac (struct crypto_shash *tfm,const u8 *aad, -const u8 *data,size_t data_len,u8 *mic, -unsigned int mic_len); -void ieee80211_aes_cmac_key_free (struct crypto_shash *tfm); +void ieee80211_aes_cmac (const struct aes_cmac_key *key,const u8 *aad, +const u8 *data,size_t data_len,u8 *mic, +unsigned int mic_len);#endif /* AES_CMAC_H */
net/mac80211/key.c +3 -8
@@ -688,14 +688,13 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, seq[IEEE80211_CMAC_PN_LEN - j -1 ];/* * Initialize AES key state here as an optimization so that * it does not need to be initialized for every packet. */ - key->u.aes_cmac.tfm = -ieee80211_aes_cmac_key_setup (key_data, key_len); -if (IS_ERR (key->u.aes_cmac.tfm)) { - err =PTR_ERR (key->u.aes_cmac.tfm); + err =aes_cmac_preparekey (&key->u.aes_cmac.key, key_data, + key_len); +if (err) {kfree (key);return ERR_PTR (err); }break ;case WLAN_CIPHER_SUITE_BIP_GMAC_128 :
@@ -748,14 +747,10 @@ static void ieee80211_key_free_common(struct ieee80211_key *key)switch (key->conf.cipher) {case WLAN_CIPHER_SUITE_CCMP :case WLAN_CIPHER_SUITE_CCMP_256 :ieee80211_aes_key_free (key->u.ccmp.tfm);break ; -case WLAN_CIPHER_SUITE_AES_CMAC : -case WLAN_CIPHER_SUITE_BIP_CMAC_256 : -ieee80211_aes_cmac_key_free (key->u.aes_cmac.tfm); -break ;case WLAN_CIPHER_SUITE_BIP_GMAC_128 :case WLAN_CIPHER_SUITE_BIP_GMAC_256 :ieee80211_aes_gmac_key_free (key->u.aes_gmac.tfm);break ;case WLAN_CIPHER_SUITE_GCMP :
net/mac80211/key.h +2 -1
@@ -10,10 +10,11 @@#include <linux/types.h> #include <linux/list.h> #include <linux/crypto.h> #include <linux/rcupdate.h> +#include <crypto/aes-cbc-macs.h> #include <crypto/arc4.h> #include <net/mac80211.h> #define NUM_DEFAULT_KEYS 4#define NUM_DEFAULT_MGMT_KEYS 2
@@ -91,11 +92,11 @@ struct ieee80211_key {struct crypto_aead *tfm;u32 replays;/* dot11RSNAStatsCCMPReplays */ } ccmp;struct {u8 rx_pn[IEEE80211_CMAC_PN_LEN ]; -struct crypto_shash *tfm; +struct aes_cmac_key key;u32 replays;/* dot11RSNAStatsCMACReplays */ u32 icverrors;/* dot11RSNAStatsCMACICVErrors */ } aes_cmac;struct {u8 rx_pn[IEEE80211_GMAC_PN_LEN ];
net/mac80211/wpa.c +4 -9
@@ -870,15 +870,12 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx,if (info->control.hw_key)return TX_CONTINUE ;bip_aad (skb, aad); -if (ieee80211_aes_cmac (key->u.aes_cmac.tfm, aad, - skb->data +24 , skb->len -24 , - mmie->mic, mic_len)) -return TX_DROP ; - +ieee80211_aes_cmac (&key->u.aes_cmac.key, aad, skb->data +24 , + skb->len -24 , mmie->mic, mic_len);return TX_CONTINUE ; } ieee80211_rx_result ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx,
@@ -916,14 +913,12 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx, }if (!(status->flag &RX_FLAG_DECRYPTED )) {/* hardware didn't decrypt/verify MIC */ bip_aad (skb, aad); -if (ieee80211_aes_cmac (key->u.aes_cmac.tfm, aad, - skb->data +24 , skb->len -24 , - mic, mic_len)) -return RX_DROP_U_DECRYPT_FAIL ; +ieee80211_aes_cmac (&key->u.aes_cmac.key, aad, skb->data +24 , + skb->len -24 , mic, mic_len);if (crypto_memneq (mic, mmie->mic, mic_len)) { key->u.aes_cmac.icverrors++;return RX_DROP_U_MIC_FAIL ; } }
Signature · 1 line
2.53.0
Re: [PATCH 14/15] wifi: mac80211: Use AES-CMAC library in ieee80211_aes_cmac()
Quoted 7 lines · Eric Biggers
Now that AES-CMAC has a library API, convert the mac80211 AES-CMAC packet authentication code to use it instead of a "cmac(aes)"
crypto_shash. This has multiple benefits, such as:- It's faster. The AES-CMAC code is now called directly, without unnecessary overhead such as indirect calls.
Quoted 9 lines
- MAC calculation can no longer fail.
- The AES-CMAC key struct is now a fixed size, allowing it to be embedded directly into 'struct
ieee80211_key' rather than using a separate allocation. Note that although this increases the size of the 'u.cmac' field of 'structieee80211_key', it doesn't cause it to exceed the size of the largest variant of the union 'u'. Therefore, the size of 'structieee80211_key' itself is unchanged.
Looks good to me in principle, I suppose we should test it? :)
net/mac80211/key.c ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, · line 698
Quoted 6 lines
net/mac80211/key.c +3
-0+ err =aes_cmac_preparekey (&key->u.aes_cmac.key, key_data, + key_len); +if (err) {kfree (key);return ERR_PTR (err); }
Pretty sure that can't fail, per the documentation for aes_prepareenckey() and then aes_cmac_preparekey(), but it doesn't really matter. We can only get here with a key with size checked by cfg80211_validate_key_settings() already.
Since you're probably going to send it through the crypto tree:
johannes
Eric Biggers
maintainerRe: [PATCH 14/15] wifi: mac80211: Use AES-CMAC library in ieee80211_aes_cmac()
Quoted 18 lines · Johannes Berg
Quoted 7 lines · Eric Biggers
Now that AES-CMAC has a library API, convert the mac80211 AES-CMAC packet authentication code to use it instead of a "cmac(aes)"
crypto_shash. This has multiple benefits, such as:- It's faster. The AES-CMAC code is now called directly, without unnecessary overhead such as indirect calls.
Quoted 9 lines
- MAC calculation can no longer fail.
- The AES-CMAC key struct is now a fixed size, allowing it to be embedded directly into 'struct
ieee80211_key' rather than using a separate allocation. Note that although this increases the size of the 'u.cmac' field of 'structieee80211_key', it doesn't cause it to exceed the size of the largest variant of the union 'u'. Therefore, the size of 'structieee80211_key' itself is unchanged.
Quoted 1 line
Looks good to me in principle, I suppose we should test it? :)
Yes, I don't expect any issues, but testing of this patch would be appreciated. I don't know how to test every kernel subsystem.
Quoted 11 lines
net/mac80211/key.c ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, · line 698
Quoted 6 lines
net/mac80211/key.c +3
-0+ err =aes_cmac_preparekey (&key->u.aes_cmac.key, key_data, + key_len); +if (err) {kfree (key);return ERR_PTR (err); }Pretty sure that can't fail, per the documentation for
aes_prepareenckey()and thenaes_cmac_preparekey(), but it doesn't really matter. We can only get here with a key with size checked bycfg80211_validate_key_settings()already.
aes_cmac_preparekey() indeed always succeeds when passed a valid key length, as documented in its kerneldoc. But in this case I recommend just checking the error code anyway, since ieee80211_key_alloc() can already fail for other reasons (i.e., it needs the ability to report errors anyway) and the key length isn't a compile-time constant here.
Quoted 3 lines
Since you're probably going to send it through the crypto tree:
Acked-by Johannes Berg <[email protected]>
For library conversions like this I've usually been taking the library itself through libcrypto-next, then sending the subsystem conversions afterwards for subsystem maintainers to take in the next release. But I'd also be glad to just take this alongside the library itself.
- Eric
Johannes Berg
maintainerRe: [PATCH 14/15] wifi: mac80211: Use AES-CMAC library in ieee80211_aes_cmac()
Quoted 4 lines · Eric Biggers
Quoted 1 line
Looks good to me in principle, I suppose we should test it? :)
Yes, I don't expect any issues, but testing of this patch would be appreciated. I don't know how to test every kernel subsystem.
Done, works fine. I checked FILS (which is against hostapd userspace implementation) and validated the MME MIC against wlantest.
Quoted 12 lines
Quoted 11 lines
net/mac80211/key.c ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, · line 698
Quoted 6 lines
net/mac80211/key.c +3
-0+ err =aes_cmac_preparekey (&key->u.aes_cmac.key, key_data, + key_len); +if (err) {kfree (key);return ERR_PTR (err); }Pretty sure that can't fail, per the documentation for
aes_prepareenckey()and thenaes_cmac_preparekey(), but it doesn't really matter. We can only get here with a key with size checked bycfg80211_validate_key_settings()already.
Quoted 5 lines
aes_cmac_preparekey()indeed always succeeds when passed a valid key length, as documented in its kerneldoc. But in this case I recommend just checking the error code anyway, sinceieee80211_key_alloc()can already fail for other reasons (i.e., it needs the ability to report errors anyway) and the key length isn't a compile-time constant here.
Right, sure.
Quoted 8 lines
Quoted 3 lines
Since you're probably going to send it through the crypto tree:
Acked-by Johannes Berg <[email protected]>For library conversions like this I've usually been taking the library itself through libcrypto-next, then sending the subsystem conversions afterwards for subsystem maintainers to take in the next release. But I'd also be glad to just take this alongside the library itself.
OK, whichever you prefer. Feel free to take it, this code did change recently for some additional error checking, but it otherwise almost never changes, so there shouldn't be conflicts.
johannes
Eric Biggers
maintainerPATCH 15/15 wifi: mac80211: Use AES-CMAC library in aes_s2v()
In reply to Eric BiggersNow that AES-CMAC has a library API, convert aes_s2v() to use it instead of a "cmac(aes)" crypto_shash. The result is faster and simpler code.
It's also more reliable, since with the library the only step that can fail is preparing the key. In contrast, crypto_shash_digest(), crypto_shash_init(), crypto_shash_update(), and crypto_shash_final() could all fail and return an errno value. aes_s2v() ignored these errors, which was a bug. So that bug is fixed as well.
As part of this, change the prototype of aes_s2v() to take the raw key directly instead of a prepared key. Its only two callers prepare a key for each call, so it might as well be done directly in aes_s2v().
Since this removes the last dependency on the "cmac(aes)" crypto_shash from mac80211, also remove the 'select CRYPTO_CMAC'.
--- net/mac80211/Kconfig | 1 - net/mac80211/fils_aead.c | 48 ++++++++++++++-------------------------- 2 files changed, 17 insertions(+), 32 deletions(-)
net/mac80211/Kconfig +0 -1
@@ -6,11 +6,10 @@ config MAC80211 select CRYPTO_LIB_AES_CBC_MACS select CRYPTO_LIB_ARC4 select CRYPTO_AES select CRYPTO_CCM select CRYPTO_GCM - select CRYPTO_CMAC select CRC32 help This option enables the hardware independent IEEE 802.11 networking stack.
net/mac80211/fils_aead.c +17 -31
141 lines not on this page · raw message
Signature · 1 line
2.53.0
Re: [PATCH 15/15] wifi: mac80211: Use AES-CMAC library in aes_s2v()
Quoted 24 lines · Eric Biggers
Now that AES-CMAC has a library API, convert
aes_s2v()to use it instead of a "cmac(aes)"crypto_shash. The result is faster and simpler code.It's also more reliable, since with the library the only step that can fail is preparing the key. In contrast,
crypto_shash_digest(),crypto_shash_init(),crypto_shash_update(), andcrypto_shash_final()could all fail and return an errno value.aes_s2v()ignored these errors, which was a bug. So that bug is fixed as well.As part of this, change the prototype of
aes_s2v()to take the raw key directly instead of a prepared key. Its only two callers prepare a key for each call, so it might as well be done directly inaes_s2v().Since this removes the last dependency on the "cmac(aes)"
crypto_shashfrom mac80211, also remove the 'selectCRYPTO_CMAC'.net/mac80211/fils_aead.c +1
-1-static int aes_s2v (struct crypto_shash *tfm, +static int aes_s2v (const u8 *in_key,size_t key_len,size_t num_elem,const u8 *addr[],size_t len[],u8 *v) {u8 d[AES_BLOCK_SIZE ], tmp[AES_BLOCK_SIZE ] = {};
net/mac80211/fils_aead.c static void gf_mulx(u8 *pad) · line 34
Quoted 10 lines
net/mac80211/fils_aead.c +6
-2-SHASH_DESC_ON_STACK (desc, tfm); +struct aes_cmac_key key; +struct aes_cmac_ctx ctx;size_t i; +int res; - desc->tfm = tfm; + res =aes_cmac_preparekey (&key, in_key, key_len); +if (res) +return res;
Same here, maybe, technically, but also doesn't matter.
johannes
Eric Biggers
maintainerRe: [PATCH 15/15] wifi: mac80211: Use AES-CMAC library in aes_s2v()
Quoted 36 lines · Johannes Berg
Quoted 22 lines · Eric Biggers
Now that AES-CMAC has a library API, convert
aes_s2v()to use it instead of a "cmac(aes)"crypto_shash. The result is faster and simpler code.It's also more reliable, since with the library the only step that can fail is preparing the key. In contrast,
crypto_shash_digest(),crypto_shash_init(),crypto_shash_update(), andcrypto_shash_final()could all fail and return an errno value.aes_s2v()ignored these errors, which was a bug. So that bug is fixed as well.As part of this, change the prototype of
aes_s2v()to take the raw key directly instead of a prepared key. Its only two callers prepare a key for each call, so it might as well be done directly inaes_s2v().Since this removes the last dependency on the "cmac(aes)"
crypto_shashfrom mac80211, also remove the 'selectCRYPTO_CMAC'.net/mac80211/fils_aead.c +1
-1-static int aes_s2v (struct crypto_shash *tfm, +static int aes_s2v (const u8 *in_key,size_t key_len,size_t num_elem,const u8 *addr[],size_t len[],u8 *v) {u8 d[AES_BLOCK_SIZE ], tmp[AES_BLOCK_SIZE ] = {};net/mac80211/fils_aead.c static void gf_mulx(u8 *pad) · line 34
Quoted 10 lines
net/mac80211/fils_aead.c +6
-2-SHASH_DESC_ON_STACK (desc, tfm); +struct aes_cmac_key key; +struct aes_cmac_ctx ctx;size_t i; +int res; - desc->tfm = tfm; + res =aes_cmac_preparekey (&key, in_key, key_len); +if (res) +return res;Same here, maybe, technically, but also doesn't matter.
Quoted 3 lines
Acked-by Johannes Berg <[email protected]>johannes
In this case aes_s2v() wouldn't otherwise be able to fail, so ignoring the aes_cmac_preparekey() return value would indeed be a simplification.
However, since the key length isn't a compile-time constant here, we'd have to rely on non-local validation, which isn't ideal.
To ignore the return value entirely I'd prefer a static_assert that the length is equal to one of AES_KEYSIZE_*, which isn't possible here.
It's actually not clear to me where the length validation happens before here. nl80211_associate() for example just copies the length from userspace without validating it. ieee80211_mgd_assoc() only checks that the length is at most FILS_MAX_KEK_LEN (64).
- Eric
Johannes Berg
maintainerRe: [PATCH 15/15] wifi: mac80211: Use AES-CMAC library in aes_s2v()
Quoted 18 lines · Eric Biggers
Quoted 18 lines
Quoted 5 lines
net/mac80211/fils_aead.c +1
-1-static int aes_s2v (struct crypto_shash *tfm, +static int aes_s2v (const u8 *in_key,size_t key_len,size_t num_elem,const u8 *addr[],size_t len[],u8 *v) {u8 d[AES_BLOCK_SIZE ], tmp[AES_BLOCK_SIZE ] = {};net/mac80211/fils_aead.c static void gf_mulx(u8 *pad) · line 34
Quoted 10 lines
net/mac80211/fils_aead.c +6
-2-SHASH_DESC_ON_STACK (desc, tfm); +struct aes_cmac_key key; +struct aes_cmac_ctx ctx;size_t i; +int res; - desc->tfm = tfm; + res =aes_cmac_preparekey (&key, in_key, key_len); +if (res) +return res;Same here, maybe, technically, but also doesn't matter.
Quoted 6 lines
Quoted 3 lines
Acked-by Johannes Berg <[email protected]>johannes
In this case
aes_s2v()wouldn't otherwise be able to fail, so ignoring theaes_cmac_preparekey()return value would indeed be a simplification.
Right.
Quoted 2 lines
However, since the key length isn't a compile-time constant here, we'd have to rely on non-local validation, which isn't ideal.
That's true.
Quoted 2 lines
To ignore the return value entirely I'd prefer a
static_assertthat the length is equal to one of AES_KEYSIZE_*, which isn't possible here.
Indeed.
Quoted 4 lines
It's actually not clear to me where the length validation happens before here.
nl80211_associate()for example just copies the length from userspace without validating it.ieee80211_mgd_assoc()only checks that the length is at mostFILS_MAX_KEK_LEN(64).
Oh, right, I forgot this was FILS and mixed it up with the previous patch. We probably _should_ check it earlier there, but it won't be local here either way, and we have the error paths already so that's fine.
johannes
Quoted 28 lines · Eric Biggers
This series can also be retrieved from:
git fetch
https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git
aes-cmac-v1This series adds support for AES CBC-based MACs to the crypto library, specifically AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC. The implementation is fully optimized with the existing architecture-optimized AES code, either single-block AES en/decryption or arm64's
neon_aes_mac_update()andce_aes_mac_update(). As usual, optimizations are now enabled by default as well.AES-CMAC support will be useful for at least the SMB client and server, and the bluetooth and mac80211 drivers. Patches 8-15 convert these users to use the crypto library API instead of
crypto_shash, though these patches will likely go in via subsystem trees later. They result in some significant simplifications and performance improvements.As usual, a KUnit test suite, FIPS self-test, and traditional crypto API wrapper algorithms are included as well.
Note that I'm also planning to add additional AES modes to the library. This is just an initial set of AES modes to get things started. Notably, with the SMB client and server already using the SHA* and MD5 libraries, "cmac(aes)" was the only remaining use of
crypto_shashthere. So it makes sense to take care of that.
Quoted 17 lines
Eric Biggers (15):
lib/crypto: aes: Add support for CBC-based MACs
crypto: aes - Add cmac, xcbc, and cbcmac algorithms using library
crypto: arm64/aes - Fix 32-bitaes_mac_update()arg treated as 64-bit lib/crypto: arm64/aes: Move assembly code for AES modes into libaes lib/crypto: arm64/aes: Migrate optimized CBC-based MACs into library lib/crypto: tests: Add KUnit tests for CBC-based MACs lib/crypto: aes: Add FIPS self-test for CMAC
smb: client: Use AES-CMAC library for SMB3 signature calculation
smb: client: Remove obsolete cmac(aes) allocation
smb: client: Makegenerate_key()return void
smb: client: Drop 'allocate_crypto' arg from smb*_calc_signature()
ksmbd: Use AES-CMAC library for SMB3 signature calculation
Bluetooth: SMP: Use AES-CMAC library API
wifi: mac80211: Use AES-CMAC library inieee80211_aes_cmac()
wifi: mac80211: Use AES-CMAC library inaes_s2v()
Eric Biggers
maintainerQuoted 26 lines · Eric Biggers
This series can also be retrieved from:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git aes-cmac-v1
This series adds support for AES CBC-based MACs to the crypto library, specifically AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC. The implementation is fully optimized with the existing architecture-optimized AES code, either single-block AES en/decryption or arm64's
neon_aes_mac_update()andce_aes_mac_update(). As usual, optimizations are now enabled by default as well.AES-CMAC support will be useful for at least the SMB client and server, and the bluetooth and mac80211 drivers. Patches 8-15 convert these users to use the crypto library API instead of
crypto_shash, though these patches will likely go in via subsystem trees later. They result in some significant simplifications and performance improvements.As usual, a KUnit test suite, FIPS self-test, and traditional crypto API wrapper algorithms are included as well.
Note that I'm also planning to add additional AES modes to the library. This is just an initial set of AES modes to get things started. Notably, with the SMB client and server already using the SHA* and MD5 libraries, "cmac(aes)" was the only remaining use of
crypto_shashthere. So it makes sense to take care of that.
Quoted 16 lines
Eric Biggers (15):
lib/crypto: aes: Add support for CBC-based MACs
crypto: aes - Add cmac, xcbc, and cbcmac algorithms using library
crypto: arm64/aes - Fix 32-bitaes_mac_update()arg treated as 64-bit lib/crypto: arm64/aes: Move assembly code for AES modes into libaes lib/crypto: arm64/aes: Migrate optimized CBC-based MACs into library lib/crypto: tests: Add KUnit tests for CBC-based MACs lib/crypto: aes: Add FIPS self-test for CMAC
smb: client: Use AES-CMAC library for SMB3 signature calculation
smb: client: Remove obsolete cmac(aes) allocation
smb: client: Makegenerate_key()return void
smb: client: Drop 'allocate_crypto' arg from smb*_calc_signature()
ksmbd: Use AES-CMAC library for SMB3 signature calculation
Bluetooth: SMP: Use AES-CMAC library API
wifi: mac80211: Use AES-CMAC library inieee80211_aes_cmac()
wifi: mac80211: Use AES-CMAC library inaes_s2v()
Applied patches 1-7 and 14-15 to
https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/log/?h=libcrypto-next
Patches 8-13 (smb client, smb server, and bluetooth) can go in via subsystem trees later.
I edited "lib/crypto: arm64/aes: Move assembly code for AES modes into libaes" to update the file comments to remove the file paths.
- Eric