aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx
diff options
context:
space:
mode:
authorJuuso Oikarinen <juuso.oikarinen@nokia.com>2009-10-08 14:56:19 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-10-27 16:47:48 -0400
commitac4e4ce54eb9cb4963a1d3d91fc65536d882ffb2 (patch)
tree7ce830794c7029ab65ecb00562e48d00acc98d87 /drivers/net/wireless/wl12xx
parent3b4be9e08abd8c390d13001f5dd55f64afa5ab93 (diff)
wl1271: Security sequence number handling for TX (for WPA)
Add security sequence number handling to the driver TX data path needed by WPA. Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com> Reviewed-by: Kalle Valo <kalle.valo@nokia.com> Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx')
-rw-r--r--drivers/net/wireless/wl12xx/wl1271.h5
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_cmd.c11
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_cmd.h3
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_main.c13
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_tx.c11
5 files changed, 38 insertions, 5 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 55818f94017..e575dcc9df2 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -337,6 +337,11 @@ struct wl1271 {
337 /* Pending TX frames */ 337 /* Pending TX frames */
338 struct sk_buff *tx_frames[16]; 338 struct sk_buff *tx_frames[16];
339 339
340 /* Security sequence number counters */
341 u8 tx_security_last_seq;
342 u16 tx_security_seq_16;
343 u32 tx_security_seq_32;
344
340 /* FW Rx counter */ 345 /* FW Rx counter */
341 u32 rx_counter; 346 u32 rx_counter;
342 347
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 2a4351ff54d..1ee1b2b4dfa 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -228,6 +228,10 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval,
228 228
229 join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET; 229 join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET;
230 230
231 /* reset TX security counters */
232 wl->tx_security_last_seq = 0;
233 wl->tx_security_seq_16 = 0;
234 wl->tx_security_seq_32 = 0;
231 235
232 ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join)); 236 ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join));
233 if (ret < 0) { 237 if (ret < 0) {
@@ -759,7 +763,8 @@ out:
759} 763}
760 764
761int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, 765int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
762 u8 key_size, const u8 *key, const u8 *addr) 766 u8 key_size, const u8 *key, const u8 *addr,
767 u32 tx_seq_32, u16 tx_seq_16)
763{ 768{
764 struct wl1271_cmd_set_keys *cmd; 769 struct wl1271_cmd_set_keys *cmd;
765 int ret = 0; 770 int ret = 0;
@@ -777,12 +782,14 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
777 cmd->key_size = key_size; 782 cmd->key_size = key_size;
778 cmd->key_type = key_type; 783 cmd->key_type = key_type;
779 784
785 cmd->ac_seq_num16[0] = tx_seq_16;
786 cmd->ac_seq_num32[0] = tx_seq_32;
787
780 /* we have only one SSID profile */ 788 /* we have only one SSID profile */
781 cmd->ssid_profile = 0; 789 cmd->ssid_profile = 0;
782 790
783 cmd->id = id; 791 cmd->id = id;
784 792
785 /* FIXME: this is from wl1251, needs to be checked */
786 if (key_type == KEY_TKIP) { 793 if (key_type == KEY_TKIP) {
787 /* 794 /*
788 * We get the key in the following form: 795 * We get the key in the following form:
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index 951a8447a51..7c4d3aaaa81 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -49,7 +49,8 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid);
49int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len); 49int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len);
50int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); 50int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id);
51int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, 51int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
52 u8 key_size, const u8 *key, const u8 *addr); 52 u8 key_size, const u8 *key, const u8 *addr,
53 u32 tx_seq_32, u16 tx_seq_16);
53 54
54enum wl1271_commands { 55enum wl1271_commands {
55 CMD_INTERROGATE = 1, /*use this to read information elements*/ 56 CMD_INTERROGATE = 1, /*use this to read information elements*/
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 27298b19d5b..bedd19b5749 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -592,6 +592,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
592 wl->tx_blocks_available = 0; 592 wl->tx_blocks_available = 0;
593 wl->tx_results_count = 0; 593 wl->tx_results_count = 0;
594 wl->tx_packets_count = 0; 594 wl->tx_packets_count = 0;
595 wl->tx_security_last_seq = 0;
596 wl->tx_security_seq_16 = 0;
597 wl->tx_security_seq_32 = 0;
595 wl->time_offset = 0; 598 wl->time_offset = 0;
596 wl->session_counter = 0; 599 wl->session_counter = 0;
597 for (i = 0; i < NUM_TX_QUEUES; i++) 600 for (i = 0; i < NUM_TX_QUEUES; i++)
@@ -823,6 +826,8 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
823 struct wl1271 *wl = hw->priv; 826 struct wl1271 *wl = hw->priv;
824 const u8 *addr; 827 const u8 *addr;
825 int ret; 828 int ret;
829 u32 tx_seq_32 = 0;
830 u16 tx_seq_16 = 0;
826 u8 key_type; 831 u8 key_type;
827 832
828 static const u8 bcast_addr[ETH_ALEN] = 833 static const u8 bcast_addr[ETH_ALEN] =
@@ -861,11 +866,15 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
861 key_type = KEY_TKIP; 866 key_type = KEY_TKIP;
862 867
863 key_conf->hw_key_idx = key_conf->keyidx; 868 key_conf->hw_key_idx = key_conf->keyidx;
869 tx_seq_32 = wl->tx_security_seq_32;
870 tx_seq_16 = wl->tx_security_seq_16;
864 break; 871 break;
865 case ALG_CCMP: 872 case ALG_CCMP:
866 key_type = KEY_AES; 873 key_type = KEY_AES;
867 874
868 key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 875 key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
876 tx_seq_32 = wl->tx_security_seq_32;
877 tx_seq_16 = wl->tx_security_seq_16;
869 break; 878 break;
870 default: 879 default:
871 wl1271_error("Unknown key algo 0x%x", key_conf->alg); 880 wl1271_error("Unknown key algo 0x%x", key_conf->alg);
@@ -879,7 +888,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
879 ret = wl1271_cmd_set_key(wl, KEY_ADD_OR_REPLACE, 888 ret = wl1271_cmd_set_key(wl, KEY_ADD_OR_REPLACE,
880 key_conf->keyidx, key_type, 889 key_conf->keyidx, key_type,
881 key_conf->keylen, key_conf->key, 890 key_conf->keylen, key_conf->key,
882 addr); 891 addr, tx_seq_32, tx_seq_16);
883 if (ret < 0) { 892 if (ret < 0) {
884 wl1271_error("Could not add or replace key"); 893 wl1271_error("Could not add or replace key");
885 goto out_sleep; 894 goto out_sleep;
@@ -890,7 +899,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
890 ret = wl1271_cmd_set_key(wl, KEY_REMOVE, 899 ret = wl1271_cmd_set_key(wl, KEY_REMOVE,
891 key_conf->keyidx, key_type, 900 key_conf->keyidx, key_type,
892 key_conf->keylen, key_conf->key, 901 key_conf->keylen, key_conf->key,
893 addr); 902 addr, 0, 0);
894 if (ret < 0) { 903 if (ret < 0) {
895 wl1271_error("Could not remove key"); 904 wl1271_error("Could not remove key");
896 goto out_sleep; 905 goto out_sleep;
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index 0c19688f440..162f0267a20 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -258,6 +258,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
258 struct ieee80211_tx_info *info; 258 struct ieee80211_tx_info *info;
259 struct sk_buff *skb; 259 struct sk_buff *skb;
260 u32 header_len; 260 u32 header_len;
261 u16 seq;
261 int id = result->id; 262 int id = result->id;
262 263
263 /* check for id legality */ 264 /* check for id legality */
@@ -284,6 +285,16 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
284 /* info->status.retry_count = result->ack_failures; */ 285 /* info->status.retry_count = result->ack_failures; */
285 wl->stats.retry_count += result->ack_failures; 286 wl->stats.retry_count += result->ack_failures;
286 287
288 /* update security sequence number */
289 seq = wl->tx_security_seq_16 +
290 (result->lsb_security_sequence_number -
291 wl->tx_security_last_seq);
292 wl->tx_security_last_seq = result->lsb_security_sequence_number;
293
294 if (seq < wl->tx_security_seq_16)
295 wl->tx_security_seq_32++;
296 wl->tx_security_seq_16 = seq;
297
287 /* get header len */ 298 /* get header len */
288 if (info->control.hw_key && 299 if (info->control.hw_key &&
289 info->control.hw_key->alg == ALG_TKIP) 300 info->control.hw_key->alg == ALG_TKIP)