From: Janusz Dziedzic <[email protected]>
Date: Wed, 1 Jun 2011 14:40:13 +0200
This commit implements WAPI support for hardware-accelerated devices.
Signed-off-by: Dmitry Tarnyagin <[email protected]>
---
include/linux/ieee80211.h | 3 ++
include/linux/nl80211.h | 5 ++-
include/linux/wireless.h | 6 ++++
net/mac80211/Makefile | 1 +
net/mac80211/ieee80211_i.h | 2 +-
net/mac80211/key.c | 4 ++
net/mac80211/key.h | 2 +
net/mac80211/main.c | 1 +
net/mac80211/rx.c | 4 ++
net/mac80211/tx.c | 6 ++++
net/mac80211/wapi.c | 71
++++++++++++++++++++++++++++++++++++++++++++
net/mac80211/wapi.h | 27 ++++++++++++++++
net/wireless/nl80211.c | 7 ++--
net/wireless/util.c | 8 +++++
net/wireless/wext-compat.c | 39 +++++++++++++++++++++--
15 files changed, 176 insertions(+), 10 deletions(-)
create mode 100644 net/mac80211/wapi.c
create mode 100644 net/mac80211/wapi.h
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 48363c3..bf86b0d 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1395,6 +1395,7 @@ enum ieee80211_key_len {
WLAN_KEY_LEN_CCMP = 16,
WLAN_KEY_LEN_TKIP = 32,
WLAN_KEY_LEN_AES_CMAC = 16,
+ WLAN_KEY_LEN_SMS4 = 32,
};
/* Public action codes */
@@ -1551,12 +1552,14 @@ enum ieee80211_sa_query_action {
#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04
#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
+#define WLAN_CIPHER_SUITE_SMS4 0x000FAC07
/* AKM suite selectors */
#define WLAN_AKM_SUITE_8021X 0x000FAC01
#define WLAN_AKM_SUITE_PSK 0x000FAC02
#define WLAN_AKM_SUITE_SAE 0x000FAC08
#define WLAN_AKM_SUITE_FT_OVER_SAE 0x000FAC09
+#define WLAN_AKM_SUITE_WAPI_PSK 0x000FAC03
#define WLAN_MAX_KEY_LEN 32
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 9d797f2..be125a5 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1379,8 +1379,8 @@ enum nl80211_attrs {
#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24
#define NL80211_HT_CAPABILITY_LEN 26
-#define NL80211_MAX_NR_CIPHER_SUITES 5
-#define NL80211_MAX_NR_AKM_SUITES 2
+#define NL80211_MAX_NR_CIPHER_SUITES 6
+#define NL80211_MAX_NR_AKM_SUITES 3
/**
* enum nl80211_iftype - (virtual) interface types
@@ -2207,6 +2207,7 @@ enum nl80211_mfp {
enum nl80211_wpa_versions {
NL80211_WPA_VERSION_1 = 1 << 0,
NL80211_WPA_VERSION_2 = 1 << 1,
+ NL80211_WAPI_VERSION_1 = 1 << 2,
};
/**
diff --git a/include/linux/wireless.h b/include/linux/wireless.h
index 4395b28..f3e2375 100644
--- a/include/linux/wireless.h
+++ b/include/linux/wireless.h
@@ -586,6 +586,7 @@
#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001
#define IW_AUTH_WPA_VERSION_WPA 0x00000002
#define IW_AUTH_WPA_VERSION_WPA2 0x00000004
+#define IW_AUTH_WPA_VERSION_WAPI 0x00000008
/* IW_AUTH_PAIRWISE_CIPHER, IW_AUTH_GROUP_CIPHER, and
IW_AUTH_CIPHER_GROUP_MGMT
* values (bit field) */
@@ -595,10 +596,12 @@
#define IW_AUTH_CIPHER_CCMP 0x00000008
#define IW_AUTH_CIPHER_WEP104 0x00000010
#define IW_AUTH_CIPHER_AES_CMAC 0x00000020
+#define IW_AUTH_CIPHER_SMS4 0x00000040
/* IW_AUTH_KEY_MGMT values (bit field) */
#define IW_AUTH_KEY_MGMT_802_1X 1
#define IW_AUTH_KEY_MGMT_PSK 2
+#define IW_AUTH_KEY_MGMT_WAPI_PSK 4
/* IW_AUTH_80211_AUTH_ALG values (bit field) */
#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001
@@ -624,6 +627,7 @@
#define IW_ENCODE_ALG_CCMP 3
#define IW_ENCODE_ALG_PMK 4
#define IW_ENCODE_ALG_AES_CMAC 5
+#define IW_ENCODE_ALG_SMS4 6
/* struct iw_encode_ext ->ext_flags */
#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001
#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002
@@ -644,6 +648,8 @@
#define IW_ENC_CAPA_CIPHER_TKIP 0x00000004
#define IW_ENC_CAPA_CIPHER_CCMP 0x00000008
#define IW_ENC_CAPA_4WAY_HANDSHAKE 0x00000010
+#define IW_ENC_CAPA_WAPI 0x00000020
+#define IW_ENC_CAPA_CIPHER_SMS4 0x00000040
/* Event capability macros - in (struct iw_range *)->event_capa
* Because we have more than 32 possible events, we use an array of
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index fdb54e6..ed3dd35 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -6,6 +6,7 @@ mac80211-y := \
sta_info.o \
wep.o \
wpa.o \
+ wapi.o \
scan.o offchannel.o \
ht.o agg-tx.o agg-rx.o \
ibss.o \
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 46fbf7f..1eaa7b3 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -42,7 +42,7 @@ struct ieee80211_local;
#define TOTAL_MAX_TX_BUFFER 512
/* Required encryption head and tailroom */
-#define IEEE80211_ENCRYPT_HEADROOM 8
+#define IEEE80211_ENCRYPT_HEADROOM 20
#define IEEE80211_ENCRYPT_TAILROOM 18
/* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index e8ff846..91f0141 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -413,6 +413,10 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher,
int idx, size_t key_len,
return ERR_PTR(err);
}
break;
+ case WLAN_CIPHER_SUITE_SMS4:
+ key->conf.iv_len = WAPI_IV_LEN;
+ key->conf.icv_len = WAPI_ICV_LEN;
+ break;
}
memcpy(key->conf.key, key_data, key_len);
INIT_LIST_HEAD(&key->list);
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 7d4e31f..455f1fe 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -29,6 +29,8 @@
#define TKIP_IV_LEN 8
#define TKIP_ICV_LEN 4
#define CMAC_PN_LEN 6
+#define WAPI_IV_LEN 18
+#define WAPI_ICV_LEN 16
#define NUM_RX_DATA_QUEUES 16
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 163226e..b9b9765 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -716,6 +716,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
WLAN_CIPHER_SUITE_WEP104,
WLAN_CIPHER_SUITE_TKIP,
WLAN_CIPHER_SUITE_CCMP,
+ WLAN_CIPHER_SUITE_SMS4,
/* keep last -- depends on hw flags! */
WLAN_CIPHER_SUITE_AES_CMAC
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 8bd8683..6cc9800 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -28,6 +28,7 @@
#include "wpa.h"
#include "tkip.h"
#include "wme.h"
+#include "wapi.h"
/*
* monitor mode reception
@@ -1058,6 +1059,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
case WLAN_CIPHER_SUITE_AES_CMAC:
result = ieee80211_crypto_aes_cmac_decrypt(rx);
break;
+ case WLAN_CIPHER_SUITE_SMS4:
+ result = ieee80211_crypto_wapi_decrypt(rx);
+ break;
default:
/*
* We can reach here only with HW-only algorithms
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index e2cdd6e..64ca6c1 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -31,6 +31,7 @@
#include "mesh.h"
#include "wep.h"
#include "wpa.h"
+#include "wapi.h"
#include "wme.h"
#include "rate.h"
@@ -592,6 +593,11 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data
*tx)
if (!ieee80211_is_mgmt(hdr->frame_control))
tx->key = NULL;
break;
+
+ case WLAN_CIPHER_SUITE_SMS4:
+ if (tx->ethertype == ETH_P_WAPI)
+ tx->key = NULL;
+ break;
}
if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED))
diff --git a/net/mac80211/wapi.c b/net/mac80211/wapi.c
new file mode 100644
index 0000000..4780808
--- /dev/null
+++ b/net/mac80211/wapi.c
@@ -0,0 +1,71 @@
+/*
+ * Software WAPI encryption implementation
+ * Copyright (c) 2011, ST-Ericsson
+ * Author: Janusz Dziedzic <[email protected]>
+ *
+ * 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/netdevice.h>
+#include <linux/types.h>
+#include <linux/random.h>
+#include <linux/compiler.h>
+#include <linux/crc32.h>
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <asm/unaligned.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "wapi.h"
+
+
+static int ieee80211_wapi_decrypt(struct ieee80211_local *local,
+ struct sk_buff *skb,
+ struct ieee80211_key *key)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ int hdrlen = ieee80211_hdrlen(hdr->frame_control);
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+ int data_len;
+
+ if (!(status->flag & RX_FLAG_DECRYPTED)) {
+ /* TODO - SMS4 decryption for firmware without
+ * SMS4 support */
+ return RX_DROP_UNUSABLE;
+ }
+
+
+ data_len = skb->len - hdrlen - WAPI_IV_LEN - WAPI_ICV_LEN;
+ if (data_len < 0)
+ return RX_DROP_UNUSABLE;
+
+ /* Trim ICV */
+ skb_trim(skb, skb->len - WAPI_ICV_LEN);
+
+ /* Remove IV */
+ memmove(skb->data + WAPI_IV_LEN, skb->data, hdrlen);
+ skb_pull(skb, WAPI_IV_LEN);
+
+ return RX_CONTINUE;
+}
+
+ieee80211_rx_result
+ieee80211_crypto_wapi_decrypt(struct ieee80211_rx_data *rx)
+{
+ struct sk_buff *skb = rx->skb;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+
+ if (!ieee80211_is_data(hdr->frame_control))
+ return RX_CONTINUE;
+
+ if (ieee80211_wapi_decrypt(rx->local, rx->skb, rx->key))
+ return RX_DROP_UNUSABLE;
+
+ return RX_CONTINUE;
+}
diff --git a/net/mac80211/wapi.h b/net/mac80211/wapi.h
new file mode 100644
index 0000000..f06eee0
--- /dev/null
+++ b/net/mac80211/wapi.h
@@ -0,0 +1,27 @@
+/*
+ * Software WAPI encryption implementation
+ * Copyright (c) 2011, ST-Ericsson
+ * Author: Janusz Dziedzic <[email protected]>
+ *
+ * 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.
+ */
+
+#ifndef WAPI_H
+#define WAPI_H
+
+#include <linux/skbuff.h>
+#include <linux/types.h>
+#include "ieee80211_i.h"
+#include "key.h"
+
+#ifndef ETH_P_WAPI
+#define ETH_P_WAPI 0x88B4
+#endif
+
+
+ieee80211_rx_result
+ieee80211_crypto_wapi_decrypt(struct ieee80211_rx_data *rx);
+
+#endif /* WAPI_H */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index fe059b1..4b7c1d4 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -98,7 +98,7 @@ static const struct nla_policy
nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
[NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
[NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
- [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
+ [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
[NL80211_ATTR_KEY_TYPE] = { .type = NLA_U32 },
[NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
@@ -204,7 +204,7 @@ static const struct nla_policy
nl80211_key_policy[NL80211_KEY_MAX + 1] = {
[NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
[NL80211_KEY_IDX] = { .type = NLA_U8 },
[NL80211_KEY_CIPHER] = { .type = NLA_U32 },
- [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
+ [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
[NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
[NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
[NL80211_KEY_TYPE] = { .type = NLA_U32 },
@@ -4167,7 +4167,8 @@ static bool nl80211_valid_auth_type(enum
nl80211_auth_type auth_type)
static bool nl80211_valid_wpa_versions(u32 wpa_versions)
{
return !(wpa_versions & ~(NL80211_WPA_VERSION_1 |
- NL80211_WPA_VERSION_2));
+ NL80211_WPA_VERSION_2 |
+ NL80211_WAPI_VERSION_1));
}
static int nl80211_authenticate(struct sk_buff *skb, struct genl_info
*info)
diff --git a/net/wireless/util.c b/net/wireless/util.c
index f5bd881..e0bd192 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -208,6 +208,10 @@ int cfg80211_validate_key_settings(struct
cfg80211_registered_device *rdev,
if (params->key_len != WLAN_KEY_LEN_AES_CMAC)
return -EINVAL;
break;
+ case WLAN_CIPHER_SUITE_SMS4:
+ if (params->key_len != WLAN_KEY_LEN_SMS4)
+ return -EINVAL;
+ break;
default:
/*
* We don't know anything about this algorithm,
@@ -231,6 +235,10 @@ int cfg80211_validate_key_settings(struct
cfg80211_registered_device *rdev,
if (params->seq_len != 6)
return -EINVAL;
break;
+ case WLAN_CIPHER_SUITE_SMS4:
+ if (params->seq_len != 16)
+ return -EINVAL;
+ break;
}
}
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 2aaca82..f63c7c4 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -216,6 +216,11 @@ int cfg80211_wext_giwrange(struct net_device *dev,
range->encoding_size[range->num_encoding_sizes++] =
WLAN_KEY_LEN_WEP104;
break;
+
+ case WLAN_CIPHER_SUITE_SMS4:
+ range->enc_capa |= (IW_ENC_CAPA_CIPHER_SMS4 |
+ IW_ENC_CAPA_WAPI);
+ break;
}
}
@@ -699,6 +704,9 @@ static int cfg80211_wext_siwencodeext(struct
net_device *dev,
case IW_ENCODE_ALG_AES_CMAC:
cipher = WLAN_CIPHER_SUITE_AES_CMAC;
break;
+ case IW_ENCODE_ALG_SMS4:
+ cipher = WLAN_CIPHER_SUITE_SMS4;
+ break;
default:
return -EOPNOTSUPP;
}
@@ -953,17 +961,21 @@ static int cfg80211_set_wpa_version(struct
wireless_dev *wdev, u32 wpa_versions)
{
if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA |
IW_AUTH_WPA_VERSION_WPA2|
+ IW_AUTH_WPA_VERSION_WAPI|
IW_AUTH_WPA_VERSION_DISABLED))
return -EINVAL;
if ((wpa_versions & IW_AUTH_WPA_VERSION_DISABLED) &&
(wpa_versions & (IW_AUTH_WPA_VERSION_WPA|
- IW_AUTH_WPA_VERSION_WPA2)))
+ IW_AUTH_WPA_VERSION_WPA2|
+ IW_AUTH_WPA_VERSION_WAPI)))
return -EINVAL;
if (wpa_versions & IW_AUTH_WPA_VERSION_DISABLED)
wdev->wext.connect.crypto.wpa_versions &=
- ~(NL80211_WPA_VERSION_1|NL80211_WPA_VERSION_2);
+ ~(NL80211_WPA_VERSION_1|
+ NL80211_WPA_VERSION_2|
+ NL80211_WAPI_VERSION_1);
if (wpa_versions & IW_AUTH_WPA_VERSION_WPA)
wdev->wext.connect.crypto.wpa_versions |=
@@ -973,6 +985,10 @@ static int cfg80211_set_wpa_version(struct
wireless_dev *wdev, u32 wpa_versions)
wdev->wext.connect.crypto.wpa_versions |=
NL80211_WPA_VERSION_2;
+ if (wpa_versions & IW_AUTH_WPA_VERSION_WAPI)
+ wdev->wext.connect.crypto.wpa_versions |=
+ NL80211_WAPI_VERSION_1;
+
return 0;
}
@@ -995,6 +1011,9 @@ static int cfg80211_set_cipher_group(struct
wireless_dev *wdev, u32 cipher)
WLAN_CIPHER_SUITE_AES_CMAC;
else if (cipher & IW_AUTH_CIPHER_NONE)
wdev->wext.connect.crypto.cipher_group = 0;
+ else if (cipher & IW_AUTH_CIPHER_SMS4)
+ wdev->wext.connect.crypto.cipher_group =
+ WLAN_CIPHER_SUITE_SMS4;
else
return -EINVAL;
@@ -1031,7 +1050,12 @@ static int cfg80211_set_cipher_pairwise(struct
wireless_dev *wdev, u32 cipher)
nr_ciphers++;
}
- BUILD_BUG_ON(NL80211_MAX_NR_CIPHER_SUITES < 5);
+ if (cipher & IW_AUTH_CIPHER_SMS4) {
+ ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_SMS4;
+ nr_ciphers++;
+ }
+
+ BUILD_BUG_ON(NL80211_MAX_NR_CIPHER_SUITES < 6);
wdev->wext.connect.crypto.n_ciphers_pairwise = nr_ciphers;
@@ -1044,7 +1068,8 @@ static int cfg80211_set_key_mgt(struct wireless_dev
*wdev, u32 key_mgt)
int nr_akm_suites = 0;
if (key_mgt & ~(IW_AUTH_KEY_MGMT_802_1X |
- IW_AUTH_KEY_MGMT_PSK))
+ IW_AUTH_KEY_MGMT_PSK |
+ IW_AUTH_KEY_MGMT_WAPI_PSK))
return -EINVAL;
if (key_mgt & IW_AUTH_KEY_MGMT_802_1X) {
@@ -1059,6 +1084,12 @@ static int cfg80211_set_key_mgt(struct wireless_dev
*wdev, u32 key_mgt)
nr_akm_suites++;
}
+ if (key_mgt & IW_AUTH_KEY_MGMT_WAPI_PSK) {
+ wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
+ WLAN_AKM_SUITE_WAPI_PSK;
+ nr_akm_suites++;
+ }
+
wdev->wext.connect.crypto.n_akm_suites = nr_akm_suites;
return 0;
--
1.7.1
Hi Dmitry,
Some minor comments on your patch:
Note that I'm not a maintainer and that these are comments on the
patch itself, not the code it adds.
On Wed, Oct 12, 2011 at 12:02, Dmitry Tarnyagin <[email protected]> wrote:
> From: Janusz Dziedzic <[email protected]>
> Date: Wed, 1 Jun 2011 14:40:13 +0200
>
> This commit implements WAPI support for hardware-accelerated devices.
>
> Signed-off-by: Dmitry Tarnyagin <[email protected]>
> ---
> diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
> index 48363c3..bf86b0d 100644
> --- a/include/linux/ieee80211.h
> +++ b/include/linux/ieee80211.h
> @@ -1551,12 +1552,14 @@ enum ieee80211_sa_query_action {
> ?#define WLAN_CIPHER_SUITE_CCMP ? ? ? ? 0x000FAC04
> ?#define WLAN_CIPHER_SUITE_WEP104 ? ? ? 0x000FAC05
> ?#define WLAN_CIPHER_SUITE_AES_CMAC ? ? 0x000FAC06
> +#define WLAN_CIPHER_SUITE_SMS4 ? ? ? ? 0x000FAC07
>
> ?/* AKM suite selectors */
> ?#define WLAN_AKM_SUITE_8021X ? ? ? ? ? 0x000FAC01
> ?#define WLAN_AKM_SUITE_PSK ? ? ? ? ? ? 0x000FAC02
> ?#define WLAN_AKM_SUITE_SAE ? ? ? ? ? ? ? ? ? ? 0x000FAC08
> ?#define WLAN_AKM_SUITE_FT_OVER_SAE ? ? 0x000FAC09
> +#define WLAN_AKM_SUITE_WAPI_PSK ? ? ? ? ? ? ? ?0x000FAC03
Should these go in numerical order?
> diff --git a/net/mac80211/wapi.h b/net/mac80211/wapi.h
> new file mode 100644
> index 0000000..f06eee0
> --- /dev/null
> +++ b/net/mac80211/wapi.h
> @@ -0,0 +1,27 @@
[snip]
> +#ifndef ETH_P_WAPI
> +#define ETH_P_WAPI ? ? 0x88B4
> +#endif
Should this go somewhere else? Maybe where the other ETH_P_* #defines
are defined?
Thanks,
--
Julian Calaby
Email: [email protected]
Profile: http://www.google.com/profiles/julian.calaby/
.Plan: http://sites.google.com/site/juliancalaby/
On Wed, Oct 12, 2011 at 03:02:29AM +0200, Dmitry Tarnyagin wrote:
> diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
> @@ -1551,12 +1552,14 @@ enum ieee80211_sa_query_action {
> #define WLAN_CIPHER_SUITE_CCMP 0x000FAC04
> #define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
> #define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
> +#define WLAN_CIPHER_SUITE_SMS4 0x000FAC07
>
> /* AKM suite selectors */
> #define WLAN_AKM_SUITE_8021X 0x000FAC01
> #define WLAN_AKM_SUITE_PSK 0x000FAC02
> #define WLAN_AKM_SUITE_SAE 0x000FAC08
> #define WLAN_AKM_SUITE_FT_OVER_SAE 0x000FAC09
> +#define WLAN_AKM_SUITE_WAPI_PSK 0x000FAC03
Where do these values come from?
00-0F-AC:7 cipher suite selector has already been allocated for other
purposes ("Group addressed traffic not allowed") and similarly, AKM
suite 00-0F-AC:3 is already in use ("FT authentication negotiated over
IEEE 802.1X"). The 00-0F-AC OUI is managed by IEEE 802.11 and you cannot
just pick a random suite type from that OUI and hope for the best. This
will result in conflicts with other uses.
These need to be either allocated by IEEE 802.11 ANA or maybe more
likely, by any vendor that has their own OUI could allocate a unique
identifier for this purpose.
--
Jouni Malinen PGP id EFC895FA
Hi Dmitry,
Thanks for sending these patches.
Process things first: Your patches are line-wrapped in a few places.
You'll have to fix that later (but it's not very important for the first
round of review)
> This commit implements WAPI support for hardware-accelerated devices.
Note that there's at least one device that supports WAPI already, it has
HW crypto for SMS4. So it is already possible to implement. I'm not
saying this patch is bad though, it may be good to make things gradually
more generic.
> --- a/include/linux/wireless.h
> +++ b/include/linux/wireless.h
> @@ -586,6 +586,7 @@
> #define IW_AUTH_WPA_VERSION_DISABLED 0x00000001
> #define IW_AUTH_WPA_VERSION_WPA 0x00000002
> #define IW_AUTH_WPA_VERSION_WPA2 0x00000004
> +#define IW_AUTH_WPA_VERSION_WAPI 0x00000008
I don't think we should be extending wireless extensions any more, so
please remove all the wireless extensions bits from your patch(es).
> --- a/net/mac80211/Makefile
This patch is changing both mac80211 and cfg80211. I'd prefer to have
clearly separated patches so it is easier to tell which part is mac80211
specific and which will apply to other drivers that don't use mac80211.
> +++ b/net/mac80211/ieee80211_i.h
> @@ -42,7 +42,7 @@ struct ieee80211_local;
> #define TOTAL_MAX_TX_BUFFER 512
>
> /* Required encryption head and tailroom */
> -#define IEEE80211_ENCRYPT_HEADROOM 8
> +#define IEEE80211_ENCRYPT_HEADROOM 20
Hmm. This is pretty wasteful. Is this really the only way you can do
this?
> --- a/net/mac80211/main.c
> +++ b/net/mac80211/main.c
> @@ -716,6 +716,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
> WLAN_CIPHER_SUITE_WEP104,
> WLAN_CIPHER_SUITE_TKIP,
> WLAN_CIPHER_SUITE_CCMP,
> + WLAN_CIPHER_SUITE_SMS4,
This is quite clearly not true -- you don't support SMS4 unless the
hardware has support for it. As a result, you can't put this here -- you
need to make your low-level driver override the cipher list. See wl12xx
for example.
> --- a/net/mac80211/tx.c
> +++ b/net/mac80211/tx.c
> @@ -31,6 +31,7 @@
> #include "mesh.h"
> #include "wep.h"
> #include "wpa.h"
> +#include "wapi.h"
> #include "wme.h"
> #include "rate.h"
>
> @@ -592,6 +593,11 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data
> *tx)
> if (!ieee80211_is_mgmt(hdr->frame_control))
> tx->key = NULL;
> break;
> +
> + case WLAN_CIPHER_SUITE_SMS4:
> + if (tx->ethertype == ETH_P_WAPI)
> + tx->key = NULL;
> + break;
This is wrong -- and already covered by
ieee80211_tx_h_check_control_port_protocol() if you set that up
correctly from nl80211. Another reason to get rid of wireless extensions
support for this.
> +static int ieee80211_wapi_decrypt(struct ieee80211_local *local,
> + struct sk_buff *skb,
> + struct ieee80211_key *key)
> +{
> + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
> + int hdrlen = ieee80211_hdrlen(hdr->frame_control);
> + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
> + int data_len;
> +
> + if (!(status->flag & RX_FLAG_DECRYPTED)) {
> + /* TODO - SMS4 decryption for firmware without
> + * SMS4 support */
> + return RX_DROP_UNUSABLE;
> + }
> +
> +
> + data_len = skb->len - hdrlen - WAPI_IV_LEN - WAPI_ICV_LEN;
> + if (data_len < 0)
> + return RX_DROP_UNUSABLE;
> +
> + /* Trim ICV */
> + skb_trim(skb, skb->len - WAPI_ICV_LEN);
> +
> + /* Remove IV */
> + memmove(skb->data + WAPI_IV_LEN, skb->data, hdrlen);
> + skb_pull(skb, WAPI_IV_LEN);
> +
> + return RX_CONTINUE;
This is wrong -- if the device didn't strip the IV it likely also didn't
*check* the IV, so it should be checked here. If it *did* check the IV
then we expect drivers to strip it as well.
> +}
> +
> +ieee80211_rx_result
> +ieee80211_crypto_wapi_decrypt(struct ieee80211_rx_data *rx)
> +{
> + struct sk_buff *skb = rx->skb;
> + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
> +
> + if (!ieee80211_is_data(hdr->frame_control))
> + return RX_CONTINUE;
This probably needs to check data_present, not is_data. But again, I
think if you just strip the IV you can simplify this and move it into
the driver, like wl12xx, unless you need to verify the IV.
> +++ b/net/mac80211/wapi.h
This header file is unnecessary.
> +#ifndef ETH_P_WAPI
> +#define ETH_P_WAPI 0x88B4
> +#endif
This you don't actually need any more given my comments above.
> +ieee80211_rx_result
> +ieee80211_crypto_wapi_decrypt(struct ieee80211_rx_data *rx);
We can stick that into wpa.h. It also needs to be renamed -- it's not
doing decryption. I think you should get rid of it unless you need it to
check IVs.
> @@ -4167,7 +4167,8 @@ static bool nl80211_valid_auth_type(enum
> nl80211_auth_type auth_type)
> static bool nl80211_valid_wpa_versions(u32 wpa_versions)
> {
> return !(wpa_versions & ~(NL80211_WPA_VERSION_1 |
> - NL80211_WPA_VERSION_2));
> + NL80211_WPA_VERSION_2 |
> + NL80211_WAPI_VERSION_1));
> }
If your device is a mac80211 device then this isn't really needed.
johannes