Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * AES-128-CMAC with TLen 16 for IEEE 802.11w BIP
0004  * Copyright 2008, Jouni Malinen <j@w1.fi>
0005  * Copyright (C) 2020 Intel Corporation
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 /* CMAC TLen = 64 bits (8 octets) */
0020 #define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */
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         /* mask Timestamp field to zero */
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         /* mask Timestamp field to zero */
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 }