Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * AES-GMAC for IEEE 802.11 BIP-GMAC-128 and BIP-GMAC-256
0004  * Copyright 2015, Qualcomm Atheros, Inc.
0005  */
0006 
0007 #include <linux/kernel.h>
0008 #include <linux/types.h>
0009 #include <linux/err.h>
0010 #include <crypto/aead.h>
0011 #include <crypto/aes.h>
0012 
0013 #include <net/mac80211.h>
0014 #include "key.h"
0015 #include "aes_gmac.h"
0016 
0017 int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
0018                const u8 *data, size_t data_len, u8 *mic)
0019 {
0020     struct scatterlist sg[5];
0021     u8 *zero, *__aad, iv[AES_BLOCK_SIZE];
0022     struct aead_request *aead_req;
0023     int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
0024     const __le16 *fc;
0025     int ret;
0026 
0027     if (data_len < GMAC_MIC_LEN)
0028         return -EINVAL;
0029 
0030     aead_req = kzalloc(reqsize + GMAC_MIC_LEN + GMAC_AAD_LEN, GFP_ATOMIC);
0031     if (!aead_req)
0032         return -ENOMEM;
0033 
0034     zero = (u8 *)aead_req + reqsize;
0035     __aad = zero + GMAC_MIC_LEN;
0036     memcpy(__aad, aad, GMAC_AAD_LEN);
0037 
0038     fc = (const __le16 *)aad;
0039     if (ieee80211_is_beacon(*fc)) {
0040         /* mask Timestamp field to zero */
0041         sg_init_table(sg, 5);
0042         sg_set_buf(&sg[0], __aad, GMAC_AAD_LEN);
0043         sg_set_buf(&sg[1], zero, 8);
0044         sg_set_buf(&sg[2], data + 8, data_len - 8 - GMAC_MIC_LEN);
0045         sg_set_buf(&sg[3], zero, GMAC_MIC_LEN);
0046         sg_set_buf(&sg[4], mic, GMAC_MIC_LEN);
0047     } else {
0048         sg_init_table(sg, 4);
0049         sg_set_buf(&sg[0], __aad, GMAC_AAD_LEN);
0050         sg_set_buf(&sg[1], data, data_len - GMAC_MIC_LEN);
0051         sg_set_buf(&sg[2], zero, GMAC_MIC_LEN);
0052         sg_set_buf(&sg[3], mic, GMAC_MIC_LEN);
0053     }
0054 
0055     memcpy(iv, nonce, GMAC_NONCE_LEN);
0056     memset(iv + GMAC_NONCE_LEN, 0, sizeof(iv) - GMAC_NONCE_LEN);
0057     iv[AES_BLOCK_SIZE - 1] = 0x01;
0058 
0059     aead_request_set_tfm(aead_req, tfm);
0060     aead_request_set_crypt(aead_req, sg, sg, 0, iv);
0061     aead_request_set_ad(aead_req, GMAC_AAD_LEN + data_len);
0062 
0063     ret = crypto_aead_encrypt(aead_req);
0064     kfree_sensitive(aead_req);
0065 
0066     return ret;
0067 }
0068 
0069 struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[],
0070                          size_t key_len)
0071 {
0072     struct crypto_aead *tfm;
0073     int err;
0074 
0075     tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
0076     if (IS_ERR(tfm))
0077         return tfm;
0078 
0079     err = crypto_aead_setkey(tfm, key, key_len);
0080     if (!err)
0081         err = crypto_aead_setauthsize(tfm, GMAC_MIC_LEN);
0082     if (!err)
0083         return tfm;
0084 
0085     crypto_free_aead(tfm);
0086     return ERR_PTR(err);
0087 }
0088 
0089 void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm)
0090 {
0091     crypto_free_aead(tfm);
0092 }