aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-sta.c
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2008-04-17 19:03:36 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-07 15:02:11 -0400
commit3ec47732a0be038f15a0b8d852a4e4ff9c5b0196 (patch)
tree2cb45a6582df77a571554850152256df611ce094 /drivers/net/wireless/iwlwifi/iwl-sta.c
parentc6adbd2158fee972adcc6232de5e2ef375f1f782 (diff)
iwlwifi: HW crypto acceleration fixes
This patch fixes several issues in security: 1) the uCode doesn't know about TKIP-MMIC failure, if uCode set RX_RES_STATUS_BAD_ICV_MIC, it means ICV failure: drop the packet silently. 2) do not allocate room in the key table of the uCode is the set_key call is a replacement of an old key 3) check the keyidx of the key in the uCode before removing it upon disable_key call 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/iwl-sta.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c53
1 files changed, 44 insertions, 9 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index fa463ce6399b..d39ac1cffb57 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -207,10 +207,14 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
207 memcpy(&priv->stations[sta_id].sta.key.key[3], 207 memcpy(&priv->stations[sta_id].sta.key.key[3],
208 keyconf->key, keyconf->keylen); 208 keyconf->key, keyconf->keylen);
209 209
210 priv->stations[sta_id].sta.key.key_offset = 210 if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
211 == STA_KEY_FLG_NO_ENC)
212 priv->stations[sta_id].sta.key.key_offset =
211 iwl_get_free_ucode_key_index(priv); 213 iwl_get_free_ucode_key_index(priv);
212 priv->stations[sta_id].sta.key.key_flags = key_flags; 214 /* else, we are overriding an existing key => no need to allocated room
215 * in uCode. */
213 216
217 priv->stations[sta_id].sta.key.key_flags = key_flags;
214 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; 218 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
215 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 219 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
216 220
@@ -249,8 +253,13 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
249 memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 253 memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
250 keyconf->keylen); 254 keyconf->keylen);
251 255
252 priv->stations[sta_id].sta.key.key_offset = 256 if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
253 iwl_get_free_ucode_key_index(priv); 257 == STA_KEY_FLG_NO_ENC)
258 priv->stations[sta_id].sta.key.key_offset =
259 iwl_get_free_ucode_key_index(priv);
260 /* else, we are overriding an existing key => no need to allocated room
261 * in uCode. */
262
254 priv->stations[sta_id].sta.key.key_flags = key_flags; 263 priv->stations[sta_id].sta.key.key_flags = key_flags;
255 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; 264 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
256 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 265 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
@@ -278,8 +287,13 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
278 priv->stations[sta_id].keyinfo.alg = keyconf->alg; 287 priv->stations[sta_id].keyinfo.alg = keyconf->alg;
279 priv->stations[sta_id].keyinfo.conf = keyconf; 288 priv->stations[sta_id].keyinfo.conf = keyconf;
280 priv->stations[sta_id].keyinfo.keylen = 16; 289 priv->stations[sta_id].keyinfo.keylen = 16;
281 priv->stations[sta_id].sta.key.key_offset = 290
291 if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
292 == STA_KEY_FLG_NO_ENC)
293 priv->stations[sta_id].sta.key.key_offset =
282 iwl_get_free_ucode_key_index(priv); 294 iwl_get_free_ucode_key_index(priv);
295 /* else, we are overriding an existing key => no need to allocated room
296 * in uCode. */
283 297
284 /* This copy is acutally not needed: we get the key with each TX */ 298 /* This copy is acutally not needed: we get the key with each TX */
285 memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); 299 memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
@@ -291,13 +305,31 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
291 return ret; 305 return ret;
292} 306}
293 307
294int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id) 308int iwl_remove_dynamic_key(struct iwl_priv *priv,
309 struct ieee80211_key_conf *keyconf,
310 u8 sta_id)
295{ 311{
296 unsigned long flags; 312 unsigned long flags;
313 int ret = 0;
314 u16 key_flags;
315 u8 keyidx;
297 316
298 priv->key_mapping_key = 0; 317 priv->key_mapping_key = 0;
299 318
300 spin_lock_irqsave(&priv->sta_lock, flags); 319 spin_lock_irqsave(&priv->sta_lock, flags);
320 key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
321 keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
322
323 if (keyconf->keyidx != keyidx) {
324 /* We need to remove a key with index different that the one
325 * in the uCode. This means that the key we need to remove has
326 * been replaced by another one with different index.
327 * Don't do anything and return ok
328 */
329 spin_unlock_irqrestore(&priv->sta_lock, flags);
330 return 0;
331 }
332
301 if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset, 333 if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
302 &priv->ucode_key_table)) 334 &priv->ucode_key_table))
303 IWL_ERROR("index %d not used in uCode key table.\n", 335 IWL_ERROR("index %d not used in uCode key table.\n",
@@ -306,13 +338,16 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id)
306 sizeof(struct iwl4965_hw_key)); 338 sizeof(struct iwl4965_hw_key));
307 memset(&priv->stations[sta_id].sta.key, 0, 339 memset(&priv->stations[sta_id].sta.key, 0,
308 sizeof(struct iwl4965_keyinfo)); 340 sizeof(struct iwl4965_keyinfo));
309 priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; 341 priv->stations[sta_id].sta.key.key_flags =
342 STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
343 priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
310 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; 344 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
311 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 345 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
312 spin_unlock_irqrestore(&priv->sta_lock, flags);
313 346
314 IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n"); 347 IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n");
315 return iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0); 348 ret = iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0);
349 spin_unlock_irqrestore(&priv->sta_lock, flags);
350 return ret;
316} 351}
317 352
318int iwl_set_dynamic_key(struct iwl_priv *priv, 353int iwl_set_dynamic_key(struct iwl_priv *priv,