mac80111: Add BIP-GMAC-128 and BIP-GMAC-256 ciphers
authorJouni Malinen <jouni@qca.qualcomm.com>
Sat, 24 Jan 2015 17:52:09 +0000 (19:52 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 27 Jan 2015 10:10:13 +0000 (11:10 +0100)
This allows mac80211 to configure BIP-GMAC-128 and BIP-GMAC-256 to the
driver and also use software-implementation within mac80211 when the
driver does not support this with hardware accelaration.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
13 files changed:
include/net/mac80211.h
net/mac80211/Makefile
net/mac80211/aes_gmac.c [new file with mode: 0644]
net/mac80211/aes_gmac.h [new file with mode: 0644]
net/mac80211/cfg.c
net/mac80211/debugfs_key.c
net/mac80211/key.c
net/mac80211/key.h
net/mac80211/main.c
net/mac80211/rx.c
net/mac80211/tx.c
net/mac80211/wpa.c
net/mac80211/wpa.h

index ae66384..d52914b 100644 (file)
@@ -4098,6 +4098,8 @@ void ieee80211_aes_cmac_calculate_k1_k2(struct ieee80211_key_conf *keyconf,
  *     reverse order than in packet)
  * @aes_cmac: PN data, most significant byte first (big endian,
  *     reverse order than in packet)
+ * @aes_gmac: PN data, most significant byte first (big endian,
+ *     reverse order than in packet)
  * @gcmp: PN data, most significant byte first (big endian,
  *     reverse order than in packet)
  */
@@ -4113,6 +4115,9 @@ struct ieee80211_key_seq {
                struct {
                        u8 pn[6];
                } aes_cmac;
+               struct {
+                       u8 pn[6];
+               } aes_gmac;
                struct {
                        u8 pn[6];
                } gcmp;
index 0cbf936..3275f01 100644 (file)
@@ -17,6 +17,7 @@ mac80211-y := \
        aes_ccm.o \
        aes_gcm.o \
        aes_cmac.o \
+       aes_gmac.o \
        cfg.o \
        ethtool.o \
        rx.o \
diff --git a/net/mac80211/aes_gmac.c b/net/mac80211/aes_gmac.c
new file mode 100644 (file)
index 0000000..1c72edc
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * AES-GMAC for IEEE 802.11 BIP-GMAC-128 and BIP-GMAC-256
+ * Copyright 2015, Qualcomm Atheros, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <crypto/aes.h>
+
+#include <net/mac80211.h>
+#include "key.h"
+#include "aes_gmac.h"
+
+#define GMAC_MIC_LEN 16
+#define GMAC_NONCE_LEN 12
+#define AAD_LEN 20
+
+int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
+                      const u8 *data, size_t data_len, u8 *mic)
+{
+       struct scatterlist sg[3], ct[1];
+       char aead_req_data[sizeof(struct aead_request) +
+                          crypto_aead_reqsize(tfm)]
+               __aligned(__alignof__(struct aead_request));
+       struct aead_request *aead_req = (void *)aead_req_data;
+       u8 zero[GMAC_MIC_LEN], iv[AES_BLOCK_SIZE];
+
+       if (data_len < GMAC_MIC_LEN)
+               return -EINVAL;
+
+       memset(aead_req, 0, sizeof(aead_req_data));
+
+       memset(zero, 0, GMAC_MIC_LEN);
+       sg_init_table(sg, 3);
+       sg_set_buf(&sg[0], aad, AAD_LEN);
+       sg_set_buf(&sg[1], data, data_len - GMAC_MIC_LEN);
+       sg_set_buf(&sg[2], zero, GMAC_MIC_LEN);
+
+       memcpy(iv, nonce, GMAC_NONCE_LEN);
+       memset(iv + GMAC_NONCE_LEN, 0, sizeof(iv) - GMAC_NONCE_LEN);
+       iv[AES_BLOCK_SIZE - 1] = 0x01;
+
+       sg_init_table(ct, 1);
+       sg_set_buf(&ct[0], mic, GMAC_MIC_LEN);
+
+       aead_request_set_tfm(aead_req, tfm);
+       aead_request_set_assoc(aead_req, sg, AAD_LEN + data_len);
+       aead_request_set_crypt(aead_req, NULL, ct, 0, iv);
+
+       crypto_aead_encrypt(aead_req);
+
+       return 0;
+}
+
+struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[],
+                                                size_t key_len)
+{
+       struct crypto_aead *tfm;
+       int err;
+
+       tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
+       if (IS_ERR(tfm))
+               return tfm;
+
+       err = crypto_aead_setkey(tfm, key, key_len);
+       if (!err)
+               return tfm;
+       if (!err)
+               err = crypto_aead_setauthsize(tfm, GMAC_MIC_LEN);
+
+       crypto_free_aead(tfm);
+       return ERR_PTR(err);
+}
+
+void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm)
+{
+       crypto_free_aead(tfm);
+}
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge