{"id":2197947,"url":"http://patchwork.ozlabs.org/api/1.0/patches/2197947/?format=json","project":{"id":12,"url":"http://patchwork.ozlabs.org/api/1.0/projects/12/?format=json","name":"Linux CIFS Client","link_name":"linux-cifs-client","list_id":"linux-cifs.vger.kernel.org","list_email":"linux-cifs@vger.kernel.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20260218213501.136844-2-ebiggers@kernel.org>","date":"2026-02-18T21:34:47","name":"[01/15] lib/crypto: aes: Add support for CBC-based MACs","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"3ca82b1e9848c2f4216c2f9bbad24546e557dcb4","submitter":{"id":74690,"url":"http://patchwork.ozlabs.org/api/1.0/people/74690/?format=json","name":"Eric Biggers","email":"ebiggers@kernel.org"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/linux-cifs-client/patch/20260218213501.136844-2-ebiggers@kernel.org/mbox/","series":[{"id":492621,"url":"http://patchwork.ozlabs.org/api/1.0/series/492621/?format=json","date":"2026-02-18T21:34:46","name":"AES-CMAC library","version":1,"mbox":"http://patchwork.ozlabs.org/series/492621/mbox/"}],"check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2197947/checks/","tags":{},"headers":{"Return-Path":"\n <linux-cifs+bounces-9442-incoming=patchwork.ozlabs.org@vger.kernel.org>","X-Original-To":["incoming@patchwork.ozlabs.org","linux-cifs@vger.kernel.org"],"Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=ZNY7X+UH;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c0a:e001:db::12fc:5321; helo=sea.lore.kernel.org;\n envelope-from=linux-cifs+bounces-9442-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)","smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=\"ZNY7X+UH\"","smtp.subspace.kernel.org;\n arc=none smtp.client-ip=10.30.226.201"],"Received":["from sea.lore.kernel.org (sea.lore.kernel.org\n [IPv6:2600:3c0a:e001:db::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fGVGR5yt0z1xvS\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 19 Feb 2026 08:37:19 +1100 (AEDT)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id 5AE503034DC3\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 18 Feb 2026 21:36:53 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id B7C5F2F363B;\n\tWed, 18 Feb 2026 21:36:50 +0000 (UTC)","from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org\n [10.30.226.201])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 94C062F1FF1;\n\tWed, 18 Feb 2026 21:36:50 +0000 (UTC)","by smtp.kernel.org (Postfix) with ESMTPSA id 07080C116D0;\n\tWed, 18 Feb 2026 21:36:49 +0000 (UTC)"],"ARC-Seal":"i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1771450610; cv=none;\n b=CZtkrZAR7qmYOeDxGmxoyiTtPPC8bqHWXt66Ke1nKtKqiAeopWk/y+Yfxl2eVkHd/2G2wbcu1AvsLlSQdHeHiPKc5K9u5LEXg1OtDN1F8Vz5QxCAssQ39WX6MOiCrKBSnNs8ixga82tYy5z16Yn+6kJrqaBuPKt/qax31EnGSPY=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1771450610; c=relaxed/simple;\n\tbh=B6d275uZRRFPEx+cNjtBQltncVwySv2uEdCFV1CD0Jo=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=uJi/9gAYyyDFTZhtWXbpYZ8aU97ihhWBsvtvWu8evRfffFe4llb3Mv1pWfLeJbbQm+WrMGPkcCaeuwFKflORI5vBlniwJPkDINzMk4TCHOkXP9vmDAS4EvBVCLf/eMxk/6knnN92k/HUQR3aIr4A478Y5beMD/YJd6GgpubRKGk=","ARC-Authentication-Results":"i=1; smtp.subspace.kernel.org;\n dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=ZNY7X+UH; arc=none smtp.client-ip=10.30.226.201","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;\n\ts=k20201202; t=1771450610;\n\tbh=B6d275uZRRFPEx+cNjtBQltncVwySv2uEdCFV1CD0Jo=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=ZNY7X+UHZkxBL5KtYlX57pYHzFDROFqV80iskbBKwTzWrLT1AQjOgcQ4kxC1lVn4G\n\t 1RvOmbJfTuasBuvEAhhbS1ZwONy+UmkxRUyp8hM/8DMwyjFbPUhhjKQJRfF1JWIdob\n\t Wx1lDKy1LlFPPog6CqVyk0zjnmxrBgRr/FRAPYWG4R2gnooPqZPZRqFt5ZCBIsg5EU\n\t wiKS4C+QDx9fxk7FvDTLNojs9oyaHBE4sJB0dd5RJKcjEgIVsVrl5uVi5m5jnRfRGJ\n\t Ed4GJ9NLvBqh5HnRdGIGgpZyc066hq2i5R58iYsA9uc4j+Mejh55RL4loy+sCmH3YS\n\t 9QdRnuw8iJr9w==","From":"Eric Biggers <ebiggers@kernel.org>","To":"linux-crypto@vger.kernel.org","Cc":"linux-kernel@vger.kernel.org,\n\tArd Biesheuvel <ardb@kernel.org>,\n\t\"Jason A . Donenfeld\" <Jason@zx2c4.com>,\n\tHerbert Xu <herbert@gondor.apana.org.au>,\n\tlinux-arm-kernel@lists.infradead.org,\n\tlinux-cifs@vger.kernel.org,\n\tlinux-wireless@vger.kernel.org,\n\tEric Biggers <ebiggers@kernel.org>","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-cifs@vger.kernel.org","List-Id":"<linux-cifs.vger.kernel.org>","List-Subscribe":"<mailto:linux-cifs+subscribe@vger.kernel.org>","List-Unsubscribe":"<mailto:linux-cifs+unsubscribe@vger.kernel.org>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit"},"content":"Add support for CBC-based MACs to the AES library, specifically\nAES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC.\n\nOf these three algorithms, AES-CMAC is the most modern and the most\ncommonly used.  Use cases for the AES-CMAC library include the kernel's\nSMB client and server, and the bluetooth and mac80211 drivers.\n\nSupport for AES-XCBC-MAC and AES-CBC-MAC is included so that there will\nbe no performance regression in the \"xcbc(aes)\" and \"ccm(aes)\" support\nin the traditional crypto API once the arm64-optimized code is migrated\ninto the library.  AES-XCBC-MAC is given its own key preparation\nfunction but is otherwise identical to AES-CMAC and just reuses the\nAES-CMAC structs and functions.\n\nThe implementation automatically uses the optimized AES key expansion\nand single block en/decryption functions.  It also allows architectures\nto provide an optimized implementation of aes_cbcmac_blocks(), which\nallows the existing arm64-optimized code for these modes to be used.\n\nJust put the code for these modes directly in the libaes module rather\nthan in a separate module.  This is simpler, it makes it easier to share\ncode between AES modes, and it increases the amount of inlining that is\npossible.  (Indeed, for these reasons, most of the\narchitecture-optimized AES code already provides multiple modes per\nmodule.  x86 for example has only a single aesni-intel module.  So to a\nlarge extent, this design choice just reflects the status quo.)\n\nHowever, since there are a lot of AES modes, there's still some value in\nomitting modes that are not needed at all in a given kernel.  Therefore,\nmake these modes an optional feature of libaes, controlled by\nCONFIG_CRYPTO_LIB_AES_CBC_MACS.  This seems like a good middle ground.\n\nSigned-off-by: Eric Biggers <ebiggers@kernel.org>\n---\n include/crypto/aes-cbc-macs.h | 154 ++++++++++++++++++++++++++\n lib/crypto/Kconfig            |  10 ++\n lib/crypto/aes.c              | 198 ++++++++++++++++++++++++++++++++++\n 3 files changed, 362 insertions(+)\n create mode 100644 include/crypto/aes-cbc-macs.h","diff":"diff --git a/include/crypto/aes-cbc-macs.h b/include/crypto/aes-cbc-macs.h\nnew file mode 100644\nindex 000000000000..e61df108b926\n--- /dev/null\n+++ b/include/crypto/aes-cbc-macs.h\n@@ -0,0 +1,154 @@\n+/* SPDX-License-Identifier: GPL-2.0 */\n+/*\n+ * Support for AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC\n+ *\n+ * Copyright 2026 Google LLC\n+ */\n+#ifndef _CRYPTO_AES_CBC_MACS_H\n+#define _CRYPTO_AES_CBC_MACS_H\n+\n+#include <crypto/aes.h>\n+\n+/**\n+ * struct aes_cmac_key - Prepared key for AES-CMAC or AES-XCBC-MAC\n+ * @aes: The AES key for cipher block chaining\n+ * @k_final: Finalization subkeys for the final block.\n+ *\t     k_final[0] (CMAC K1, XCBC-MAC K2) is used if it's a full block.\n+ *\t     k_final[1] (CMAC K2, XCBC-MAC K3) is used if it's a partial block.\n+ */\n+struct aes_cmac_key {\n+\tstruct aes_enckey aes;\n+\tunion {\n+\t\tu8 b[AES_BLOCK_SIZE];\n+\t\t__be64 w[2];\n+\t} k_final[2];\n+};\n+\n+/**\n+ * struct aes_cmac_ctx - Context for computing an AES-CMAC or AES-XCBC-MAC value\n+ * @key: Pointer to the key struct.  A pointer is used rather than a copy of the\n+ *\t struct, since the key struct size may be large.  It is assumed that the\n+ *\t key lives at least as long as the context.\n+ * @partial_len: Number of bytes that have been XOR'ed into @h since the last\n+ *\t\t AES encryption.  This is 0 if no data has been processed yet,\n+ *\t\t or between 1 and AES_BLOCK_SIZE inclusive otherwise.\n+ * @h: The current chaining value\n+ */\n+struct aes_cmac_ctx {\n+\tconst struct aes_cmac_key *key;\n+\tsize_t partial_len;\n+\tu8 h[AES_BLOCK_SIZE];\n+};\n+\n+/**\n+ * aes_cmac_preparekey() - Prepare a key for AES-CMAC\n+ * @key: (output) The key struct to initialize\n+ * @in_key: The raw AES key\n+ * @key_len: Length of the raw key in bytes.  The supported values are\n+ *\t     AES_KEYSIZE_128, AES_KEYSIZE_192, and AES_KEYSIZE_256.\n+ *\n+ * Context: Any context.\n+ * Return: 0 on success or -EINVAL if the given key length is invalid.  No other\n+ *\t   errors are possible, so callers that always pass a valid key length\n+ *\t   don't need to check for errors.\n+ */\n+int aes_cmac_preparekey(struct aes_cmac_key *key, const u8 *in_key,\n+\t\t\tsize_t key_len);\n+\n+/**\n+ * aes_xcbcmac_preparekey() - Prepare a key for AES-XCBC-MAC\n+ * @key: (output) The key struct to initialize\n+ * @in_key: The raw key.  As per the AES-XCBC-MAC specification (RFC 3566), this\n+ *\t    is 128 bits, matching the internal use of AES-128.\n+ *\n+ * AES-XCBC-MAC and AES-CMAC are the same except for the key preparation.  After\n+ * that step, AES-XCBC-MAC is supported via the aes_cmac_* functions.\n+ *\n+ * New users should use AES-CMAC instead of AES-XCBC-MAC.\n+ *\n+ * Context: Any context.\n+ */\n+void aes_xcbcmac_preparekey(struct aes_cmac_key *key,\n+\t\t\t    const u8 in_key[at_least AES_KEYSIZE_128]);\n+\n+/**\n+ * aes_cmac_init() - Start computing an AES-CMAC or AES-XCBC-MAC value\n+ * @ctx: (output) The context to initialize\n+ * @key: The key to use.  Note that a pointer to the key is saved in the\n+ *\t context, so the key must live at least as long as the context.\n+ *\n+ * This supports both AES-CMAC and AES-XCBC-MAC.  Which one is done depends on\n+ * whether aes_cmac_preparekey() or aes_xcbcmac_preparekey() was called.\n+ */\n+static inline void aes_cmac_init(struct aes_cmac_ctx *ctx,\n+\t\t\t\t const struct aes_cmac_key *key)\n+{\n+\t*ctx = (struct aes_cmac_ctx){ .key = key };\n+}\n+\n+/**\n+ * aes_cmac_update() - Update an AES-CMAC or AES-XCBC-MAC context with more data\n+ * @ctx: The context to update; must have been initialized\n+ * @data: The message data\n+ * @data_len: The data length in bytes.  Doesn't need to be block-aligned.\n+ *\n+ * This can be called any number of times.\n+ *\n+ * Context: Any context.\n+ */\n+void aes_cmac_update(struct aes_cmac_ctx *ctx, const u8 *data, size_t data_len);\n+\n+/**\n+ * aes_cmac_final() - Finish computing an AES-CMAC or AES-XCBC-MAC value\n+ * @ctx: The context to finalize; must have been initialized\n+ * @out: (output) The resulting MAC\n+ *\n+ * After finishing, this zeroizes @ctx.  So the caller does not need to do it.\n+ *\n+ * Context: Any context.\n+ */\n+void aes_cmac_final(struct aes_cmac_ctx *ctx, u8 out[at_least AES_BLOCK_SIZE]);\n+\n+/**\n+ * aes_cmac() - Compute AES-CMAC or AES-XCBC-MAC in one shot\n+ * @key: The key to use\n+ * @data: The message data\n+ * @data_len: The data length in bytes\n+ * @out: (output) The resulting AES-CMAC or AES-XCBC-MAC value\n+ *\n+ * This supports both AES-CMAC and AES-XCBC-MAC.  Which one is done depends on\n+ * whether aes_cmac_preparekey() or aes_xcbcmac_preparekey() was called.\n+ *\n+ * Context: Any context.\n+ */\n+static inline void aes_cmac(const struct aes_cmac_key *key, const u8 *data,\n+\t\t\t    size_t data_len, u8 out[at_least AES_BLOCK_SIZE])\n+{\n+\tstruct aes_cmac_ctx ctx;\n+\n+\taes_cmac_init(&ctx, key);\n+\taes_cmac_update(&ctx, data, data_len);\n+\taes_cmac_final(&ctx, out);\n+}\n+\n+/*\n+ * AES-CBC-MAC support.  This is provided only for use by the implementation of\n+ * AES-CCM.  It should have no other users.  Warning: unlike AES-CMAC and\n+ * AES-XCBC-MAC, AES-CBC-MAC isn't a secure MAC for variable-length messages.\n+ */\n+struct aes_cbcmac_ctx {\n+\tconst struct aes_enckey *key;\n+\tsize_t partial_len;\n+\tu8 h[AES_BLOCK_SIZE];\n+};\n+static inline void aes_cbcmac_init(struct aes_cbcmac_ctx *ctx,\n+\t\t\t\t   const struct aes_enckey *key)\n+{\n+\t*ctx = (struct aes_cbcmac_ctx){ .key = key };\n+}\n+void aes_cbcmac_update(struct aes_cbcmac_ctx *ctx, const u8 *data,\n+\t\t       size_t data_len);\n+void aes_cbcmac_final(struct aes_cbcmac_ctx *ctx,\n+\t\t      u8 out[at_least AES_BLOCK_SIZE]);\n+\n+#endif /* _CRYPTO_AES_CBC_MACS_H */\ndiff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig\nindex 032f9755f999..42ec51645915 100644\n--- a/lib/crypto/Kconfig\n+++ b/lib/crypto/Kconfig\n@@ -8,10 +8,12 @@ config CRYPTO_HASH_INFO\n config CRYPTO_LIB_UTILS\n \ttristate\n \n config CRYPTO_LIB_AES\n \ttristate\n+\t# Select dependencies of modes that are part of libaes.\n+\tselect CRYPTO_LIB_UTILS if CRYPTO_LIB_AES_CBC_MACS\n \n config CRYPTO_LIB_AES_ARCH\n \tbool\n \tdepends on CRYPTO_LIB_AES && !UML && !KMSAN\n \tdefault y if ARM\n@@ -26,10 +28,18 @@ config CRYPTO_LIB_AES_ARCH\n config CRYPTO_LIB_AESCFB\n \ttristate\n \tselect CRYPTO_LIB_AES\n \tselect CRYPTO_LIB_UTILS\n \n+config CRYPTO_LIB_AES_CBC_MACS\n+\ttristate\n+\tselect CRYPTO_LIB_AES\n+\thelp\n+\t  The AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC library functions.  Select\n+\t  this if your module uses any of the functions from\n+\t  <crypto/aes-cbc-macs.h>.\n+\n config CRYPTO_LIB_AESGCM\n \ttristate\n \tselect CRYPTO_LIB_AES\n \tselect CRYPTO_LIB_GF128MUL\n \tselect CRYPTO_LIB_UTILS\ndiff --git a/lib/crypto/aes.c b/lib/crypto/aes.c\nindex b73e19f1bb95..39deae6105c0 100644\n--- a/lib/crypto/aes.c\n+++ b/lib/crypto/aes.c\n@@ -2,11 +2,13 @@\n /*\n  * Copyright (C) 2017-2019 Linaro Ltd <ard.biesheuvel@linaro.org>\n  * Copyright 2026 Google LLC\n  */\n \n+#include <crypto/aes-cbc-macs.h>\n #include <crypto/aes.h>\n+#include <crypto/utils.h>\n #include <linux/cache.h>\n #include <linux/crypto.h>\n #include <linux/export.h>\n #include <linux/module.h>\n #include <linux/unaligned.h>\n@@ -510,10 +512,206 @@ void aes_decrypt(const struct aes_key *key, u8 out[AES_BLOCK_SIZE],\n {\n \taes_decrypt_arch(key, out, in);\n }\n EXPORT_SYMBOL(aes_decrypt);\n \n+#if IS_ENABLED(CONFIG_CRYPTO_LIB_AES_CBC_MACS)\n+\n+#ifndef aes_cbcmac_blocks_arch\n+static bool aes_cbcmac_blocks_arch(u8 h[AES_BLOCK_SIZE],\n+\t\t\t\t   const struct aes_enckey *key, const u8 *data,\n+\t\t\t\t   size_t nblocks, bool enc_before,\n+\t\t\t\t   bool enc_after)\n+{\n+\treturn false;\n+}\n+#endif\n+\n+/* This assumes nblocks >= 1. */\n+static void aes_cbcmac_blocks(u8 h[AES_BLOCK_SIZE],\n+\t\t\t      const struct aes_enckey *key, const u8 *data,\n+\t\t\t      size_t nblocks, bool enc_before, bool enc_after)\n+{\n+\tif (aes_cbcmac_blocks_arch(h, key, data, nblocks, enc_before,\n+\t\t\t\t   enc_after))\n+\t\treturn;\n+\n+\tif (enc_before)\n+\t\taes_encrypt(key, h, h);\n+\tfor (; nblocks > 1; nblocks--) {\n+\t\tcrypto_xor(h, data, AES_BLOCK_SIZE);\n+\t\tdata += AES_BLOCK_SIZE;\n+\t\taes_encrypt(key, h, h);\n+\t}\n+\tcrypto_xor(h, data, AES_BLOCK_SIZE);\n+\tif (enc_after)\n+\t\taes_encrypt(key, h, h);\n+}\n+\n+int aes_cmac_preparekey(struct aes_cmac_key *key, const u8 *in_key,\n+\t\t\tsize_t key_len)\n+{\n+\tu64 hi, lo, mask;\n+\tint err;\n+\n+\t/* Prepare the AES key. */\n+\terr = aes_prepareenckey(&key->aes, in_key, key_len);\n+\tif (err)\n+\t\treturn err;\n+\n+\t/*\n+\t * Prepare the subkeys K1 and K2 by encrypting the all-zeroes block,\n+\t * then multiplying by 'x' and 'x^2' (respectively) in GF(2^128).\n+\t * Reference: NIST SP 800-38B, Section 6.1 \"Subkey Generation\".\n+\t */\n+\tmemset(key->k_final[0].b, 0, AES_BLOCK_SIZE);\n+\taes_encrypt(&key->aes, key->k_final[0].b, key->k_final[0].b);\n+\thi = be64_to_cpu(key->k_final[0].w[0]);\n+\tlo = be64_to_cpu(key->k_final[0].w[1]);\n+\tfor (int i = 0; i < 2; i++) {\n+\t\tmask = ((s64)hi >> 63) & 0x87;\n+\t\thi = (hi << 1) ^ (lo >> 63);\n+\t\tlo = (lo << 1) ^ mask;\n+\t\tkey->k_final[i].w[0] = cpu_to_be64(hi);\n+\t\tkey->k_final[i].w[1] = cpu_to_be64(lo);\n+\t}\n+\treturn 0;\n+}\n+EXPORT_SYMBOL_GPL(aes_cmac_preparekey);\n+\n+void aes_xcbcmac_preparekey(struct aes_cmac_key *key,\n+\t\t\t    const u8 in_key[AES_KEYSIZE_128])\n+{\n+\tstatic const u8 constants[3][AES_BLOCK_SIZE] = {\n+\t\t{ [0 ... AES_BLOCK_SIZE - 1] = 0x1 },\n+\t\t{ [0 ... AES_BLOCK_SIZE - 1] = 0x2 },\n+\t\t{ [0 ... AES_BLOCK_SIZE - 1] = 0x3 },\n+\t};\n+\tu8 new_aes_key[AES_BLOCK_SIZE];\n+\n+\tstatic_assert(AES_BLOCK_SIZE == AES_KEYSIZE_128);\n+\taes_prepareenckey(&key->aes, in_key, AES_BLOCK_SIZE);\n+\taes_encrypt(&key->aes, new_aes_key, constants[0]);\n+\taes_encrypt(&key->aes, key->k_final[0].b, constants[1]);\n+\taes_encrypt(&key->aes, key->k_final[1].b, constants[2]);\n+\taes_prepareenckey(&key->aes, new_aes_key, AES_BLOCK_SIZE);\n+\tmemzero_explicit(new_aes_key, AES_BLOCK_SIZE);\n+}\n+EXPORT_SYMBOL_GPL(aes_xcbcmac_preparekey);\n+\n+void aes_cmac_update(struct aes_cmac_ctx *ctx, const u8 *data, size_t data_len)\n+{\n+\tbool enc_before = false;\n+\tsize_t nblocks;\n+\n+\tif (ctx->partial_len) {\n+\t\t/* XOR data into a pending block. */\n+\t\tsize_t l = min(data_len, AES_BLOCK_SIZE - ctx->partial_len);\n+\n+\t\tcrypto_xor(&ctx->h[ctx->partial_len], data, l);\n+\t\tdata += l;\n+\t\tdata_len -= l;\n+\t\tctx->partial_len += l;\n+\t\tif (data_len == 0) {\n+\t\t\t/*\n+\t\t\t * Either the pending block hasn't been filled yet, or\n+\t\t\t * no more data was given so it's not yet known whether\n+\t\t\t * the block is the final block.\n+\t\t\t */\n+\t\t\treturn;\n+\t\t}\n+\t\t/* Pending block has been filled and isn't the final block. */\n+\t\tenc_before = true;\n+\t}\n+\n+\tnblocks = data_len / AES_BLOCK_SIZE;\n+\tdata_len %= AES_BLOCK_SIZE;\n+\tif (nblocks == 0) {\n+\t\t/* 0 additional full blocks, then optionally a partial block */\n+\t\tif (enc_before)\n+\t\t\taes_encrypt(&ctx->key->aes, ctx->h, ctx->h);\n+\t\tcrypto_xor(ctx->h, data, data_len);\n+\t\tctx->partial_len = data_len;\n+\t} else if (data_len != 0) {\n+\t\t/* 1 or more additional full blocks, then a partial block */\n+\t\taes_cbcmac_blocks(ctx->h, &ctx->key->aes, data, nblocks,\n+\t\t\t\t  enc_before, /* enc_after= */ true);\n+\t\tdata += nblocks * AES_BLOCK_SIZE;\n+\t\tcrypto_xor(ctx->h, data, data_len);\n+\t\tctx->partial_len = data_len;\n+\t} else {\n+\t\t/*\n+\t\t * 1 or more additional full blocks only.  Encryption of the\n+\t\t * last block is delayed until it's known whether it's the final\n+\t\t * block in the message or not.\n+\t\t */\n+\t\taes_cbcmac_blocks(ctx->h, &ctx->key->aes, data, nblocks,\n+\t\t\t\t  enc_before, /* enc_after= */ false);\n+\t\tctx->partial_len = AES_BLOCK_SIZE;\n+\t}\n+}\n+EXPORT_SYMBOL_GPL(aes_cmac_update);\n+\n+void aes_cmac_final(struct aes_cmac_ctx *ctx, u8 out[AES_BLOCK_SIZE])\n+{\n+\tif (ctx->partial_len == AES_BLOCK_SIZE) {\n+\t\t/* Final block is a full block.  Use k_final[0]. */\n+\t\tcrypto_xor(ctx->h, ctx->key->k_final[0].b, AES_BLOCK_SIZE);\n+\t} else {\n+\t\t/* Final block is a partial block.  Pad, and use k_final[1]. */\n+\t\tctx->h[ctx->partial_len] ^= 0x80;\n+\t\tcrypto_xor(ctx->h, ctx->key->k_final[1].b, AES_BLOCK_SIZE);\n+\t}\n+\taes_encrypt(&ctx->key->aes, out, ctx->h);\n+\tmemzero_explicit(ctx, sizeof(*ctx));\n+}\n+EXPORT_SYMBOL_GPL(aes_cmac_final);\n+\n+void aes_cbcmac_update(struct aes_cbcmac_ctx *ctx, const u8 *data,\n+\t\t       size_t data_len)\n+{\n+\tbool enc_before = false;\n+\tsize_t nblocks;\n+\n+\tif (ctx->partial_len) {\n+\t\tsize_t l = min(data_len, AES_BLOCK_SIZE - ctx->partial_len);\n+\n+\t\tcrypto_xor(&ctx->h[ctx->partial_len], data, l);\n+\t\tdata += l;\n+\t\tdata_len -= l;\n+\t\tctx->partial_len += l;\n+\t\tif (ctx->partial_len < AES_BLOCK_SIZE)\n+\t\t\treturn;\n+\t\tenc_before = true;\n+\t}\n+\n+\tnblocks = data_len / AES_BLOCK_SIZE;\n+\tdata_len %= AES_BLOCK_SIZE;\n+\tif (nblocks == 0) {\n+\t\tif (enc_before)\n+\t\t\taes_encrypt(ctx->key, ctx->h, ctx->h);\n+\t} else {\n+\t\taes_cbcmac_blocks(ctx->h, ctx->key, data, nblocks, enc_before,\n+\t\t\t\t  /* enc_after= */ true);\n+\t\tdata += nblocks * AES_BLOCK_SIZE;\n+\t}\n+\tcrypto_xor(ctx->h, data, data_len);\n+\tctx->partial_len = data_len;\n+}\n+EXPORT_SYMBOL_NS_GPL(aes_cbcmac_update, \"CRYPTO_INTERNAL\");\n+\n+void aes_cbcmac_final(struct aes_cbcmac_ctx *ctx, u8 out[AES_BLOCK_SIZE])\n+{\n+\tif (ctx->partial_len)\n+\t\taes_encrypt(ctx->key, out, ctx->h);\n+\telse\n+\t\tmemcpy(out, ctx->h, AES_BLOCK_SIZE);\n+\tmemzero_explicit(ctx, sizeof(*ctx));\n+}\n+EXPORT_SYMBOL_NS_GPL(aes_cbcmac_final, \"CRYPTO_INTERNAL\");\n+#endif /* CONFIG_CRYPTO_LIB_AES_CBC_MACS */\n+\n #ifdef aes_mod_init_arch\n static int __init aes_mod_init(void)\n {\n \taes_mod_init_arch();\n \treturn 0;\n","prefixes":["01/15"]}