diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2007-08-28 17:01:55 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:48:53 -0400 |
commit | 11a843b7e16062389c53ba393c7913956e034eb2 (patch) | |
tree | 7f557a55220a0de38f0eafe1a5147487ec39b790 /net/mac80211/wpa.c | |
parent | 3aefaa3294193c931b20a574f718efee6baf27d4 (diff) |
[MAC80211]: rework key handling
This moves all the key handling code out from ieee80211_ioctl.c
into key.c and also does the following changes including documentation
updates in mac80211.h:
1) Turn off hardware acceleration for keys when the interface
is down. This is necessary because otherwise monitor
interfaces could be decrypting frames for other interfaces
that are down at the moment. Also, it should go some way
towards better suspend/resume support, in any case the
routines used here could be used for that as well.
Additionally, this makes the driver interface nicer, keys
for a specific local MAC address are only ever present
while an interface with that MAC address is enabled.
2) Change driver set_key() callback interface to allow only
return values of -ENOSPC, -EOPNOTSUPP and 0, warn on all
other return values. This allows debugging the stack when
a driver notices it's handed a key while it is down.
3) Invert the flag meaning to KEY_FLAG_UPLOADED_TO_HARDWARE.
4) Remove REMOVE_ALL_KEYS command as it isn't used nor do we
want to use it, we'll use DISABLE_KEY for each key. It is
hard to use REMOVE_ALL_KEYS because we can handle multiple
virtual interfaces with different key configuration, so we'd
have to keep track of a lot of state for this and that isn't
worth it.
5) Warn when disabling a key fails, it musn't.
6) Remove IEEE80211_HW_NO_TKIP_WMM_HWACCEL in favour of per-key
IEEE80211_KEY_FLAG_WMM_STA to let driver sort it out itself.
7) Tell driver that a (non-WEP) key is used only for transmission
by using an all-zeroes station MAC address when configuring.
8) Change the set_key() callback to have access to the local MAC
address the key is being added for.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Acked-by: Michael Wu <flamingice@sourmilk.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/mac80211/wpa.c')
-rw-r--r-- | net/mac80211/wpa.c | 30 |
1 files changed, 15 insertions, 15 deletions
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 4a2a9aa638b3..b6cd66e0ee58 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -89,7 +89,7 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx) | |||
89 | if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len)) | 89 | if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len)) |
90 | return TXRX_DROP; | 90 | return TXRX_DROP; |
91 | 91 | ||
92 | if (!(tx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) && | 92 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && |
93 | !(tx->flags & IEEE80211_TXRXD_FRAGMENTED) && | 93 | !(tx->flags & IEEE80211_TXRXD_FRAGMENTED) && |
94 | !(tx->local->hw.flags & IEEE80211_HW_TKIP_INCLUDE_MMIC) && | 94 | !(tx->local->hw.flags & IEEE80211_HW_TKIP_INCLUDE_MMIC) && |
95 | !wpa_test) { | 95 | !wpa_test) { |
@@ -146,7 +146,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx) | |||
146 | return TXRX_CONTINUE; | 146 | return TXRX_CONTINUE; |
147 | 147 | ||
148 | if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && | 148 | if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && |
149 | !(rx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) { | 149 | (rx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { |
150 | if (rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) { | 150 | if (rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) { |
151 | if (skb->len < MICHAEL_MIC_LEN) | 151 | if (skb->len < MICHAEL_MIC_LEN) |
152 | return TXRX_DROP; | 152 | return TXRX_DROP; |
@@ -205,10 +205,10 @@ static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx, | |||
205 | hdrlen = ieee80211_get_hdrlen(fc); | 205 | hdrlen = ieee80211_get_hdrlen(fc); |
206 | len = skb->len - hdrlen; | 206 | len = skb->len - hdrlen; |
207 | 207 | ||
208 | if (tx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) | 208 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) |
209 | tailneed = TKIP_ICV_LEN; | ||
210 | else | ||
211 | tailneed = 0; | 209 | tailneed = 0; |
210 | else | ||
211 | tailneed = TKIP_ICV_LEN; | ||
212 | 212 | ||
213 | if ((skb_headroom(skb) < TKIP_IV_LEN || | 213 | if ((skb_headroom(skb) < TKIP_IV_LEN || |
214 | skb_tailroom(skb) < tailneed)) { | 214 | skb_tailroom(skb) < tailneed)) { |
@@ -227,7 +227,7 @@ static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx, | |||
227 | if (key->u.tkip.iv16 == 0) | 227 | if (key->u.tkip.iv16 == 0) |
228 | key->u.tkip.iv32++; | 228 | key->u.tkip.iv32++; |
229 | 229 | ||
230 | if (!(tx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) { | 230 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { |
231 | u32 flags = tx->local->hw.flags; | 231 | u32 flags = tx->local->hw.flags; |
232 | hdr = (struct ieee80211_hdr *)skb->data; | 232 | hdr = (struct ieee80211_hdr *)skb->data; |
233 | 233 | ||
@@ -286,7 +286,7 @@ ieee80211_tx_h_tkip_encrypt(struct ieee80211_txrx_data *tx) | |||
286 | tx->u.tx.control->iv_len = TKIP_IV_LEN; | 286 | tx->u.tx.control->iv_len = TKIP_IV_LEN; |
287 | ieee80211_tx_set_iswep(tx); | 287 | ieee80211_tx_set_iswep(tx); |
288 | 288 | ||
289 | if (!(tx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) && | 289 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && |
290 | !(tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) && | 290 | !(tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) && |
291 | !wpa_test) { | 291 | !wpa_test) { |
292 | /* hwaccel - with no need for preallocated room for IV/ICV */ | 292 | /* hwaccel - with no need for preallocated room for IV/ICV */ |
@@ -331,7 +331,7 @@ ieee80211_rx_h_tkip_decrypt(struct ieee80211_txrx_data *rx) | |||
331 | return TXRX_DROP; | 331 | return TXRX_DROP; |
332 | 332 | ||
333 | if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && | 333 | if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && |
334 | !(key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) { | 334 | (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { |
335 | if (!(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) { | 335 | if (!(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) { |
336 | /* Hardware takes care of all processing, including | 336 | /* Hardware takes care of all processing, including |
337 | * replay protection, so no need to continue here. */ | 337 | * replay protection, so no need to continue here. */ |
@@ -475,10 +475,10 @@ static int ccmp_encrypt_skb(struct ieee80211_txrx_data *tx, | |||
475 | hdrlen = ieee80211_get_hdrlen(fc); | 475 | hdrlen = ieee80211_get_hdrlen(fc); |
476 | len = skb->len - hdrlen; | 476 | len = skb->len - hdrlen; |
477 | 477 | ||
478 | if (key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) | 478 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) |
479 | tailneed = CCMP_MIC_LEN; | ||
480 | else | ||
481 | tailneed = 0; | 479 | tailneed = 0; |
480 | else | ||
481 | tailneed = CCMP_MIC_LEN; | ||
482 | 482 | ||
483 | if ((skb_headroom(skb) < CCMP_HDR_LEN || | 483 | if ((skb_headroom(skb) < CCMP_HDR_LEN || |
484 | skb_tailroom(skb) < tailneed)) { | 484 | skb_tailroom(skb) < tailneed)) { |
@@ -504,7 +504,7 @@ static int ccmp_encrypt_skb(struct ieee80211_txrx_data *tx, | |||
504 | 504 | ||
505 | ccmp_pn2hdr(pos, pn, key->conf.keyidx); | 505 | ccmp_pn2hdr(pos, pn, key->conf.keyidx); |
506 | 506 | ||
507 | if (!(key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) { | 507 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { |
508 | /* hwaccel - with preallocated room for CCMP header */ | 508 | /* hwaccel - with preallocated room for CCMP header */ |
509 | tx->u.tx.control->key_idx = key->conf.hw_key_idx; | 509 | tx->u.tx.control->key_idx = key->conf.hw_key_idx; |
510 | return 0; | 510 | return 0; |
@@ -537,7 +537,7 @@ ieee80211_tx_h_ccmp_encrypt(struct ieee80211_txrx_data *tx) | |||
537 | tx->u.tx.control->iv_len = CCMP_HDR_LEN; | 537 | tx->u.tx.control->iv_len = CCMP_HDR_LEN; |
538 | ieee80211_tx_set_iswep(tx); | 538 | ieee80211_tx_set_iswep(tx); |
539 | 539 | ||
540 | if (!(tx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) && | 540 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && |
541 | !(tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) { | 541 | !(tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) { |
542 | /* hwaccel - with no need for preallocated room for CCMP " | 542 | /* hwaccel - with no need for preallocated room for CCMP " |
543 | * header or MIC fields */ | 543 | * header or MIC fields */ |
@@ -586,7 +586,7 @@ ieee80211_rx_h_ccmp_decrypt(struct ieee80211_txrx_data *rx) | |||
586 | return TXRX_DROP; | 586 | return TXRX_DROP; |
587 | 587 | ||
588 | if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && | 588 | if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && |
589 | !(key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) && | 589 | (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && |
590 | !(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) | 590 | !(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) |
591 | return TXRX_CONTINUE; | 591 | return TXRX_CONTINUE; |
592 | 592 | ||
@@ -607,7 +607,7 @@ ieee80211_rx_h_ccmp_decrypt(struct ieee80211_txrx_data *rx) | |||
607 | } | 607 | } |
608 | 608 | ||
609 | if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && | 609 | if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && |
610 | !(key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) { | 610 | (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { |
611 | /* hwaccel has already decrypted frame and verified MIC */ | 611 | /* hwaccel has already decrypted frame and verified MIC */ |
612 | } else { | 612 | } else { |
613 | u8 *scratch, *b_0, *aad; | 613 | u8 *scratch, *b_0, *aad; |