Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 66346
b: refs/heads/master
c: 3017b80
h: refs/heads/master
v: v3
  • Loading branch information
Johannes Berg authored and David S. Miller committed Oct 10, 2007
1 parent 5cf6f05 commit 9720cc8
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 55 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 82f716056fb1c214289fe6c284b0316858c1b70c
refs/heads/master: 3017b80bf0c4d6a44ccf0d35db9dadf01092b54e
37 changes: 29 additions & 8 deletions trunk/include/net/mac80211.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
/*
* Low-level hardware driver -- IEEE 802.11 driver (80211.o) interface
* mac80211 <-> driver interface
*
* Copyright 2002-2005, Devicescape Software, Inc.
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
Expand Down Expand Up @@ -472,10 +474,16 @@ struct ieee80211_hw {
*/
#define IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE (1<<1)

/* Some devices handle decryption internally and do not
/*
* Some devices handle decryption internally and do not
* indicate whether the frame was encrypted (unencrypted frames
* will be dropped by the hardware, unless specifically allowed
* through) */
* through.)
* It is permissible to not handle all encrypted frames and fall
* back to software encryption; however, if this flag is set
* unencrypted frames must be dropped unless the driver is told
* otherwise via the set_ieee8021x() callback.
*/
#define IEEE80211_HW_DEVICE_HIDES_WEP (1<<2)

/* Whether RX frames passed to ieee80211_rx() include FCS in the end */
Expand All @@ -489,18 +497,31 @@ struct ieee80211_hw {
* can fetch them with ieee80211_get_buffered_bc(). */
#define IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING (1<<4)

/*
* This flag is only relevant if hardware encryption is used.
* If set, it has two meanings:
* 1) the IV and ICV are present in received frames that have
* been decrypted (unless IEEE80211_HW_DEVICE_HIDES_WEP is
* also set)
* 2) on transmission, the IV should be generated in software.
*
* Please let us know if you *don't* use this flag, the stack would
* really like to be able to get the IV to keep key statistics
* accurate.
*/
#define IEEE80211_HW_WEP_INCLUDE_IV (1<<5)

/* hole at 6 */

/* Force software encryption for TKIP packets if WMM is enabled. */
#define IEEE80211_HW_NO_TKIP_WMM_HWACCEL (1<<7)

/* Some devices handle Michael MIC internally and do not include MIC in
* the received packets passed up. device_strips_mic must be set
* for such devices. The 'encryption' frame control bit is expected to
* be still set in the IEEE 802.11 header with this option unlike with
* the device_hides_wep configuration option.
/*
* Some devices handle Michael MIC internally and do not include MIC in
* the received packets passed up. This flag must be set for such
* devices. The 'encryption' frame control bit is expected to be still
* set in the IEEE 802.11 header with this option unlike with the
* IEEE80211_HW_DEVICE_HIDES_WEP flag.
*/
#define IEEE80211_HW_DEVICE_STRIPS_MIC (1<<8)

Expand Down
113 changes: 70 additions & 43 deletions trunk/net/mac80211/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,52 +310,77 @@ static ieee80211_txrx_result
ieee80211_rx_h_load_key(struct ieee80211_txrx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
int always_sta_key;
int keyidx;
int hdrlen;

if (rx->sdata->type == IEEE80211_IF_TYPE_STA)
always_sta_key = 0;
else
always_sta_key = 1;
/*
* Key selection 101
*
* There are three types of keys:
* - GTK (group keys)
* - PTK (pairwise keys)
* - STK (station-to-station pairwise keys)
*
* When selecting a key, we have to distinguish between multicast
* (including broadcast) and unicast frames, the latter can only
* use PTKs and STKs while the former always use GTKs. Unless, of
* course, actual WEP keys ("pre-RSNA") are used, then unicast
* frames can also use key indizes like GTKs. Hence, if we don't
* have a PTK/STK we check the key index for a WEP key.
*
* There is also a slight problem in IBSS mode: GTKs are negotiated
* with each station, that is something we don't currently handle.
*/

if (!(rx->fc & IEEE80211_FCTL_PROTECTED))
return TXRX_CONTINUE;

if (rx->sta && rx->sta->key && always_sta_key) {
/*
* No point in finding a key if the frame is neither
* addressed to us nor a multicast frame.
*/
if (!rx->u.rx.ra_match)
return TXRX_CONTINUE;

if (!is_multicast_ether_addr(hdr->addr1) && rx->sta && rx->sta->key) {
rx->key = rx->sta->key;
} else {
if (rx->sta && rx->sta->key)
rx->key = rx->sta->key;
else
rx->key = rx->sdata->default_key;
/*
* The device doesn't give us the IV so we won't be
* able to look up the key. That's ok though, we
* don't need to decrypt the frame, we just won't
* be able to keep statistics accurate.
* Except for key threshold notifications, should
* we somehow allow the driver to tell us which key
* the hardware used if this flag is set?
*/
if (!(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV))
return TXRX_CONTINUE;

if ((rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) &&
rx->fc & IEEE80211_FCTL_PROTECTED) {
int keyidx = ieee80211_wep_get_keyidx(rx->skb);
hdrlen = ieee80211_get_hdrlen(rx->fc);

if (keyidx >= 0 && keyidx < NUM_DEFAULT_KEYS &&
(!rx->sta || !rx->sta->key || keyidx > 0))
rx->key = rx->sdata->keys[keyidx];
if (rx->skb->len < 8 + hdrlen)
return TXRX_DROP; /* TODO: count this? */

if (!rx->key) {
if (!rx->u.rx.ra_match)
return TXRX_DROP;
if (net_ratelimit())
printk(KERN_DEBUG "%s: RX WEP frame "
"with unknown keyidx %d "
"(A1=" MAC_FMT
" A2=" MAC_FMT
" A3=" MAC_FMT ")\n",
rx->dev->name, keyidx,
MAC_ARG(hdr->addr1),
MAC_ARG(hdr->addr2),
MAC_ARG(hdr->addr3));
/*
* TODO: notify userspace about this
* via cfg/nl80211
*/
return TXRX_DROP;
}
}
/*
* no need to call ieee80211_wep_get_keyidx,
* it verifies a bunch of things we've done already
*/
keyidx = rx->skb->data[hdrlen + 3] >> 6;

rx->key = rx->sdata->keys[keyidx];

/*
* RSNA-protected unicast frames should always be sent with
* pairwise or station-to-station keys, but for WEP we allow
* using a key index as well.
*/
if (rx->key && rx->key->alg != ALG_WEP &&
!is_multicast_ether_addr(hdr->addr1))
rx->key = NULL;
}

if (rx->fc & IEEE80211_FCTL_PROTECTED && rx->key && rx->u.rx.ra_match) {
if (rx->key) {
rx->key->tx_rx_count++;
if (unlikely(rx->local->key_tx_rx_threshold &&
rx->key->tx_rx_count >
Expand Down Expand Up @@ -516,10 +541,6 @@ ieee80211_rx_h_wep_weak_iv_detection(struct ieee80211_txrx_data *rx)
static ieee80211_txrx_result
ieee80211_rx_h_wep_decrypt(struct ieee80211_txrx_data *rx)
{
/* If the device handles decryption totally, skip this test */
if (rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP)
return TXRX_CONTINUE;

if ((rx->key && rx->key->alg != ALG_WEP) ||
!(rx->fc & IEEE80211_FCTL_PROTECTED) ||
((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA &&
Expand Down Expand Up @@ -871,8 +892,14 @@ ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx)
static ieee80211_txrx_result
ieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx)
{
/* If the device handles decryption totally, skip this test */
if (rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP)
/*
* Pass through unencrypted frames if the hardware might have
* decrypted them already without telling us, but that can only
* be true if we either didn't find a key or the found key is
* uploaded to the hardware.
*/
if ((rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP) &&
(!rx->key || !rx->key->force_sw_encrypt))
return TXRX_CONTINUE;

/* Drop unencrypted frames if key is set. */
Expand Down
7 changes: 4 additions & 3 deletions trunk/net/mac80211/wpa.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,10 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx)

fc = rx->fc;

/* If device handles decryption totally, skip this check */
if ((rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP) ||
(rx->local->hw.flags & IEEE80211_HW_DEVICE_STRIPS_MIC))
/*
* No way to verify the MIC if the hardware stripped it
*/
if (rx->local->hw.flags & IEEE80211_HW_DEVICE_STRIPS_MIC)
return TXRX_CONTINUE;

if (!rx->key || rx->key->alg != ALG_TKIP ||
Expand Down

0 comments on commit 9720cc8

Please sign in to comment.