xref: /linux/net/mac80211/aes_cmac.c (revision 6bc9effb4cbf9b6eba0f51aba1c8893dfd4c8100)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * AES-128-CMAC with TLen 16 for IEEE 802.11w BIP
4  * Copyright 2008, Jouni Malinen <j@w1.fi>
5  * Copyright (C) 2020 Intel Corporation
6  */
7 
8 #include <linux/kernel.h>
9 #include <linux/types.h>
10 #include <linux/export.h>
11 #include <linux/err.h>
12 #include <crypto/aes-cbc-macs.h>
13 
14 #include <net/mac80211.h>
15 #include "key.h"
16 #include "aes_cmac.h"
17 
18 #define AAD_LEN 20
19 
20 static const u8 zero[IEEE80211_CMAC_256_MIC_LEN];
21 
22 void ieee80211_aes_cmac(const struct aes_cmac_key *key, const u8 *aad,
23 			const u8 *data, size_t data_len, u8 *mic,
24 			unsigned int mic_len)
25 {
26 	struct aes_cmac_ctx ctx;
27 	u8 out[AES_BLOCK_SIZE];
28 	const __le16 *fc;
29 
30 	aes_cmac_init(&ctx, key);
31 	aes_cmac_update(&ctx, aad, AAD_LEN);
32 	fc = (const __le16 *)aad;
33 	if (ieee80211_is_beacon(*fc)) {
34 		/* mask Timestamp field to zero */
35 		aes_cmac_update(&ctx, zero, 8);
36 		aes_cmac_update(&ctx, data + 8, data_len - 8 - mic_len);
37 	} else {
38 		aes_cmac_update(&ctx, data, data_len - mic_len);
39 	}
40 	aes_cmac_update(&ctx, zero, mic_len);
41 	aes_cmac_final(&ctx, out);
42 	memcpy(mic, out, mic_len);
43 }
44