linux/net/mac80211/aes_cmac.c
Eric Biggers c9de7246d5 wifi: mac80211: Use AES-CMAC library in ieee80211_aes_cmac()
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.

Acked-by: Johannes Berg <johannes@sipsolutions.net>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20260218213501.136844-15-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
2026-03-09 13:27:21 -07:00

44 lines
1.1 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* AES-128-CMAC with TLen 16 for IEEE 802.11w BIP
* Copyright 2008, Jouni Malinen <j@w1.fi>
* Copyright (C) 2020 Intel Corporation
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/export.h>
#include <linux/err.h>
#include <crypto/aes-cbc-macs.h>
#include <net/mac80211.h>
#include "key.h"
#include "aes_cmac.h"
#define AAD_LEN 20
static const u8 zero[IEEE80211_CMAC_256_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)
{
struct aes_cmac_ctx ctx;
u8 out[AES_BLOCK_SIZE];
const __le16 *fc;
aes_cmac_init(&ctx, key);
aes_cmac_update(&ctx, aad, AAD_LEN);
fc = (const __le16 *)aad;
if (ieee80211_is_beacon(*fc)) {
/* mask Timestamp field to zero */
aes_cmac_update(&ctx, zero, 8);
aes_cmac_update(&ctx, data + 8, data_len - 8 - mic_len);
} else {
aes_cmac_update(&ctx, data, data_len - mic_len);
}
aes_cmac_update(&ctx, zero, mic_len);
aes_cmac_final(&ctx, out);
memcpy(mic, out, mic_len);
}