From nobody Fri Apr 3 07:59:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 94C062F1FF1; Wed, 18 Feb 2026 21:36:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450610; cv=none; b=CZtkrZAR7qmYOeDxGmxoyiTtPPC8bqHWXt66Ke1nKtKqiAeopWk/y+Yfxl2eVkHd/2G2wbcu1AvsLlSQdHeHiPKc5K9u5LEXg1OtDN1F8Vz5QxCAssQ39WX6MOiCrKBSnNs8ixga82tYy5z16Yn+6kJrqaBuPKt/qax31EnGSPY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450610; c=relaxed/simple; bh=B6d275uZRRFPEx+cNjtBQltncVwySv2uEdCFV1CD0Jo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uJi/9gAYyyDFTZhtWXbpYZ8aU97ihhWBsvtvWu8evRfffFe4llb3Mv1pWfLeJbbQm+WrMGPkcCaeuwFKflORI5vBlniwJPkDINzMk4TCHOkXP9vmDAS4EvBVCLf/eMxk/6knnN92k/HUQR3aIr4A478Y5beMD/YJd6GgpubRKGk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ZNY7X+UH; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ZNY7X+UH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 07080C116D0; Wed, 18 Feb 2026 21:36:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771450610; bh=B6d275uZRRFPEx+cNjtBQltncVwySv2uEdCFV1CD0Jo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZNY7X+UHZkxBL5KtYlX57pYHzFDROFqV80iskbBKwTzWrLT1AQjOgcQ4kxC1lVn4G 1RvOmbJfTuasBuvEAhhbS1ZwONy+UmkxRUyp8hM/8DMwyjFbPUhhjKQJRfF1JWIdob Wx1lDKy1LlFPPog6CqVyk0zjnmxrBgRr/FRAPYWG4R2gnooPqZPZRqFt5ZCBIsg5EU wiKS4C+QDx9fxk7FvDTLNojs9oyaHBE4sJB0dd5RJKcjEgIVsVrl5uVi5m5jnRfRGJ Ed4GJ9NLvBqh5HnRdGIGgpZyc066hq2i5R58iYsA9uc4j+Mejh55RL4loy+sCmH3YS 9QdRnuw8iJr9w== From: Eric Biggers To: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , linux-arm-kernel@lists.infradead.org, linux-cifs@vger.kernel.org, linux-wireless@vger.kernel.org, Eric Biggers Subject: [PATCH 01/15] lib/crypto: aes: Add support for CBC-based MACs Date: Wed, 18 Feb 2026 13:34:47 -0800 Message-ID: <20260218213501.136844-2-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260218213501.136844-1-ebiggers@kernel.org> References: <20260218213501.136844-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- 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 diff --git a/include/crypto/aes-cbc-macs.h b/include/crypto/aes-cbc-macs.h new file mode 100644 index 000000000000..e61df108b926 --- /dev/null +++ b/include/crypto/aes-cbc-macs.h @@ -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 + +/** + * 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 l= ast + * 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 depend= s 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 =3D (struct aes_cmac_ctx){ .key =3D key }; +} + +/** + * aes_cmac_update() - Update an AES-CMAC or AES-XCBC-MAC context with mor= e 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_SI= ZE]); + +/** + * 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 depend= s 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 implementati= on 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 messag= es. + */ +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 =3D (struct aes_cbcmac_ctx){ .key =3D 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 */ diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index 032f9755f999..42ec51645915 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -8,10 +8,12 @@ config CRYPTO_HASH_INFO config CRYPTO_LIB_UTILS tristate =20 config CRYPTO_LIB_AES tristate + # Select dependencies of modes that are part of libaes. + select CRYPTO_LIB_UTILS if CRYPTO_LIB_AES_CBC_MACS =20 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 =20 +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 + . + config CRYPTO_LIB_AESGCM tristate select CRYPTO_LIB_AES select CRYPTO_LIB_GF128MUL select CRYPTO_LIB_UTILS diff --git a/lib/crypto/aes.c b/lib/crypto/aes.c index b73e19f1bb95..39deae6105c0 100644 --- a/lib/crypto/aes.c +++ b/lib/crypto/aes.c @@ -2,11 +2,13 @@ /* * Copyright (C) 2017-2019 Linaro Ltd * Copyright 2026 Google LLC */ =20 +#include #include +#include #include #include #include #include #include @@ -510,10 +512,206 @@ void aes_decrypt(const struct aes_key *key, u8 out[A= ES_BLOCK_SIZE], { aes_decrypt_arch(key, out, in); } EXPORT_SYMBOL(aes_decrypt); =20 +#if IS_ENABLED(CONFIG_CRYPTO_LIB_AES_CBC_MACS) + +#ifndef aes_cbcmac_blocks_arch +static bool aes_cbcmac_blocks_arch(u8 h[AES_BLOCK_SIZE], + const struct aes_enckey *key, const u8 *data, + size_t nblocks, bool enc_before, + bool enc_after) +{ + return false; +} +#endif + +/* This assumes nblocks >=3D 1. */ +static void aes_cbcmac_blocks(u8 h[AES_BLOCK_SIZE], + const struct aes_enckey *key, const u8 *data, + size_t nblocks, bool enc_before, bool enc_after) +{ + if (aes_cbcmac_blocks_arch(h, key, data, nblocks, enc_before, + enc_after)) + return; + + if (enc_before) + aes_encrypt(key, h, h); + for (; nblocks > 1; nblocks--) { + crypto_xor(h, data, AES_BLOCK_SIZE); + data +=3D AES_BLOCK_SIZE; + aes_encrypt(key, h, h); + } + crypto_xor(h, data, AES_BLOCK_SIZE); + if (enc_after) + aes_encrypt(key, h, h); +} + +int aes_cmac_preparekey(struct aes_cmac_key *key, const u8 *in_key, + size_t key_len) +{ + u64 hi, lo, mask; + int err; + + /* Prepare the AES key. */ + err =3D aes_prepareenckey(&key->aes, in_key, key_len); + if (err) + return err; + + /* + * Prepare the subkeys K1 and K2 by encrypting the all-zeroes block, + * then multiplying by 'x' and 'x^2' (respectively) in GF(2^128). + * Reference: NIST SP 800-38B, Section 6.1 "Subkey Generation". + */ + memset(key->k_final[0].b, 0, AES_BLOCK_SIZE); + aes_encrypt(&key->aes, key->k_final[0].b, key->k_final[0].b); + hi =3D be64_to_cpu(key->k_final[0].w[0]); + lo =3D be64_to_cpu(key->k_final[0].w[1]); + for (int i =3D 0; i < 2; i++) { + mask =3D ((s64)hi >> 63) & 0x87; + hi =3D (hi << 1) ^ (lo >> 63); + lo =3D (lo << 1) ^ mask; + key->k_final[i].w[0] =3D cpu_to_be64(hi); + key->k_final[i].w[1] =3D cpu_to_be64(lo); + } + return 0; +} +EXPORT_SYMBOL_GPL(aes_cmac_preparekey); + +void aes_xcbcmac_preparekey(struct aes_cmac_key *key, + const u8 in_key[AES_KEYSIZE_128]) +{ + static const u8 constants[3][AES_BLOCK_SIZE] =3D { + { [0 ... AES_BLOCK_SIZE - 1] =3D 0x1 }, + { [0 ... AES_BLOCK_SIZE - 1] =3D 0x2 }, + { [0 ... AES_BLOCK_SIZE - 1] =3D 0x3 }, + }; + u8 new_aes_key[AES_BLOCK_SIZE]; + + static_assert(AES_BLOCK_SIZE =3D=3D AES_KEYSIZE_128); + aes_prepareenckey(&key->aes, in_key, AES_BLOCK_SIZE); + aes_encrypt(&key->aes, new_aes_key, constants[0]); + aes_encrypt(&key->aes, key->k_final[0].b, constants[1]); + aes_encrypt(&key->aes, key->k_final[1].b, constants[2]); + aes_prepareenckey(&key->aes, new_aes_key, AES_BLOCK_SIZE); + memzero_explicit(new_aes_key, AES_BLOCK_SIZE); +} +EXPORT_SYMBOL_GPL(aes_xcbcmac_preparekey); + +void aes_cmac_update(struct aes_cmac_ctx *ctx, const u8 *data, size_t data= _len) +{ + bool enc_before =3D false; + size_t nblocks; + + if (ctx->partial_len) { + /* XOR data into a pending block. */ + size_t l =3D min(data_len, AES_BLOCK_SIZE - ctx->partial_len); + + crypto_xor(&ctx->h[ctx->partial_len], data, l); + data +=3D l; + data_len -=3D l; + ctx->partial_len +=3D l; + if (data_len =3D=3D 0) { + /* + * Either the pending block hasn't been filled yet, or + * no more data was given so it's not yet known whether + * the block is the final block. + */ + return; + } + /* Pending block has been filled and isn't the final block. */ + enc_before =3D true; + } + + nblocks =3D data_len / AES_BLOCK_SIZE; + data_len %=3D AES_BLOCK_SIZE; + if (nblocks =3D=3D 0) { + /* 0 additional full blocks, then optionally a partial block */ + if (enc_before) + aes_encrypt(&ctx->key->aes, ctx->h, ctx->h); + crypto_xor(ctx->h, data, data_len); + ctx->partial_len =3D data_len; + } else if (data_len !=3D 0) { + /* 1 or more additional full blocks, then a partial block */ + aes_cbcmac_blocks(ctx->h, &ctx->key->aes, data, nblocks, + enc_before, /* enc_after=3D */ true); + data +=3D nblocks * AES_BLOCK_SIZE; + crypto_xor(ctx->h, data, data_len); + ctx->partial_len =3D data_len; + } else { + /* + * 1 or more additional full blocks only. Encryption of the + * last block is delayed until it's known whether it's the final + * block in the message or not. + */ + aes_cbcmac_blocks(ctx->h, &ctx->key->aes, data, nblocks, + enc_before, /* enc_after=3D */ false); + ctx->partial_len =3D AES_BLOCK_SIZE; + } +} +EXPORT_SYMBOL_GPL(aes_cmac_update); + +void aes_cmac_final(struct aes_cmac_ctx *ctx, u8 out[AES_BLOCK_SIZE]) +{ + if (ctx->partial_len =3D=3D AES_BLOCK_SIZE) { + /* Final block is a full block. Use k_final[0]. */ + crypto_xor(ctx->h, ctx->key->k_final[0].b, AES_BLOCK_SIZE); + } else { + /* Final block is a partial block. Pad, and use k_final[1]. */ + ctx->h[ctx->partial_len] ^=3D 0x80; + crypto_xor(ctx->h, ctx->key->k_final[1].b, AES_BLOCK_SIZE); + } + aes_encrypt(&ctx->key->aes, out, ctx->h); + memzero_explicit(ctx, sizeof(*ctx)); +} +EXPORT_SYMBOL_GPL(aes_cmac_final); + +void aes_cbcmac_update(struct aes_cbcmac_ctx *ctx, const u8 *data, + size_t data_len) +{ + bool enc_before =3D false; + size_t nblocks; + + if (ctx->partial_len) { + size_t l =3D min(data_len, AES_BLOCK_SIZE - ctx->partial_len); + + crypto_xor(&ctx->h[ctx->partial_len], data, l); + data +=3D l; + data_len -=3D l; + ctx->partial_len +=3D l; + if (ctx->partial_len < AES_BLOCK_SIZE) + return; + enc_before =3D true; + } + + nblocks =3D data_len / AES_BLOCK_SIZE; + data_len %=3D AES_BLOCK_SIZE; + if (nblocks =3D=3D 0) { + if (enc_before) + aes_encrypt(ctx->key, ctx->h, ctx->h); + } else { + aes_cbcmac_blocks(ctx->h, ctx->key, data, nblocks, enc_before, + /* enc_after=3D */ true); + data +=3D nblocks * AES_BLOCK_SIZE; + } + crypto_xor(ctx->h, data, data_len); + ctx->partial_len =3D data_len; +} +EXPORT_SYMBOL_NS_GPL(aes_cbcmac_update, "CRYPTO_INTERNAL"); + +void aes_cbcmac_final(struct aes_cbcmac_ctx *ctx, u8 out[AES_BLOCK_SIZE]) +{ + if (ctx->partial_len) + aes_encrypt(ctx->key, out, ctx->h); + 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 static int __init aes_mod_init(void) { aes_mod_init_arch(); return 0; --=20 2.53.0 From nobody Fri Apr 3 07:59:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 593232F6920; Wed, 18 Feb 2026 21:36:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450611; cv=none; b=njgDNyEnoARfHs2+U0r4r3+8Gpa1J/urff5Gr1AGFBcxJw2OuAMhIIQuj0haiRKuDIZzPS3Ho/E+Azy4ooavCabfOS9QtFmxURtgyCdLhIOSqtrerpuRA85dtd3OkyFVCCBITIxcyrRvFJRX2/h3SoldPb2G6T6wTTsNoxef/P8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450611; c=relaxed/simple; bh=S4zQmtBxe0E3DIi0hm6e0ss7TJDmWjR02e2kDFr1lzc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nmFdqXTCg/nXSACamRjUzZotlCD0ds2eqmQ2TVSTF/fra/HOmtflubH8wSw3twHG3J8KNVNQegnTxdIF0eHj0vPOgHFnIYGn+DRwxOq5ApKdM6t5lU8CDl8NFX1WlwgEFDLSmoT1y8A5JYJsqB4OVQChXrBiwE+7CxdPL6yoRus= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UYQ3AI9B; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UYQ3AI9B" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9B66DC2BC87; Wed, 18 Feb 2026 21:36:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771450611; bh=S4zQmtBxe0E3DIi0hm6e0ss7TJDmWjR02e2kDFr1lzc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UYQ3AI9Bo8dGg0hMwROuintnVLzOqhK2vZI4c2yOwLofe1PQg6B/pItjzSqDpqS3I ZV2871TKNFtzdqmW8TE5YM9EXZ7HRE8OWvdgawxtqpdQ5m7f/s8uS2vg+U8FEf7ikf qcmc5aiVI4hhVHYMpjUEpv+HqJ13ZDr59hPhSR3Wla5Hw2htKzwRoxkQboT/b2SCBu fbuQn8dLFKNA49erokFxe3JaiwdRd64x25iZMsgTojSyxvkU7xbJJ6PXS5XwPszmVQ L1aCSsZQEX7m/YEgdFEU52qfbxDgSVR72hlpsVcMKI6DxiU2GhhwjD1XfT4D+YKp4s B2vB+9dxg1Hmg== From: Eric Biggers To: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , linux-arm-kernel@lists.infradead.org, linux-cifs@vger.kernel.org, linux-wireless@vger.kernel.org, Eric Biggers Subject: [PATCH 02/15] crypto: aes - Add cmac, xcbc, and cbcmac algorithms using library Date: Wed, 18 Feb 2026 13:34:48 -0800 Message-ID: <20260218213501.136844-3-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260218213501.136844-1-ebiggers@kernel.org> References: <20260218213501.136844-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Update 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. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- 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(-) diff --git a/crypto/Kconfig b/crypto/Kconfig index e2b4106ac961..256ce4729c8d 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -359,10 +359,12 @@ menu "Block ciphers" =20 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) =20 Rijndael appears to be consistently a very good performer in both hardware and software across a wide range of computing diff --git a/crypto/aes.c b/crypto/aes.c index ae8385df0ce5..6bf23eb0503f 100644 --- a/crypto/aes.c +++ b/crypto/aes.c @@ -3,12 +3,14 @@ * Crypto API support for AES block cipher * * Copyright 2026 Google LLC */ =20 +#include #include #include +#include #include =20 static_assert(__alignof__(struct aes_key) <=3D CRYPTO_MINALIGN); =20 static int crypto_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key, @@ -31,10 +33,102 @@ static void crypto_aes_decrypt(struct crypto_tfm *tfm,= u8 *out, const u8 *in) const struct aes_key *key =3D crypto_tfm_ctx(tfm); =20 aes_decrypt(key, out, in); } =20 +static_assert(__alignof__(struct aes_cmac_key) <=3D CRYPTO_MINALIGN); +#define AES_CMAC_KEY(tfm) ((struct aes_cmac_key *)crypto_shash_ctx(tfm)) +#define AES_CMAC_CTX(desc) ((struct aes_cmac_ctx *)shash_desc_ctx(desc)) + +static int __maybe_unused crypto_aes_cmac_setkey(struct crypto_shash *tfm, + const u8 *in_key, + unsigned int key_len) +{ + return aes_cmac_preparekey(AES_CMAC_KEY(tfm), in_key, key_len); +} + +static int __maybe_unused crypto_aes_xcbc_setkey(struct crypto_shash *tfm, + const u8 *in_key, + unsigned int key_len) +{ + if (key_len !=3D AES_KEYSIZE_128) + return -EINVAL; + aes_xcbcmac_preparekey(AES_CMAC_KEY(tfm), in_key); + return 0; +} + +static int __maybe_unused crypto_aes_cmac_init(struct shash_desc *desc) +{ + aes_cmac_init(AES_CMAC_CTX(desc), AES_CMAC_KEY(desc->tfm)); + return 0; +} + +static int __maybe_unused crypto_aes_cmac_update(struct shash_desc *desc, + const u8 *data, + unsigned int len) +{ + aes_cmac_update(AES_CMAC_CTX(desc), data, len); + return 0; +} + +static int __maybe_unused crypto_aes_cmac_final(struct shash_desc *desc, + u8 *out) +{ + aes_cmac_final(AES_CMAC_CTX(desc), out); + return 0; +} + +static int __maybe_unused crypto_aes_cmac_digest(struct shash_desc *desc, + const u8 *data, + unsigned int len, u8 *out) +{ + aes_cmac(AES_CMAC_KEY(desc->tfm), data, len, out); + return 0; +} + +static_assert(__alignof__(struct aes_enckey) <=3D CRYPTO_MINALIGN); +#define AES_CBCMAC_KEY(tfm) ((struct aes_enckey *)crypto_shash_ctx(tfm)) +#define AES_CBCMAC_CTX(desc) ((struct aes_cbcmac_ctx *)shash_desc_ctx(desc= )) + +static int __maybe_unused crypto_aes_cbcmac_setkey(struct crypto_shash *tf= m, + const u8 *in_key, + unsigned int key_len) +{ + return aes_prepareenckey(AES_CBCMAC_KEY(tfm), in_key, key_len); +} + +static int __maybe_unused crypto_aes_cbcmac_init(struct shash_desc *desc) +{ + aes_cbcmac_init(AES_CBCMAC_CTX(desc), AES_CBCMAC_KEY(desc->tfm)); + return 0; +} + +static int __maybe_unused crypto_aes_cbcmac_update(struct shash_desc *desc, + const u8 *data, + unsigned int len) +{ + aes_cbcmac_update(AES_CBCMAC_CTX(desc), data, len); + return 0; +} + +static int __maybe_unused crypto_aes_cbcmac_final(struct shash_desc *desc, + u8 *out) +{ + aes_cbcmac_final(AES_CBCMAC_CTX(desc), out); + return 0; +} + +static int __maybe_unused crypto_aes_cbcmac_digest(struct shash_desc *desc, + const u8 *data, + unsigned int len, u8 *out) +{ + aes_cbcmac_init(AES_CBCMAC_CTX(desc), AES_CBCMAC_KEY(desc->tfm)); + aes_cbcmac_update(AES_CBCMAC_CTX(desc), data, len); + aes_cbcmac_final(AES_CBCMAC_CTX(desc), out); + return 0; +} + static struct crypto_alg alg =3D { .cra_name =3D "aes", .cra_driver_name =3D "aes-lib", .cra_priority =3D 100, .cra_flags =3D CRYPTO_ALG_TYPE_CIPHER, @@ -46,21 +140,108 @@ static struct crypto_alg alg =3D { .cia_setkey =3D crypto_aes_setkey, .cia_encrypt =3D crypto_aes_encrypt, .cia_decrypt =3D crypto_aes_decrypt } } }; =20 +static struct shash_alg mac_algs[] =3D { +#if IS_ENABLED(CONFIG_CRYPTO_CMAC) + { + .base.cra_name =3D "cmac(aes)", + .base.cra_driver_name =3D "cmac-aes-lib", + .base.cra_priority =3D 300, + .base.cra_blocksize =3D AES_BLOCK_SIZE, + .base.cra_ctxsize =3D sizeof(struct aes_cmac_key), + .base.cra_module =3D THIS_MODULE, + .digestsize =3D AES_BLOCK_SIZE, + .setkey =3D crypto_aes_cmac_setkey, + .init =3D crypto_aes_cmac_init, + .update =3D crypto_aes_cmac_update, + .final =3D crypto_aes_cmac_final, + .digest =3D crypto_aes_cmac_digest, + .descsize =3D sizeof(struct aes_cmac_ctx), + }, +#endif +#if IS_ENABLED(CONFIG_CRYPTO_XCBC) + { + /* + * Note that the only difference between xcbc(aes) and cmac(aes) + * is the preparekey function. + */ + .base.cra_name =3D "xcbc(aes)", + .base.cra_driver_name =3D "xcbc-aes-lib", + .base.cra_priority =3D 300, + .base.cra_blocksize =3D AES_BLOCK_SIZE, + .base.cra_ctxsize =3D sizeof(struct aes_cmac_key), + .base.cra_module =3D THIS_MODULE, + .digestsize =3D AES_BLOCK_SIZE, + .setkey =3D crypto_aes_xcbc_setkey, + .init =3D crypto_aes_cmac_init, + .update =3D crypto_aes_cmac_update, + .final =3D crypto_aes_cmac_final, + .digest =3D crypto_aes_cmac_digest, + .descsize =3D sizeof(struct aes_cmac_ctx), + }, +#endif +#if IS_ENABLED(CONFIG_CRYPTO_CCM) + { + .base.cra_name =3D "cbcmac(aes)", + .base.cra_driver_name =3D "cbcmac-aes-lib", + .base.cra_priority =3D 300, + .base.cra_blocksize =3D AES_BLOCK_SIZE, + .base.cra_ctxsize =3D sizeof(struct aes_enckey), + .base.cra_module =3D THIS_MODULE, + .digestsize =3D AES_BLOCK_SIZE, + .setkey =3D crypto_aes_cbcmac_setkey, + .init =3D crypto_aes_cbcmac_init, + .update =3D crypto_aes_cbcmac_update, + .final =3D crypto_aes_cbcmac_final, + .digest =3D crypto_aes_cbcmac_digest, + .descsize =3D sizeof(struct aes_cbcmac_ctx), + }, +#endif +}; + static int __init crypto_aes_mod_init(void) { - return crypto_register_alg(&alg); + int err =3D crypto_register_alg(&alg); + + if (err) + return err; + + if (ARRAY_SIZE(mac_algs) > 0) { + err =3D crypto_register_shashes(mac_algs, ARRAY_SIZE(mac_algs)); + if (err) + goto err_unregister_alg; + } /* Else, CONFIG_CRYPTO_HASH might not be enabled. */ + return 0; + +err_unregister_alg: + crypto_unregister_alg(&alg); + return err; } module_init(crypto_aes_mod_init); =20 static void __exit crypto_aes_mod_exit(void) { + if (ARRAY_SIZE(mac_algs) > 0) + crypto_unregister_shashes(mac_algs, ARRAY_SIZE(mac_algs)); crypto_unregister_alg(&alg); } module_exit(crypto_aes_mod_exit); =20 MODULE_DESCRIPTION("Crypto API support for AES block cipher"); +MODULE_IMPORT_NS("CRYPTO_INTERNAL"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CRYPTO("aes"); MODULE_ALIAS_CRYPTO("aes-lib"); +#if IS_ENABLED(CONFIG_CRYPTO_CMAC) +MODULE_ALIAS_CRYPTO("cmac(aes)"); +MODULE_ALIAS_CRYPTO("cmac-aes-lib"); +#endif +#if IS_ENABLED(CONFIG_CRYPTO_XCBC) +MODULE_ALIAS_CRYPTO("xcbc(aes)"); +MODULE_ALIAS_CRYPTO("xcbc-aes-lib"); +#endif +#if IS_ENABLED(CONFIG_CRYPTO_CCM) +MODULE_ALIAS_CRYPTO("cbcmac(aes)"); +MODULE_ALIAS_CRYPTO("cbcmac-aes-lib"); +#endif diff --git a/crypto/testmgr.c b/crypto/testmgr.c index b940721447fa..fa7217029f44 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -4386,11 +4386,11 @@ static const struct alg_test_desc alg_test_descs[] = =3D { .cipher =3D __VECS(aes_cbc_tv_template) } }, { #endif .alg =3D "cbcmac(aes)", - .generic_driver =3D "cbcmac(aes-lib)", + .generic_driver =3D "cbcmac-aes-lib", .test =3D alg_test_hash, .suite =3D { .hash =3D __VECS(aes_cbcmac_tv_template) } }, { @@ -4399,11 +4399,11 @@ static const struct alg_test_desc alg_test_descs[] = =3D { .suite =3D { .hash =3D __VECS(sm4_cbcmac_tv_template) } }, { .alg =3D "ccm(aes)", - .generic_driver =3D "ccm_base(ctr(aes-lib),cbcmac(aes-lib))", + .generic_driver =3D "ccm_base(ctr(aes-lib),cbcmac-aes-lib)", .test =3D alg_test_aead, .fips_allowed =3D 1, .suite =3D { .aead =3D { ____VECS(aes_ccm_tv_template), @@ -4427,11 +4427,11 @@ static const struct alg_test_desc alg_test_descs[] = =3D { .suite =3D { .cipher =3D __VECS(chacha20_tv_template) }, }, { .alg =3D "cmac(aes)", - .generic_driver =3D "cmac(aes-lib)", + .generic_driver =3D "cmac-aes-lib", .fips_allowed =3D 1, .test =3D alg_test_hash, .suite =3D { .hash =3D __VECS(aes_cmac128_tv_template) } @@ -5324,11 +5324,11 @@ static const struct alg_test_desc alg_test_descs[] = =3D { .aad_iv =3D 1, } } }, { .alg =3D "rfc4309(ccm(aes))", - .generic_driver =3D "rfc4309(ccm_base(ctr(aes-lib),cbcmac(aes-lib)))", + .generic_driver =3D "rfc4309(ccm_base(ctr(aes-lib),cbcmac-aes-lib))", .test =3D alg_test_aead, .fips_allowed =3D 1, .suite =3D { .aead =3D { ____VECS(aes_ccm_rfc4309_tv_template), @@ -5513,11 +5513,11 @@ static const struct alg_test_desc alg_test_descs[] = =3D { .suite =3D { .sig =3D __VECS(x962_ecdsa_nist_p521_tv_template) } }, { .alg =3D "xcbc(aes)", - .generic_driver =3D "xcbc(aes-lib)", + .generic_driver =3D "xcbc-aes-lib", .test =3D alg_test_hash, .suite =3D { .hash =3D __VECS(aes_xcbc128_tv_template) } }, { diff --git a/drivers/crypto/starfive/jh7110-aes.c b/drivers/crypto/starfive= /jh7110-aes.c index c1dc1e43e117..2e2d97d17e6c 100644 --- a/drivers/crypto/starfive/jh7110-aes.c +++ b/drivers/crypto/starfive/jh7110-aes.c @@ -1001,11 +1001,11 @@ static int starfive_aes_ctr_init_tfm(struct crypto_= skcipher *tfm) return starfive_aes_init_tfm(tfm, "ctr(aes-lib)"); } =20 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)"); } =20 static int starfive_aes_gcm_init_tfm(struct crypto_aead *tfm) { return starfive_aes_aead_init_tfm(tfm, "gcm_base(ctr(aes-lib),ghash-gener= ic)"); --=20 2.53.0 From nobody Fri Apr 3 07:59:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C23ED314A76; Wed, 18 Feb 2026 21:36:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450611; cv=none; b=P/5o7hyBeHBA0As4ctVjIvNBv9pH/csJJw6ReMi3nWFBco57oXnPH9QEiZ8m+bH+S7HfcAX99CAyPYBkg0ia4LOKmF03NiESybtCUP/b9UzwdQesmmVitnNt8gvbHvjgjq40G6X67WYxJRWjjfKKN8W1VMFqaFJI+0daSnrvKsc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450611; c=relaxed/simple; bh=FLhIcGYigj/cYDh5+twKKz5F+F3mi/gUG7aJ/XLLfTA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=esQhbKfweICcKC9mY7K9t0lrpnSKw0UjvntadSkvPjA6ZeL4clyKOUtgU1b3hZmYn4o+CdsXY8j/JJyhpSO/lMHpEHB70e4AqF9SsnQZL4zLTogGIFTKWPtw2Keexjwz4t/M6QIUE8JxvFSuYglzCtTrAsZAiJRSI0XaQxofFro= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ROUaJ6P8; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ROUaJ6P8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3932CC2BC9E; Wed, 18 Feb 2026 21:36:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771450611; bh=FLhIcGYigj/cYDh5+twKKz5F+F3mi/gUG7aJ/XLLfTA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ROUaJ6P8UlCMN4JmpFGGTRSlivUcHoJGRc+eVoE6kP/DW5Y7YMNqs+roqftoa/gnV ZwDlrMQ693KOcLjlRIMUfS1y7sKUTH1zO1nkVWuEMZY2k2/91AidpDrJw9bPtC3dmR 5Udw//bK+DsZUsShJM42cHcB/ciYFKBaq2P+7hNLQSW+D7AVPNldf1i7qhy3dpdD7f gLSPjy1VBwRBR4kssZcgjCV6zH7OxxUqehvbY1cjcC50JWrcPh/ob9W6VyJ0qM73EB cdLoS5E4mBCqNz6ShijoHyLhAfTFL7bE0hPtEeWfjDZw/Kdnkwl8XU9BjxHr6DAXvp iH+hy7FYJaUYg== From: Eric Biggers To: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , linux-arm-kernel@lists.infradead.org, linux-cifs@vger.kernel.org, linux-wireless@vger.kernel.org, Eric Biggers , stable@vger.kernel.org Subject: [PATCH 03/15] crypto: arm64/aes - Fix 32-bit aes_mac_update() arg treated as 64-bit Date: Wed, 18 Feb 2026 13:34:49 -0800 Message-ID: <20260218213501.136844-4-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260218213501.136844-1-ebiggers@kernel.org> References: <20260218213501.136844-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Since 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. Fixes: 4860620da7e5 ("crypto: arm64/aes - add NEON/Crypto Extensions CBCMAC= /CMAC/XCBC driver") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- arch/arm64/crypto/aes-modes.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/crypto/aes-modes.S b/arch/arm64/crypto/aes-modes.S index 0e834a2c062c..e793478f37c1 100644 --- a/arch/arm64/crypto/aes-modes.S +++ b/arch/arm64/crypto/aes-modes.S @@ -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 */ =20 subs w3, w3, #1 - csinv x5, x6, xzr, eq + csinv w5, w6, wzr, eq cbz w5, .Lmacout =20 .Lmacenc: encrypt_block v0, w2, x1, x7, w8 b .Lmacloop --=20 2.53.0 From nobody Fri Apr 3 07:59:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 948AE335077; Wed, 18 Feb 2026 21:36:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450612; cv=none; b=VzKG2Cr5rSt9ZQATyKPPGJThp/I3psM7eLDMBFBcN65jUEythosDWsadxbIfTCiEOUze8tGh+gtkzOdjr8nePhzL+mN3DcmDMUYgdfPEmdveoTzGIqqE/kyBWSgLwDm7famkqH0SCk6puAp8Py/Vn0PojqXi+ZoIkxqz8aqn3o0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450612; c=relaxed/simple; bh=phuk8jYQce0F4jNXOX5zObjH9GAYqfm6mN8RyTfqKxI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IRr2XnJAssRjOLJgzCzEgDDw+Lrlc8apRlhiqMnrbutNe+MiNUgEjAidnBzBnDL9D+QALZruLX11riCYy8Y20j3YjuPBxOpZASLxki3TXCRKZG2pA50FP1/d19rCn4KIceewfHm1V5me7wmkuGW7RfDG6FQqFPk4nMC03vsPNG8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YDk5vBec; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YDk5vBec" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D194EC2BC87; Wed, 18 Feb 2026 21:36:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771450612; bh=phuk8jYQce0F4jNXOX5zObjH9GAYqfm6mN8RyTfqKxI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YDk5vBecbvLAatyHy+8rPljkUDUjwovG/5lkR86yOs+aba04Sw8ScWMjzZHM5nsP8 TYE1PW3d0A8+E2LJNr6h+18HQzhjPszUeXD5MhP7JZniMxF6auAInqxEzYB7eSczZI 2nushArwUNjn1uy1Imf7sPrjgUXBPjn70s1vJV/mLqClKipQ6F3hA38dLFoIUd9tc4 H6F4K0xUkPXDYa60HRZNx3CVa/9rrarlW4ne1mBraYE60RoXWL1OyhsouQQbnR38ti WkBoUP7XrG7B1xH5zO3pGZyNlJkUfRKGV2w3Xnx7+3/HkMcyNoaNPWLP4KLBh0kWrm Sv7Y7ERBgPDmw== From: Eric Biggers To: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , linux-arm-kernel@lists.infradead.org, linux-cifs@vger.kernel.org, linux-wireless@vger.kernel.org, Eric Biggers Subject: [PATCH 04/15] lib/crypto: arm64/aes: Move assembly code for AES modes into libaes Date: Wed, 18 Feb 2026 13:34:50 -0800 Message-ID: <20260218213501.136844-5-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260218213501.136844-1-ebiggers@kernel.org> References: <20260218213501.136844-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" To 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 ; 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. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- 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 =3D> lib/crypto/arm64}/aes-ce.S | 0 .../crypto =3D> lib/crypto/arm64}/aes-modes.S | 0 .../crypto =3D> lib/crypto/arm64}/aes-neon.S | 0 lib/crypto/arm64/aes.h | 30 ++++++++ 10 files changed, 106 insertions(+), 67 deletions(-) rename {arch/arm64/crypto =3D> lib/crypto/arm64}/aes-ce.S (100%) rename {arch/arm64/crypto =3D> lib/crypto/arm64}/aes-modes.S (100%) rename {arch/arm64/crypto =3D> lib/crypto/arm64}/aes-neon.S (100%) diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile index 3574e917bc37..8a8e3e551ed3 100644 --- a/arch/arm64/crypto/Makefile +++ b/arch/arm64/crypto/Makefile @@ -31,12 +31,12 @@ ghash-ce-y :=3D ghash-ce-glue.o ghash-ce-core.o =20 obj-$(CONFIG_CRYPTO_AES_ARM64_CE_CCM) +=3D aes-ce-ccm.o aes-ce-ccm-y :=3D aes-ce-ccm-glue.o aes-ce-ccm-core.o =20 obj-$(CONFIG_CRYPTO_AES_ARM64_CE_BLK) +=3D aes-ce-blk.o -aes-ce-blk-y :=3D aes-glue-ce.o aes-ce.o +aes-ce-blk-y :=3D aes-glue-ce.o =20 obj-$(CONFIG_CRYPTO_AES_ARM64_NEON_BLK) +=3D aes-neon-blk.o -aes-neon-blk-y :=3D aes-glue-neon.o aes-neon.o +aes-neon-blk-y :=3D aes-glue-neon.o =20 obj-$(CONFIG_CRYPTO_AES_ARM64_BS) +=3D aes-neon-bs.o aes-neon-bs-y :=3D aes-neonbs-core.o aes-neonbs-glue.o diff --git a/arch/arm64/crypto/aes-ce-ccm-glue.c b/arch/arm64/crypto/aes-ce= -ccm-glue.c index db371ac051fc..45aed0073283 100644 --- a/arch/arm64/crypto/aes-ce-ccm-glue.c +++ b/arch/arm64/crypto/aes-ce-ccm-glue.c @@ -29,14 +29,10 @@ static int num_rounds(struct crypto_aes_ctx *ctx) * =3D> n byte key =3D> 6 + (n/4) rounds */ return 6 + ctx->key_length / 4; } =20 -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[]); =20 asmlinkage void ce_aes_ccm_decrypt(u8 out[], u8 const in[], u32 cbytes, diff --git a/arch/arm64/crypto/aes-glue.c b/arch/arm64/crypto/aes-glue.c index 92f43e1cd097..fd7c3a560a71 100644 --- a/arch/arm64/crypto/aes-glue.c +++ b/arch/arm64/crypto/aes-glue.c @@ -69,52 +69,13 @@ MODULE_ALIAS_CRYPTO("essiv(cbc(aes),sha256)"); MODULE_ALIAS_CRYPTO("cmac(aes)"); MODULE_ALIAS_CRYPTO("xcbc(aes)"); MODULE_ALIAS_CRYPTO("cbcmac(aes)"); =20 MODULE_AUTHOR("Ard Biesheuvel "); +MODULE_IMPORT_NS("CRYPTO_INTERNAL"); MODULE_LICENSE("GPL v2"); =20 -/* defined in aes-modes.S */ -asmlinkage void aes_ecb_encrypt(u8 out[], u8 const in[], u32 const rk[], - int rounds, int blocks); -asmlinkage void aes_ecb_decrypt(u8 out[], u8 const in[], u32 const rk[], - int rounds, int blocks); - -asmlinkage void aes_cbc_encrypt(u8 out[], u8 const in[], u32 const rk[], - int rounds, int blocks, u8 iv[]); -asmlinkage void aes_cbc_decrypt(u8 out[], u8 const in[], u32 const rk[], - int rounds, int blocks, u8 iv[]); - -asmlinkage void aes_cbc_cts_encrypt(u8 out[], u8 const in[], u32 const rk[= ], - int rounds, int bytes, u8 const iv[]); -asmlinkage void aes_cbc_cts_decrypt(u8 out[], u8 const in[], u32 const rk[= ], - int rounds, int bytes, u8 const iv[]); - -asmlinkage void aes_ctr_encrypt(u8 out[], u8 const in[], u32 const rk[], - int rounds, int bytes, u8 ctr[]); - -asmlinkage void aes_xctr_encrypt(u8 out[], u8 const in[], u32 const rk[], - int rounds, int bytes, u8 ctr[], int byte_ctr); - -asmlinkage void aes_xts_encrypt(u8 out[], u8 const in[], u32 const rk1[], - int rounds, int bytes, u32 const rk2[], u8 iv[], - int first); -asmlinkage void aes_xts_decrypt(u8 out[], u8 const in[], u32 const rk1[], - int rounds, int bytes, u32 const rk2[], u8 iv[], - int first); - -asmlinkage void aes_essiv_cbc_encrypt(u8 out[], u8 const in[], u32 const r= k1[], - int rounds, int blocks, u8 iv[], - u32 const rk2[]); -asmlinkage void aes_essiv_cbc_decrypt(u8 out[], u8 const in[], u32 const r= k1[], - int rounds, int blocks, u8 iv[], - u32 const rk2[]); - -asmlinkage int aes_mac_update(u8 const in[], u32 const rk[], int rounds, - int blocks, u8 dg[], int enc_before, - int enc_after); - struct crypto_aes_xts_ctx { struct crypto_aes_ctx key1; struct crypto_aes_ctx __aligned(8) key2; }; =20 @@ -969,15 +930,9 @@ static int __init aes_init(void) return err; } =20 #ifdef USE_V8_CRYPTO_EXTENSIONS module_cpu_feature_match(AES, aes_init); -EXPORT_SYMBOL_NS(ce_aes_mac_update, "CRYPTO_INTERNAL"); #else module_init(aes_init); -EXPORT_SYMBOL(neon_aes_ecb_encrypt); -EXPORT_SYMBOL(neon_aes_cbc_encrypt); -EXPORT_SYMBOL(neon_aes_ctr_encrypt); -EXPORT_SYMBOL(neon_aes_xts_encrypt); -EXPORT_SYMBOL(neon_aes_xts_decrypt); #endif module_exit(aes_exit); diff --git a/arch/arm64/crypto/aes-neonbs-glue.c b/arch/arm64/crypto/aes-ne= onbs-glue.c index cb87c8fc66b3..7630a7bf5da9 100644 --- a/arch/arm64/crypto/aes-neonbs-glue.c +++ b/arch/arm64/crypto/aes-neonbs-glue.c @@ -15,10 +15,11 @@ #include #include =20 MODULE_AUTHOR("Ard Biesheuvel "); MODULE_DESCRIPTION("Bit sliced AES using NEON instructions"); +MODULE_IMPORT_NS("CRYPTO_INTERNAL"); MODULE_LICENSE("GPL v2"); =20 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[]); =20 -/* 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); =20 diff --git a/include/crypto/aes.h b/include/crypto/aes.h index cbf1cc96db52..91bf4667d3e9 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -165,10 +165,79 @@ int aes_expandkey(struct crypto_aes_ctx *ctx, const u= 8 *in_key, * that code is migrated into lib/crypto/. */ #ifdef CONFIG_ARM64 int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, unsigned int key_len); +asmlinkage void neon_aes_ecb_encrypt(u8 out[], u8 const in[], u32 const rk= [], + int rounds, int blocks); +asmlinkage void neon_aes_ecb_decrypt(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_cbc_decrypt(u8 out[], u8 const in[], u32 const rk= [], + int rounds, int blocks, u8 iv[]); +asmlinkage void neon_aes_cbc_cts_encrypt(u8 out[], u8 const in[], + u32 const rk[], int rounds, int bytes, + u8 const iv[]); +asmlinkage void neon_aes_cbc_cts_decrypt(u8 out[], u8 const in[], + u32 const rk[], int rounds, int bytes, + u8 const 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_xctr_encrypt(u8 out[], u8 const in[], u32 const r= k[], + int rounds, int bytes, u8 ctr[], + int byte_ctr); +asmlinkage void neon_aes_xts_encrypt(u8 out[], u8 const in[], u32 const rk= 1[], + int rounds, int bytes, u32 const rk2[], + u8 iv[], int first); +asmlinkage void neon_aes_xts_decrypt(u8 out[], u8 const in[], u32 const rk= 1[], + int rounds, int bytes, u32 const rk2[], + u8 iv[], int first); +asmlinkage void neon_aes_essiv_cbc_encrypt(u8 out[], u8 const in[], + u32 const rk1[], int rounds, + int blocks, u8 iv[], + 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 roun= ds, + 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); +asmlinkage void ce_aes_cbc_encrypt(u8 out[], u8 const in[], u32 const rk[], + int rounds, int blocks, u8 iv[]); +asmlinkage void ce_aes_cbc_decrypt(u8 out[], u8 const in[], u32 const rk[], + int rounds, int blocks, u8 iv[]); +asmlinkage void ce_aes_cbc_cts_encrypt(u8 out[], u8 const in[], u32 const = rk[], + int rounds, int bytes, u8 const iv[]); +asmlinkage void ce_aes_cbc_cts_decrypt(u8 out[], u8 const in[], u32 const = rk[], + int rounds, int bytes, u8 const iv[]); +asmlinkage void ce_aes_ctr_encrypt(u8 out[], u8 const in[], u32 const rk[], + int rounds, int bytes, u8 ctr[]); +asmlinkage void ce_aes_xctr_encrypt(u8 out[], u8 const in[], u32 const rk[= ], + int rounds, int bytes, u8 ctr[], + int byte_ctr); +asmlinkage void ce_aes_xts_encrypt(u8 out[], u8 const in[], u32 const rk1[= ], + int rounds, int bytes, u32 const rk2[], + u8 iv[], int first); +asmlinkage void ce_aes_xts_decrypt(u8 out[], u8 const in[], u32 const rk1[= ], + int rounds, int bytes, u32 const rk2[], + u8 iv[], int first); +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); #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); diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 725eef05b758..c05d4b4e8e82 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -24,11 +24,13 @@ CFLAGS_aes.o +=3D -I$(src)/$(SRCARCH) =20 libaes-$(CONFIG_ARM) +=3D arm/aes-cipher-core.o =20 ifeq ($(CONFIG_ARM64),y) libaes-y +=3D arm64/aes-cipher-core.o -libaes-$(CONFIG_KERNEL_MODE_NEON) +=3D arm64/aes-ce-core.o +libaes-$(CONFIG_KERNEL_MODE_NEON) +=3D arm64/aes-ce-core.o \ + arm64/aes-ce.o \ + arm64/aes-neon.o endif =20 ifeq ($(CONFIG_PPC),y) ifeq ($(CONFIG_SPE),y) libaes-y +=3D powerpc/aes-spe-core.o \ diff --git a/arch/arm64/crypto/aes-ce.S b/lib/crypto/arm64/aes-ce.S similarity index 100% rename from arch/arm64/crypto/aes-ce.S rename to lib/crypto/arm64/aes-ce.S diff --git a/arch/arm64/crypto/aes-modes.S b/lib/crypto/arm64/aes-modes.S similarity index 100% rename from arch/arm64/crypto/aes-modes.S rename to lib/crypto/arm64/aes-modes.S diff --git a/arch/arm64/crypto/aes-neon.S b/lib/crypto/arm64/aes-neon.S similarity index 100% rename from arch/arm64/crypto/aes-neon.S rename to lib/crypto/arm64/aes-neon.S diff --git a/lib/crypto/arm64/aes.h b/lib/crypto/arm64/aes.h index 63eea6271ef9..69f465c668f0 100644 --- a/lib/crypto/arm64/aes.h +++ b/lib/crypto/arm64/aes.h @@ -124,10 +124,40 @@ int ce_aes_expandkey(struct crypto_aes_ctx *ctx, cons= t u8 *in_key, 6 + key_len / 4); return 0; } EXPORT_SYMBOL(ce_aes_expandkey); =20 +#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) && --=20 2.53.0 From nobody Fri Apr 3 07:59:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 28B642ECEA3; Wed, 18 Feb 2026 21:36:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450613; cv=none; b=WgtBDN0aWJzAauBwygJTD2fDvjlXn7PCPpNOwyWsTArrYy3rHBOQNlNex3H3beyYUot8xz3bhzH0NrmhwOFD4Z1OW0vS8Kgicezo+nKtj72+xEMrt9TfAmCpQXkPq1QOwFa/Rvs2T19DUlzzhOQaxASmVSdFEP1Zeil+ptjCHRs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450613; c=relaxed/simple; bh=0LeGm98KqVExci2vvu6SjzoBtiGH1qcdbzcO5wJ5lqM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fYQ074nZyze9fFZGhyosLz7IbSoyKRJ8NZfv3pX1y7n1joWjZRlXhNFcCcJXmqnixQyqXgSD1sPxlJ3iuRVzmh+TC5xyEasbFuzhwWR74a2wRwAvpRxZ8iaiN2175DhYFvGqgB4LKmq9z/2SNaW50o3b1YrgoapUwMY8lG9W6j8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MbJq6E7d; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MbJq6E7d" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6D0F2C19425; Wed, 18 Feb 2026 21:36:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771450612; bh=0LeGm98KqVExci2vvu6SjzoBtiGH1qcdbzcO5wJ5lqM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MbJq6E7dirP6hem2BPoJf7hEAikTjbr3hVlsE85ume5etX0r62FaVHsSVLkjOmejW ePbJxSQYQzLHqpMTY3wp2DNbv2cuwgGCFEbvTT+i5OAfd6zfTcnTRZIBthd++Hxg4f v118WKqVPhyvA3RuXsBfd70pUtebHZTiHBS+7n8yQzaViumKZ0AtyN5WYOLJreV+p8 SRiVGLkS48KvrIiocik5O6ADvhtnqLVAvUqhc/gsSn7+5km9lnxDE9YBnnfV0fSW4J ktxlyRbeEbtF7EwfFFFspdwYGJLJgYeLXKIpQT/F2aMwZV3byLAKL1LChfMaHbuxd0 ghbVX/hL6hFfQ== From: Eric Biggers To: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , linux-arm-kernel@lists.infradead.org, linux-cifs@vger.kernel.org, linux-wireless@vger.kernel.org, Eric Biggers Subject: [PATCH 05/15] lib/crypto: arm64/aes: Migrate optimized CBC-based MACs into library Date: Wed, 18 Feb 2026 13:34:51 -0800 Message-ID: <20260218213501.136844-6-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260218213501.136844-1-ebiggers@kernel.org> References: <20260218213501.136844-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Instead 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. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- 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(-) diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig index 81ed892b3b72..82794afaffc9 100644 --- a/arch/arm64/crypto/Kconfig +++ b/arch/arm64/crypto/Kconfig @@ -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) =20 diff --git a/arch/arm64/crypto/aes-glue.c b/arch/arm64/crypto/aes-glue.c index fd7c3a560a71..e1b88f7e2d39 100644 --- a/arch/arm64/crypto/aes-glue.c +++ b/arch/arm64/crypto/aes-glue.c @@ -35,11 +35,10 @@ #define aes_essiv_cbc_decrypt ce_aes_essiv_cbc_decrypt #define aes_ctr_encrypt ce_aes_ctr_encrypt #define aes_xctr_encrypt ce_aes_xctr_encrypt #define aes_xts_encrypt ce_aes_xts_encrypt #define aes_xts_decrypt ce_aes_xts_decrypt -#define aes_mac_update ce_aes_mac_update MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS/XCTR using ARMv8 Crypto Extensions= "); #else #define MODE "neon" #define PRIO 200 #define aes_ecb_encrypt neon_aes_ecb_encrypt @@ -52,11 +51,10 @@ MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS/XCTR using ARMv= 8 Crypto Extensions"); #define aes_essiv_cbc_decrypt neon_aes_essiv_cbc_decrypt #define aes_ctr_encrypt neon_aes_ctr_encrypt #define aes_xctr_encrypt neon_aes_xctr_encrypt #define aes_xts_encrypt neon_aes_xts_encrypt #define aes_xts_decrypt neon_aes_xts_decrypt -#define aes_mac_update neon_aes_mac_update MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS/XCTR using ARMv8 NEON"); #endif #if defined(USE_V8_CRYPTO_EXTENSIONS) || !IS_ENABLED(CONFIG_CRYPTO_AES_ARM= 64_BS) MODULE_ALIAS_CRYPTO("ecb(aes)"); MODULE_ALIAS_CRYPTO("cbc(aes)"); @@ -64,13 +62,10 @@ MODULE_ALIAS_CRYPTO("ctr(aes)"); MODULE_ALIAS_CRYPTO("xts(aes)"); MODULE_ALIAS_CRYPTO("xctr(aes)"); #endif MODULE_ALIAS_CRYPTO("cts(cbc(aes))"); MODULE_ALIAS_CRYPTO("essiv(cbc(aes),sha256)"); -MODULE_ALIAS_CRYPTO("cmac(aes)"); -MODULE_ALIAS_CRYPTO("xcbc(aes)"); -MODULE_ALIAS_CRYPTO("cbcmac(aes)"); =20 MODULE_AUTHOR("Ard Biesheuvel "); MODULE_IMPORT_NS("CRYPTO_INTERNAL"); MODULE_LICENSE("GPL v2"); =20 @@ -82,19 +77,10 @@ struct crypto_aes_xts_ctx { struct crypto_aes_essiv_cbc_ctx { struct crypto_aes_ctx key1; struct crypto_aes_ctx __aligned(8) key2; }; =20 -struct mac_tfm_ctx { - struct crypto_aes_ctx key; - u8 __aligned(8) consts[]; -}; - -struct mac_desc_ctx { - u8 dg[AES_BLOCK_SIZE]; -}; - static int skcipher_aes_setkey(struct crypto_skcipher *tfm, const u8 *in_k= ey, unsigned int key_len) { struct crypto_aes_ctx *ctx =3D crypto_skcipher_ctx(tfm); =20 @@ -721,215 +707,18 @@ static struct skcipher_alg aes_algs[] =3D { { .setkey =3D essiv_cbc_set_key, .encrypt =3D essiv_cbc_encrypt, .decrypt =3D essiv_cbc_decrypt, } }; =20 -static int cbcmac_setkey(struct crypto_shash *tfm, const u8 *in_key, - unsigned int key_len) -{ - struct mac_tfm_ctx *ctx =3D crypto_shash_ctx(tfm); - - return aes_expandkey(&ctx->key, in_key, key_len); -} - -static void cmac_gf128_mul_by_x(be128 *y, const be128 *x) -{ - u64 a =3D be64_to_cpu(x->a); - u64 b =3D be64_to_cpu(x->b); - - y->a =3D cpu_to_be64((a << 1) | (b >> 63)); - y->b =3D cpu_to_be64((b << 1) ^ ((a >> 63) ? 0x87 : 0)); -} - -static int cmac_setkey(struct crypto_shash *tfm, const u8 *in_key, - unsigned int key_len) -{ - struct mac_tfm_ctx *ctx =3D crypto_shash_ctx(tfm); - be128 *consts =3D (be128 *)ctx->consts; - int rounds =3D 6 + key_len / 4; - int err; - - err =3D cbcmac_setkey(tfm, in_key, key_len); - if (err) - return err; - - /* encrypt the zero vector */ - scoped_ksimd() - aes_ecb_encrypt(ctx->consts, (u8[AES_BLOCK_SIZE]){}, - ctx->key.key_enc, rounds, 1); - - cmac_gf128_mul_by_x(consts, consts); - cmac_gf128_mul_by_x(consts + 1, consts); - - return 0; -} - -static int xcbc_setkey(struct crypto_shash *tfm, const u8 *in_key, - unsigned int key_len) -{ - static u8 const ks[3][AES_BLOCK_SIZE] =3D { - { [0 ... AES_BLOCK_SIZE - 1] =3D 0x1 }, - { [0 ... AES_BLOCK_SIZE - 1] =3D 0x2 }, - { [0 ... AES_BLOCK_SIZE - 1] =3D 0x3 }, - }; - - struct mac_tfm_ctx *ctx =3D crypto_shash_ctx(tfm); - int rounds =3D 6 + key_len / 4; - u8 key[AES_BLOCK_SIZE]; - int err; - - err =3D cbcmac_setkey(tfm, in_key, key_len); - if (err) - return err; - - scoped_ksimd() { - aes_ecb_encrypt(key, ks[0], ctx->key.key_enc, rounds, 1); - aes_ecb_encrypt(ctx->consts, ks[1], ctx->key.key_enc, rounds, 2); - } - - return cbcmac_setkey(tfm, key, sizeof(key)); -} - -static int mac_init(struct shash_desc *desc) -{ - struct mac_desc_ctx *ctx =3D shash_desc_ctx(desc); - - memset(ctx->dg, 0, AES_BLOCK_SIZE); - return 0; -} - -static void mac_do_update(struct crypto_aes_ctx *ctx, u8 const in[], int b= locks, - u8 dg[], int enc_before) -{ - int rounds =3D 6 + ctx->key_length / 4; - int rem; - - do { - scoped_ksimd() - rem =3D aes_mac_update(in, ctx->key_enc, rounds, blocks, - dg, enc_before, !enc_before); - in +=3D (blocks - rem) * AES_BLOCK_SIZE; - blocks =3D rem; - } while (blocks); -} - -static int mac_update(struct shash_desc *desc, const u8 *p, unsigned int l= en) -{ - struct mac_tfm_ctx *tctx =3D crypto_shash_ctx(desc->tfm); - struct mac_desc_ctx *ctx =3D shash_desc_ctx(desc); - int blocks =3D len / AES_BLOCK_SIZE; - - len %=3D AES_BLOCK_SIZE; - mac_do_update(&tctx->key, p, blocks, ctx->dg, 0); - return len; -} - -static int cbcmac_finup(struct shash_desc *desc, const u8 *src, - unsigned int len, u8 *out) -{ - struct mac_tfm_ctx *tctx =3D crypto_shash_ctx(desc->tfm); - struct mac_desc_ctx *ctx =3D shash_desc_ctx(desc); - - if (len) { - crypto_xor(ctx->dg, src, len); - mac_do_update(&tctx->key, NULL, 0, ctx->dg, 1); - } - memcpy(out, ctx->dg, AES_BLOCK_SIZE); - return 0; -} - -static int cmac_finup(struct shash_desc *desc, const u8 *src, unsigned int= len, - u8 *out) -{ - struct mac_tfm_ctx *tctx =3D crypto_shash_ctx(desc->tfm); - struct mac_desc_ctx *ctx =3D shash_desc_ctx(desc); - u8 *consts =3D tctx->consts; - - crypto_xor(ctx->dg, src, len); - if (len !=3D AES_BLOCK_SIZE) { - ctx->dg[len] ^=3D 0x80; - consts +=3D AES_BLOCK_SIZE; - } - mac_do_update(&tctx->key, consts, 1, ctx->dg, 0); - memcpy(out, ctx->dg, AES_BLOCK_SIZE); - return 0; -} - -static struct shash_alg mac_algs[] =3D { { - .base.cra_name =3D "cmac(aes)", - .base.cra_driver_name =3D "cmac-aes-" MODE, - .base.cra_priority =3D PRIO, - .base.cra_flags =3D CRYPTO_AHASH_ALG_BLOCK_ONLY | - CRYPTO_AHASH_ALG_FINAL_NONZERO, - .base.cra_blocksize =3D AES_BLOCK_SIZE, - .base.cra_ctxsize =3D sizeof(struct mac_tfm_ctx) + - 2 * AES_BLOCK_SIZE, - .base.cra_module =3D THIS_MODULE, - - .digestsize =3D AES_BLOCK_SIZE, - .init =3D mac_init, - .update =3D mac_update, - .finup =3D cmac_finup, - .setkey =3D cmac_setkey, - .descsize =3D sizeof(struct mac_desc_ctx), -}, { - .base.cra_name =3D "xcbc(aes)", - .base.cra_driver_name =3D "xcbc-aes-" MODE, - .base.cra_priority =3D PRIO, - .base.cra_flags =3D CRYPTO_AHASH_ALG_BLOCK_ONLY | - CRYPTO_AHASH_ALG_FINAL_NONZERO, - .base.cra_blocksize =3D AES_BLOCK_SIZE, - .base.cra_ctxsize =3D sizeof(struct mac_tfm_ctx) + - 2 * AES_BLOCK_SIZE, - .base.cra_module =3D THIS_MODULE, - - .digestsize =3D AES_BLOCK_SIZE, - .init =3D mac_init, - .update =3D mac_update, - .finup =3D cmac_finup, - .setkey =3D xcbc_setkey, - .descsize =3D sizeof(struct mac_desc_ctx), -}, { - .base.cra_name =3D "cbcmac(aes)", - .base.cra_driver_name =3D "cbcmac-aes-" MODE, - .base.cra_priority =3D PRIO, - .base.cra_flags =3D CRYPTO_AHASH_ALG_BLOCK_ONLY, - .base.cra_blocksize =3D AES_BLOCK_SIZE, - .base.cra_ctxsize =3D sizeof(struct mac_tfm_ctx), - .base.cra_module =3D THIS_MODULE, - - .digestsize =3D AES_BLOCK_SIZE, - .init =3D mac_init, - .update =3D mac_update, - .finup =3D cbcmac_finup, - .setkey =3D cbcmac_setkey, - .descsize =3D sizeof(struct mac_desc_ctx), -} }; - static void aes_exit(void) { - crypto_unregister_shashes(mac_algs, ARRAY_SIZE(mac_algs)); crypto_unregister_skciphers(aes_algs, ARRAY_SIZE(aes_algs)); } =20 static int __init aes_init(void) { - int err; - - err =3D crypto_register_skciphers(aes_algs, ARRAY_SIZE(aes_algs)); - if (err) - return err; - - err =3D crypto_register_shashes(mac_algs, ARRAY_SIZE(mac_algs)); - if (err) - goto unregister_ciphers; - - return 0; - -unregister_ciphers: - crypto_unregister_skciphers(aes_algs, ARRAY_SIZE(aes_algs)); - return err; + return crypto_register_skciphers(aes_algs, ARRAY_SIZE(aes_algs)); } =20 #ifdef USE_V8_CRYPTO_EXTENSIONS module_cpu_feature_match(AES, aes_init); #else diff --git a/include/crypto/aes.h b/include/crypto/aes.h index 91bf4667d3e9..3feb4105c2a2 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -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 roun= ds, - int blocks, u8 dg[], int enc_before, - int enc_after); =20 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 rou= nds, + 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); diff --git a/lib/crypto/arm64/aes-modes.S b/lib/crypto/arm64/aes-modes.S index e793478f37c1..fb1332108986 100644 --- a/lib/crypto/arm64/aes-modes.S +++ b/lib/crypto/arm64/aes-modes.S @@ -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) =20 +#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 =20 encrypt_block v0, w2, x1, x7, w8 =20 .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 */ =20 - subs w3, w3, #1 + subs x3, x3, #1 csinv w5, w6, wzr, eq cbz w5, .Lmacout =20 .Lmacenc: encrypt_block v0, w2, x1, x7, w8 b .Lmacloop =20 .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 */ diff --git a/lib/crypto/arm64/aes.h b/lib/crypto/arm64/aes.h index 69f465c668f0..78e7b4e5f120 100644 --- a/lib/crypto/arm64/aes.h +++ b/lib/crypto/arm64/aes.h @@ -9,10 +9,11 @@ #include #include #include #include =20 +static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon); static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_aes); =20 struct aes_block { u8 b[AES_BLOCK_SIZE]; }; @@ -26,10 +27,13 @@ asmlinkage void __aes_ce_encrypt(const u32 rk[], u8 out= [AES_BLOCK_SIZE], asmlinkage void __aes_ce_decrypt(const u32 inv_rk[], u8 out[AES_BLOCK_SIZE= ], const u8 in[AES_BLOCK_SIZE], int rounds); asmlinkage u32 __aes_ce_sub(u32 l); asmlinkage void __aes_ce_invert(struct aes_block *out, const struct aes_block *in); +asmlinkage size_t neon_aes_mac_update(u8 const in[], u32 const rk[], int r= ounds, + size_t blocks, u8 dg[], int enc_before, + int enc_after); =20 /* * Expand an AES key using the crypto extensions if supported and usable or * generic code otherwise. The expanded key format is compatible between = the * two cases. The outputs are @rndkeys (required) and @inv_rndkeys (optio= nal). @@ -137,11 +141,10 @@ EXPORT_SYMBOL_NS_GPL(neon_aes_ctr_encrypt, "CRYPTO_IN= TERNAL"); 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"); =20 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"); @@ -151,10 +154,12 @@ EXPORT_SYMBOL_NS_GPL(ce_aes_ctr_encrypt, "CRYPTO_INTE= RNAL"); 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"); +#endif +#if IS_MODULE(CONFIG_CRYPTO_AES_ARM64_CE_CCM) EXPORT_SYMBOL_NS_GPL(ce_aes_mac_update, "CRYPTO_INTERNAL"); #endif =20 static void aes_encrypt_arch(const struct aes_enckey *key, u8 out[AES_BLOCK_SIZE], @@ -182,13 +187,50 @@ static void aes_decrypt_arch(const struct aes_key *ke= y, __aes_arm64_decrypt(key->inv_k.inv_rndkeys, out, in, key->nrounds); } } =20 +#if IS_ENABLED(CONFIG_CRYPTO_LIB_AES_CBC_MACS) +#define aes_cbcmac_blocks_arch aes_cbcmac_blocks_arch +static bool aes_cbcmac_blocks_arch(u8 h[AES_BLOCK_SIZE], + const struct aes_enckey *key, const u8 *data, + size_t nblocks, bool enc_before, + bool enc_after) +{ + if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && + static_branch_likely(&have_neon) && likely(may_use_simd())) { + do { + size_t rem; + + scoped_ksimd() { + if (static_branch_likely(&have_aes)) + rem =3D ce_aes_mac_update( + data, key->k.rndkeys, + key->nrounds, nblocks, h, + enc_before, enc_after); + else + rem =3D neon_aes_mac_update( + data, key->k.rndkeys, + key->nrounds, nblocks, h, + enc_before, enc_after); + } + data +=3D (nblocks - rem) * AES_BLOCK_SIZE; + nblocks =3D rem; + enc_before =3D false; + } while (nblocks); + return true; + } + return false; +} +#endif /* CONFIG_CRYPTO_LIB_AES_CBC_MACS */ + #ifdef CONFIG_KERNEL_MODE_NEON #define aes_mod_init_arch aes_mod_init_arch static void aes_mod_init_arch(void) { - if (cpu_have_named_feature(AES)) - static_branch_enable(&have_aes); + if (cpu_have_named_feature(ASIMD)) { + static_branch_enable(&have_neon); + if (cpu_have_named_feature(AES)) + static_branch_enable(&have_aes); + } } #endif /* CONFIG_KERNEL_MODE_NEON */ --=20 2.53.0 From nobody Fri Apr 3 07:59:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 964EF3358A6; Wed, 18 Feb 2026 21:36:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450613; cv=none; b=IVhjOdt9eChYodWmaD0u3R6GUjE8qQHEZMx24xN9c5ZCkLp4jmm2YNajiXZ4S4K/NpcBjrhd41cVvCHd9gwVXJQRp922VyLEoaJTUXIUyQmycdkfDCDJCZZizD9alXeM9EUdCIAa7HNOZ2mLoNkOvk9X26vzWopC5Uf5bGD04dA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450613; c=relaxed/simple; bh=WsEqvASqnfKYvYAsnz2LEtDg1yiW7NveNu+mk7c4JE0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=D84zCcpiqjYrIMrPFUGTBs5/70BR11jwvQPwSmvAF9UqN9UTsqE33vePyrFStTv6vm9DxlfCp+nlCxLd9ZahkXbmZJfVhAl5JsEuWDP9Efc1cRzn/P48ZJ8x7tLcqShoeTqNfxqz4t/EqCvTT61Y61yEDzFva0S7vR76+V+oWMk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=rPwtpcM4; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="rPwtpcM4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0CE09C2BCAF; Wed, 18 Feb 2026 21:36:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771450613; bh=WsEqvASqnfKYvYAsnz2LEtDg1yiW7NveNu+mk7c4JE0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rPwtpcM4GMCYsfw00sGC/0Nbr6RO+bXz7y8PSeuDxJ/8iWe9dCU6q1Ldei6lNxaky h1k/vnVu1H7L3wVLQJ8ReOkR+5KmzPKLyIQn/Q/gTFS9YBqAB4M/DlGRsRnP66IcYa yGiWuieGWT1r8kmtTn3MU+DT/NlQrkC1fTxw7wo5tMz860tv8DvCy7TpYuxResQX9M 7ajbWg1UUYr+WAc+c3bDpXayUHXx86yV8X4U8soJmWkl5R4gyCmiPmTTKWsIz4fBEi NsBdFac05w3fqpoxe6DotFcIxXY5xs8iJ8yiCg1qzY/bwC/NdzDgKC8aYUPF+l/hyI lPhS6jBREfGog== From: Eric Biggers To: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , linux-arm-kernel@lists.infradead.org, linux-cifs@vger.kernel.org, linux-wireless@vger.kernel.org, Eric Biggers Subject: [PATCH 06/15] lib/crypto: tests: Add KUnit tests for CBC-based MACs Date: Wed, 18 Feb 2026 13:34:52 -0800 Message-ID: <20260218213501.136844-7-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260218213501.136844-1-ebiggers@kernel.org> References: <20260218213501.136844-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a KUnit test suite for the AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC library functions. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- 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 diff --git a/lib/crypto/tests/Kconfig b/lib/crypto/tests/Kconfig index 4970463ea0aa..2433b988bc5b 100644 --- a/lib/crypto/tests/Kconfig +++ b/lib/crypto/tests/Kconfig @@ -1,7 +1,17 @@ # SPDX-License-Identifier: GPL-2.0-or-later =20 +config CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST + tristate "KUnit tests for AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC" if !KU= NIT_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 diff --git a/lib/crypto/tests/Makefile b/lib/crypto/tests/Makefile index f4262379f56c..f864e0ffbee4 100644 --- a/lib/crypto/tests/Makefile +++ b/lib/crypto/tests/Makefile @@ -1,7 +1,8 @@ # SPDX-License-Identifier: GPL-2.0-or-later =20 +obj-$(CONFIG_CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST) +=3D aes_cbc_macs_kunit.o obj-$(CONFIG_CRYPTO_LIB_BLAKE2B_KUNIT_TEST) +=3D blake2b_kunit.o obj-$(CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST) +=3D blake2s_kunit.o obj-$(CONFIG_CRYPTO_LIB_CURVE25519_KUNIT_TEST) +=3D curve25519_kunit.o obj-$(CONFIG_CRYPTO_LIB_MD5_KUNIT_TEST) +=3D md5_kunit.o obj-$(CONFIG_CRYPTO_LIB_MLDSA_KUNIT_TEST) +=3D mldsa_kunit.o diff --git a/lib/crypto/tests/aes-cmac-testvecs.h b/lib/crypto/tests/aes-cm= ac-testvecs.h new file mode 100644 index 000000000000..8177862ba5a3 --- /dev/null +++ b/lib/crypto/tests/aes-cmac-testvecs.h @@ -0,0 +1,181 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* This file was generated by: ./scripts/crypto/gen-hash-testvecs.py aes-c= mac */ + +static const struct { + size_t data_len; + u8 digest[AES_BLOCK_SIZE]; +} hash_testvecs[] =3D { + { + .data_len =3D 0, + .digest =3D { + 0x9a, 0xeb, 0x94, 0xc1, 0xe9, 0xc1, 0x57, 0x49, + 0x7e, 0xba, 0x66, 0x47, 0x9f, 0x03, 0x2c, 0x5b, + }, + }, + { + .data_len =3D 1, + .digest =3D { + 0x52, 0xef, 0x65, 0xda, 0x7b, 0x92, 0x0c, 0x0f, + 0xdd, 0xd6, 0xb9, 0x68, 0x3f, 0xcc, 0x5f, 0xea, + }, + }, + { + .data_len =3D 2, + .digest =3D { + 0xc3, 0x95, 0x15, 0xea, 0x16, 0x33, 0xbe, 0x5a, + 0xd4, 0x2c, 0x25, 0x06, 0x15, 0xc6, 0x10, 0x19, + }, + }, + { + .data_len =3D 3, + .digest =3D { + 0x82, 0x41, 0x41, 0xd5, 0x33, 0x26, 0x0b, 0xb6, + 0xc8, 0xf7, 0x8d, 0x76, 0x8a, 0xfc, 0x0e, 0xe4, + }, + }, + { + .data_len =3D 16, + .digest =3D { + 0x94, 0x09, 0x80, 0x07, 0xba, 0x7c, 0xed, 0xd2, + 0x74, 0x72, 0x30, 0x26, 0xb5, 0x11, 0x64, 0xc1, + }, + }, + { + .data_len =3D 32, + .digest =3D { + 0xeb, 0xcf, 0x1e, 0x67, 0x21, 0x64, 0x93, 0xa0, + 0xea, 0xc4, 0xb9, 0x2d, 0x55, 0xc8, 0xac, 0x99, + }, + }, + { + .data_len =3D 48, + .digest =3D { + 0xd0, 0xd6, 0xdb, 0xe2, 0x45, 0x98, 0x6a, 0x7a, + 0x5f, 0xd6, 0xcd, 0x9d, 0x12, 0x26, 0x20, 0x87, + }, + }, + { + .data_len =3D 49, + .digest =3D { + 0x63, 0x25, 0x3c, 0xe2, 0x2a, 0xfa, 0xe3, 0x1e, + 0x54, 0x10, 0x18, 0x28, 0xc6, 0xb8, 0xcb, 0x58, + }, + }, + { + .data_len =3D 63, + .digest =3D { + 0x4d, 0xab, 0xae, 0x99, 0x90, 0x13, 0x3f, 0x4f, + 0x42, 0x0f, 0x19, 0x94, 0xa2, 0x52, 0xfd, 0xaf, + }, + }, + { + .data_len =3D 64, + .digest =3D { + 0xf7, 0x49, 0xb9, 0xa7, 0xf9, 0x3e, 0xa0, 0xca, + 0xb2, 0x6c, 0xd7, 0x87, 0x7d, 0x1e, 0xd2, 0xcb, + }, + }, + { + .data_len =3D 65, + .digest =3D { + 0x27, 0x2c, 0xb7, 0xc8, 0xdd, 0x26, 0xa9, 0xfe, + 0x37, 0x64, 0x84, 0x38, 0xa5, 0x7e, 0xbc, 0x04, + }, + }, + { + .data_len =3D 127, + .digest =3D { + 0xfd, 0x1f, 0x01, 0xa4, 0xea, 0x9b, 0xbd, 0xef, + 0x09, 0x97, 0x57, 0x60, 0x95, 0x23, 0xcc, 0x71, + }, + }, + { + .data_len =3D 128, + .digest =3D { + 0x28, 0x21, 0xee, 0x56, 0x9f, 0x38, 0xd6, 0x0e, + 0xe3, 0x22, 0x06, 0x20, 0xad, 0xd8, 0x33, 0x74, + }, + }, + { + .data_len =3D 129, + .digest =3D { + 0x07, 0x28, 0x4a, 0x2a, 0xd3, 0x85, 0xa6, 0x87, + 0x5c, 0x01, 0x8c, 0xb9, 0xd3, 0x4b, 0xce, 0x20, + }, + }, + { + .data_len =3D 256, + .digest =3D { + 0xe6, 0x12, 0x25, 0x6b, 0xf9, 0x69, 0x4d, 0x5a, + 0x1a, 0xb0, 0xe6, 0x11, 0x46, 0x24, 0x08, 0xdf, + }, + }, + { + .data_len =3D 511, + .digest =3D { + 0xce, 0x28, 0x1f, 0x14, 0xb9, 0xcc, 0x7e, 0x1f, + 0xb5, 0x13, 0x2b, 0x45, 0x04, 0x54, 0xe9, 0x5f, + }, + }, + { + .data_len =3D 513, + .digest =3D { + 0x63, 0x12, 0xbd, 0x85, 0x60, 0x1b, 0x99, 0x7e, + 0x0a, 0xf7, 0x0f, 0xc1, 0xb5, 0x66, 0xf8, 0x9a, + }, + }, + { + .data_len =3D 1000, + .digest =3D { + 0xbd, 0x49, 0x5e, 0x21, 0xc6, 0x58, 0x74, 0x6b, + 0x21, 0xc2, 0x62, 0x6a, 0x15, 0xca, 0x1d, 0x8a, + }, + }, + { + .data_len =3D 3333, + .digest =3D { + 0xfe, 0x6b, 0xfa, 0xfc, 0x4c, 0x0b, 0x63, 0x0d, + 0x41, 0x7f, 0xa9, 0xd8, 0xba, 0xe3, 0xce, 0xce, + }, + }, + { + .data_len =3D 4096, + .digest =3D { + 0x41, 0x7c, 0xbc, 0x2e, 0x2f, 0xff, 0xdf, 0x09, + 0x31, 0xc5, 0x79, 0x0a, 0x1d, 0x6e, 0x46, 0xec, + }, + }, + { + .data_len =3D 4128, + .digest =3D { + 0x6a, 0x9d, 0x86, 0xa8, 0xab, 0xa5, 0xc1, 0xc5, + 0x0d, 0x54, 0xf3, 0x51, 0x10, 0x46, 0x25, 0x5a, + }, + }, + { + .data_len =3D 4160, + .digest =3D { + 0x4c, 0x50, 0xff, 0x2a, 0xe9, 0xca, 0x9e, 0x07, + 0x8a, 0x86, 0x67, 0x5e, 0xe5, 0x0a, 0xfd, 0x69, + }, + }, + { + .data_len =3D 4224, + .digest =3D { + 0x3a, 0xfa, 0x80, 0x9d, 0x80, 0xe3, 0x1e, 0x95, + 0x53, 0x93, 0x39, 0x17, 0xd3, 0xda, 0x49, 0x15, + }, + }, + { + .data_len =3D 16384, + .digest =3D { + 0x48, 0xf4, 0x4f, 0x2d, 0x5d, 0xf2, 0x02, 0xcf, + 0x51, 0x3c, 0x1b, 0x12, 0x80, 0x8f, 0xb0, 0xd6, + }, + }, +}; + +static const u8 hash_testvec_consolidated[AES_BLOCK_SIZE] =3D { + 0x41, 0xad, 0x25, 0xa1, 0xeb, 0xce, 0x6b, 0x9c, + 0x06, 0xdf, 0x47, 0xc4, 0x3a, 0x59, 0x50, 0x07, +}; diff --git a/lib/crypto/tests/aes_cbc_macs_kunit.c b/lib/crypto/tests/aes_c= bc_macs_kunit.c new file mode 100644 index 000000000000..ae3745212f03 --- /dev/null +++ b/lib/crypto/tests/aes_cbc_macs_kunit.c @@ -0,0 +1,228 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2026 Google LLC + */ +#include +#include "aes-cmac-testvecs.h" + +/* + * A fixed key used when presenting AES-CMAC as an unkeyed hash function in + * order to reuse hash-test-template.h. At the beginning of the test suit= e, + * this is initialized to a key prepared from bytes generated from a fixed= seed. + */ +static struct aes_cmac_key test_key; + +static void aes_cmac_init_withtestkey(struct aes_cmac_ctx *ctx) +{ + aes_cmac_init(ctx, &test_key); +} + +static void aes_cmac_withtestkey(const u8 *data, size_t data_len, + u8 out[AES_BLOCK_SIZE]) +{ + aes_cmac(&test_key, data, data_len, out); +} + +#define HASH aes_cmac_withtestkey +#define HASH_CTX aes_cmac_ctx +#define HASH_SIZE AES_BLOCK_SIZE +#define HASH_INIT aes_cmac_init_withtestkey +#define HASH_UPDATE aes_cmac_update +#define HASH_FINAL aes_cmac_final +#include "hash-test-template.h" + +static int aes_cbc_macs_suite_init(struct kunit_suite *suite) +{ + u8 raw_key[AES_KEYSIZE_256]; + int err; + + rand_bytes_seeded_from_len(raw_key, sizeof(raw_key)); + err =3D aes_cmac_preparekey(&test_key, raw_key, sizeof(raw_key)); + if (err) + return err; + return hash_suite_init(suite); +} + +static void aes_cbc_macs_suite_exit(struct kunit_suite *suite) +{ + hash_suite_exit(suite); +} + +/* Verify compatibility of the AES-CMAC implementation with RFC 4493. */ +static void test_aes_cmac_rfc4493(struct kunit *test) +{ + static const u8 raw_key[AES_KEYSIZE_128] =3D { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, + }; + static const struct { + size_t data_len; + const u8 data[40]; + const u8 mac[AES_BLOCK_SIZE]; + } testvecs[] =3D { + { + /* Example 1 from RFC 4493 */ + .data_len =3D 0, + .mac =3D { + 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46, + }, + + }, + { + /* Example 2 from RFC 4493 */ + .data =3D { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + }, + .data_len =3D 16, + .mac =3D { + 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c, + }, + }, + { + /* Example 3 from RFC 4493 */ + .data =3D { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + }, + .data_len =3D 40, + .mac =3D { + 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, + 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27, + }, + }, + }; + struct aes_cmac_key key; + int err; + + err =3D aes_cmac_preparekey(&key, raw_key, sizeof(raw_key)); + KUNIT_ASSERT_EQ(test, err, 0); + + for (size_t i =3D 0; i < ARRAY_SIZE(testvecs); i++) { + u8 mac[AES_BLOCK_SIZE]; + + aes_cmac(&key, testvecs[i].data, testvecs[i].data_len, mac); + KUNIT_ASSERT_MEMEQ(test, mac, testvecs[i].mac, AES_BLOCK_SIZE); + } +} + +/* + * Verify compatibility of the AES-XCBC-MAC implementation with RFC 3566. + * + * Additional AES-XCBC-MAC tests are not necessary, since the AES-XCBC-MAC + * implementation is well covered by the AES-CMAC tests already. Only the= key + * preparation function differs; the rest of the code is shared. + */ +static void test_aes_xcbcmac_rfc3566(struct kunit *test) +{ + struct aes_cmac_key key; + /* AES-XCBC-MAC Test Case #4 from RFC 3566 */ + static const u8 raw_key[AES_KEYSIZE_128] =3D { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }; + static const u8 message[20] =3D { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + }; + static const u8 expected_mac[AES_BLOCK_SIZE] =3D { + 0x47, 0xf5, 0x1b, 0x45, 0x64, 0x96, 0x62, 0x15, + 0xb8, 0x98, 0x5c, 0x63, 0x05, 0x5e, 0xd3, 0x08, + }; + u8 actual_mac[AES_BLOCK_SIZE]; + + aes_xcbcmac_preparekey(&key, raw_key); + aes_cmac(&key, message, sizeof(message), actual_mac); + KUNIT_ASSERT_MEMEQ(test, actual_mac, expected_mac, AES_BLOCK_SIZE); +} + +static void test_aes_cbcmac_rfc3610(struct kunit *test) +{ + /* + * The following AES-CBC-MAC test vector is extracted from RFC 3610 + * Packet Vector #11. It required some rearrangement to get the actual + * input to AES-CBC-MAC from the values given. + */ + static const u8 raw_key[AES_KEYSIZE_128] =3D { + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + }; + const size_t unpadded_data_len =3D 52; + static const u8 data[64] =3D { + /* clang-format off */ + /* CCM header */ + 0x61, 0x00, 0x00, 0x00, 0x0d, 0x0c, 0x0b, 0x0a, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x14, + /* CCM additional authentication blocks */ + 0x00, 0x0c, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x00, 0x00, + /* CCM message blocks */ + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* clang-format on */ + }; + static const u8 expected_mac[AES_BLOCK_SIZE] =3D { + 0x6b, 0x5e, 0x24, 0x34, 0x12, 0xcc, 0xc2, 0xad, + 0x6f, 0x1b, 0x11, 0xc3, 0xa1, 0xa9, 0xd8, 0xbc, + }; + struct aes_enckey key; + struct aes_cbcmac_ctx ctx; + u8 actual_mac[AES_BLOCK_SIZE]; + int err; + + err =3D aes_prepareenckey(&key, raw_key, sizeof(raw_key)); + KUNIT_ASSERT_EQ(test, err, 0); + + /* + * Trailing zeroes should not affect the CBC-MAC value, up to the next + * AES block boundary. + */ + for (size_t data_len =3D unpadded_data_len; data_len <=3D sizeof(data); + data_len++) { + aes_cbcmac_init(&ctx, &key); + aes_cbcmac_update(&ctx, data, data_len); + aes_cbcmac_final(&ctx, actual_mac); + KUNIT_ASSERT_MEMEQ(test, actual_mac, expected_mac, + AES_BLOCK_SIZE); + + /* Incremental computations should produce the same result. */ + for (size_t part1_len =3D 0; part1_len <=3D data_len; part1_len++) { + aes_cbcmac_init(&ctx, &key); + aes_cbcmac_update(&ctx, data, part1_len); + aes_cbcmac_update(&ctx, &data[part1_len], + data_len - part1_len); + aes_cbcmac_final(&ctx, actual_mac); + KUNIT_ASSERT_MEMEQ(test, actual_mac, expected_mac, + AES_BLOCK_SIZE); + } + } +} + +static struct kunit_case aes_cbc_macs_test_cases[] =3D { + HASH_KUNIT_CASES, + KUNIT_CASE(test_aes_cmac_rfc4493), + KUNIT_CASE(test_aes_xcbcmac_rfc3566), + KUNIT_CASE(test_aes_cbcmac_rfc3610), + KUNIT_CASE(benchmark_hash), + {}, +}; + +static struct kunit_suite aes_cbc_macs_test_suite =3D { + .name =3D "aes_cbc_macs", + .test_cases =3D aes_cbc_macs_test_cases, + .suite_init =3D aes_cbc_macs_suite_init, + .suite_exit =3D aes_cbc_macs_suite_exit, +}; +kunit_test_suite(aes_cbc_macs_test_suite); + +MODULE_DESCRIPTION( + "KUnit tests and benchmark for AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC"); +MODULE_IMPORT_NS("CRYPTO_INTERNAL"); +MODULE_LICENSE("GPL"); diff --git a/scripts/crypto/gen-hash-testvecs.py b/scripts/crypto/gen-hash-= testvecs.py index 8eeb650fcada..34b7c48f3456 100755 --- a/scripts/crypto/gen-hash-testvecs.py +++ b/scripts/crypto/gen-hash-testvecs.py @@ -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 =20 +import cryptography.hazmat.primitives.ciphers +import cryptography.hazmat.primitives.cmac import hashlib import hmac import sys =20 DATA_LENS =3D [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 =3D (seed * 25214903917 + 11) % 2**48 out.append((seed >> 16) % 256) return bytes(out) =20 +AES_256_KEY_SIZE =3D 32 + +# AES-CMAC. Just wraps the implementation from python-cryptography. +class AesCmac: + def __init__(self, key): + aes =3D cryptography.hazmat.primitives.ciphers.algorithms.AES(key) + self.cmac =3D cryptography.hazmat.primitives.cmac.CMAC(aes) + + def update(self, data): + self.cmac.update(data) + + def digest(self): + return self.cmac.finalize() + POLY1305_KEY_SIZE =3D 32 =20 # A straightforward, unoptimized implementation of Poly1305. # Reference: https://cr.yp.to/mac/poly1305-20050329.pdf class Poly1305: @@ -78,13 +96,16 @@ class Polyval: =20 def digest(self): return self.acc.to_bytes(16, byteorder=3D'little') =20 def hash_init(alg): + # The keyed hash functions are assigned a fixed random key here, to pr= esent + # them as unkeyed hash functions. This allows all the test cases for + # unkeyed hash functions to work on them. + if alg =3D=3D 'aes-cmac': + return AesCmac(rand_bytes(AES_256_KEY_SIZE)) if alg =3D=3D 'poly1305': - # Use a fixed random key here, to present Poly1305 as an unkeyed h= ash. - # This allows all the test cases for unkeyed hashes to work on Pol= y1305. return Poly1305(rand_bytes(POLY1305_KEY_SIZE)) if alg =3D=3D 'polyval': return Polyval(rand_bytes(POLYVAL_BLOCK_SIZE)) return hashlib.new(alg) =20 @@ -114,10 +135,12 @@ def print_c_struct_u8_array_field(name, value): print(f'\t\t.{name} =3D {{') print_bytes('\t\t\t', value, 8) print('\t\t},') =20 def alg_digest_size_const(alg): + if alg =3D=3D 'aes-cmac': + return 'AES_BLOCK_SIZE' if alg.startswith('blake2'): return f'{alg.upper()}_HASH_SIZE' return f"{alg.upper().replace('-', '_')}_DIGEST_SIZE" =20 def gen_unkeyed_testvecs(alg): @@ -250,11 +273,13 @@ if len(sys.argv) !=3D 2: sys.exit(1) =20 alg =3D 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 =3D=3D 'aes-cmac': + gen_unkeyed_testvecs(alg) +elif alg.startswith('blake2'): gen_unkeyed_testvecs(alg) gen_additional_blake2_testvecs(alg) elif alg =3D=3D 'nh': gen_nh_testvecs() elif alg =3D=3D 'poly1305': --=20 2.53.0 From nobody Fri Apr 3 07:59:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 40F962F39B4; Wed, 18 Feb 2026 21:36:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450614; cv=none; b=Ia7eueX7L3bPG5hAROmCo+U8afODD7VpsDbknsoKQ2xFCN4UkgQ4vd2gN4DKdvclY8k4zmbrmQ1Zrp0D1MdfxSMc5V26Fh4/RzXh2AHFSXznXi+AX10CKPGh9uv3mPsmAxOsDsoWMNDGloeZ/sJvMMCL6UuKVfOSyqgOF+eQc1w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450614; c=relaxed/simple; bh=rAp5p3HDmh8Bp7UNW6r+uRPuPyK59EaigYeIc+rCLB8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SDOPEFR+XQFxggpvgpq5VrLMaGurMfcdUk484/UkSDqU6ZhT6vZJ7jmHUGSqbMBxcVj/zUpWM9iARuZ84dI8/2LxqLRmdqUwx2TnxbMZPYR5asSM0W7/z56hDRo0Z4PAx6Q0tMR/SseBmgspBjs2ytZDyYlsI/3AoEa/herL9p8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bS8mXGBZ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bS8mXGBZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9BBBCC2BC86; Wed, 18 Feb 2026 21:36:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771450614; bh=rAp5p3HDmh8Bp7UNW6r+uRPuPyK59EaigYeIc+rCLB8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bS8mXGBZIZm7D0xIRb2dfANtTBm2nMQJn6ZJn7qSQafN8cLWnn0Tj4h0VgxNQmDFf 2zlPR/kUlg3EUQfA87QF3iw4xHUotS7vyUwK4Jzwua2Rzc/Stfkx6codz/EwHcw338 xoq5em8nIQnw9Nw0mHlnIE+SUx4U5hbuGRJxM7+k/tLlnsTVuBGBtE74MfMJqGqeTb 4d6ch0xmQPfPHj6odH2o+0FK/dZs4Yb75iBZOL2Q8WfXY++UMA/7GVcKP9XhWJG7zN SauD09ZbBVfcBZCmwC8nyVrjJQ0MegCrEzksJtgY0Fz8tXfPq9BLYaLStNBWJVwLBl RhYga15fgJqXA== From: Eric Biggers To: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , linux-arm-kernel@lists.infradead.org, linux-cifs@vger.kernel.org, linux-wireless@vger.kernel.org, Eric Biggers Subject: [PATCH 07/15] lib/crypto: aes: Add FIPS self-test for CMAC Date: Wed, 18 Feb 2026 13:34:53 -0800 Message-ID: <20260218213501.136844-8-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260218213501.136844-1-ebiggers@kernel.org> References: <20260218213501.136844-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add 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. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- lib/crypto/aes.c | 35 ++++++++++++++++++++++++++--- lib/crypto/fips.h | 5 +++++ scripts/crypto/gen-fips-testvecs.py | 10 +++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/lib/crypto/aes.c b/lib/crypto/aes.c index 39deae6105c0..ca733f15b2a8 100644 --- a/lib/crypto/aes.c +++ b/lib/crypto/aes.c @@ -10,10 +10,11 @@ #include #include #include #include #include +#include "fips.h" =20 static const u8 ____cacheline_aligned aes_sbox[] =3D { 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 */ =20 -#ifdef aes_mod_init_arch +/* + * FIPS cryptographic algorithm self-test for AES-CMAC. As per the FIPS 1= 40-3 + * Implementation Guidance, a cryptographic algorithm self-test for at lea= st 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)) !=3D + 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)) !=3D 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_arch aes_mod_init_arch(); +#endif + if (fips_enabled) + aes_cmac_fips_test(); return 0; } subsys_initcall(aes_mod_init); =20 static void __exit aes_mod_exit(void) { } module_exit(aes_mod_exit); -#endif =20 MODULE_DESCRIPTION("AES block cipher"); MODULE_AUTHOR("Ard Biesheuvel "); MODULE_AUTHOR("Eric Biggers "); MODULE_LICENSE("GPL v2"); diff --git a/lib/crypto/fips.h b/lib/crypto/fips.h index 023410c2e0db..9fc49747db64 100644 --- a/lib/crypto/fips.h +++ b/lib/crypto/fips.h @@ -41,5 +41,10 @@ static const u8 fips_test_sha3_256_value[] __initconst _= _maybe_unused =3D { 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 =3D { + 0xc5, 0x88, 0x28, 0x55, 0xd7, 0x2c, 0x00, 0xb6, + 0x6a, 0xa7, 0xfc, 0x82, 0x90, 0x81, 0xcf, 0x18, +}; diff --git a/scripts/crypto/gen-fips-testvecs.py b/scripts/crypto/gen-fips-= testvecs.py index db873f88619a..9f18bcb97412 100755 --- a/scripts/crypto/gen-fips-testvecs.py +++ b/scripts/crypto/gen-fips-testvecs.py @@ -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 =20 +import cryptography.hazmat.primitives.ciphers +import cryptography.hazmat.primitives.cmac import hashlib import hmac =20 fips_test_data =3D b"fips test data\0\0" fips_test_key =3D 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.di= gest()) =20 print_static_u8_array_definition(f'fips_test_sha3_256_value', hashlib.sha3_256(fips_test_data).digest()) + +aes =3D cryptography.hazmat.primitives.ciphers.algorithms.AES(fips_test_ke= y) +aes_cmac =3D 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()) --=20 2.53.0 From nobody Fri Apr 3 07:59:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D99C13370F3; Wed, 18 Feb 2026 21:36:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450614; cv=none; b=AqHclAmbAOGasS300cPp6WOfHldXAaieVPIJhiyy/XZMPutzI+cbzbWNr8inPBI38Odi96jsyoP4DNZijehOkP+lzYFyrbs8o0Tnv0EtRrla/azctTNBoPen9FUZ2UTxLceZ7vNx1weyFqlz9Fqo96EoT3NAWLkF/2jwGRjX7aI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450614; c=relaxed/simple; bh=RfXKwO9L3mlz5kqOurMbNRJCV4vYWaJHp6x9x+hkRPc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=T0UHcHA61SGJE2C5eVFWkFMYdJDF387/UaaSS1jP09yiWbR5fag1UtF3CO5RKTmre37sjM5ycjyI9UVabGbJOTCuZQTFZOlzNp/D/Zc3sQ0qzagthLDpaF1zVIWwdx8qgEYf1PO7HJTDL2g3QH6TUAcNr3355FaTqrwF2PKUjU4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Su8jtnhs; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Su8jtnhs" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 34D2CC2BCB2; Wed, 18 Feb 2026 21:36:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771450614; bh=RfXKwO9L3mlz5kqOurMbNRJCV4vYWaJHp6x9x+hkRPc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Su8jtnhsciBt1sckGun8RAAdjFMXTLnvoRdF+ZZ7Tf+YPetiXSfdMtWA+QCrq/xuZ LC+tZUeX5QgxkAU1DH9WFTtxMlERcAAtnUJwHX8FpeXH9lx/jmbjWTbjl3ooJ98GFd NkvmtcEfxgccMdgMGT4QwVMtCQvvxh3sHqP41VWdfhD6g+QpIzYSyGbKRvfPuX+AFs i+ny6LvBf9MroUEPF8hCY5B1qpRdzypyCee0GTJ2phCjowvtvZaBl/Ox1dd991a22j YabktEmIWGaQVTKjgRCGGUqVbTdhWXQ1IPRxinbAfHwrnFlg4FVLKiLYhgy3wSlbID oeGNcXA04Nsww== From: Eric Biggers To: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , linux-arm-kernel@lists.infradead.org, linux-cifs@vger.kernel.org, linux-wireless@vger.kernel.org, Eric Biggers Subject: [PATCH 08/15] smb: client: Use AES-CMAC library for SMB3 signature calculation Date: Wed, 18 Feb 2026 13:34:54 -0800 Message-ID: <20260218213501.136844-9-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260218213501.136844-1-ebiggers@kernel.org> References: <20260218213501.136844-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Convert 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. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- 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(-) diff --git a/fs/smb/client/Kconfig b/fs/smb/client/Kconfig index 17bd368574e9..64afd302202f 100644 --- a/fs/smb/client/Kconfig +++ b/fs/smb/client/Kconfig @@ -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 diff --git a/fs/smb/client/cifsencrypt.c b/fs/smb/client/cifsencrypt.c index 50b7ec39053c..f39894113821 100644 --- a/fs/smb/client/cifsencrypt.c +++ b/fs/smb/client/cifsencrypt.c @@ -20,66 +20,49 @@ #include #include #include #include #include +#include #include #include #include =20 -static int cifs_sig_update(struct cifs_calc_sig_ctx *ctx, - const u8 *data, size_t len) +static size_t cifs_sig_step(void *iter_base, size_t progress, size_t len, + void *priv, void *priv2) { - if (ctx->md5) { - md5_update(ctx->md5, data, len); - return 0; - } - if (ctx->hmac) { - hmac_sha256_update(ctx->hmac, data, len); - return 0; - } - return crypto_shash_update(ctx->shash, data, len); + struct cifs_calc_sig_ctx *ctx =3D priv; + + if (ctx->md5) + md5_update(ctx->md5, iter_base, len); + else if (ctx->hmac) + hmac_sha256_update(ctx->hmac, iter_base, len); + else + aes_cmac_update(ctx->cmac, iter_base, len); + return 0; /* Return value is length *not* processed, i.e. 0. */ } =20 -static int cifs_sig_final(struct cifs_calc_sig_ctx *ctx, u8 *out) +static void cifs_sig_final(struct cifs_calc_sig_ctx *ctx, u8 *out) { - if (ctx->md5) { + if (ctx->md5) md5_final(ctx->md5, out); - return 0; - } - if (ctx->hmac) { + else if (ctx->hmac) hmac_sha256_final(ctx->hmac, out); - return 0; - } - return crypto_shash_final(ctx->shash, out); -} - -static size_t cifs_sig_step(void *iter_base, size_t progress, size_t len, - void *priv, void *priv2) -{ - struct cifs_calc_sig_ctx *ctx =3D priv; - int ret, *pret =3D priv2; - - ret =3D cifs_sig_update(ctx, iter_base, len); - if (ret < 0) { - *pret =3D ret; - return len; - } - return 0; + else + aes_cmac_final(ctx->cmac, out); } =20 /* * Pass the data from an iterator into a hash. */ static int cifs_sig_iter(const struct iov_iter *iter, size_t maxsize, struct cifs_calc_sig_ctx *ctx) { struct iov_iter tmp_iter =3D *iter; size_t did; - int err; =20 - did =3D iterate_and_advance_kernel(&tmp_iter, maxsize, ctx, &err, + did =3D iterate_and_advance_kernel(&tmp_iter, maxsize, ctx, NULL, cifs_sig_step); if (did !=3D maxsize) return smb_EIO2(smb_eio_trace_sig_iter, did, maxsize); return 0; } @@ -106,15 +89,12 @@ int __cifs_calc_signature(struct smb_rqst *rqst, struc= t TCP_Server_Info *server, =20 rc =3D cifs_sig_iter(&rqst->rq_iter, iov_iter_count(&rqst->rq_iter), ctx); if (rc < 0) return rc; =20 - rc =3D cifs_sig_final(ctx, signature); - if (rc) - cifs_dbg(VFS, "%s: Could not generate hash\n", __func__); - - return rc; + cifs_sig_final(ctx, signature); + return 0; } =20 /* Build a proper attribute value/target info pairs blob. * Fill in netbios and dns domain name and workstation name * and client time (total five av pairs and + one end of fields indicator. diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 080ea601c209..2ff43bd35c5f 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -2285,11 +2285,11 @@ static inline void mid_execute_callback(struct TCP_= Server_Info *server, FILE_SUPPORTS_REPARSE_POINTS)) =20 struct cifs_calc_sig_ctx { struct md5_ctx *md5; struct hmac_sha256_ctx *hmac; - struct shash_desc *shash; + struct aes_cmac_ctx *cmac; }; =20 #define CIFS_RECONN_DELAY_SECS 30 #define CIFS_MAX_RECONN_DELAY (4 * CIFS_RECONN_DELAY_SECS) =20 diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c index 81be2b226e26..b233e0cd9152 100644 --- a/fs/smb/client/smb2transport.c +++ b/fs/smb/client/smb2transport.c @@ -17,10 +17,11 @@ #include #include #include #include #include +#include #include #include #include "cifsglob.h" #include "cifsproto.h" #include "smb2proto.h" @@ -472,11 +473,12 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP= _Server_Info *server, { int rc; unsigned char smb3_signature[SMB2_CMACAES_SIZE]; struct kvec *iov =3D rqst->rq_iov; struct smb2_hdr *shdr =3D (struct smb2_hdr *)iov[0].iov_base; - struct shash_desc *shash =3D NULL; + struct aes_cmac_key cmac_key; + struct aes_cmac_ctx cmac_ctx; struct smb_rqst drqst; u8 key[SMB3_SIGN_KEY_SIZE]; =20 if (server->vals->protocol_id <=3D SMB21_PROT_ID) return smb2_calc_signature(rqst, server, allocate_crypto); @@ -485,67 +487,40 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP= _Server_Info *server, if (unlikely(rc)) { cifs_server_dbg(FYI, "%s: Could not get signing key\n", __func__); return rc; } =20 - if (allocate_crypto) { - rc =3D cifs_alloc_hash("cmac(aes)", &shash); - if (rc) - return rc; - } else { - shash =3D server->secmech.aes_cmac; - } - memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE); memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE); =20 - rc =3D crypto_shash_setkey(shash->tfm, key, SMB2_CMACAES_SIZE); + rc =3D aes_cmac_preparekey(&cmac_key, key, SMB2_CMACAES_SIZE); if (rc) { cifs_server_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__); - goto out; + return rc; } =20 - /* - * we already allocate aes_cmac when we init smb3 signing key, - * so unlike smb2 case we do not have to check here if secmech are - * initialized - */ - rc =3D crypto_shash_init(shash); - if (rc) { - cifs_server_dbg(VFS, "%s: Could not init cmac aes\n", __func__); - goto out; - } + aes_cmac_init(&cmac_ctx, &cmac_key); =20 /* * For SMB2+, __cifs_calc_signature() expects to sign only the actual * data, that is, iov[0] should not contain a rfc1002 length. * * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to * __cifs_calc_signature(). */ drqst =3D *rqst; if (drqst.rq_nvec >=3D 2 && iov[0].iov_len =3D=3D 4) { - rc =3D crypto_shash_update(shash, iov[0].iov_base, - iov[0].iov_len); - if (rc) { - cifs_server_dbg(VFS, "%s: Could not update with payload\n", - __func__); - goto out; - } + aes_cmac_update(&cmac_ctx, iov[0].iov_base, iov[0].iov_len); drqst.rq_iov++; drqst.rq_nvec--; } =20 rc =3D __cifs_calc_signature( &drqst, server, smb3_signature, - &(struct cifs_calc_sig_ctx){ .shash =3D shash }); + &(struct cifs_calc_sig_ctx){ .cmac =3D &cmac_ctx }); if (!rc) memcpy(shdr->Signature, smb3_signature, SMB2_SIGNATURE_SIZE); - -out: - if (allocate_crypto) - cifs_free_hash(&shash); return rc; } =20 /* must be called with server->srv_mutex held */ static int --=20 2.53.0 From nobody Fri Apr 3 07:59:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 731B63375D5; Wed, 18 Feb 2026 21:36:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450615; cv=none; b=a2VD7OEc6fEyl8UV2gdLafA+biNyZHP2b7YJHp3Hq/VYK76VIkhFa3aWFLlXYzrqHQDyuoDUYvcWn8ZqElJzBI6/lsDVbah1rLVAfGAIMZzbOm6ttqrLdcg7nYNzInxJZM+A0HXqZ0FATfaxyMU/AeoOPXXdTJKdW33cX/wVSR0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450615; c=relaxed/simple; bh=5ChXT8GOxfVTVJ7ZRccEEE7TuA1oPtRqqzapCDcH3D4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=H4GU73kt4URxRgwxRpm0ra6QrCTLeTKAAQo8b91xP3n6WaHTBb8flRC2N5YClPieJMOVKZifeP6XJzAjJdWEPedbJyPCfJxFFyHySvqyuWEjMbNrOu2iFcH9fCieabzvNppbirz4RWe1iYH8RjGqvXDBpMZP/hj9oUuntxWp8E0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bflmsHWg; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bflmsHWg" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BE38BC19422; Wed, 18 Feb 2026 21:36:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771450615; bh=5ChXT8GOxfVTVJ7ZRccEEE7TuA1oPtRqqzapCDcH3D4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bflmsHWg+61Iok0YtQ+cSBh3ad/TVqbOLSKzj5XlqhhL0m3ThlQWUx5qsc6aSCndf Z5hwiJ2HfOeSqqij4CMAM3/U7uA4N2wiOFpmTCT/9eQM/xkJ+/9oaNs8o8H9fNcN90 yFaG+jDh9pWhxkH62QU4P32DCvyaN2I0i9o0/G3NKiwBFMBobnJ8fvFI6DVOlvFVOJ A1rGXtxWN0vrF9VV+ThVdv4qW9CAnECcPdSTUGx0VZ6wqHyxKIvdoK796X8GByXFpf JOM9lYPqKCmqDd59IeNPOKyVsN1aHbp1A6XhqfAuqL0ct+zGId73+YdRqSY5aP/9Qz UrCjRHHkGkwfg== From: Eric Biggers To: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , linux-arm-kernel@lists.infradead.org, linux-cifs@vger.kernel.org, linux-wireless@vger.kernel.org, Eric Biggers Subject: [PATCH 09/15] smb: client: Remove obsolete cmac(aes) allocation Date: Wed, 18 Feb 2026 13:34:55 -0800 Message-ID: <20260218213501.136844-10-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260218213501.136844-1-ebiggers@kernel.org> References: <20260218213501.136844-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Since 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 being included transitively via . Since the latter include is removed, make cifs_unicode.c include explicitly. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- 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(-) diff --git a/fs/smb/client/Kconfig b/fs/smb/client/Kconfig index 64afd302202f..29d7dffab51b 100644 --- a/fs/smb/client/Kconfig +++ b/fs/smb/client/Kconfig @@ -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 diff --git a/fs/smb/client/cifs_unicode.c b/fs/smb/client/cifs_unicode.c index e7891b4406f2..c6e81ba011bb 100644 --- a/fs/smb/client/cifs_unicode.c +++ b/fs/smb/client/cifs_unicode.c @@ -4,10 +4,11 @@ * Copyright (c) International Business Machines Corp., 2000,2009 * Modified by Steve French (sfrench@us.ibm.com) */ #include #include +#include #include "cifs_fs_sb.h" #include "cifs_unicode.h" #include "cifsglob.h" #include "cifs_debug.h" =20 diff --git a/fs/smb/client/cifsencrypt.c b/fs/smb/client/cifsencrypt.c index f39894113821..a566ce2ae9f8 100644 --- a/fs/smb/client/cifsencrypt.c +++ b/fs/smb/client/cifsencrypt.c @@ -501,12 +501,10 @@ calc_seckey(struct cifs_ses *ses) } =20 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 =3D NULL; } if (server->secmech.dec) { diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index afda1d7c1ee1..46499bdcebfe 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -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) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 2ff43bd35c5f..24f2a367aad5 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -20,11 +20,10 @@ #include #include #include #include "cifs_fs_sb.h" #include "cifsacl.h" -#include #include #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; }; =20 -/* 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= ) */ }; =20 /* per smb session structure/fields */ diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index 96d6b5325aa3..025db2285968 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -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); =20 -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 *if= ace); diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c index 1773e3b471aa..d7300d224a63 100644 --- a/fs/smb/client/misc.c +++ b/fs/smb/client/misc.c @@ -736,67 +736,10 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp,= u32 rsp_size, *num_of_nodes =3D 0; } return rc; } =20 -/** - * cifs_alloc_hash - allocate hash and hash context together - * @name: The name of the crypto hash algo - * @sdesc: SHASH descriptor where to put the pointer to the hash TFM - * - * The caller has to make sure @sdesc is initialized to either NULL or - * a valid context. It can be freed via cifs_free_hash(). - */ -int -cifs_alloc_hash(const char *name, struct shash_desc **sdesc) -{ - int rc =3D 0; - struct crypto_shash *alg =3D NULL; - - if (*sdesc) - return 0; - - alg =3D crypto_alloc_shash(name, 0, 0); - if (IS_ERR(alg)) { - cifs_dbg(VFS, "Could not allocate shash TFM '%s'\n", name); - rc =3D PTR_ERR(alg); - *sdesc =3D NULL; - return rc; - } - - *sdesc =3D kmalloc(sizeof(struct shash_desc) + crypto_shash_descsize(alg)= , GFP_KERNEL); - if (*sdesc =3D=3D NULL) { - cifs_dbg(VFS, "no memory left to allocate shash TFM '%s'\n", name); - crypto_free_shash(alg); - return -ENOMEM; - } - - (*sdesc)->tfm =3D alg; - return 0; -} - -/** - * cifs_free_hash - free hash and hash context together - * @sdesc: Where to find the pointer to the hash TFM - * - * Freeing a NULL descriptor is safe. - */ -void -cifs_free_hash(struct shash_desc **sdesc) -{ - if (unlikely(!sdesc) || !*sdesc) - return; - - if ((*sdesc)->tfm) { - crypto_free_shash((*sdesc)->tfm); - (*sdesc)->tfm =3D NULL; - } - - kfree_sensitive(*sdesc); - *sdesc =3D NULL; -} - void extract_unc_hostname(const char *unc, const char **h, size_t *len) { const char *end; =20 /* skip initial slashes */ diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c index d523540565ef..11a09a1d8806 100644 --- a/fs/smb/client/sess.c +++ b/fs/smb/client/sess.c @@ -593,21 +593,10 @@ cifs_ses_add_channel(struct cifs_ses *ses, cifs_chan_set_need_reconnect(ses, chan->server); =20 spin_unlock(&ses->chan_lock); =20 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 =3D smb3_crypto_shash_allocate(chan->server); - if (rc) { - cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__); - mutex_unlock(&ses->session_mutex); - goto out; - } =20 rc =3D cifs_negotiate_protocol(xid, ses, chan->server); if (!rc) rc =3D cifs_setup_session(xid, ses, chan->server, ses->local_nls); =20 diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h index 881e42cf66ce..e7b35d500943 100644 --- a/fs/smb/client/smb2proto.h +++ b/fs/smb/client/smb2proto.h @@ -253,11 +253,10 @@ int smb2_validate_iov(unsigned int offset, unsigned i= nt buffer_length, int smb2_validate_and_copy_iov(unsigned int offset, unsigned int buffer_le= ngth, 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 *tco= n, const char *path, u32 desired_access, u32 class, diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c index b233e0cd9152..716e58d1b1c9 100644 --- a/fs/smb/client/smb2transport.c +++ b/fs/smb/client/smb2transport.c @@ -27,18 +27,10 @@ #include "smb2proto.h" #include "cifs_debug.h" #include "../common/smb2status.h" #include "smb2glob.h" =20 -int -smb3_crypto_shash_allocate(struct TCP_Server_Info *server) -{ - struct cifs_secmech *p =3D &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 *ke= y) { 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 =3D 0x0; __u8 i[4] =3D {0, 0, 0, 1}; __u8 L128[4] =3D {0, 0, 0, 128}; __u8 L256[4] =3D {0, 0, 1, 0}; - int rc =3D 0; unsigned char prfhash[SMB2_HMACSHA256_SIZE]; struct TCP_Server_Info *server =3D ses->server; struct hmac_sha256_ctx hmac_ctx; =20 memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE); memset(key, 0x0, key_size); =20 - rc =3D 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); --=20 2.53.0 From nobody Fri Apr 3 07:59:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8B65D2FE575; Wed, 18 Feb 2026 21:36:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450616; cv=none; b=TLUCR7pWE8DBQviNsT//f6Pa0dulOoBLETa9BdVnu5INIKXRBKYNWxxSp3zj2WnXhnwWSpAGhyb9Frz3ZrVRGx9yCmD5XkJtnxM9Lcvl/cT5mJdVQI7T+3UBrYi12gn3+w+NyntjsT7zupYtSyGHJS9Vnx+JisRqmNQaIqZja1U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450616; c=relaxed/simple; bh=LoZhuuxzNWOyrPmwe9ku8/14QhyJ8CKzIMFUQopSDgQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DAr++gPo9lZFRQ7KFvGlBheQrNNE2iHJcXWEpIagIEEpaOQQeLkgWjRERWq0x0rVnXCvaQz7cEhTbwBBheR9HD+QipfUm3D3ige9GpQuVbNY6J8ikNQ+xPrHC8C0lSpsVWiUjLowsdcfL/Xl3taXD7Lo0SZi57bTqoXs1OkNR0c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=c0vKBFRD; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="c0vKBFRD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 54F24C19421; Wed, 18 Feb 2026 21:36:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771450616; bh=LoZhuuxzNWOyrPmwe9ku8/14QhyJ8CKzIMFUQopSDgQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=c0vKBFRDl5TZsypRiZLNxLu+gyGyL/z7hDpq+OPPeKBKVI4VkdjUN6evSVA+WExM4 M5wEqlOBLmYXFkedkv22ojxpcmNWsKHhqYotwkXWhivyLdyWuXh6DpmlslLgzNfSFt aV8XJw8qfD0RbGBKHO9BKzaNODK7LY0h6V+UNcn9Tj2d5U6gSQ5CAdSDgN7fKUG1yA trftxnltQKqv2rFNPbkRjJNBq7qw4hrLp4KfWkfkachUqZ+60bmF1+6jsHlBZNnen9 DSHxYzddUtracdqj55ayRleE2P3sNmGU0zojugQw/semrjOQZHbAjbmF9g8ZNX4pwt GpjaoIQ5XEixA== From: Eric Biggers To: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , linux-arm-kernel@lists.infradead.org, linux-cifs@vger.kernel.org, linux-wireless@vger.kernel.org, Eric Biggers Subject: [PATCH 10/15] smb: client: Make generate_key() return void Date: Wed, 18 Feb 2026 13:34:56 -0800 Message-ID: <20260218213501.136844-11-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260218213501.136844-1-ebiggers@kernel.org> References: <20260218213501.136844-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Since 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. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- fs/smb/client/smb2transport.c | 45 +++++++++++++---------------------- 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c index 716e58d1b1c9..0176185a1efc 100644 --- a/fs/smb/client/smb2transport.c +++ b/fs/smb/client/smb2transport.c @@ -249,12 +249,12 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP= _Server_Info *server, memcpy(shdr->Signature, smb2_signature, SMB2_SIGNATURE_SIZE); =20 return rc; } =20 -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 =3D 0x0; __u8 i[4] =3D {0, 0, 0, 1}; __u8 L128[4] =3D {0, 0, 0, 128}; __u8 L256[4] =3D {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); =20 memcpy(key, prfhash, key_size); - return 0; } =20 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 =3D false; int chan_index =3D 0; =20 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 */ =20 if (is_binding) { - rc =3D 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 =3D 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); =20 /* 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); =20 - rc =3D generate_key(ses, ptriplet->encryption.label, - ptriplet->encryption.context, - ses->smb3encryptionkey, - SMB3_ENC_DEC_KEY_SIZE); - if (rc) - return rc; - rc =3D 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); } =20 #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; } =20 int generate_smb30signingkey(struct cifs_ses *ses, struct TCP_Server_Info *server) --=20 2.53.0 From nobody Fri Apr 3 07:59:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E6F1B312832; Wed, 18 Feb 2026 21:36:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450618; cv=none; b=O7Pv8QwB9BukV7U6FHIVtAXzdVN9+8bv+y3rV/52PHNm+GwzcqhogZacRXN+XmKpmOQZt+YQL26DJcvaqDVXuF6eELPCy/1eRIaqbQbWU70aXw6IwMG89AoKDXU/jwf5fi45n5eMBUUlxmICxM4WUzp+Uj/Ba+K6Sl2+yK2Kgrk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450618; c=relaxed/simple; bh=yUsqjSnPbDX/S+rnsu/6yIO+0mII4wRuFeRbW6zNwMQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QZE1lrHWcMVCv2kQ7OE/oBnv7BKe3E48Van5UpK7ipFrWlEBF5nQ9nc73lAvTgq8jmrGD3JQalZKU5KeVLbmV6csmWYErnWl8tYTvwoI3us8jbrQQ626ZvaFXNxoxPmvCzSiIyKyiIgyM2GrZvsVwWHxK9061y3PLj4cOMWl/qI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kmNioAnd; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="kmNioAnd" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AE83AC2BCAF; Wed, 18 Feb 2026 21:36:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771450617; bh=yUsqjSnPbDX/S+rnsu/6yIO+0mII4wRuFeRbW6zNwMQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kmNioAndIDtJqj5zX9UyQqC8ga+DPfMLGWcDMmKgmWKPeQ6Q/tAv1kutYsfIc/rdO LQc6vHbw6C4wUcfk79joquORCE6pT+BwnMNBpRz35c1b2dIWQU+mUHBoeUUpHHchyi vCFdheo5Gr2gOFWWh91VetqLe8BHP3ojSeB/m9Pa9pCjP7cYfZiv2M9q0O7EXkoV98 wmhrjyLDJijMQwri+QwicxPTllfq3HVOV4byCCYumyD6TD5KbOUoeNAzTmRzBOEBsw fsl7PXcZvEXEnGPr1/zMWgIe9cTmfaW5UkU/BVNVmge+NzCT6vQT5nTuvpKkpoQSZs J1hK43sD4g2ZQ== From: Eric Biggers To: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , linux-arm-kernel@lists.infradead.org, linux-cifs@vger.kernel.org, linux-wireless@vger.kernel.org, Eric Biggers Subject: [PATCH 11/15] smb: client: Drop 'allocate_crypto' arg from smb*_calc_signature() Date: Wed, 18 Feb 2026 13:34:57 -0800 Message-ID: <20260218213501.136844-12-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260218213501.136844-1-ebiggers@kernel.org> References: <20260218213501.136844-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 to smb2_calc_signature() and smb3_calc_signature() is no longer used. Remove this unused argument. Signed-off-by: Eric Biggers Acked-by: Steve French Reviewed-by: Ard Biesheuvel --- fs/smb/client/smb2transport.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c index 0176185a1efc..41009039b4cb 100644 --- a/fs/smb/client/smb2transport.c +++ b/fs/smb/client/smb2transport.c @@ -202,12 +202,11 @@ smb2_find_smb_tcon(struct TCP_Server_Info *server, __= u64 ses_id, __u32 tid) =20 return tcon; } =20 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 =3D rqst->rq_iov; struct smb2_hdr *shdr =3D (struct smb2_hdr *)iov[0].iov_base; @@ -438,12 +437,11 @@ generate_smb311signingkey(struct cifs_ses *ses, =20 return generate_smb3signingkey(ses, server, &triplet); } =20 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 =3D rqst->rq_iov; struct smb2_hdr *shdr =3D (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]; =20 if (server->vals->protocol_id <=3D SMB21_PROT_ID) - return smb2_calc_signature(rqst, server, allocate_crypto); + return smb2_calc_signature(rqst, server); =20 rc =3D 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_Serv= er_Info *server) if (!is_binding && !server->session_estab) { strscpy(shdr->Signature, "BSRSPYL"); return 0; } =20 - return smb3_calc_signature(rqst, server, false); + return smb3_calc_signature(rqst, server); } =20 int smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *serve= r) { @@ -558,11 +556,11 @@ smb2_verify_signature(struct smb_rqst *rqst, struct T= CP_Server_Info *server) */ memcpy(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE); =20 memset(shdr->Signature, 0, SMB2_SIGNATURE_SIZE); =20 - rc =3D smb3_calc_signature(rqst, server, true); + rc =3D smb3_calc_signature(rqst, server); =20 if (rc) return rc; =20 if (crypto_memneq(server_response_sig, shdr->Signature, --=20 2.53.0 From nobody Fri Apr 3 07:59:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 77CB831C567; Wed, 18 Feb 2026 21:36:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450618; cv=none; b=OtIgUNr/a75eOfj+tpMboaicUReQR5y71CNiaHznY82bR1B/x0612BxTdrmW2xhqFP893aalMC7mXbE/GqNs4mrromgr27+qSC3YHh5WEbCOVwUoRXkUIRn9d3ch1yFoWElJDD9NWeSy0qWtOktTSS5/gE4T0lhx8ME6Rwhg1us= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450618; c=relaxed/simple; bh=ZYqIlQtwnbFetuVQNGe0mxtg3leOUfnKsQb3/hSGeAY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Sx1Bc51a+NIQilVpvuvNzjDxQZyCsv4V5EU8QltnuCy5yLSH6Ho/58vE9W7vCeRJz4+nYZwBR5o8z9udSQTZBQlE6xPBuu5G+8PCFlEUcOA5AatHp6Fx2GbYwB3+NNo/aaE1wtRx2YJtPNI9+UgxkLi0mAUayyoQodNUf2xpgAI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=g5y8ewUh; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="g5y8ewUh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CA9A2C2BCB6; Wed, 18 Feb 2026 21:36:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771450618; bh=ZYqIlQtwnbFetuVQNGe0mxtg3leOUfnKsQb3/hSGeAY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=g5y8ewUh5ElMc0r4CQ+/6110CWS7emGEDkYxi9P4CD+n9254VvFfIV7kNufM30hwW DYWnPg/aakMF7QE5EbTc764kRKkbqoNWnTXXhvxFBTzDQc3r/S3/LSCEzWj8zxx/cP 42DvyGaBxVtDmkIXQ8Hj4n5zS/mq9DIMeiuDdnbFBo42tE2S3POe8vSu0TsUIz+Ygl aJtEbzrsmsPaEEI6l+BNklX7CFr0/D4CDGtYixL5J/TZmXnTwGe8K3r9fdMXjHuDrg q8gyv0iQVwjgObGvyPC4FVQjRPiLMJFyRBxL4ST0gX37y3v1WI80zhrdWMn4bcfQ7+ lL2Nhl8W9eMzg== From: Eric Biggers To: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , linux-arm-kernel@lists.infradead.org, linux-cifs@vger.kernel.org, linux-wireless@vger.kernel.org, Eric Biggers Subject: [PATCH 12/15] ksmbd: Use AES-CMAC library for SMB3 signature calculation Date: Wed, 18 Feb 2026 13:34:58 -0800 Message-ID: <20260218213501.136844-13-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260218213501.136844-1-ebiggers@kernel.org> References: <20260218213501.136844-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 Acked-by: Namjae Jeon Reviewed-by: Ard Biesheuvel --- 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(-) diff --git a/fs/smb/server/Kconfig b/fs/smb/server/Kconfig index 12594879cb64..eae3728cff54 100644 --- a/fs/smb/server/Kconfig +++ b/fs/smb/server/Kconfig @@ -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 diff --git a/fs/smb/server/auth.c b/fs/smb/server/auth.c index a69e8694605a..05234e5bd16e 100644 --- a/fs/smb/server/auth.c +++ b/fs/smb/server/auth.c @@ -9,12 +9,12 @@ #include #include #include #include #include -#include #include +#include #include #include #include #include #include @@ -488,50 +488,25 @@ void ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, cha= r *key, struct kvec *iov, * @iov: buffer iov array * @n_vec: number of iovecs * @sig: signature value generated for client request packet * */ -int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *i= ov, - int n_vec, char *sig) +void ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *= iov, + int n_vec, char *sig) { - struct ksmbd_crypto_ctx *ctx; - int rc, i; - - ctx =3D ksmbd_crypto_ctx_find_cmacaes(); - if (!ctx) { - ksmbd_debug(AUTH, "could not crypto alloc cmac\n"); - return -ENOMEM; - } - - rc =3D crypto_shash_setkey(CRYPTO_CMACAES_TFM(ctx), - key, - SMB2_CMACAES_SIZE); - if (rc) - goto out; - - rc =3D crypto_shash_init(CRYPTO_CMACAES(ctx)); - if (rc) { - ksmbd_debug(AUTH, "cmaces init error %d\n", rc); - goto out; - } + struct aes_cmac_key cmac_key; + struct aes_cmac_ctx cmac_ctx; + int i; =20 - for (i =3D 0; i < n_vec; i++) { - rc =3D crypto_shash_update(CRYPTO_CMACAES(ctx), - iov[i].iov_base, - iov[i].iov_len); - if (rc) { - ksmbd_debug(AUTH, "cmaces update error %d\n", rc); - goto out; - } - } + /* This cannot fail, since we always pass a valid key length. */ + static_assert(SMB2_CMACAES_SIZE =3D=3D AES_KEYSIZE_128); + aes_cmac_preparekey(&cmac_key, key, SMB2_CMACAES_SIZE); =20 - rc =3D crypto_shash_final(CRYPTO_CMACAES(ctx), sig); - if (rc) - ksmbd_debug(AUTH, "cmaces generation error %d\n", rc); -out: - ksmbd_release_crypto_ctx(ctx); - return rc; + aes_cmac_init(&cmac_ctx, &cmac_key); + for (i =3D 0; i < n_vec; i++) + aes_cmac_update(&cmac_ctx, iov[i].iov_base, iov[i].iov_len); + aes_cmac_final(&cmac_ctx, sig); } =20 struct derivation { struct kvec label; struct kvec context; diff --git a/fs/smb/server/auth.h b/fs/smb/server/auth.h index 6d351d61b0e5..5767aabc63c9 100644 --- a/fs/smb/server/auth.h +++ b/fs/smb/server/auth.h @@ -52,12 +52,12 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_mes= sage *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 *i= ov, - 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, diff --git a/fs/smb/server/crypto_ctx.c b/fs/smb/server/crypto_ctx.c index fe29d186baf6..1cb0ea2042b5 100644 --- a/fs/smb/server/crypto_ctx.c +++ b/fs/smb/server/crypto_ctx.c @@ -26,18 +26,10 @@ static inline void free_aead(struct crypto_aead *aead) { if (aead) crypto_free_aead(aead); } =20 -static void free_shash(struct shash_desc *shash) -{ - if (shash) { - crypto_free_shash(shash->tfm); - kfree(shash); - } -} - static struct crypto_aead *alloc_aead(int id) { struct crypto_aead *tfm =3D NULL; =20 switch (id) { @@ -58,41 +50,14 @@ static struct crypto_aead *alloc_aead(int id) } =20 return tfm; } =20 -static struct shash_desc *alloc_shash_desc(int id) -{ - struct crypto_shash *tfm =3D NULL; - struct shash_desc *shash; - - switch (id) { - case CRYPTO_SHASH_CMACAES: - tfm =3D crypto_alloc_shash("cmac(aes)", 0, 0); - break; - default: - return NULL; - } - - if (IS_ERR(tfm)) - return NULL; - - shash =3D kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm), - KSMBD_DEFAULT_GFP); - if (!shash) - crypto_free_shash(tfm); - else - shash->tfm =3D tfm; - return shash; -} - static void ctx_free(struct ksmbd_crypto_ctx *ctx) { int i; =20 - for (i =3D 0; i < CRYPTO_SHASH_MAX; i++) - free_shash(ctx->desc[i]); for (i =3D 0; i < CRYPTO_AEAD_MAX; i++) free_aead(ctx->ccmaes[i]); kfree(ctx); } =20 @@ -151,33 +116,10 @@ void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx= *ctx) ctx_list.avail_ctx--; spin_unlock(&ctx_list.ctx_lock); ctx_free(ctx); } =20 -static struct ksmbd_crypto_ctx *____crypto_shash_ctx_find(int id) -{ - struct ksmbd_crypto_ctx *ctx; - - if (id >=3D CRYPTO_SHASH_MAX) - return NULL; - - ctx =3D ksmbd_find_crypto_ctx(); - if (ctx->desc[id]) - return ctx; - - ctx->desc[id] =3D alloc_shash_desc(id); - if (ctx->desc[id]) - return ctx; - ksmbd_release_crypto_ctx(ctx); - return NULL; -} - -struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void) -{ - return ____crypto_shash_ctx_find(CRYPTO_SHASH_CMACAES); -} - static struct ksmbd_crypto_ctx *____crypto_aead_ctx_find(int id) { struct ksmbd_crypto_ctx *ctx; =20 if (id >=3D CRYPTO_AEAD_MAX) diff --git a/fs/smb/server/crypto_ctx.h b/fs/smb/server/crypto_ctx.h index b9476ed520ae..02d2893665a4 100644 --- a/fs/smb/server/crypto_ctx.h +++ b/fs/smb/server/crypto_ctx.h @@ -4,18 +4,12 @@ */ =20 #ifndef __CRYPTO_CTX_H__ #define __CRYPTO_CTX_H__ =20 -#include #include =20 -enum { - CRYPTO_SHASH_CMACAES =3D 0, - CRYPTO_SHASH_MAX, -}; - enum { CRYPTO_AEAD_AES_GCM =3D 16, CRYPTO_AEAD_AES_CCM, CRYPTO_AEAD_MAX, }; @@ -26,23 +20,17 @@ enum { }; =20 struct ksmbd_crypto_ctx { struct list_head list; =20 - struct shash_desc *desc[CRYPTO_SHASH_MAX]; struct crypto_aead *ccmaes[CRYPTO_AEAD_MAX]; }; =20 -#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]) =20 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); =20 diff --git a/fs/smb/server/server.c b/fs/smb/server/server.c index c2c074346da1..cc15d9d8468f 100644 --- a/fs/smb/server/server.c +++ b/fs/smb/server/server.c @@ -631,11 +631,10 @@ MODULE_AUTHOR("Namjae Jeon "); 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) diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index 7a88cf3bd29e..02bfe15edcab 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -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 =3D (char *)&hdr->ProtocolId; iov[0].iov_len =3D len; =20 - if (ksmbd_sign_smb3_pdu(conn, signing_key, iov, 1, signature)) - return 0; + ksmbd_sign_smb3_pdu(conn, signing_key, iov, 1, signature); =20 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 =3D &work->iov[work->iov_idx]; } =20 - 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); } =20 /** * smb3_preauth_hash_rsp() - handler for computing preauth hash on response * @work: smb work containing response buffer --=20 2.53.0 From nobody Fri Apr 3 07:59:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 42F0733A6E4; Wed, 18 Feb 2026 21:36:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450619; cv=none; b=jb0dksK+aeKdYF/JJK35MsTZSexLRmHKkU8Onbi7nQH8vvCL9M05cys3NJwDpk7Zo93ks+NeaIdShdOTP+FPzeIqiBScnZ3Kh9WkU/1ykxWSxsP+3sSN8j0g+64CI3tmLM9fIhMa2q9vWzLCMm+7z0dtGJIqcL8op1pLW5uaXj8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450619; c=relaxed/simple; bh=FzLAFnsSHFvGoAfqcNAmnj11tq4ngHpZmu//ht8ZFP8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fhFRdSMHg2TPxe++Jhsvtuy4ZIJQ/wasZLnwok0HhpR9jsI2Lc8xbFWVd/SwSHjH4/UCjHZA49MpSTCfwtFgBf0w1H3Th5DeKiq41ZlRvJ41c5oeS8PnQprKFVgHN7zHJa8PBoKeN6L7YMm96ZLpbmjC63rG5/UfGs9i17UVoIQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YcuPq7zs; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YcuPq7zs" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 882ABC2BCB8; Wed, 18 Feb 2026 21:36:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771450619; bh=FzLAFnsSHFvGoAfqcNAmnj11tq4ngHpZmu//ht8ZFP8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YcuPq7zseL7qa2f5JntY6yXCOgdmRPyVUGvZfB0hrUON8qybXL9pmipnu0l5X8Me9 k50dE0j/zduMMaMjQ3xHZtc7r31YImu4Eljw8cwSdC+Og7b5dRKCvnGGDY0HyHHZZk jC2VkmiNO+hGlCr7Nbvv4AuhWvouKlWuyC/uidmsu26Pq+DxLJgWFJU/u6FkMKR8nq NbX/GFWcA7BJWLPxhMfaCvz25HDK5X+UvkjpCIjGLQetvbmexiS63VUMIIub7GgfZ0 M0boI+WZvNSFMWB0Kza6nGKggQRjp5MoHSuLdog2IJTuaRSFfjHjVtmbM49Dby5+AU Sh5jwxrhDVntw== From: Eric Biggers To: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , linux-arm-kernel@lists.infradead.org, linux-cifs@vger.kernel.org, linux-wireless@vger.kernel.org, Eric Biggers Subject: [PATCH 13/15] Bluetooth: SMP: Use AES-CMAC library API Date: Wed, 18 Feb 2026 13:34:59 -0800 Message-ID: <20260218213501.136844-14-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260218213501.136844-1-ebiggers@kernel.org> References: <20260218213501.136844-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now 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. Signed-off-by: Eric Biggers Reviewed-by: Ard Biesheuvel --- net/bluetooth/Kconfig | 3 +- net/bluetooth/smp.c | 180 +++++++++++++++--------------------------- 2 files changed, 65 insertions(+), 118 deletions(-) diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index 6b2b65a66700..48972f7790ec 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig @@ -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. diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index bf61e8841535..fd2cd7f1b12a 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -20,12 +20,12 @@ SOFTWARE IS DISCLAIMED. */ =20 #include #include +#include #include -#include #include #include =20 #include #include @@ -61,11 +61,11 @@ =20 #define AUTH_REQ_MASK(dev) (hci_dev_test_flag(dev, HCI_SC_ENABLED) ? \ 0x3f : 0x07) #define KEY_DIST_MASK 0x07 =20 -/* Maximum message length that can be passed to aes_cmac */ +/* Maximum message length that can be passed to smp_aes_cmac */ #define CMAC_MSG_MAX 80 =20 enum { SMP_FLAG_TK_VALID, SMP_FLAG_CFM_PENDING, @@ -87,11 +87,10 @@ struct smp_dev { bool local_oob; u8 local_pk[64]; u8 local_rand[16]; bool debug_key; =20 - struct crypto_shash *tfm_cmac; struct crypto_kpp *tfm_ecdh; }; =20 struct smp_chan { struct l2cap_conn *conn; @@ -125,11 +124,10 @@ struct smp_chan { u8 local_pk[64]; u8 remote_pk[64]; u8 dhkey[32]; u8 mackey[16]; =20 - struct crypto_shash *tfm_cmac; struct crypto_kpp *tfm_ecdh; }; =20 /* These debug key values are defined in the SMP section of the core * specification. debug_pk is the public debug key and debug_sk the @@ -164,52 +162,40 @@ static inline void swap_buf(const u8 *src, u8 *dst, s= ize_t len) =20 /* The following functions map to the LE SC SMP crypto functions * AES-CMAC, f4, f5, f6, g2 and h6. */ =20 -static int aes_cmac(struct crypto_shash *tfm, const u8 k[16], const u8 *m, - size_t len, u8 mac[16]) +static int smp_aes_cmac(const u8 k[16], const u8 *m, size_t len, u8 mac[16= ]) { uint8_t tmp[16], mac_msb[16], msg_msb[CMAC_MSG_MAX]; + struct aes_cmac_key key; int err; =20 if (len > CMAC_MSG_MAX) return -EFBIG; =20 - if (!tfm) { - BT_ERR("tfm %p", tfm); - return -EINVAL; - } - /* Swap key and message from LSB to MSB */ swap_buf(k, tmp, 16); swap_buf(m, msg_msb, len); =20 SMP_DBG("msg (len %zu) %*phN", len, (int) len, m); SMP_DBG("key %16phN", k); =20 - err =3D crypto_shash_setkey(tfm, tmp, 16); - if (err) { - BT_ERR("cipher setkey failed: %d", err); + err =3D aes_cmac_preparekey(&key, tmp, 16); + if (WARN_ON_ONCE(err)) /* Should never happen, as 16 is valid keylen */ return err; - } - - err =3D crypto_shash_tfm_digest(tfm, msg_msb, len, mac_msb); - if (err) { - BT_ERR("Hash computation error %d", err); - return err; - } + aes_cmac(&key, msg_msb, len, mac_msb); =20 swap_buf(mac_msb, mac, 16); =20 SMP_DBG("mac %16phN", mac); =20 return 0; } =20 -static int smp_f4(struct crypto_shash *tfm_cmac, const u8 u[32], - const u8 v[32], const u8 x[16], u8 z, u8 res[16]) +static int smp_f4(const u8 u[32], const u8 v[32], const u8 x[16], u8 z, + u8 res[16]) { u8 m[65]; int err; =20 SMP_DBG("u %32phN", u); @@ -218,22 +204,21 @@ static int smp_f4(struct crypto_shash *tfm_cmac, cons= t u8 u[32], =20 m[0] =3D z; memcpy(m + 1, v, 32); memcpy(m + 33, u, 32); =20 - err =3D aes_cmac(tfm_cmac, x, m, sizeof(m), res); + err =3D smp_aes_cmac(x, m, sizeof(m), res); if (err) return err; =20 SMP_DBG("res %16phN", res); =20 return err; } =20 -static int smp_f5(struct crypto_shash *tfm_cmac, const u8 w[32], - const u8 n1[16], const u8 n2[16], const u8 a1[7], - const u8 a2[7], u8 mackey[16], u8 ltk[16]) +static int smp_f5(const u8 w[32], const u8 n1[16], const u8 n2[16], + const u8 a1[7], const u8 a2[7], u8 mackey[16], u8 ltk[16]) { /* The btle, salt and length "magic" values are as defined in * the SMP section of the Bluetooth core specification. In ASCII * the btle value ends up being 'btle'. The salt is just a * random number whereas length is the value 256 in little @@ -248,11 +233,11 @@ static int smp_f5(struct crypto_shash *tfm_cmac, cons= t u8 w[32], =20 SMP_DBG("w %32phN", w); SMP_DBG("n1 %16phN n2 %16phN", n1, n2); SMP_DBG("a1 %7phN a2 %7phN", a1, a2); =20 - err =3D aes_cmac(tfm_cmac, salt, w, 32, t); + err =3D smp_aes_cmac(salt, w, 32, t); if (err) return err; =20 SMP_DBG("t %16phN", t); =20 @@ -263,31 +248,30 @@ static int smp_f5(struct crypto_shash *tfm_cmac, cons= t u8 w[32], memcpy(m + 32, n1, 16); memcpy(m + 48, btle, 4); =20 m[52] =3D 0; /* Counter */ =20 - err =3D aes_cmac(tfm_cmac, t, m, sizeof(m), mackey); + err =3D smp_aes_cmac(t, m, sizeof(m), mackey); if (err) return err; =20 SMP_DBG("mackey %16phN", mackey); =20 m[52] =3D 1; /* Counter */ =20 - err =3D aes_cmac(tfm_cmac, t, m, sizeof(m), ltk); + err =3D smp_aes_cmac(t, m, sizeof(m), ltk); if (err) return err; =20 SMP_DBG("ltk %16phN", ltk); =20 return 0; } =20 -static int smp_f6(struct crypto_shash *tfm_cmac, const u8 w[16], - const u8 n1[16], const u8 n2[16], const u8 r[16], - const u8 io_cap[3], const u8 a1[7], const u8 a2[7], - u8 res[16]) +static int smp_f6(const u8 w[16], const u8 n1[16], const u8 n2[16], + const u8 r[16], const u8 io_cap[3], const u8 a1[7], + const u8 a2[7], u8 res[16]) { u8 m[65]; int err; =20 SMP_DBG("w %16phN", w); @@ -299,21 +283,21 @@ static int smp_f6(struct crypto_shash *tfm_cmac, cons= t u8 w[16], memcpy(m + 14, io_cap, 3); memcpy(m + 17, r, 16); memcpy(m + 33, n2, 16); memcpy(m + 49, n1, 16); =20 - err =3D aes_cmac(tfm_cmac, w, m, sizeof(m), res); + err =3D smp_aes_cmac(w, m, sizeof(m), res); if (err) return err; =20 SMP_DBG("res %16phN", res); =20 return err; } =20 -static int smp_g2(struct crypto_shash *tfm_cmac, const u8 u[32], const u8 = v[32], - const u8 x[16], const u8 y[16], u32 *val) +static int smp_g2(const u8 u[32], const u8 v[32], const u8 x[16], + const u8 y[16], u32 *val) { u8 m[80], tmp[16]; int err; =20 SMP_DBG("u %32phN", u); @@ -322,11 +306,11 @@ static int smp_g2(struct crypto_shash *tfm_cmac, cons= t u8 u[32], const u8 v[32], =20 memcpy(m, y, 16); memcpy(m + 16, v, 32); memcpy(m + 48, u, 32); =20 - err =3D aes_cmac(tfm_cmac, x, m, sizeof(m), tmp); + err =3D smp_aes_cmac(x, m, sizeof(m), tmp); if (err) return err; =20 *val =3D get_unaligned_le32(tmp); *val %=3D 1000000; @@ -334,34 +318,32 @@ static int smp_g2(struct crypto_shash *tfm_cmac, cons= t u8 u[32], const u8 v[32], SMP_DBG("val %06u", *val); =20 return 0; } =20 -static int smp_h6(struct crypto_shash *tfm_cmac, const u8 w[16], - const u8 key_id[4], u8 res[16]) +static int smp_h6(const u8 w[16], const u8 key_id[4], u8 res[16]) { int err; =20 SMP_DBG("w %16phN key_id %4phN", w, key_id); =20 - err =3D aes_cmac(tfm_cmac, w, key_id, 4, res); + err =3D smp_aes_cmac(w, key_id, 4, res); if (err) return err; =20 SMP_DBG("res %16phN", res); =20 return err; } =20 -static int smp_h7(struct crypto_shash *tfm_cmac, const u8 w[16], - const u8 salt[16], u8 res[16]) +static int smp_h7(const u8 w[16], const u8 salt[16], u8 res[16]) { int err; =20 SMP_DBG("w %16phN salt %16phN", w, salt); =20 - err =3D aes_cmac(tfm_cmac, salt, w, 16, res); + err =3D smp_aes_cmac(salt, w, 16, res); if (err) return err; =20 SMP_DBG("res %16phN", res); =20 @@ -572,12 +554,11 @@ int smp_generate_oob(struct hci_dev *hdev, u8 hash[16= ], u8 rand[16]) SMP_DBG("OOB Public Key X: %32phN", smp->local_pk); SMP_DBG("OOB Public Key Y: %32phN", smp->local_pk + 32); =20 get_random_bytes(smp->local_rand, 16); =20 - err =3D smp_f4(smp->tfm_cmac, smp->local_pk, smp->local_pk, - smp->local_rand, 0, hash); + err =3D smp_f4(smp->local_pk, smp->local_pk, smp->local_rand, 0, hash); if (err < 0) return err; =20 memcpy(rand, smp->local_rand, 16); =20 @@ -755,11 +736,10 @@ static void smp_chan_destroy(struct l2cap_conn *conn) =20 kfree_sensitive(smp->csrk); kfree_sensitive(smp->responder_csrk); kfree_sensitive(smp->link_key); =20 - crypto_free_shash(smp->tfm_cmac); crypto_free_kpp(smp->tfm_ecdh); =20 /* Ensure that we don't leave any debug key around if debug key * support hasn't been explicitly enabled. */ @@ -1161,27 +1141,27 @@ static void sc_generate_link_key(struct smp_chan *s= mp) =20 if (test_bit(SMP_FLAG_CT2, &smp->flags)) { /* SALT =3D 0x000000000000000000000000746D7031 */ const u8 salt[16] =3D { 0x31, 0x70, 0x6d, 0x74 }; =20 - if (smp_h7(smp->tfm_cmac, smp->tk, salt, smp->link_key)) { + if (smp_h7(smp->tk, salt, smp->link_key)) { kfree_sensitive(smp->link_key); smp->link_key =3D NULL; return; } } else { /* From core spec. Spells out in ASCII as 'tmp1'. */ const u8 tmp1[4] =3D { 0x31, 0x70, 0x6d, 0x74 }; =20 - if (smp_h6(smp->tfm_cmac, smp->tk, tmp1, smp->link_key)) { + if (smp_h6(smp->tk, tmp1, smp->link_key)) { kfree_sensitive(smp->link_key); smp->link_key =3D NULL; return; } } =20 - if (smp_h6(smp->tfm_cmac, smp->link_key, lebr, smp->link_key)) { + if (smp_h6(smp->link_key, lebr, smp->link_key)) { kfree_sensitive(smp->link_key); smp->link_key =3D NULL; return; } } @@ -1219,21 +1199,21 @@ static void sc_generate_ltk(struct smp_chan *smp) =20 if (test_bit(SMP_FLAG_CT2, &smp->flags)) { /* SALT =3D 0x000000000000000000000000746D7032 */ const u8 salt[16] =3D { 0x32, 0x70, 0x6d, 0x74 }; =20 - if (smp_h7(smp->tfm_cmac, key->val, salt, smp->tk)) + if (smp_h7(key->val, salt, smp->tk)) return; } else { /* From core spec. Spells out in ASCII as 'tmp2'. */ const u8 tmp2[4] =3D { 0x32, 0x70, 0x6d, 0x74 }; =20 - if (smp_h6(smp->tfm_cmac, key->val, tmp2, smp->tk)) + if (smp_h6(key->val, tmp2, smp->tk)) return; } =20 - if (smp_h6(smp->tfm_cmac, smp->tk, brle, smp->tk)) + if (smp_h6(smp->tk, brle, smp->tk)) return; =20 sc_add_ltk(smp); } =20 @@ -1390,20 +1370,14 @@ static struct smp_chan *smp_chan_create(struct l2ca= p_conn *conn) =20 smp =3D kzalloc(sizeof(*smp), GFP_ATOMIC); if (!smp) return NULL; =20 - smp->tfm_cmac =3D crypto_alloc_shash("cmac(aes)", 0, 0); - if (IS_ERR(smp->tfm_cmac)) { - bt_dev_err(hcon->hdev, "Unable to create CMAC crypto context"); - goto zfree_smp; - } - smp->tfm_ecdh =3D crypto_alloc_kpp("ecdh-nist-p256", 0, 0); if (IS_ERR(smp->tfm_ecdh)) { bt_dev_err(hcon->hdev, "Unable to create ECDH crypto context"); - goto free_shash; + goto zfree_smp; } =20 smp->conn =3D conn; chan->data =3D smp; =20 @@ -1413,12 +1387,10 @@ static struct smp_chan *smp_chan_create(struct l2ca= p_conn *conn) =20 hci_conn_hold(hcon); =20 return smp; =20 -free_shash: - crypto_free_shash(smp->tfm_cmac); zfree_smp: kfree_sensitive(smp); return NULL; } =20 @@ -1438,11 +1410,11 @@ static int sc_mackey_and_ltk(struct smp_chan *smp, = u8 mackey[16], u8 ltk[16]) memcpy(a, &hcon->init_addr, 6); memcpy(b, &hcon->resp_addr, 6); a[6] =3D hcon->init_addr_type; b[6] =3D hcon->resp_addr_type; =20 - return smp_f5(smp->tfm_cmac, smp->dhkey, na, nb, a, b, mackey, ltk); + return smp_f5(smp->dhkey, na, nb, a, b, mackey, ltk); } =20 static void sc_dhkey_check(struct smp_chan *smp) { struct hci_conn *hcon =3D smp->conn->hcon; @@ -1471,12 +1443,12 @@ static void sc_dhkey_check(struct smp_chan *smp) put_unaligned_le32(hcon->passkey_notify, r); =20 if (smp->method =3D=3D REQ_OOB) memcpy(r, smp->rr, 16); =20 - smp_f6(smp->tfm_cmac, smp->mackey, smp->prnd, smp->rrnd, r, io_cap, - local_addr, remote_addr, check.e); + smp_f6(smp->mackey, smp->prnd, smp->rrnd, r, io_cap, local_addr, + remote_addr, check.e); =20 smp_send_cmd(smp->conn, SMP_CMD_DHKEY_CHECK, sizeof(check), &check); } =20 static u8 sc_passkey_send_confirm(struct smp_chan *smp) @@ -1489,11 +1461,11 @@ static u8 sc_passkey_send_confirm(struct smp_chan *= smp) r =3D ((hcon->passkey_notify >> smp->passkey_round) & 0x01); r |=3D 0x80; =20 get_random_bytes(smp->prnd, sizeof(smp->prnd)); =20 - if (smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd, r, + if (smp_f4(smp->local_pk, smp->remote_pk, smp->prnd, r, cfm.confirm_val)) return SMP_UNSPECIFIED; =20 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cfm), &cfm); =20 @@ -1514,12 +1486,11 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8= smp_op) switch (smp_op) { case SMP_CMD_PAIRING_RANDOM: r =3D ((hcon->passkey_notify >> smp->passkey_round) & 0x01); r |=3D 0x80; =20 - if (smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk, - smp->rrnd, r, cfm)) + if (smp_f4(smp->remote_pk, smp->local_pk, smp->rrnd, r, cfm)) return SMP_UNSPECIFIED; =20 if (crypto_memneq(smp->pcnf, cfm, 16)) return SMP_CONFIRM_FAILED; =20 @@ -2175,12 +2146,11 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn = *conn, struct sk_buff *skb) return sc_passkey_round(smp, SMP_CMD_PAIRING_RANDOM); =20 if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { u8 cfm[16]; =20 - err =3D smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk, - smp->rrnd, 0, cfm); + err =3D smp_f4(smp->remote_pk, smp->local_pk, smp->rrnd, 0, cfm); if (err) return SMP_UNSPECIFIED; =20 if (crypto_memneq(smp->pcnf, cfm, 16)) return SMP_CONFIRM_FAILED; @@ -2202,11 +2172,11 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn = *conn, struct sk_buff *skb) SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); } return 0; } =20 - err =3D smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey); + err =3D smp_g2(pkax, pkbx, na, nb, &passkey); if (err) return SMP_UNSPECIFIED; =20 /* Always require user confirmation for Just-Works pairing to prevent * impersonation attacks, or in case of a legitimate device that is @@ -2747,12 +2717,12 @@ static int smp_cmd_public_key(struct l2cap_conn *co= nn, struct sk_buff *skb) } =20 memcpy(smp->remote_pk, key, 64); =20 if (test_bit(SMP_FLAG_REMOTE_OOB, &smp->flags)) { - err =3D smp_f4(smp->tfm_cmac, smp->remote_pk, smp->remote_pk, - smp->rr, 0, cfm.confirm_val); + err =3D smp_f4(smp->remote_pk, smp->remote_pk, smp->rr, 0, + cfm.confirm_val); if (err) return SMP_UNSPECIFIED; =20 if (crypto_memneq(cfm.confirm_val, smp->pcnf, 16)) return SMP_CONFIRM_FAILED; @@ -2848,12 +2818,12 @@ static int smp_cmd_public_key(struct l2cap_conn *co= nn, struct sk_buff *skb) * send the confirm value. */ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) return 0; =20 - err =3D smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd, - 0, cfm.confirm_val); + err =3D smp_f4(smp->local_pk, smp->remote_pk, smp->prnd, 0, + cfm.confirm_val); if (err) return SMP_UNSPECIFIED; =20 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cfm), &cfm); SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM); @@ -2896,12 +2866,12 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *c= onn, struct sk_buff *skb) if (smp->method =3D=3D REQ_PASSKEY || smp->method =3D=3D DSP_PASSKEY) put_unaligned_le32(hcon->passkey_notify, r); else if (smp->method =3D=3D REQ_OOB) memcpy(r, smp->lr, 16); =20 - err =3D smp_f6(smp->tfm_cmac, smp->mackey, smp->rrnd, smp->prnd, r, - io_cap, remote_addr, local_addr, e); + err =3D smp_f6(smp->mackey, smp->rrnd, smp->prnd, r, io_cap, remote_addr, + local_addr, e); if (err) return SMP_UNSPECIFIED; =20 if (crypto_memneq(check->e, e, 16)) return SMP_DHKEY_CHECK_FAILED; @@ -3283,11 +3253,10 @@ static const struct l2cap_ops smp_root_chan_ops =3D= { =20 static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) { struct l2cap_chan *chan; struct smp_dev *smp; - struct crypto_shash *tfm_cmac; struct crypto_kpp *tfm_ecdh; =20 if (cid =3D=3D L2CAP_CID_SMP_BREDR) { smp =3D NULL; goto create_chan; @@ -3295,34 +3264,24 @@ static struct l2cap_chan *smp_add_cid(struct hci_de= v *hdev, u16 cid) =20 smp =3D kzalloc(sizeof(*smp), GFP_KERNEL); if (!smp) return ERR_PTR(-ENOMEM); =20 - tfm_cmac =3D crypto_alloc_shash("cmac(aes)", 0, 0); - if (IS_ERR(tfm_cmac)) { - bt_dev_err(hdev, "Unable to create CMAC crypto context"); - kfree_sensitive(smp); - return ERR_CAST(tfm_cmac); - } - tfm_ecdh =3D crypto_alloc_kpp("ecdh-nist-p256", 0, 0); if (IS_ERR(tfm_ecdh)) { bt_dev_err(hdev, "Unable to create ECDH crypto context"); - crypto_free_shash(tfm_cmac); kfree_sensitive(smp); return ERR_CAST(tfm_ecdh); } =20 smp->local_oob =3D false; - smp->tfm_cmac =3D tfm_cmac; smp->tfm_ecdh =3D tfm_ecdh; =20 create_chan: chan =3D l2cap_chan_create(); if (!chan) { if (smp) { - crypto_free_shash(smp->tfm_cmac); crypto_free_kpp(smp->tfm_ecdh); kfree_sensitive(smp); } return ERR_PTR(-ENOMEM); } @@ -3365,11 +3324,10 @@ static void smp_del_chan(struct l2cap_chan *chan) BT_DBG("chan %p", chan); =20 smp =3D chan->data; if (smp) { chan->data =3D NULL; - crypto_free_shash(smp->tfm_cmac); crypto_free_kpp(smp->tfm_ecdh); kfree_sensitive(smp); } =20 l2cap_chan_put(chan); @@ -3562,11 +3520,11 @@ static int __init test_s1(void) return -EINVAL; =20 return 0; } =20 -static int __init test_f4(struct crypto_shash *tfm_cmac) +static int __init test_f4(void) { const u8 u[32] =3D { 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, 0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef, 0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e, @@ -3584,21 +3542,21 @@ static int __init test_f4(struct crypto_shash *tfm_= cmac) 0x2d, 0x87, 0x74, 0xa9, 0xbe, 0xa1, 0xed, 0xf1, 0x1c, 0xbd, 0xa9, 0x07, 0xf1, 0x16, 0xc9, 0xf2 }; u8 res[16]; int err; =20 - err =3D smp_f4(tfm_cmac, u, v, x, z, res); + err =3D smp_f4(u, v, x, z, res); if (err) return err; =20 if (crypto_memneq(res, exp, 16)) return -EINVAL; =20 return 0; } =20 -static int __init test_f5(struct crypto_shash *tfm_cmac) +static int __init test_f5(void) { const u8 w[32] =3D { 0x98, 0xa6, 0xbf, 0x73, 0xf3, 0x34, 0x8d, 0x86, 0xf1, 0x66, 0xf8, 0xb4, 0x13, 0x6b, 0x79, 0x99, 0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34, @@ -3618,11 +3576,11 @@ static int __init test_f5(struct crypto_shash *tfm_= cmac) 0x20, 0x6e, 0x63, 0xce, 0x20, 0x6a, 0x3f, 0xfd, 0x02, 0x4a, 0x08, 0xa1, 0x76, 0xf1, 0x65, 0x29 }; u8 mackey[16], ltk[16]; int err; =20 - err =3D smp_f5(tfm_cmac, w, n1, n2, a1, a2, mackey, ltk); + err =3D smp_f5(w, n1, n2, a1, a2, mackey, ltk); if (err) return err; =20 if (crypto_memneq(mackey, exp_mackey, 16)) return -EINVAL; @@ -3631,11 +3589,11 @@ static int __init test_f5(struct crypto_shash *tfm_= cmac) return -EINVAL; =20 return 0; } =20 -static int __init test_f6(struct crypto_shash *tfm_cmac) +static int __init test_f6(void) { const u8 w[16] =3D { 0x20, 0x6e, 0x63, 0xce, 0x20, 0x6a, 0x3f, 0xfd, 0x02, 0x4a, 0x08, 0xa1, 0x76, 0xf1, 0x65, 0x29 }; const u8 n1[16] =3D { @@ -3654,21 +3612,21 @@ static int __init test_f6(struct crypto_shash *tfm_= cmac) 0x61, 0x8f, 0x95, 0xda, 0x09, 0x0b, 0x6c, 0xd2, 0xc5, 0xe8, 0xd0, 0x9c, 0x98, 0x73, 0xc4, 0xe3 }; u8 res[16]; int err; =20 - err =3D smp_f6(tfm_cmac, w, n1, n2, r, io_cap, a1, a2, res); + err =3D smp_f6(w, n1, n2, r, io_cap, a1, a2, res); if (err) return err; =20 if (crypto_memneq(res, exp, 16)) return -EINVAL; =20 return 0; } =20 -static int __init test_g2(struct crypto_shash *tfm_cmac) +static int __init test_g2(void) { const u8 u[32] =3D { 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, 0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef, 0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e, @@ -3686,21 +3644,21 @@ static int __init test_g2(struct crypto_shash *tfm_= cmac) 0x6e, 0x5f, 0xa7, 0x25, 0xcc, 0xe7, 0xe8, 0xa6 }; const u32 exp_val =3D 0x2f9ed5ba % 1000000; u32 val; int err; =20 - err =3D smp_g2(tfm_cmac, u, v, x, y, &val); + err =3D smp_g2(u, v, x, y, &val); if (err) return err; =20 if (val !=3D exp_val) return -EINVAL; =20 return 0; } =20 -static int __init test_h6(struct crypto_shash *tfm_cmac) +static int __init test_h6(void) { const u8 w[16] =3D { 0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34, 0x05, 0xad, 0xc8, 0x57, 0xa3, 0x34, 0x02, 0xec }; const u8 key_id[4] =3D { 0x72, 0x62, 0x65, 0x6c }; @@ -3708,11 +3666,11 @@ static int __init test_h6(struct crypto_shash *tfm_= cmac) 0x99, 0x63, 0xb1, 0x80, 0xe2, 0xa9, 0xd3, 0xe8, 0x1c, 0xc9, 0x6d, 0xe7, 0x02, 0xe1, 0x9a, 0x2d }; u8 res[16]; int err; =20 - err =3D smp_h6(tfm_cmac, w, key_id, res); + err =3D smp_h6(w, key_id, res); if (err) return err; =20 if (crypto_memneq(res, exp, 16)) return -EINVAL; @@ -3733,12 +3691,11 @@ static const struct file_operations test_smp_fops = =3D { .open =3D simple_open, .read =3D test_smp_read, .llseek =3D default_llseek, }; =20 -static int __init run_selftests(struct crypto_shash *tfm_cmac, - struct crypto_kpp *tfm_ecdh) +static int __init run_selftests(struct crypto_kpp *tfm_ecdh) { ktime_t calltime, delta, rettime; unsigned long long duration; int err; =20 @@ -3766,35 +3723,35 @@ static int __init run_selftests(struct crypto_shash= *tfm_cmac, if (err) { BT_ERR("smp_s1 test failed"); goto done; } =20 - err =3D test_f4(tfm_cmac); + err =3D test_f4(); if (err) { BT_ERR("smp_f4 test failed"); goto done; } =20 - err =3D test_f5(tfm_cmac); + err =3D test_f5(); if (err) { BT_ERR("smp_f5 test failed"); goto done; } =20 - err =3D test_f6(tfm_cmac); + err =3D test_f6(); if (err) { BT_ERR("smp_f6 test failed"); goto done; } =20 - err =3D test_g2(tfm_cmac); + err =3D test_g2(); if (err) { BT_ERR("smp_g2 test failed"); goto done; } =20 - err =3D test_h6(tfm_cmac); + err =3D test_h6(); if (err) { BT_ERR("smp_h6 test failed"); goto done; } =20 @@ -3817,30 +3774,21 @@ static int __init run_selftests(struct crypto_shash= *tfm_cmac, return err; } =20 int __init bt_selftest_smp(void) { - struct crypto_shash *tfm_cmac; struct crypto_kpp *tfm_ecdh; int err; =20 - tfm_cmac =3D crypto_alloc_shash("cmac(aes)", 0, 0); - if (IS_ERR(tfm_cmac)) { - BT_ERR("Unable to create CMAC crypto context"); - return PTR_ERR(tfm_cmac); - } - tfm_ecdh =3D crypto_alloc_kpp("ecdh-nist-p256", 0, 0); if (IS_ERR(tfm_ecdh)) { BT_ERR("Unable to create ECDH crypto context"); - crypto_free_shash(tfm_cmac); return PTR_ERR(tfm_ecdh); } =20 - err =3D run_selftests(tfm_cmac, tfm_ecdh); + err =3D run_selftests(tfm_ecdh); =20 - crypto_free_shash(tfm_cmac); crypto_free_kpp(tfm_ecdh); =20 return err; } =20 --=20 2.53.0 From nobody Fri Apr 3 07:59:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E73A532E68D; Wed, 18 Feb 2026 21:36:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450620; cv=none; b=lVi20MsJQLwhQ9XMuWbd+/2ie0rm5QZM/ci3HnQOVeeMQ+ksqiiT9TDIpF+m0UmGjilZWR/NUnOBYBILn7Z+Jv+8zt9uyKbyvgUCtn50lO1bTgTenYjtOwFQ5hHe4YorWuMdFWyH7dfp2wNdWAWGv1EN559Y99Qgwx+cE9rs+7o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450620; c=relaxed/simple; bh=DnjzfD8UUtPv4slYL2pB1p87UHI2Kx6DNAW3W2bIPLI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZkFoiHQb7Zg6FYx44rAQYi/02Vr7fqphBLSxwWSDXzFTF01AcxcfMM4HFnL0L3TfR1NLEVTxizhacIYI34UpawVj2Z8eom6108wv+PKX/IwT3rta6nlJQ68qCzziROSk4h9dL/+cHl/KbaFgqzNPBy6/75BG9tayuep+dhFillM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=d9nC0y+8; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="d9nC0y+8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3C6DFC2BCB6; Wed, 18 Feb 2026 21:36:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771450619; bh=DnjzfD8UUtPv4slYL2pB1p87UHI2Kx6DNAW3W2bIPLI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=d9nC0y+8/G9755xCvbvHN7DAKjWuIifVrEaCp0dH8JCWSY/8/37cCz4/JnQuj7feq 7Y7XXMYb8fsKXNrT6/WTFWzZj2+yxF5NkANQMz+oVnWsBRlGJaurnowsom4L2nZ+Nm Ym4oX9qP9/zITYlEI9YfMoGTwcAAe8GLr92c44TfjXeZspAAtgr7UpZoviaX5VXx+l hTHXNg25Lu3VkKGAkTYbR2QA0UKgwMjm6/st6FQbn6gjOr0pWObiKLPnAoyjbmKBce PfD5qahcQ+51pdMH8lVmK6F/lPHgr1QIKjnd4hk3XKjR8ng+EBDqxyIH6+mRCOeBrG 8eVL99dt8et3Q== From: Eric Biggers To: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , linux-arm-kernel@lists.infradead.org, linux-cifs@vger.kernel.org, linux-wireless@vger.kernel.org, Eric Biggers Subject: [PATCH 14/15] wifi: mac80211: Use AES-CMAC library in ieee80211_aes_cmac() Date: Wed, 18 Feb 2026 13:35:00 -0800 Message-ID: <20260218213501.136844-15-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260218213501.136844-1-ebiggers@kernel.org> References: <20260218213501.136844-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. - 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. Signed-off-by: Eric Biggers Acked-by: Johannes Berg Reviewed-by: Ard Biesheuvel --- 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(-) diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index cf0f7780fb10..0afbe4f4f976 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -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 diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c index 0827965455dc..55b674ad7d7a 100644 --- a/net/mac80211/aes_cmac.c +++ b/net/mac80211/aes_cmac.c @@ -5,80 +5,39 @@ * Copyright (C) 2020 Intel Corporation */ =20 #include #include -#include #include #include -#include +#include =20 #include #include "key.h" #include "aes_cmac.h" =20 #define AAD_LEN 20 =20 static const u8 zero[IEEE80211_CMAC_256_MIC_LEN]; =20 -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(const struct aes_cmac_key *key, const u8 *aad, + const u8 *data, size_t data_len, u8 *mic, + unsigned int mic_len) { - int err; - SHASH_DESC_ON_STACK(desc, tfm); + struct aes_cmac_ctx ctx; u8 out[AES_BLOCK_SIZE]; const __le16 *fc; =20 - desc->tfm =3D tfm; - - err =3D crypto_shash_init(desc); - if (err) - return err; - err =3D crypto_shash_update(desc, aad, AAD_LEN); - if (err) - return err; + aes_cmac_init(&ctx, key); + aes_cmac_update(&ctx, aad, AAD_LEN); fc =3D (const __le16 *)aad; if (ieee80211_is_beacon(*fc)) { /* mask Timestamp field to zero */ - err =3D crypto_shash_update(desc, zero, 8); - if (err) - return err; - err =3D crypto_shash_update(desc, data + 8, - data_len - 8 - mic_len); - if (err) - return err; + aes_cmac_update(&ctx, zero, 8); + aes_cmac_update(&ctx, data + 8, data_len - 8 - mic_len); } else { - err =3D crypto_shash_update(desc, data, data_len - mic_len); - if (err) - return err; + aes_cmac_update(&ctx, data, data_len - mic_len); } - err =3D crypto_shash_finup(desc, zero, mic_len, out); - if (err) - return err; + aes_cmac_update(&ctx, zero, mic_len); + aes_cmac_final(&ctx, out); memcpy(mic, out, mic_len); - - return 0; -} - -struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[], - size_t key_len) -{ - struct crypto_shash *tfm; - - tfm =3D crypto_alloc_shash("cmac(aes)", 0, 0); - if (!IS_ERR(tfm)) { - int err =3D crypto_shash_setkey(tfm, key, key_len); - - if (err) { - crypto_free_shash(tfm); - return ERR_PTR(err); - } - } - - return tfm; -} - -void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm) -{ - crypto_free_shash(tfm); } diff --git a/net/mac80211/aes_cmac.h b/net/mac80211/aes_cmac.h index 5f971a8298cb..c7a6df47b327 100644 --- a/net/mac80211/aes_cmac.h +++ b/net/mac80211/aes_cmac.h @@ -4,16 +4,12 @@ */ =20 #ifndef AES_CMAC_H #define AES_CMAC_H =20 -#include -#include +#include =20 -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); =20 #endif /* AES_CMAC_H */ diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 04c8809173d7..4b8965633df3 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -688,14 +688,13 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_l= en, 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 =3D - ieee80211_aes_cmac_key_setup(key_data, key_len); - if (IS_ERR(key->u.aes_cmac.tfm)) { - err =3D PTR_ERR(key->u.aes_cmac.tfm); + err =3D 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 ieee8021= 1_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: diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 1fa0f4f78962..826e4e9387c5 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -10,10 +10,11 @@ =20 #include #include #include #include +#include #include #include =20 #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]; diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index fdf98c21d32c..59324b367bdd 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -870,15 +870,12 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx= _data *tx, if (info->control.hw_key) return TX_CONTINUE; =20 bip_aad(skb, aad); =20 - 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; } =20 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, } =20 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; } } --=20 2.53.0 From nobody Fri Apr 3 07:59:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3A36D3375D5; Wed, 18 Feb 2026 21:37:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450621; cv=none; b=B0OziwgOG8oIf1jF2T5GxCA8AVXCKkZcVRR3MxDwahbxsu4vpenDFAakexYvfUCf299cdNSE+u0sQvrbmStxTqRuxBFOIkYRjDSkqPDZG8WA5h3UzJhhPcd2cFFl7iiXVToiN5sxxaPvFYRCM6VpFkRwjJLHmYBppz2KtCylBLM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771450621; c=relaxed/simple; bh=MukATPOpIzjauahsnyw5/LgkOoeHj4ze2Fz2UAEw0rw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bCARcHjaAa9I7psvg9/omScekM0LR5tdRQGf+BgCxPiPrgCLtJpJiMMOUEw10fY0+mxPBewE/BdQVPR1s2Jfy7tvoH0+5ZDX0HqrrdqfrOa+oD8EgOCbA/YZHim90f/ZSjp2tXILWiF5JxQPFJArATF1mnH9i4uguP2GDy1T9/k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=S7cvUUs2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="S7cvUUs2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F2924C2BCB4; Wed, 18 Feb 2026 21:36:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771450620; bh=MukATPOpIzjauahsnyw5/LgkOoeHj4ze2Fz2UAEw0rw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=S7cvUUs2MbPHShNzMReODOXXx0055P+B5i6wUSiG6e9WEN6m6eioCUpXWfIz4SPHd o2Jp/TgF7O6k4rs3A3NJzK32Pj7x0O9bWs75sgyw05p+8QPHl6J3iXMMcY2J/BSv03 pBovcGwo2XyB8w7WI+rZziQRib7Q7PXdefsaQDZORQah7mhr+W2KC+iVMfIJnwzjTn Wv2DoQtvp6FRV+kUAeWFOybO9Ojm9HEgHVDla4zh2fQOJnhZTDqYNKySvsx6PNr4D4 lDUbu1wGNmXaGuU4e3y2JDb25S/GbeOLp7/b1VANEkR53N572/mF3aKaK96nxZXrDo gYvDPt8fT+elQ== From: Eric Biggers To: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel , "Jason A . Donenfeld" , Herbert Xu , linux-arm-kernel@lists.infradead.org, linux-cifs@vger.kernel.org, linux-wireless@vger.kernel.org, Eric Biggers Subject: [PATCH 15/15] wifi: mac80211: Use AES-CMAC library in aes_s2v() Date: Wed, 18 Feb 2026 13:35:01 -0800 Message-ID: <20260218213501.136844-16-ebiggers@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260218213501.136844-1-ebiggers@kernel.org> References: <20260218213501.136844-1-ebiggers@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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(), 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'. Signed-off-by: Eric Biggers Acked-by: Johannes Berg Reviewed-by: Ard Biesheuvel --- net/mac80211/Kconfig | 1 - net/mac80211/fils_aead.c | 48 ++++++++++++++-------------------------- 2 files changed, 17 insertions(+), 32 deletions(-) diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 0afbe4f4f976..d6bc295e23a1 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -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. =20 diff --git a/net/mac80211/fils_aead.c b/net/mac80211/fils_aead.c index 912c46f74d24..d2f4a17eab99 100644 --- a/net/mac80211/fils_aead.c +++ b/net/mac80211/fils_aead.c @@ -2,17 +2,15 @@ /* * FILS AEAD for (Re)Association Request/Response frames * Copyright 2016, Qualcomm Atheros, Inc. */ =20 -#include -#include +#include #include #include =20 #include "ieee80211_i.h" -#include "aes_cmac.h" #include "fils_aead.h" =20 static void gf_mulx(u8 *pad) { u64 a =3D get_unaligned_be64(pad); @@ -20,58 +18,63 @@ static void gf_mulx(u8 *pad) =20 put_unaligned_be64((a << 1) | (b >> 63), pad); put_unaligned_be64((b << 1) ^ ((a >> 63) ? 0x87 : 0), pad + 8); } =20 -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] =3D {}; - SHASH_DESC_ON_STACK(desc, tfm); + struct aes_cmac_key key; + struct aes_cmac_ctx ctx; size_t i; + int res; =20 - desc->tfm =3D tfm; + res =3D aes_cmac_preparekey(&key, in_key, key_len); + if (res) + return res; =20 /* D =3D AES-CMAC(K, ) */ - crypto_shash_digest(desc, tmp, AES_BLOCK_SIZE, d); + aes_cmac(&key, tmp, AES_BLOCK_SIZE, d); =20 for (i =3D 0; i < num_elem - 1; i++) { /* D =3D dbl(D) xor AES_CMAC(K, Si) */ gf_mulx(d); /* dbl */ - crypto_shash_digest(desc, addr[i], len[i], tmp); + aes_cmac(&key, addr[i], len[i], tmp); crypto_xor(d, tmp, AES_BLOCK_SIZE); } =20 - crypto_shash_init(desc); + aes_cmac_init(&ctx, &key); =20 if (len[i] >=3D AES_BLOCK_SIZE) { /* len(Sn) >=3D 128 */ /* T =3D Sn xorend D */ - crypto_shash_update(desc, addr[i], len[i] - AES_BLOCK_SIZE); + aes_cmac_update(&ctx, addr[i], len[i] - AES_BLOCK_SIZE); crypto_xor(d, addr[i] + len[i] - AES_BLOCK_SIZE, AES_BLOCK_SIZE); } else { /* len(Sn) < 128 */ /* T =3D dbl(D) xor pad(Sn) */ gf_mulx(d); /* dbl */ crypto_xor(d, addr[i], len[i]); d[len[i]] ^=3D 0x80; } /* V =3D AES-CMAC(K, T) */ - crypto_shash_finup(desc, d, AES_BLOCK_SIZE, v); + aes_cmac_update(&ctx, d, AES_BLOCK_SIZE); + aes_cmac_final(&ctx, v); =20 + memzero_explicit(&key, sizeof(key)); return 0; } =20 /* Note: addr[] and len[] needs to have one extra slot at the end. */ static int aes_siv_encrypt(const u8 *key, size_t key_len, const u8 *plain, size_t plain_len, size_t num_elem, const u8 *addr[], size_t len[], u8 *out) { u8 v[AES_BLOCK_SIZE]; - struct crypto_shash *tfm; struct crypto_skcipher *tfm2; struct skcipher_request *req; int res; struct scatterlist src[1], dst[1]; u8 *tmp; @@ -81,19 +84,11 @@ static int aes_siv_encrypt(const u8 *key, size_t key_le= n, addr[num_elem] =3D plain; len[num_elem] =3D plain_len; num_elem++; =20 /* S2V */ - - tfm =3D crypto_alloc_shash("cmac(aes)", 0, 0); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - /* K1 for S2V */ - res =3D crypto_shash_setkey(tfm, key, key_len); - if (!res) - res =3D aes_s2v(tfm, num_elem, addr, len, v); - crypto_free_shash(tfm); + res =3D aes_s2v(key /* K1 */, key_len, num_elem, addr, len, v); if (res) return res; =20 /* Use a temporary buffer of the plaintext to handle need for * overwriting this during AES-CTR. @@ -144,11 +139,10 @@ static int aes_siv_encrypt(const u8 *key, size_t key_= len, static int aes_siv_decrypt(const u8 *key, size_t key_len, const u8 *iv_crypt, size_t iv_c_len, size_t num_elem, const u8 *addr[], size_t len[], u8 *out) { - struct crypto_shash *tfm; struct crypto_skcipher *tfm2; struct skcipher_request *req; struct scatterlist src[1], dst[1]; size_t crypt_len; int res; @@ -196,19 +190,11 @@ static int aes_siv_decrypt(const u8 *key, size_t key_= len, crypto_free_skcipher(tfm2); if (res) return res; =20 /* S2V */ - - tfm =3D crypto_alloc_shash("cmac(aes)", 0, 0); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - /* K1 for S2V */ - res =3D crypto_shash_setkey(tfm, key, key_len); - if (!res) - res =3D aes_s2v(tfm, num_elem, addr, len, check); - crypto_free_shash(tfm); + res =3D aes_s2v(key /* K1 */, key_len, num_elem, addr, len, check); if (res) return res; if (memcmp(check, frame_iv, AES_BLOCK_SIZE) !=3D 0) return -EINVAL; return 0; --=20 2.53.0