aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl4965-base.c
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2008-04-15 00:16:06 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-04-16 15:59:58 -0400
commit6974e36356524fa856435cb1be40aaffbac9601a (patch)
treec5a98e784ce1d5c20ce99dec5ffcc7b1bca46efa /drivers/net/wireless/iwlwifi/iwl4965-base.c
parent0a0bed1d10105a9f58cd14ebe216e8479dd31fda (diff)
iwlwifi: default WEP HW encryption
This patch adds HW encryption support in default WEP mode. When no key mapping key/pairwise key is used. The key is broadcast key is used as default/global/static key. This code assumes that group cast key is added after pairwise key. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl4965-base.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c90
1 files changed, 51 insertions, 39 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index ecc9cba62bf9..dfd2b75492e6 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -50,6 +50,7 @@
50#include "iwl-core.h" 50#include "iwl-core.h"
51#include "iwl-io.h" 51#include "iwl-io.h"
52#include "iwl-helpers.h" 52#include "iwl-helpers.h"
53#include "iwl-sta.h"
53 54
54static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv, 55static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
55 struct iwl4965_tx_queue *txq); 56 struct iwl4965_tx_queue *txq);
@@ -941,6 +942,9 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
941 return -EIO; 942 return -EIO;
942 } 943 }
943 priv->assoc_station_added = 1; 944 priv->assoc_station_added = 1;
945 if (priv->default_wep_key &&
946 iwl_send_static_wepkey_cmd(priv, 0))
947 IWL_ERROR("Could not send WEP static key.\n");
944 } 948 }
945 949
946 return 0; 950 return 0;
@@ -1180,6 +1184,8 @@ static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
1180{ 1184{
1181 unsigned long flags; 1185 unsigned long flags;
1182 1186
1187 priv->key_mapping_key = 0;
1188
1183 spin_lock_irqsave(&priv->sta_lock, flags); 1189 spin_lock_irqsave(&priv->sta_lock, flags);
1184 memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl4965_hw_key)); 1190 memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl4965_hw_key));
1185 memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo)); 1191 memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo));
@@ -1198,6 +1204,8 @@ static int iwl4965_set_dynamic_key(struct iwl_priv *priv,
1198{ 1204{
1199 int ret; 1205 int ret;
1200 1206
1207 priv->key_mapping_key = 1;
1208
1201 switch (key->alg) { 1209 switch (key->alg) {
1202 case ALG_CCMP: 1210 case ALG_CCMP:
1203 ret = iwl4965_set_ccmp_dynamic_key_info(priv, key, sta_id); 1211 ret = iwl4965_set_ccmp_dynamic_key_info(priv, key, sta_id);
@@ -1216,23 +1224,6 @@ static int iwl4965_set_dynamic_key(struct iwl_priv *priv,
1216 return ret; 1224 return ret;
1217} 1225}
1218 1226
1219static int iwl4965_remove_static_key(struct iwl_priv *priv)
1220{
1221 int ret = -EOPNOTSUPP;
1222
1223 return ret;
1224}
1225
1226static int iwl4965_set_static_key(struct iwl_priv *priv,
1227 struct ieee80211_key_conf *key)
1228{
1229 if (key->alg == ALG_WEP)
1230 return -EOPNOTSUPP;
1231
1232 IWL_ERROR("Static key invalid: alg %d\n", key->alg);
1233 return -EINVAL;
1234}
1235
1236static void iwl4965_clear_free_frames(struct iwl_priv *priv) 1227static void iwl4965_clear_free_frames(struct iwl_priv *priv)
1237{ 1228{
1238 struct list_head *element; 1229 struct list_head *element;
@@ -2115,6 +2106,10 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
2115 int sta_id) 2106 int sta_id)
2116{ 2107{
2117 struct iwl4965_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; 2108 struct iwl4965_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
2109 struct iwl_wep_key *wepkey;
2110 int keyidx = 0;
2111
2112 BUG_ON(ctl->key_idx > 3);
2118 2113
2119 switch (keyinfo->alg) { 2114 switch (keyinfo->alg) {
2120 case ALG_CCMP: 2115 case ALG_CCMP:
@@ -2133,16 +2128,24 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
2133 break; 2128 break;
2134 2129
2135 case ALG_WEP: 2130 case ALG_WEP:
2136 cmd->cmd.tx.sec_ctl = TX_CMD_SEC_WEP | 2131 wepkey = &priv->wep_keys[ctl->key_idx];
2137 (ctl->key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; 2132 cmd->cmd.tx.sec_ctl = 0;
2138 2133 if (priv->default_wep_key) {
2139 if (keyinfo->keylen == 13) 2134 /* the WEP key was sent as static */
2140 cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; 2135 keyidx = ctl->key_idx;
2136 memcpy(&cmd->cmd.tx.key[3], wepkey->key,
2137 wepkey->key_size);
2138 if (wepkey->key_size == WEP_KEY_LEN_128)
2139 cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
2140 } else {
2141 IWL_ERROR("No support for WEP key mappings key\n");
2142 }
2141 2143
2142 memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen); 2144 cmd->cmd.tx.sec_ctl |= (TX_CMD_SEC_WEP |
2145 (keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
2143 2146
2144 IWL_DEBUG_TX("Configuring packet for WEP encryption " 2147 IWL_DEBUG_TX("Configuring packet for WEP encryption "
2145 "with key %d\n", ctl->key_idx); 2148 "with key %d\n", keyidx);
2146 break; 2149 break;
2147 2150
2148 default: 2151 default:
@@ -6989,7 +6992,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
6989 DECLARE_MAC_BUF(mac); 6992 DECLARE_MAC_BUF(mac);
6990 int ret = 0; 6993 int ret = 0;
6991 u8 sta_id = IWL_INVALID_STATION; 6994 u8 sta_id = IWL_INVALID_STATION;
6992 u8 static_key; 6995 u8 is_default_wep_key = 0;
6993 6996
6994 IWL_DEBUG_MAC80211("enter\n"); 6997 IWL_DEBUG_MAC80211("enter\n");
6995 6998
@@ -7002,33 +7005,42 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
7002 /* only support pairwise keys */ 7005 /* only support pairwise keys */
7003 return -EOPNOTSUPP; 7006 return -EOPNOTSUPP;
7004 7007
7005 /* FIXME: need to differenciate between static and dynamic key 7008 sta_id = iwl4965_hw_find_station(priv, addr);
7006 * in the level of mac80211 */ 7009 if (sta_id == IWL_INVALID_STATION) {
7007 static_key = !iwl_is_associated(priv); 7010 IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
7011 print_mac(mac, addr));
7012 return -EINVAL;
7008 7013
7009 if (!static_key) {
7010 sta_id = iwl4965_hw_find_station(priv, addr);
7011 if (sta_id == IWL_INVALID_STATION) {
7012 IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
7013 print_mac(mac, addr));
7014 return -EINVAL;
7015 }
7016 } 7014 }
7017 7015
7016 mutex_lock(&priv->mutex);
7018 iwl4965_scan_cancel_timeout(priv, 100); 7017 iwl4965_scan_cancel_timeout(priv, 100);
7018 mutex_unlock(&priv->mutex);
7019
7020 /* If we are getting WEP group key and we didn't receive any key mapping
7021 * so far, we are in legacy wep mode (group key only), otherwise we are
7022 * in 1X mode.
7023 * In legacy wep mode, we use another host command to the uCode */
7024 if (key->alg == ALG_WEP && sta_id == priv->hw_setting.bcast_sta_id &&
7025 priv->iw_mode != IEEE80211_IF_TYPE_AP) {
7026 if (cmd == SET_KEY)
7027 is_default_wep_key = !priv->key_mapping_key;
7028 else
7029 is_default_wep_key = priv->default_wep_key;
7030 }
7019 7031
7020 switch (cmd) { 7032 switch (cmd) {
7021 case SET_KEY: 7033 case SET_KEY:
7022 if (static_key) 7034 if (is_default_wep_key)
7023 ret = iwl4965_set_static_key(priv, key); 7035 ret = iwl_set_default_wep_key(priv, key);
7024 else 7036 else
7025 ret = iwl4965_set_dynamic_key(priv, key, sta_id); 7037 ret = iwl4965_set_dynamic_key(priv, key, sta_id);
7026 7038
7027 IWL_DEBUG_MAC80211("enable hwcrypto key\n"); 7039 IWL_DEBUG_MAC80211("enable hwcrypto key\n");
7028 break; 7040 break;
7029 case DISABLE_KEY: 7041 case DISABLE_KEY:
7030 if (static_key) 7042 if (is_default_wep_key)
7031 ret = iwl4965_remove_static_key(priv); 7043 ret = iwl_remove_default_wep_key(priv, key);
7032 else 7044 else
7033 ret = iwl4965_clear_sta_key_info(priv, sta_id); 7045 ret = iwl4965_clear_sta_key_info(priv, sta_id);
7034 7046