diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2008-04-15 00:16:06 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-04-16 15:59:58 -0400 |
commit | 6974e36356524fa856435cb1be40aaffbac9601a (patch) | |
tree | c5a98e784ce1d5c20ce99dec5ffcc7b1bca46efa /drivers/net/wireless/iwlwifi/iwl4965-base.c | |
parent | 0a0bed1d10105a9f58cd14ebe216e8479dd31fda (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.c | 90 |
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 | ||
54 | static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv, | 55 | static 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 | ||
1219 | static int iwl4965_remove_static_key(struct iwl_priv *priv) | ||
1220 | { | ||
1221 | int ret = -EOPNOTSUPP; | ||
1222 | |||
1223 | return ret; | ||
1224 | } | ||
1225 | |||
1226 | static 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 | |||
1236 | static void iwl4965_clear_free_frames(struct iwl_priv *priv) | 1227 | static 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 | ||