diff options
Diffstat (limited to 'net/mac80211/aes_cmac.c')
| -rw-r--r-- | net/mac80211/aes_cmac.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c new file mode 100644 index 000000000..55b674ad7 --- /dev/null +++ b/net/mac80211/aes_cmac.c @@ -0,0 +1,43 @@ +// 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); +} |
