| /* SPDX-License-Identifier: GPL-2.0 */ |
| /* |
| * Support for AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC |
| * |
| * Copyright 2026 Google LLC |
| */ |
| #ifndef _CRYPTO_AES_CBC_MACS_H |
| #define _CRYPTO_AES_CBC_MACS_H |
| |
| #include <crypto/aes.h> |
| |
| /** |
| * struct aes_cmac_key - Prepared key for AES-CMAC or AES-XCBC-MAC |
| * @aes: The AES key for cipher block chaining |
| * @k_final: Finalization subkeys for the final block. |
| * k_final[0] (CMAC K1, XCBC-MAC K2) is used if it's a full block. |
| * k_final[1] (CMAC K2, XCBC-MAC K3) is used if it's a partial block. |
| */ |
| struct aes_cmac_key { |
| struct aes_enckey aes; |
| union { |
| u8 b[AES_BLOCK_SIZE]; |
| __be64 w[2]; |
| } k_final[2]; |
| }; |
| |
| /** |
| * struct aes_cmac_ctx - Context for computing an AES-CMAC or AES-XCBC-MAC value |
| * @key: Pointer to the key struct. A pointer is used rather than a copy of the |
| * struct, since the key struct size may be large. It is assumed that the |
| * key lives at least as long as the context. |
| * @partial_len: Number of bytes that have been XOR'ed into @h since the last |
| * AES encryption. This is 0 if no data has been processed yet, |
| * or between 1 and AES_BLOCK_SIZE inclusive otherwise. |
| * @h: The current chaining value |
| */ |
| struct aes_cmac_ctx { |
| const struct aes_cmac_key *key; |
| size_t partial_len; |
| u8 h[AES_BLOCK_SIZE]; |
| }; |
| |
| /** |
| * aes_cmac_preparekey() - Prepare a key for AES-CMAC |
| * @key: (output) The key struct to initialize |
| * @in_key: The raw AES key |
| * @key_len: Length of the raw key in bytes. The supported values are |
| * AES_KEYSIZE_128, AES_KEYSIZE_192, and AES_KEYSIZE_256. |
| * |
| * Context: Any context. |
| * Return: 0 on success or -EINVAL if the given key length is invalid. No other |
| * errors are possible, so callers that always pass a valid key length |
| * don't need to check for errors. |
| */ |
| int aes_cmac_preparekey(struct aes_cmac_key *key, const u8 *in_key, |
| size_t key_len); |
| |
| /** |
| * aes_xcbcmac_preparekey() - Prepare a key for AES-XCBC-MAC |
| * @key: (output) The key struct to initialize |
| * @in_key: The raw key. As per the AES-XCBC-MAC specification (RFC 3566), this |
| * is 128 bits, matching the internal use of AES-128. |
| * |
| * AES-XCBC-MAC and AES-CMAC are the same except for the key preparation. After |
| * that step, AES-XCBC-MAC is supported via the aes_cmac_* functions. |
| * |
| * New users should use AES-CMAC instead of AES-XCBC-MAC. |
| * |
| * Context: Any context. |
| */ |
| void aes_xcbcmac_preparekey(struct aes_cmac_key *key, |
| const u8 in_key[at_least AES_KEYSIZE_128]); |
| |
| /** |
| * aes_cmac_init() - Start computing an AES-CMAC or AES-XCBC-MAC value |
| * @ctx: (output) The context to initialize |
| * @key: The key to use. Note that a pointer to the key is saved in the |
| * context, so the key must live at least as long as the context. |
| * |
| * This supports both AES-CMAC and AES-XCBC-MAC. Which one is done depends on |
| * whether aes_cmac_preparekey() or aes_xcbcmac_preparekey() was called. |
| */ |
| static inline void aes_cmac_init(struct aes_cmac_ctx *ctx, |
| const struct aes_cmac_key *key) |
| { |
| *ctx = (struct aes_cmac_ctx){ .key = key }; |
| } |
| |
| /** |
| * aes_cmac_update() - Update an AES-CMAC or AES-XCBC-MAC context with more data |
| * @ctx: The context to update; must have been initialized |
| * @data: The message data |
| * @data_len: The data length in bytes. Doesn't need to be block-aligned. |
| * |
| * This can be called any number of times. |
| * |
| * Context: Any context. |
| */ |
| void aes_cmac_update(struct aes_cmac_ctx *ctx, const u8 *data, size_t data_len); |
| |
| /** |
| * aes_cmac_final() - Finish computing an AES-CMAC or AES-XCBC-MAC value |
| * @ctx: The context to finalize; must have been initialized |
| * @out: (output) The resulting MAC |
| * |
| * After finishing, this zeroizes @ctx. So the caller does not need to do it. |
| * |
| * Context: Any context. |
| */ |
| void aes_cmac_final(struct aes_cmac_ctx *ctx, u8 out[at_least AES_BLOCK_SIZE]); |
| |
| /** |
| * aes_cmac() - Compute AES-CMAC or AES-XCBC-MAC in one shot |
| * @key: The key to use |
| * @data: The message data |
| * @data_len: The data length in bytes |
| * @out: (output) The resulting AES-CMAC or AES-XCBC-MAC value |
| * |
| * This supports both AES-CMAC and AES-XCBC-MAC. Which one is done depends on |
| * whether aes_cmac_preparekey() or aes_xcbcmac_preparekey() was called. |
| * |
| * Context: Any context. |
| */ |
| static inline void aes_cmac(const struct aes_cmac_key *key, const u8 *data, |
| size_t data_len, u8 out[at_least AES_BLOCK_SIZE]) |
| { |
| struct aes_cmac_ctx ctx; |
| |
| aes_cmac_init(&ctx, key); |
| aes_cmac_update(&ctx, data, data_len); |
| aes_cmac_final(&ctx, out); |
| } |
| |
| /* |
| * AES-CBC-MAC support. This is provided only for use by the implementation of |
| * AES-CCM. It should have no other users. Warning: unlike AES-CMAC and |
| * AES-XCBC-MAC, AES-CBC-MAC isn't a secure MAC for variable-length messages. |
| */ |
| struct aes_cbcmac_ctx { |
| const struct aes_enckey *key; |
| size_t partial_len; |
| u8 h[AES_BLOCK_SIZE]; |
| }; |
| static inline void aes_cbcmac_init(struct aes_cbcmac_ctx *ctx, |
| const struct aes_enckey *key) |
| { |
| *ctx = (struct aes_cbcmac_ctx){ .key = key }; |
| } |
| void aes_cbcmac_update(struct aes_cbcmac_ctx *ctx, const u8 *data, |
| size_t data_len); |
| void aes_cbcmac_final(struct aes_cbcmac_ctx *ctx, |
| u8 out[at_least AES_BLOCK_SIZE]); |
| |
| #endif /* _CRYPTO_AES_CBC_MACS_H */ |