0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/types.h>
0010 #include <linux/crypto.h>
0011 #include <linux/export.h>
0012 #include <linux/err.h>
0013 #include <crypto/aes.h>
0014
0015 #include <net/mac80211.h>
0016 #include "key.h"
0017 #include "aes_cmac.h"
0018
0019 #define CMAC_TLEN 8
0020 #define CMAC_TLEN_256 16
0021 #define AAD_LEN 20
0022
0023 static const u8 zero[CMAC_TLEN_256];
0024
0025 void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad,
0026 const u8 *data, size_t data_len, u8 *mic)
0027 {
0028 SHASH_DESC_ON_STACK(desc, tfm);
0029 u8 out[AES_BLOCK_SIZE];
0030 const __le16 *fc;
0031
0032 desc->tfm = tfm;
0033
0034 crypto_shash_init(desc);
0035 crypto_shash_update(desc, aad, AAD_LEN);
0036 fc = (const __le16 *)aad;
0037 if (ieee80211_is_beacon(*fc)) {
0038
0039 crypto_shash_update(desc, zero, 8);
0040 crypto_shash_update(desc, data + 8, data_len - 8 - CMAC_TLEN);
0041 } else {
0042 crypto_shash_update(desc, data, data_len - CMAC_TLEN);
0043 }
0044 crypto_shash_finup(desc, zero, CMAC_TLEN, out);
0045
0046 memcpy(mic, out, CMAC_TLEN);
0047 }
0048
0049 void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad,
0050 const u8 *data, size_t data_len, u8 *mic)
0051 {
0052 SHASH_DESC_ON_STACK(desc, tfm);
0053 const __le16 *fc;
0054
0055 desc->tfm = tfm;
0056
0057 crypto_shash_init(desc);
0058 crypto_shash_update(desc, aad, AAD_LEN);
0059 fc = (const __le16 *)aad;
0060 if (ieee80211_is_beacon(*fc)) {
0061
0062 crypto_shash_update(desc, zero, 8);
0063 crypto_shash_update(desc, data + 8,
0064 data_len - 8 - CMAC_TLEN_256);
0065 } else {
0066 crypto_shash_update(desc, data, data_len - CMAC_TLEN_256);
0067 }
0068 crypto_shash_finup(desc, zero, CMAC_TLEN_256, mic);
0069 }
0070
0071 struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[],
0072 size_t key_len)
0073 {
0074 struct crypto_shash *tfm;
0075
0076 tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
0077 if (!IS_ERR(tfm)) {
0078 int err = crypto_shash_setkey(tfm, key, key_len);
0079
0080 if (err) {
0081 crypto_free_shash(tfm);
0082 return ERR_PTR(err);
0083 }
0084 }
0085
0086 return tfm;
0087 }
0088
0089 void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm)
0090 {
0091 crypto_free_shash(tfm);
0092 }