| // 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); |
| } |