aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-07-15 16:03:12 -0400
committerWey-Yi Guy <wey-yi.w.guy@intel.com>2011-07-21 10:31:25 -0400
commit5a3d9882b84edf5fa8e8ca33a5d6df25e2e727a5 (patch)
tree4dd345be2af270212e9bce75c4f9a639cc72b996 /drivers/net/wireless
parent0bfe9895d402faf03d5ccd30cc0e6bbad09e5bbc (diff)
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto is done wrong for GTKs: they should be programmed for the AP station ID (in the managed mode case) and the HW can actually deal with multiple group keys per station as well (which is useful in IBSS RSN but that I've chosen not to use this). To fix all this, modify the way keys are sent to the device and key offsets are allocated. After these changes, key offsets are stored into the hw_key_idx which we can then track for the key lifetime, not relying on our sta_cmd array. WEP default keys get special treatment, of course. Additionally, since I had the API for it, we can now pre-fill TKIP phase 1 keys for RX now that we can obtain the P1K from mac80211, a capability I had added for WoWLAN initially. Finally, some keys simply don't need to be added into the device's key cache -- a key that won't be used for RX is only needed in the TX header, so "pretend" to have accepted any key without adding it into the device -- no need to use up key space there for it. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-sta.c353
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c54
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.h5
6 files changed, 200 insertions, 224 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
index 395dee1c1440..7a2babe0dd4e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
@@ -139,6 +139,14 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx
139 return 0; 139 return 0;
140} 140}
141 141
142/*
143 * static WEP keys
144 *
145 * For each context, the device has a table of 4 static WEP keys
146 * (one for each key index) that is updated with the following
147 * commands.
148 */
149
142static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, 150static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
143 struct iwl_rxon_context *ctx, 151 struct iwl_rxon_context *ctx,
144 bool send_if_empty) 152 bool send_if_empty)
@@ -232,8 +240,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
232 return -EINVAL; 240 return -EINVAL;
233 } 241 }
234 242
235 keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; 243 keyconf->hw_key_idx = IWLAGN_HW_KEY_DEFAULT;
236 keyconf->hw_key_idx = HW_KEY_DEFAULT;
237 244
238 ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; 245 ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
239 memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key, 246 memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key,
@@ -246,147 +253,116 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
246 return ret; 253 return ret;
247} 254}
248 255
249static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, 256/*
250 struct iwl_rxon_context *ctx, 257 * dynamic (per-station) keys
251 struct ieee80211_key_conf *keyconf, 258 *
252 u8 sta_id) 259 * The dynamic keys are a little more complicated. The device has
253{ 260 * a key cache of up to STA_KEY_MAX_NUM/STA_KEY_MAX_NUM_PAN keys.
254 unsigned long flags; 261 * These are linked to stations by a table that contains an index
255 __le16 key_flags = 0; 262 * into the key table for each station/key index/{mcast,unicast},
256 struct iwl_addsta_cmd sta_cmd; 263 * i.e. it's basically an array of pointers like this:
257 264 * key_offset_t key_mapping[NUM_STATIONS][4][2];
258 lockdep_assert_held(&priv->mutex); 265 * (it really works differently, but you can think of it as such)
259 266 *
260 keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; 267 * The key uploading and linking happens in the same command, the
261 268 * add station command with STA_MODIFY_KEY_MASK.
262 key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK); 269 */
263 key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
264 key_flags &= ~STA_KEY_FLG_INVALID;
265
266 if (keyconf->keylen == WEP_KEY_LEN_128)
267 key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
268
269 if (sta_id == ctx->bcast_sta_id)
270 key_flags |= STA_KEY_MULTICAST_MSK;
271
272 spin_lock_irqsave(&priv->sta_lock, flags);
273
274 memcpy(&priv->stations[sta_id].sta.key.key[3],
275 keyconf->key, keyconf->keylen);
276
277 if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
278 == STA_KEY_FLG_NO_ENC)
279 priv->stations[sta_id].sta.key.key_offset =
280 iwl_get_free_ucode_key_index(priv);
281 /* else, we are overriding an existing key => no need to allocated room
282 * in uCode. */
283 270
284 WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, 271static u8 iwlagn_key_sta_id(struct iwl_priv *priv,
285 "no space for a new key"); 272 struct ieee80211_vif *vif,
273 struct ieee80211_sta *sta)
274{
275 struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
276 u8 sta_id = IWL_INVALID_STATION;
286 277
287 priv->stations[sta_id].sta.key.key_flags = key_flags; 278 if (sta)
288 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; 279 sta_id = iwl_sta_id(sta);
289 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
290 280
291 memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); 281 /*
292 spin_unlock_irqrestore(&priv->sta_lock, flags); 282 * The device expects GTKs for station interfaces to be
283 * installed as GTKs for the AP station. If we have no
284 * station ID, then use the ap_sta_id in that case.
285 */
286 if (!sta && vif && vif_priv->ctx) {
287 switch (vif->type) {
288 case NL80211_IFTYPE_STATION:
289 sta_id = vif_priv->ctx->ap_sta_id;
290 break;
291 default:
292 /*
293 * In all other cases, the key will be
294 * used either for TX only or is bound
295 * to a station already.
296 */
297 break;
298 }
299 }
293 300
294 return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); 301 return sta_id;
295} 302}
296 303
297static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, 304static int iwlagn_set_dynamic_key(struct iwl_priv *priv,
298 struct iwl_rxon_context *ctx, 305 struct ieee80211_key_conf *keyconf,
299 struct ieee80211_key_conf *keyconf, 306 u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k,
300 u8 sta_id) 307 u32 cmd_flags)
301{ 308{
302 unsigned long flags; 309 unsigned long flags;
303 __le16 key_flags = 0; 310 __le16 key_flags;
304 struct iwl_addsta_cmd sta_cmd; 311 struct iwl_addsta_cmd sta_cmd;
305 312 int i;
306 lockdep_assert_held(&priv->mutex);
307
308 key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
309 key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
310 key_flags &= ~STA_KEY_FLG_INVALID;
311
312 if (sta_id == ctx->bcast_sta_id)
313 key_flags |= STA_KEY_MULTICAST_MSK;
314
315 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
316
317 spin_lock_irqsave(&priv->sta_lock, flags); 313 spin_lock_irqsave(&priv->sta_lock, flags);
318 314 memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
319 memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
320 keyconf->keylen);
321
322 if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
323 == STA_KEY_FLG_NO_ENC)
324 priv->stations[sta_id].sta.key.key_offset =
325 iwl_get_free_ucode_key_index(priv);
326 /* else, we are overriding an existing key => no need to allocated room
327 * in uCode. */
328
329 WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
330 "no space for a new key");
331
332 priv->stations[sta_id].sta.key.key_flags = key_flags;
333 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
334 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
335
336 memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
337 spin_unlock_irqrestore(&priv->sta_lock, flags); 315 spin_unlock_irqrestore(&priv->sta_lock, flags);
338 316
339 return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); 317 key_flags = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
340} 318 key_flags |= STA_KEY_FLG_MAP_KEY_MSK;
341
342static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
343 struct iwl_rxon_context *ctx,
344 struct ieee80211_key_conf *keyconf,
345 u8 sta_id)
346{
347 unsigned long flags;
348 int ret = 0;
349 __le16 key_flags = 0;
350 319
351 key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK); 320 switch (keyconf->cipher) {
352 key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); 321 case WLAN_CIPHER_SUITE_CCMP:
353 key_flags &= ~STA_KEY_FLG_INVALID; 322 key_flags |= STA_KEY_FLG_CCMP;
323 memcpy(sta_cmd.key.key, keyconf->key, keyconf->keylen);
324 break;
325 case WLAN_CIPHER_SUITE_TKIP:
326 key_flags |= STA_KEY_FLG_TKIP;
327 sta_cmd.key.tkip_rx_tsc_byte2 = tkip_iv32;
328 for (i = 0; i < 5; i++)
329 sta_cmd.key.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]);
330 memcpy(sta_cmd.key.key, keyconf->key, keyconf->keylen);
331 break;
332 case WLAN_CIPHER_SUITE_WEP104:
333 key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
334 /* fall through */
335 case WLAN_CIPHER_SUITE_WEP40:
336 key_flags |= STA_KEY_FLG_WEP;
337 memcpy(&sta_cmd.key.key[3], keyconf->key, keyconf->keylen);
338 break;
339 default:
340 WARN_ON(1);
341 return -EINVAL;
342 }
354 343
355 if (sta_id == ctx->bcast_sta_id) 344 if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
356 key_flags |= STA_KEY_MULTICAST_MSK; 345 key_flags |= STA_KEY_MULTICAST_MSK;
357 346
358 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 347 /* key pointer (offset) */
359 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; 348 sta_cmd.key.key_offset = keyconf->hw_key_idx;
360
361 spin_lock_irqsave(&priv->sta_lock, flags);
362
363 if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
364 == STA_KEY_FLG_NO_ENC)
365 priv->stations[sta_id].sta.key.key_offset =
366 iwl_get_free_ucode_key_index(priv);
367 /* else, we are overriding an existing key => no need to allocated room
368 * in uCode. */
369
370 WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
371 "no space for a new key");
372 349
373 priv->stations[sta_id].sta.key.key_flags = key_flags; 350 sta_cmd.key.key_flags = key_flags;
351 sta_cmd.mode = STA_CONTROL_MODIFY_MSK;
352 sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK;
374 353
375 memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16); 354 return iwl_send_add_sta(priv, &sta_cmd, cmd_flags);
376
377 spin_unlock_irqrestore(&priv->sta_lock, flags);
378
379 return ret;
380} 355}
381 356
382void iwl_update_tkip_key(struct iwl_priv *priv, 357void iwl_update_tkip_key(struct iwl_priv *priv,
383 struct iwl_rxon_context *ctx, 358 struct ieee80211_vif *vif,
384 struct ieee80211_key_conf *keyconf, 359 struct ieee80211_key_conf *keyconf,
385 struct ieee80211_sta *sta, u32 iv32, u16 *phase1key) 360 struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
386{ 361{
387 u8 sta_id; 362 u8 sta_id = iwlagn_key_sta_id(priv, vif, sta);
388 unsigned long flags; 363
389 int i; 364 if (sta_id == IWL_INVALID_STATION)
365 return;
390 366
391 if (iwl_scan_cancel(priv)) { 367 if (iwl_scan_cancel(priv)) {
392 /* cancel scan failed, just live w/ bad key and rely 368 /* cancel scan failed, just live w/ bad key and rely
@@ -394,119 +370,110 @@ void iwl_update_tkip_key(struct iwl_priv *priv,
394 return; 370 return;
395 } 371 }
396 372
397 sta_id = iwl_sta_id_or_broadcast(priv, ctx, sta); 373 iwlagn_set_dynamic_key(priv, keyconf, sta_id,
398 if (sta_id == IWL_INVALID_STATION) 374 iv32, phase1key, CMD_ASYNC);
399 return;
400
401 spin_lock_irqsave(&priv->sta_lock, flags);
402
403 priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
404
405 for (i = 0; i < 5; i++)
406 priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
407 cpu_to_le16(phase1key[i]);
408
409 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
410 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
411
412 iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
413
414 spin_unlock_irqrestore(&priv->sta_lock, flags);
415
416} 375}
417 376
418int iwl_remove_dynamic_key(struct iwl_priv *priv, 377int iwl_remove_dynamic_key(struct iwl_priv *priv,
419 struct iwl_rxon_context *ctx, 378 struct iwl_rxon_context *ctx,
420 struct ieee80211_key_conf *keyconf, 379 struct ieee80211_key_conf *keyconf,
421 u8 sta_id) 380 struct ieee80211_sta *sta)
422{ 381{
423 unsigned long flags; 382 unsigned long flags;
424 u16 key_flags;
425 u8 keyidx;
426 struct iwl_addsta_cmd sta_cmd; 383 struct iwl_addsta_cmd sta_cmd;
384 u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta);
385
386 /* if station isn't there, neither is the key */
387 if (sta_id == IWL_INVALID_STATION)
388 return -ENOENT;
389
390 spin_lock_irqsave(&priv->sta_lock, flags);
391 memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
392 if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE))
393 sta_id = IWL_INVALID_STATION;
394 spin_unlock_irqrestore(&priv->sta_lock, flags);
395
396 if (sta_id == IWL_INVALID_STATION)
397 return 0;
427 398
428 lockdep_assert_held(&priv->mutex); 399 lockdep_assert_held(&priv->mutex);
429 400
430 ctx->key_mapping_keys--; 401 ctx->key_mapping_keys--;
431 402
432 spin_lock_irqsave(&priv->sta_lock, flags);
433 key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
434 keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
435
436 IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n", 403 IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n",
437 keyconf->keyidx, sta_id); 404 keyconf->keyidx, sta_id);
438 405
439 if (keyconf->keyidx != keyidx) { 406 if (!test_and_clear_bit(keyconf->hw_key_idx, &priv->ucode_key_table))
440 /* We need to remove a key with index different that the one 407 IWL_ERR(priv, "offset %d not used in uCode key table.\n",
441 * in the uCode. This means that the key we need to remove has 408 keyconf->hw_key_idx);
442 * been replaced by another one with different index.
443 * Don't do anything and return ok
444 */
445 spin_unlock_irqrestore(&priv->sta_lock, flags);
446 return 0;
447 }
448
449 if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
450 IWL_WARN(priv, "Removing wrong key %d 0x%x\n",
451 keyconf->keyidx, key_flags);
452 spin_unlock_irqrestore(&priv->sta_lock, flags);
453 return 0;
454 }
455
456 if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
457 &priv->ucode_key_table))
458 IWL_ERR(priv, "index %d not used in uCode key table.\n",
459 priv->stations[sta_id].sta.key.key_offset);
460 memset(&priv->stations[sta_id].sta.key, 0,
461 sizeof(struct iwl_keyinfo));
462 priv->stations[sta_id].sta.key.key_flags =
463 STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
464 priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
465 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
466 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
467 409
468 if (iwl_is_rfkill(priv)) { 410 sta_cmd.key.key_flags = STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
469 IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled.\n"); 411 sta_cmd.key.key_offset = WEP_INVALID_OFFSET;
470 spin_unlock_irqrestore(&priv->sta_lock, flags); 412 sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK;
471 return 0; 413 sta_cmd.mode = STA_CONTROL_MODIFY_MSK;
472 }
473 memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
474 spin_unlock_irqrestore(&priv->sta_lock, flags);
475 414
476 return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); 415 return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
477} 416}
478 417
479int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, 418int iwl_set_dynamic_key(struct iwl_priv *priv,
480 struct ieee80211_key_conf *keyconf, u8 sta_id) 419 struct iwl_rxon_context *ctx,
420 struct ieee80211_key_conf *keyconf,
421 struct ieee80211_sta *sta)
481{ 422{
423 struct ieee80211_key_seq seq;
424 u16 p1k[5];
482 int ret; 425 int ret;
426 u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta);
427 const u8 *addr;
428
429 if (sta_id == IWL_INVALID_STATION)
430 return -EINVAL;
483 431
484 lockdep_assert_held(&priv->mutex); 432 lockdep_assert_held(&priv->mutex);
485 433
434 keyconf->hw_key_idx = iwl_get_free_ucode_key_offset(priv);
435 if (keyconf->hw_key_idx == WEP_INVALID_OFFSET)
436 return -ENOSPC;
437
486 ctx->key_mapping_keys++; 438 ctx->key_mapping_keys++;
487 keyconf->hw_key_idx = HW_KEY_DYNAMIC;
488 439
489 switch (keyconf->cipher) { 440 switch (keyconf->cipher) {
490 case WLAN_CIPHER_SUITE_CCMP:
491 ret = iwl_set_ccmp_dynamic_key_info(priv, ctx, keyconf, sta_id);
492 break;
493 case WLAN_CIPHER_SUITE_TKIP: 441 case WLAN_CIPHER_SUITE_TKIP:
494 ret = iwl_set_tkip_dynamic_key_info(priv, ctx, keyconf, sta_id); 442 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
443 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
444
445 if (sta)
446 addr = sta->addr;
447 else /* station mode case only */
448 addr = ctx->active.bssid_addr;
449
450 /* pre-fill phase 1 key into device cache */
451 ieee80211_get_key_rx_seq(keyconf, 0, &seq);
452 ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
453 ret = iwlagn_set_dynamic_key(priv, keyconf, sta_id,
454 seq.tkip.iv32, p1k, CMD_SYNC);
495 break; 455 break;
456 case WLAN_CIPHER_SUITE_CCMP:
457 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
458 /* fall through */
496 case WLAN_CIPHER_SUITE_WEP40: 459 case WLAN_CIPHER_SUITE_WEP40:
497 case WLAN_CIPHER_SUITE_WEP104: 460 case WLAN_CIPHER_SUITE_WEP104:
498 ret = iwl_set_wep_dynamic_key_info(priv, ctx, keyconf, sta_id); 461 ret = iwlagn_set_dynamic_key(priv, keyconf, sta_id,
462 0, NULL, CMD_SYNC);
499 break; 463 break;
500 default: 464 default:
501 IWL_ERR(priv, 465 IWL_ERR(priv, "Unknown cipher %x\n", keyconf->cipher);
502 "Unknown alg: %s cipher = %x\n", __func__,
503 keyconf->cipher);
504 ret = -EINVAL; 466 ret = -EINVAL;
505 } 467 }
506 468
507 IWL_DEBUG_WEP(priv, "Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n", 469 if (ret) {
470 ctx->key_mapping_keys--;
471 clear_bit(keyconf->hw_key_idx, &priv->ucode_key_table);
472 }
473
474 IWL_DEBUG_WEP(priv, "Set dynamic key: cipher=%x len=%d idx=%d sta=%pM ret=%d\n",
508 keyconf->cipher, keyconf->keylen, keyconf->keyidx, 475 keyconf->cipher, keyconf->keylen, keyconf->keyidx,
509 sta_id, ret); 476 sta ? sta->addr : NULL, ret);
510 477
511 return ret; 478 return ret;
512} 479}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 6df244387b2f..0bab19563394 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2259,14 +2259,8 @@ static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
2259 u32 iv32, u16 *phase1key) 2259 u32 iv32, u16 *phase1key)
2260{ 2260{
2261 struct iwl_priv *priv = hw->priv; 2261 struct iwl_priv *priv = hw->priv;
2262 struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
2263
2264 IWL_DEBUG_MAC80211(priv, "enter\n");
2265 2262
2266 iwl_update_tkip_key(priv, vif_priv->ctx, keyconf, sta, 2263 iwl_update_tkip_key(priv, vif, keyconf, sta, iv32, phase1key);
2267 iv32, phase1key);
2268
2269 IWL_DEBUG_MAC80211(priv, "leave\n");
2270} 2264}
2271 2265
2272static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 2266static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
@@ -2278,7 +2272,6 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
2278 struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; 2272 struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
2279 struct iwl_rxon_context *ctx = vif_priv->ctx; 2273 struct iwl_rxon_context *ctx = vif_priv->ctx;
2280 int ret; 2274 int ret;
2281 u8 sta_id;
2282 bool is_default_wep_key = false; 2275 bool is_default_wep_key = false;
2283 2276
2284 IWL_DEBUG_MAC80211(priv, "enter\n"); 2277 IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -2289,20 +2282,27 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
2289 } 2282 }
2290 2283
2291 /* 2284 /*
2292 * To support IBSS RSN, don't program group keys in IBSS, the 2285 * We could program these keys into the hardware as well, but we
2293 * hardware will then not attempt to decrypt the frames. 2286 * don't expect much multicast traffic in IBSS and having keys
2287 * for more stations is probably more useful.
2288 *
2289 * Mark key TX-only and return 0.
2294 */ 2290 */
2295 if (vif->type == NL80211_IFTYPE_ADHOC && 2291 if (vif->type == NL80211_IFTYPE_ADHOC &&
2296 !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) 2292 !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
2297 return -EOPNOTSUPP; 2293 key->hw_key_idx = WEP_INVALID_OFFSET;
2294 return 0;
2295 }
2298 2296
2299 sta_id = iwl_sta_id_or_broadcast(priv, vif_priv->ctx, sta); 2297 /* If they key was TX-only, accept deletion */
2300 if (sta_id == IWL_INVALID_STATION) 2298 if (cmd == DISABLE_KEY && key->hw_key_idx == WEP_INVALID_OFFSET)
2301 return -EINVAL; 2299 return 0;
2302 2300
2303 mutex_lock(&priv->mutex); 2301 mutex_lock(&priv->mutex);
2304 iwl_scan_cancel_timeout(priv, 100); 2302 iwl_scan_cancel_timeout(priv, 100);
2305 2303
2304 BUILD_BUG_ON(WEP_INVALID_OFFSET == IWLAGN_HW_KEY_DEFAULT);
2305
2306 /* 2306 /*
2307 * If we are getting WEP group key and we didn't receive any key mapping 2307 * If we are getting WEP group key and we didn't receive any key mapping
2308 * so far, we are in legacy wep mode (group key only), otherwise we are 2308 * so far, we are in legacy wep mode (group key only), otherwise we are
@@ -2310,22 +2310,30 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
2310 * In legacy wep mode, we use another host command to the uCode. 2310 * In legacy wep mode, we use another host command to the uCode.
2311 */ 2311 */
2312 if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || 2312 if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
2313 key->cipher == WLAN_CIPHER_SUITE_WEP104) && 2313 key->cipher == WLAN_CIPHER_SUITE_WEP104) && !sta) {
2314 !sta) {
2315 if (cmd == SET_KEY) 2314 if (cmd == SET_KEY)
2316 is_default_wep_key = !ctx->key_mapping_keys; 2315 is_default_wep_key = !ctx->key_mapping_keys;
2317 else 2316 else
2318 is_default_wep_key = 2317 is_default_wep_key =
2319 (key->hw_key_idx == HW_KEY_DEFAULT); 2318 key->hw_key_idx == IWLAGN_HW_KEY_DEFAULT;
2320 } 2319 }
2321 2320
2321
2322 switch (cmd) { 2322 switch (cmd) {
2323 case SET_KEY: 2323 case SET_KEY:
2324 if (is_default_wep_key) 2324 if (is_default_wep_key) {
2325 ret = iwl_set_default_wep_key(priv, vif_priv->ctx, key); 2325 ret = iwl_set_default_wep_key(priv, vif_priv->ctx, key);
2326 else 2326 break;
2327 ret = iwl_set_dynamic_key(priv, vif_priv->ctx, 2327 }
2328 key, sta_id); 2328 ret = iwl_set_dynamic_key(priv, vif_priv->ctx, key, sta);
2329 if (ret) {
2330 /*
2331 * can't add key for RX, but we don't need it
2332 * in the device for TX so still return 0
2333 */
2334 ret = 0;
2335 key->hw_key_idx = WEP_INVALID_OFFSET;
2336 }
2329 2337
2330 IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n"); 2338 IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n");
2331 break; 2339 break;
@@ -2333,7 +2341,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
2333 if (is_default_wep_key) 2341 if (is_default_wep_key)
2334 ret = iwl_remove_default_wep_key(priv, ctx, key); 2342 ret = iwl_remove_default_wep_key(priv, ctx, key);
2335 else 2343 else
2336 ret = iwl_remove_dynamic_key(priv, ctx, key, sta_id); 2344 ret = iwl_remove_dynamic_key(priv, ctx, key, sta);
2337 2345
2338 IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n"); 2346 IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n");
2339 break; 2347 break;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index 785987d570c6..d941c4c98e4b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -246,11 +246,13 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
246int iwl_restore_default_wep_keys(struct iwl_priv *priv, 246int iwl_restore_default_wep_keys(struct iwl_priv *priv,
247 struct iwl_rxon_context *ctx); 247 struct iwl_rxon_context *ctx);
248int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, 248int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
249 struct ieee80211_key_conf *key, u8 sta_id); 249 struct ieee80211_key_conf *key,
250 struct ieee80211_sta *sta);
250int iwl_remove_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, 251int iwl_remove_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
251 struct ieee80211_key_conf *key, u8 sta_id); 252 struct ieee80211_key_conf *key,
253 struct ieee80211_sta *sta);
252void iwl_update_tkip_key(struct iwl_priv *priv, 254void iwl_update_tkip_key(struct iwl_priv *priv,
253 struct iwl_rxon_context *ctx, 255 struct ieee80211_vif *vif,
254 struct ieee80211_key_conf *keyconf, 256 struct ieee80211_key_conf *keyconf,
255 struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); 257 struct ieee80211_sta *sta, u32 iv32, u16 *phase1key);
256int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); 258int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 80174d1ca7c2..b58985373a71 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -832,6 +832,8 @@ struct iwl_qosparam_cmd {
832#define STA_KEY_MULTICAST_MSK cpu_to_le16(0x4000) 832#define STA_KEY_MULTICAST_MSK cpu_to_le16(0x4000)
833#define STA_KEY_MAX_NUM 8 833#define STA_KEY_MAX_NUM 8
834#define STA_KEY_MAX_NUM_PAN 16 834#define STA_KEY_MAX_NUM_PAN 16
835/* must not match WEP_INVALID_OFFSET */
836#define IWLAGN_HW_KEY_DEFAULT 0xfe
835 837
836/* Flags indicate whether to modify vs. don't change various station params */ 838/* Flags indicate whether to modify vs. don't change various station params */
837#define STA_MODIFY_KEY_MASK 0x01 839#define STA_MODIFY_KEY_MASK 0x01
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 58dba0a49f8a..1ef3b7106ad5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -669,7 +669,7 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
669 iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true); 669 iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
670} 670}
671 671
672int iwl_get_free_ucode_key_index(struct iwl_priv *priv) 672int iwl_get_free_ucode_key_offset(struct iwl_priv *priv)
673{ 673{
674 int i; 674 int i;
675 675
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index ff64027ff4cb..9a6768d66851 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -31,9 +31,6 @@
31 31
32#include "iwl-dev.h" 32#include "iwl-dev.h"
33 33
34#define HW_KEY_DYNAMIC 0
35#define HW_KEY_DEFAULT 1
36
37#define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */ 34#define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */
38#define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */ 35#define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */
39#define IWL_STA_UCODE_INPROGRESS BIT(2) /* ucode entry is in process of 36#define IWL_STA_UCODE_INPROGRESS BIT(2) /* ucode entry is in process of
@@ -47,7 +44,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
47void iwl_clear_ucode_stations(struct iwl_priv *priv, 44void iwl_clear_ucode_stations(struct iwl_priv *priv,
48 struct iwl_rxon_context *ctx); 45 struct iwl_rxon_context *ctx);
49void iwl_dealloc_bcast_stations(struct iwl_priv *priv); 46void iwl_dealloc_bcast_stations(struct iwl_priv *priv);
50int iwl_get_free_ucode_key_index(struct iwl_priv *priv); 47int iwl_get_free_ucode_key_offset(struct iwl_priv *priv);
51int iwl_send_add_sta(struct iwl_priv *priv, 48int iwl_send_add_sta(struct iwl_priv *priv,
52 struct iwl_addsta_cmd *sta, u8 flags); 49 struct iwl_addsta_cmd *sta, u8 flags);
53int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, 50int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,