diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 029e8cb7bf4e..056c225173d8 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -205,8 +205,8 @@ struct ieee80211_tx_control { * is not implemented by the driver */ u8 power_level; /* per-packet transmit power level, in dBm */ u8 antenna_sel_tx; /* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */ - s8 key_idx; /* -1 = do not encrypt, >= 0 keyidx from - * hw->set_key() */ + s8 key_idx; /* HW_KEY_IDX_INVALID = do not encrypt, + * other values: keyidx from hw->set_key() */ u8 icv_len; /* length of the ICV/MIC field in octets */ u8 iv_len; /* length of the IV field in octets */ u8 tkip_key[16]; /* generated phase2/phase1 key for hw TKIP */ @@ -392,26 +392,23 @@ struct ieee80211_if_conf { struct ieee80211_tx_control *beacon_control; }; -typedef enum { ALG_NONE, ALG_WEP, ALG_TKIP, ALG_CCMP, ALG_NULL } -ieee80211_key_alg; - +typedef enum { + ALG_NONE, + ALG_WEP, + ALG_TKIP, + ALG_CCMP, +} ieee80211_key_alg; struct ieee80211_key_conf { + /* shall be changed by the driver to anything but HW_KEY_IDX_INVALID */ + int hw_key_idx; - int hw_key_idx; /* filled + used by low-level driver */ ieee80211_key_alg alg; + int keylen; #define IEEE80211_KEY_FORCE_SW_ENCRYPT (1<<0) /* to be cleared by low-level driver */ -#define IEEE80211_KEY_DEFAULT_TX_KEY (1<<1) /* This key is the new default TX - key (used only for broadcast - keys). */ -#define IEEE80211_KEY_DEFAULT_WEP_ONLY (1<<2) /* static WEP is the only - configured security policy; - this allows some low-level - drivers to determine when - hwaccel can be used */ u32 flags; /* key configuration flags defined above */ s8 keyidx; /* WEP key index */ @@ -625,20 +622,26 @@ struct ieee80211_ops { * Must be atomic. */ int (*set_tim)(struct ieee80211_hw *hw, int aid, int set); - /* Set encryption key. IEEE 802.11 module calls this function to set - * encryption keys. addr is ff:ff:ff:ff:ff:ff for default keys and - * station hwaddr for individual keys. aid of the station is given - * to help low-level driver in selecting which key->hw_key_idx to use - * for this key. TX control data will use the hw_key_idx selected by - * the low-level driver. */ + /* + * Set encryption key. + * + * This is called to enable hardware acceleration of encryption and + * decryption. The address will be the broadcast address for default + * keys and the other station's hardware address for individual keys. + * When transmitting, the TX control data will use the hw_key_idx + * selected by the low-level driver. + */ int (*set_key)(struct ieee80211_hw *hw, set_key_cmd cmd, - u8 *addr, struct ieee80211_key_conf *key, int aid); + u8 *address, struct ieee80211_key_conf *key, + int static_wep_only); - /* Set TX key index for default/broadcast keys. This is needed in cases + /* + * Set TX key index for default/broadcast keys. This is needed in cases * where wlan card is doing full WEP/TKIP encapsulation (wep_include_iv * is not set), in other cases, this function pointer can be set to - * NULL since the IEEE 802. 11 module takes care of selecting the key - * index for each TX frame. */ + * NULL since the IEEE 802.11 module takes care of selecting the key + * index for each TX frame. + */ int (*set_key_idx)(struct ieee80211_hw *hw, int idx); /* Enable/disable IEEE 802.1X. This item requests wlan card to pass diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 077f907271cf..246938c32d4d 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c @@ -14,17 +14,17 @@ #include "debugfs.h" #include "debugfs_key.h" -#define KEY_READ(name, buflen, format_string) \ +#define KEY_READ(name, prop, buflen, format_string) \ static ssize_t key_##name##_read(struct file *file, \ char __user *userbuf, \ size_t count, loff_t *ppos) \ { \ char buf[buflen]; \ struct ieee80211_key *key = file->private_data; \ - int res = scnprintf(buf, buflen, format_string, key->name); \ + int res = scnprintf(buf, buflen, format_string, key->prop); \ return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ } -#define KEY_READ_D(name) KEY_READ(name, 20, "%d\n") +#define KEY_READ_D(name) KEY_READ(name, name, 20, "%d\n") #define KEY_OPS(name) \ static const struct file_operations key_ ##name## _ops = { \ @@ -36,10 +36,25 @@ static const struct file_operations key_ ##name## _ops = { \ KEY_READ_##format(name) \ KEY_OPS(name) -KEY_FILE(keylen, D); -KEY_FILE(force_sw_encrypt, D); -KEY_FILE(keyidx, D); -KEY_FILE(hw_key_idx, D); +#define KEY_CONF_READ(name, buflen, format_string) \ + KEY_READ(conf_##name, conf.name, buflen, format_string) +#define KEY_CONF_READ_D(name) KEY_CONF_READ(name, 20, "%d\n") +#define KEY_CONF_READ_X(name) KEY_CONF_READ(name, 20, "0x%x\n") + +#define KEY_CONF_OPS(name) \ +static const struct file_operations key_ ##name## _ops = { \ + .read = key_conf_##name##_read, \ + .open = mac80211_open_file_generic, \ +} + +#define KEY_CONF_FILE(name, format) \ + KEY_CONF_READ_##format(name) \ + KEY_CONF_OPS(name) + +KEY_CONF_FILE(keylen, D); +KEY_CONF_FILE(keyidx, D); +KEY_CONF_FILE(hw_key_idx, D); +KEY_CONF_FILE(flags, X); KEY_FILE(tx_rx_count, D); static ssize_t key_algorithm_read(struct file *file, @@ -49,7 +64,7 @@ static ssize_t key_algorithm_read(struct file *file, char *alg; struct ieee80211_key *key = file->private_data; - switch (key->alg) { + switch (key->conf.alg) { case ALG_WEP: alg = "WEP\n"; break; @@ -74,7 +89,7 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, int len; struct ieee80211_key *key = file->private_data; - switch (key->alg) { + switch (key->conf.alg) { case ALG_WEP: len = scnprintf(buf, sizeof(buf), "\n"); break; @@ -103,7 +118,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, int i, len; const u8 *rpn; - switch (key->alg) { + switch (key->conf.alg) { case ALG_WEP: len = scnprintf(buf, sizeof(buf), "\n"); break; @@ -139,7 +154,7 @@ static ssize_t key_replays_read(struct file *file, char __user *userbuf, char buf[20]; int len; - if (key->alg != ALG_CCMP) + if (key->conf.alg != ALG_CCMP) return 0; len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); return simple_read_from_buffer(userbuf, count, ppos, buf, len); @@ -150,12 +165,12 @@ static ssize_t key_key_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { struct ieee80211_key *key = file->private_data; - int i, res, bufsize = 2*key->keylen+2; + int i, res, bufsize = 2 * key->conf.keylen + 2; char *buf = kmalloc(bufsize, GFP_KERNEL); char *p = buf; - for (i = 0; i < key->keylen; i++) - p += scnprintf(p, bufsize+buf-p, "%02x", key->key[i]); + for (i = 0; i < key->conf.keylen; i++) + p += scnprintf(p, bufsize + buf - p, "%02x", key->conf.key[i]); p += scnprintf(p, bufsize+buf-p, "\n"); res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); kfree(buf); @@ -185,7 +200,7 @@ void ieee80211_debugfs_key_add(struct ieee80211_local *local, return; DEBUGFS_ADD(keylen); - DEBUGFS_ADD(force_sw_encrypt); + DEBUGFS_ADD(flags); DEBUGFS_ADD(keyidx); DEBUGFS_ADD(hw_key_idx); DEBUGFS_ADD(tx_rx_count); @@ -205,7 +220,7 @@ void ieee80211_debugfs_key_remove(struct ieee80211_key *key) return; DEBUGFS_DEL(keylen); - DEBUGFS_DEL(force_sw_encrypt); + DEBUGFS_DEL(flags); DEBUGFS_DEL(keyidx); DEBUGFS_DEL(hw_key_idx); DEBUGFS_DEL(tx_rx_count); @@ -227,7 +242,7 @@ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) if (!sdata->debugfsdir) return; - sprintf(buf, "../keys/%d", sdata->default_key->keyidx); + sprintf(buf, "../keys/%d", sdata->default_key->conf.keyidx); sdata->debugfs.default_key = debugfs_create_symlink("default_key", sdata->debugfsdir, buf); } diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 50d7af3018ea..5d5034f36fde 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c @@ -890,7 +890,7 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local, if (!key) goto no_key; - switch (key->alg) { + switch (key->conf.alg) { case ALG_WEP: iv_len = WEP_IV_LEN; mic_len = WEP_ICV_LEN; @@ -907,7 +907,8 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local, goto no_key; } - if (skb->len >= mic_len && key->force_sw_encrypt) + if (skb->len >= mic_len && + (key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) skb_trim(skb, skb->len - mic_len); if (skb->len >= iv_len && skb->len > hdrlen) { memmove(skb->data + iv_len, skb->data, hdrlen); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ef633a041dab..cc87e9d988f8 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -816,9 +816,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); int ieee80211_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev); /* key handling */ -struct ieee80211_key_conf * -ieee80211_key_data2conf(struct ieee80211_local *local, - const struct ieee80211_key *data); struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata, int idx, size_t key_len, gfp_t flags); void ieee80211_key_free(struct ieee80211_key *key); diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c index 61009176d51b..3e59afa23e4e 100644 --- a/net/mac80211/ieee80211_iface.c +++ b/net/mac80211/ieee80211_iface.c @@ -227,7 +227,8 @@ void ieee80211_if_reinit(struct net_device *dev) memset(addr, 0xff, ETH_ALEN); if (local->ops->set_key) local->ops->set_key(local_to_hw(local), DISABLE_KEY, addr, - local->keys[i], 0); + local->keys[i], + local->default_wep_only); #endif ieee80211_key_free(sdata->keys[i]); sdata->keys[i] = NULL; diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c index 9964f057bcef..380670c7a0ca 100644 --- a/net/mac80211/ieee80211_ioctl.c +++ b/net/mac80211/ieee80211_ioctl.c @@ -31,29 +31,20 @@ static void ieee80211_set_hw_encryption(struct net_device *dev, struct sta_info *sta, u8 addr[ETH_ALEN], struct ieee80211_key *key) { - struct ieee80211_key_conf *keyconf = NULL; struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); /* default to sw encryption; this will be cleared by low-level * driver if the hw supports requested encryption */ if (key) - key->force_sw_encrypt = 1; + key->conf.flags |= IEEE80211_KEY_FORCE_SW_ENCRYPT; - if (key && local->ops->set_key && - (keyconf = ieee80211_key_data2conf(local, key))) { + if (key && local->ops->set_key) { if (local->ops->set_key(local_to_hw(local), SET_KEY, addr, - keyconf, sta ? sta->aid : 0)) { - key->force_sw_encrypt = 1; - key->hw_key_idx = HW_KEY_IDX_INVALID; - } else { - key->force_sw_encrypt = - !!(keyconf->flags & IEEE80211_KEY_FORCE_SW_ENCRYPT); - key->hw_key_idx = - keyconf->hw_key_idx; - + &key->conf, local->default_wep_only)) { + key->conf.flags |= IEEE80211_KEY_FORCE_SW_ENCRYPT; + key->conf.hw_key_idx = HW_KEY_IDX_INVALID; } } - kfree(keyconf); } @@ -66,7 +57,6 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr, struct sta_info *sta; struct ieee80211_key *key, *old_key; int try_hwaccel = 1; - struct ieee80211_key_conf *keyconf; struct ieee80211_sub_if_data *sdata; sdata = IEEE80211_DEV_TO_SUB_IF(dev); @@ -154,18 +144,16 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr, } if (alg == ALG_NONE) { - keyconf = NULL; if (try_hwaccel && key && - key->hw_key_idx != HW_KEY_IDX_INVALID && + key->conf.hw_key_idx != HW_KEY_IDX_INVALID && local->ops->set_key && - (keyconf = ieee80211_key_data2conf(local, key)) != NULL && local->ops->set_key(local_to_hw(local), DISABLE_KEY, - sta_addr, keyconf, sta ? sta->aid : 0)) { + sta_addr, &key->conf, + local->default_wep_only)) { printk(KERN_DEBUG "%s: set_encrypt - low-level disable" " failed\n", dev->name); ret = -EINVAL; } - kfree(keyconf); if (set_tx_key || sdata->default_key == key) { ieee80211_debugfs_key_remove_default(sdata); @@ -189,22 +177,20 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr, /* default to sw encryption; low-level driver sets these if the * requested encryption is supported */ - key->hw_key_idx = HW_KEY_IDX_INVALID; - key->force_sw_encrypt = 1; + key->conf.hw_key_idx = HW_KEY_IDX_INVALID; + key->conf.flags |= IEEE80211_KEY_FORCE_SW_ENCRYPT; - key->alg = alg; - key->keyidx = idx; - key->keylen = key_len; - memcpy(key->key, _key, key_len); - if (set_tx_key) - key->default_tx_key = 1; + key->conf.alg = alg; + key->conf.keyidx = idx; + key->conf.keylen = key_len; + memcpy(key->conf.key, _key, key_len); if (alg == ALG_CCMP) { /* Initialize AES key state here as an optimization * so that it does not need to be initialized for every * packet. */ key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt( - key->key); + key->conf.key); if (!key->u.ccmp.tfm) { ret = -ENOMEM; goto err_free; @@ -941,43 +927,38 @@ static int ieee80211_ioctl_giwretry(struct net_device *dev, static void ieee80211_key_enable_hwaccel(struct ieee80211_local *local, struct ieee80211_key *key) { - struct ieee80211_key_conf *keyconf; u8 addr[ETH_ALEN]; - if (!key || key->alg != ALG_WEP || !key->force_sw_encrypt || + if (!key || key->conf.alg != ALG_WEP || + !(key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) || (local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP)) return; memset(addr, 0xff, ETH_ALEN); - keyconf = ieee80211_key_data2conf(local, key); - if (keyconf && local->ops->set_key && + + if (local->ops->set_key) local->ops->set_key(local_to_hw(local), - SET_KEY, addr, keyconf, 0) == 0) { - key->force_sw_encrypt = - !!(keyconf->flags & IEEE80211_KEY_FORCE_SW_ENCRYPT); - key->hw_key_idx = keyconf->hw_key_idx; - } - kfree(keyconf); + SET_KEY, addr, &key->conf, + local->default_wep_only); } static void ieee80211_key_disable_hwaccel(struct ieee80211_local *local, struct ieee80211_key *key) { - struct ieee80211_key_conf *keyconf; u8 addr[ETH_ALEN]; - if (!key || key->alg != ALG_WEP || key->force_sw_encrypt || + if (!key || key->conf.alg != ALG_WEP || + (key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) || (local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP)) return; memset(addr, 0xff, ETH_ALEN); - keyconf = ieee80211_key_data2conf(local, key); - if (keyconf && local->ops->set_key) + if (local->ops->set_key) local->ops->set_key(local_to_hw(local), DISABLE_KEY, - addr, keyconf, 0); - kfree(keyconf); - key->force_sw_encrypt = 1; + addr, &key->conf, + local->default_wep_only); + key->conf.flags |= IEEE80211_KEY_FORCE_SW_ENCRYPT; } @@ -1341,9 +1322,9 @@ static int ieee80211_ioctl_giwencode(struct net_device *dev, return 0; } - memcpy(key, sdata->keys[idx]->key, - min((int)erq->length, sdata->keys[idx]->keylen)); - erq->length = sdata->keys[idx]->keylen; + memcpy(key, sdata->keys[idx]->conf.key, + min((int)erq->length, sdata->keys[idx]->conf.keylen)); + erq->length = sdata->keys[idx]->conf.keylen; erq->flags |= IW_ENCODE_ENABLED; return 0; diff --git a/net/mac80211/ieee80211_key.h b/net/mac80211/ieee80211_key.h index c33384912782..1b5e539c678f 100644 --- a/net/mac80211/ieee80211_key.h +++ b/net/mac80211/ieee80211_key.h @@ -44,8 +44,6 @@ struct ieee80211_key { struct kref kref; - int hw_key_idx; /* filled and used by low-level driver */ - ieee80211_key_alg alg; union { struct { /* last used TSC */ @@ -73,22 +71,16 @@ struct ieee80211_key { u8 rx_crypto_buf[6 * AES_BLOCK_LEN]; } ccmp; } u; - int tx_rx_count; /* number of times this key has been used */ - int keylen; - /* if the low level driver can provide hardware acceleration it should - * clear this flag */ - unsigned int force_sw_encrypt:1; - unsigned int default_tx_key:1; /* This key is the new default TX key - * (used only for broadcast keys). */ - s8 keyidx; /* WEP key index */ + /* number of times this key has been used */ + int tx_rx_count; #ifdef CONFIG_MAC80211_DEBUGFS struct { struct dentry *stalink; struct dentry *dir; struct dentry *keylen; - struct dentry *force_sw_encrypt; + struct dentry *flags; struct dentry *keyidx; struct dentry *hw_key_idx; struct dentry *tx_rx_count; @@ -100,7 +92,11 @@ struct ieee80211_key { } debugfs; #endif - u8 key[0]; + /* + * key config, must be last because it contains key + * material as variable length member + */ + struct ieee80211_key_conf conf; }; #endif /* IEEE80211_KEY_H */ diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index fe94ebfcb157..a2443271629a 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -904,7 +904,7 @@ static int ieee80211_sta_wep_configured(struct net_device *dev) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (!sdata || !sdata->default_key || - sdata->default_key->alg != ALG_WEP) + sdata->default_key->conf.alg != ALG_WEP) return 0; return 1; } diff --git a/net/mac80211/key.c b/net/mac80211/key.c index b67558c24639..92d994f090b6 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -13,32 +13,6 @@ #include "debugfs_key.h" #include "aes_ccm.h" -struct ieee80211_key_conf * -ieee80211_key_data2conf(struct ieee80211_local *local, - const struct ieee80211_key *data) -{ - struct ieee80211_key_conf *conf; - - conf = kmalloc(sizeof(*conf) + data->keylen, GFP_ATOMIC); - if (!conf) - return NULL; - - conf->hw_key_idx = data->hw_key_idx; - conf->alg = data->alg; - conf->keylen = data->keylen; - conf->flags = 0; - if (data->force_sw_encrypt) - conf->flags |= IEEE80211_KEY_FORCE_SW_ENCRYPT; - conf->keyidx = data->keyidx; - if (data->default_tx_key) - conf->flags |= IEEE80211_KEY_DEFAULT_TX_KEY; - if (local->default_wep_only) - conf->flags |= IEEE80211_KEY_DEFAULT_WEP_ONLY; - memcpy(conf->key, data->key, data->keylen); - - return conf; -} - struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata, int idx, size_t key_len, gfp_t flags) { @@ -56,7 +30,7 @@ static void ieee80211_key_release(struct kref *kref) struct ieee80211_key *key; key = container_of(kref, struct ieee80211_key, kref); - if (key->alg == ALG_CCMP) + if (key->conf.alg == ALG_CCMP) ieee80211_aes_key_free(key->u.ccmp.tfm); ieee80211_debugfs_key_remove(key); kfree(key); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index b52e3305a8f8..976b646a40de 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -374,7 +374,7 @@ ieee80211_rx_h_load_key(struct ieee80211_txrx_data *rx) * 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 && + if (rx->key && rx->key->conf.alg != ALG_WEP && !is_multicast_ether_addr(hdr->addr1)) rx->key = NULL; } @@ -522,18 +522,15 @@ ieee80211_rx_h_wep_weak_iv_detection(struct ieee80211_txrx_data *rx) { if (!rx->sta || !(rx->fc & IEEE80211_FCTL_PROTECTED) || (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || - !rx->key || rx->key->alg != ALG_WEP || + !rx->key || rx->key->conf.alg != ALG_WEP || !(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) return TXRX_CONTINUE; /* Check for weak IVs, if hwaccel did not remove IV from the frame */ if ((rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) || - rx->key->force_sw_encrypt) { - u8 *iv = ieee80211_wep_is_weak_iv(rx->skb, rx->key); - if (iv) { + (rx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) + if (ieee80211_wep_is_weak_iv(rx->skb, rx->key)) rx->sta->wep_weak_iv_count++; - } - } return TXRX_CONTINUE; } @@ -541,7 +538,7 @@ 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 ((rx->key && rx->key->alg != ALG_WEP) || + if ((rx->key && rx->key->conf.alg != ALG_WEP) || !(rx->fc & IEEE80211_FCTL_PROTECTED) || ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA && ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT || @@ -556,7 +553,7 @@ ieee80211_rx_h_wep_decrypt(struct ieee80211_txrx_data *rx) } if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED) || - rx->key->force_sw_encrypt) { + (rx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) { if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) { if (net_ratelimit()) printk(KERN_DEBUG "%s: RX WEP frame, decrypt " @@ -680,7 +677,7 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx) /* This is the first fragment of a new frame. */ entry = ieee80211_reassemble_add(rx->sdata, frag, seq, rx->u.rx.queue, &(rx->skb)); - if (rx->key && rx->key->alg == ALG_CCMP && + if (rx->key && rx->key->conf.alg == ALG_CCMP && (rx->fc & IEEE80211_FCTL_PROTECTED)) { /* Store CCMP PN so that we can verify that the next * fragment has a sequential PN value. */ @@ -707,7 +704,7 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx) if (entry->ccmp) { int i; u8 pn[CCMP_PN_LEN], *rpn; - if (!rx->key || rx->key->alg != ALG_CCMP) + if (!rx->key || rx->key->conf.alg != ALG_CCMP) return TXRX_DROP; memcpy(pn, entry->last_pn, CCMP_PN_LEN); for (i = CCMP_PN_LEN - 1; i >= 0; i--) { @@ -900,7 +897,8 @@ ieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx) * uploaded to the hardware. */ if ((rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP) && - (!rx->key || !rx->key->force_sw_encrypt)) + (!rx->key || + !(rx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT))) return TXRX_CONTINUE; /* Drop unencrypted frames if key is set. */ diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 34245b882c2b..7e10c692c4ad 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -228,23 +228,20 @@ void sta_info_free(struct sta_info *sta) if (sta->key) { if (local->ops->set_key) { - struct ieee80211_key_conf *key; - key = ieee80211_key_data2conf(local, sta->key); - if (key) { - local->ops->set_key(local_to_hw(local), - DISABLE_KEY, - sta->addr, key, sta->aid); - kfree(key); - } + local->ops->set_key(local_to_hw(local), + DISABLE_KEY, sta->addr, + &sta->key->conf, + local->default_wep_only); } } else if (sta->key_idx_compression != HW_KEY_IDX_INVALID) { struct ieee80211_key_conf conf; memset(&conf, 0, sizeof(conf)); conf.hw_key_idx = sta->key_idx_compression; - conf.alg = ALG_NULL; + conf.alg = ALG_NONE; conf.flags |= IEEE80211_KEY_FORCE_SW_ENCRYPT; local->ops->set_key(local_to_hw(local), DISABLE_KEY, - sta->addr, &conf, sta->aid); + sta->addr, &conf, + local->default_wep_only); sta->key_idx_compression = HW_KEY_IDX_INVALID; } diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 41621720e560..b9c1d5405180 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c @@ -182,7 +182,7 @@ u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, *pos++ = iv0; *pos++ = iv1; *pos++ = iv2; - *pos++ = (key->keyidx << 6) | (1 << 5) /* Ext IV */; + *pos++ = (key->conf.keyidx << 6) | (1 << 5) /* Ext IV */; *pos++ = key->u.tkip.iv32 & 0xff; *pos++ = (key->u.tkip.iv32 >> 8) & 0xff; *pos++ = (key->u.tkip.iv32 >> 16) & 0xff; @@ -194,7 +194,7 @@ u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, void ieee80211_tkip_gen_phase1key(struct ieee80211_key *key, u8 *ta, u16 *phase1key) { - tkip_mixing_phase1(ta, &key->key[ALG_TKIP_TEMP_ENCR_KEY], + tkip_mixing_phase1(ta, &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY], key->u.tkip.iv32, phase1key); } @@ -204,12 +204,13 @@ void ieee80211_tkip_gen_rc4key(struct ieee80211_key *key, u8 *ta, /* Calculate per-packet key */ if (key->u.tkip.iv16 == 0 || !key->u.tkip.tx_initialized) { /* IV16 wrapped around - perform TKIP phase 1 */ - tkip_mixing_phase1(ta, &key->key[ALG_TKIP_TEMP_ENCR_KEY], + tkip_mixing_phase1(ta, &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY], key->u.tkip.iv32, key->u.tkip.p1k); key->u.tkip.tx_initialized = 1; } - tkip_mixing_phase2(key->u.tkip.p1k, &key->key[ALG_TKIP_TEMP_ENCR_KEY], + tkip_mixing_phase2(key->u.tkip.p1k, + &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY], key->u.tkip.iv16, rc4key); } @@ -266,7 +267,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, if (!(keyid & (1 << 5))) return TKIP_DECRYPT_NO_EXT_IV; - if ((keyid >> 6) != key->keyidx) + if ((keyid >> 6) != key->conf.keyidx) return TKIP_DECRYPT_INVALID_KEYIDX; if (key->u.tkip.rx_initialized[queue] && @@ -293,7 +294,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, key->u.tkip.iv32_rx[queue] != iv32) { key->u.tkip.rx_initialized[queue] = 1; /* IV16 wrapped around - perform TKIP phase 1 */ - tkip_mixing_phase1(ta, &key->key[ALG_TKIP_TEMP_ENCR_KEY], + tkip_mixing_phase1(ta, &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY], iv32, key->u.tkip.p1k_rx[queue]); #ifdef CONFIG_TKIP_DEBUG { @@ -302,7 +303,8 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, " TK=", MAC_ARG(ta)); for (i = 0; i < 16; i++) printk("%02x ", - key->key[ALG_TKIP_TEMP_ENCR_KEY + i]); + key->conf.key[ + ALG_TKIP_TEMP_ENCR_KEY + i]); printk("\n"); printk(KERN_DEBUG "TKIP decrypt: P1K="); for (i = 0; i < 5; i++) @@ -313,7 +315,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, } tkip_mixing_phase2(key->u.tkip.p1k_rx[queue], - &key->key[ALG_TKIP_TEMP_ENCR_KEY], + &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY], iv16, rc4key); #ifdef CONFIG_TKIP_DEBUG { diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ddb104a70161..684f928def93 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -539,11 +539,11 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx) static int wep_encrypt_skb(struct ieee80211_txrx_data *tx, struct sk_buff *skb) { - if (tx->key->force_sw_encrypt) { + if (tx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) { if (ieee80211_wep_encrypt(tx->local, skb, tx->key)) return -1; } else { - tx->u.tx.control->key_idx = tx->key->hw_key_idx; + tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx; if (tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) { if (ieee80211_wep_add_iv(tx->local, skb, tx->key) == NULL) @@ -561,7 +561,7 @@ ieee80211_tx_h_wep_encrypt(struct ieee80211_txrx_data *tx) fc = le16_to_cpu(hdr->frame_control); - if (!tx->key || tx->key->alg != ALG_WEP || + if (!tx->key || tx->key->conf.alg != ALG_WEP || ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA && ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT || (fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH))) diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 1ad3d75281cc..0b19e89fcf6a 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -67,7 +67,7 @@ void ieee80211_wep_get_iv(struct ieee80211_local *local, struct ieee80211_key *key, u8 *iv) { local->wep_iv++; - if (ieee80211_wep_weak_iv(local->wep_iv, key->keylen)) + if (ieee80211_wep_weak_iv(local->wep_iv, key->conf.keylen)) local->wep_iv += 0x0100; if (!iv) @@ -76,7 +76,7 @@ void ieee80211_wep_get_iv(struct ieee80211_local *local, *iv++ = (local->wep_iv >> 16) & 0xff; *iv++ = (local->wep_iv >> 8) & 0xff; *iv++ = local->wep_iv & 0xff; - *iv++ = key->keyidx << 6; + *iv++ = key->conf.keyidx << 6; } @@ -159,10 +159,10 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb, u8 *rc4key, *iv; size_t len; - if (!key || key->alg != ALG_WEP) + if (!key || key->conf.alg != ALG_WEP) return -1; - klen = 3 + key->keylen; + klen = 3 + key->conf.keylen; rc4key = kmalloc(klen, GFP_ATOMIC); if (!rc4key) return -1; @@ -179,7 +179,7 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb, memcpy(rc4key, iv, 3); /* Copy rest of the WEP key (the secret part) */ - memcpy(rc4key + 3, key->key, key->keylen); + memcpy(rc4key + 3, key->conf.key, key->conf.keylen); /* Add room for ICV */ skb_put(skb, WEP_ICV_LEN); @@ -251,10 +251,10 @@ int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, keyidx = skb->data[hdrlen + 3] >> 6; - if (!key || keyidx != key->keyidx || key->alg != ALG_WEP) + if (!key || keyidx != key->conf.keyidx || key->conf.alg != ALG_WEP) return -1; - klen = 3 + key->keylen; + klen = 3 + key->conf.keylen; rc4key = kmalloc(klen, GFP_ATOMIC); if (!rc4key) @@ -264,7 +264,7 @@ int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, memcpy(rc4key, skb->data + hdrlen, 3); /* Copy rest of the WEP key (the secret part) */ - memcpy(rc4key + 3, key->key, key->keylen); + memcpy(rc4key + 3, key->conf.key, key->conf.keylen); if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen, skb->data + hdrlen + WEP_IV_LEN, @@ -321,7 +321,7 @@ u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key) ivpos = skb->data + hdrlen; iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2]; - if (ieee80211_wep_weak_iv(iv, key->keylen)) + if (ieee80211_wep_weak_iv(iv, key->conf.keylen)) return ivpos; return NULL; diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 1142b42b5fe9..4a2a9aa638b3 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -82,14 +82,14 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx) fc = tx->fc; - if (!tx->key || tx->key->alg != ALG_TKIP || skb->len < 24 || + if (!tx->key || tx->key->conf.alg != ALG_TKIP || skb->len < 24 || !WLAN_FC_DATA_PRESENT(fc)) return TXRX_CONTINUE; if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len)) return TXRX_DROP; - if (!tx->key->force_sw_encrypt && + if (!(tx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) && !(tx->flags & IEEE80211_TXRXD_FRAGMENTED) && !(tx->local->hw.flags & IEEE80211_HW_TKIP_INCLUDE_MMIC) && !wpa_test) { @@ -114,8 +114,8 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx) #else authenticator = 1; #endif - key = &tx->key->key[authenticator ? ALG_TKIP_TEMP_AUTH_TX_MIC_KEY : - ALG_TKIP_TEMP_AUTH_RX_MIC_KEY]; + key = &tx->key->conf.key[authenticator ? ALG_TKIP_TEMP_AUTH_TX_MIC_KEY : + ALG_TKIP_TEMP_AUTH_RX_MIC_KEY]; mic = skb_put(skb, MICHAEL_MIC_LEN); michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); @@ -141,12 +141,12 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx) if (rx->local->hw.flags & IEEE80211_HW_DEVICE_STRIPS_MIC) return TXRX_CONTINUE; - if (!rx->key || rx->key->alg != ALG_TKIP || + if (!rx->key || rx->key->conf.alg != ALG_TKIP || !(rx->fc & IEEE80211_FCTL_PROTECTED) || !WLAN_FC_DATA_PRESENT(fc)) return TXRX_CONTINUE; if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && - !rx->key->force_sw_encrypt) { + !(rx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) { if (rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) { if (skb->len < MICHAEL_MIC_LEN) return TXRX_DROP; @@ -169,8 +169,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx) #else authenticator = 1; #endif - key = &rx->key->key[authenticator ? ALG_TKIP_TEMP_AUTH_RX_MIC_KEY : - ALG_TKIP_TEMP_AUTH_TX_MIC_KEY]; + key = &rx->key->conf.key[authenticator ? ALG_TKIP_TEMP_AUTH_RX_MIC_KEY : + ALG_TKIP_TEMP_AUTH_TX_MIC_KEY]; michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) { if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) @@ -179,7 +179,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx) printk(KERN_DEBUG "%s: invalid Michael MIC in data frame from " MAC_FMT "\n", rx->dev->name, MAC_ARG(sa)); - mac80211_ev_michael_mic_failure(rx->dev, rx->key->keyidx, + mac80211_ev_michael_mic_failure(rx->dev, rx->key->conf.keyidx, (void *) skb->data); return TXRX_DROP; } @@ -205,7 +205,11 @@ static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx, hdrlen = ieee80211_get_hdrlen(fc); len = skb->len - hdrlen; - tailneed = !tx->key->force_sw_encrypt ? 0 : TKIP_ICV_LEN; + if (tx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) + tailneed = TKIP_ICV_LEN; + else + tailneed = 0; + if ((skb_headroom(skb) < TKIP_IV_LEN || skb_tailroom(skb) < tailneed)) { I802_DEBUG_INC(tx->local->tx_expand_skb_head); @@ -223,7 +227,7 @@ static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx, if (key->u.tkip.iv16 == 0) key->u.tkip.iv32++; - if (!tx->key->force_sw_encrypt) { + if (!(tx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) { u32 flags = tx->local->hw.flags; hdr = (struct ieee80211_hdr *)skb->data; @@ -250,7 +254,7 @@ static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx, ~IEEE80211_TXCTL_TKIP_NEW_PHASE1_KEY; } - tx->u.tx.control->key_idx = tx->key->hw_key_idx; + tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx; return 0; } @@ -275,18 +279,18 @@ ieee80211_tx_h_tkip_encrypt(struct ieee80211_txrx_data *tx) fc = le16_to_cpu(hdr->frame_control); - if (!key || key->alg != ALG_TKIP || !WLAN_FC_DATA_PRESENT(fc)) + if (!key || key->conf.alg != ALG_TKIP || !WLAN_FC_DATA_PRESENT(fc)) return TXRX_CONTINUE; tx->u.tx.control->icv_len = TKIP_ICV_LEN; tx->u.tx.control->iv_len = TKIP_IV_LEN; ieee80211_tx_set_iswep(tx); - if (!tx->key->force_sw_encrypt && + if (!(tx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) && !(tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) && !wpa_test) { /* hwaccel - with no need for preallocated room for IV/ICV */ - tx->u.tx.control->key_idx = tx->key->hw_key_idx; + tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx; return TXRX_CONTINUE; } @@ -318,7 +322,7 @@ ieee80211_rx_h_tkip_decrypt(struct ieee80211_txrx_data *rx) fc = le16_to_cpu(hdr->frame_control); hdrlen = ieee80211_get_hdrlen(fc); - if (!rx->key || rx->key->alg != ALG_TKIP || + if (!rx->key || rx->key->conf.alg != ALG_TKIP || !(rx->fc & IEEE80211_FCTL_PROTECTED) || (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) return TXRX_CONTINUE; @@ -327,7 +331,7 @@ ieee80211_rx_h_tkip_decrypt(struct ieee80211_txrx_data *rx) return TXRX_DROP; if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && - !rx->key->force_sw_encrypt) { + !(key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) { if (!(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) { /* Hardware takes care of all processing, including * replay protection, so no need to continue here. */ @@ -471,7 +475,10 @@ static int ccmp_encrypt_skb(struct ieee80211_txrx_data *tx, hdrlen = ieee80211_get_hdrlen(fc); len = skb->len - hdrlen; - tailneed = !key->force_sw_encrypt ? 0 : CCMP_MIC_LEN; + if (key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) + tailneed = CCMP_MIC_LEN; + else + tailneed = 0; if ((skb_headroom(skb) < CCMP_HDR_LEN || skb_tailroom(skb) < tailneed)) { @@ -495,11 +502,11 @@ static int ccmp_encrypt_skb(struct ieee80211_txrx_data *tx, break; } - ccmp_pn2hdr(pos, pn, key->keyidx); + ccmp_pn2hdr(pos, pn, key->conf.keyidx); - if (!key->force_sw_encrypt) { + if (!(key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) { /* hwaccel - with preallocated room for CCMP header */ - tx->u.tx.control->key_idx = key->hw_key_idx; + tx->u.tx.control->key_idx = key->conf.hw_key_idx; return 0; } @@ -523,18 +530,18 @@ ieee80211_tx_h_ccmp_encrypt(struct ieee80211_txrx_data *tx) fc = le16_to_cpu(hdr->frame_control); - if (!key || key->alg != ALG_CCMP || !WLAN_FC_DATA_PRESENT(fc)) + if (!key || key->conf.alg != ALG_CCMP || !WLAN_FC_DATA_PRESENT(fc)) return TXRX_CONTINUE; tx->u.tx.control->icv_len = CCMP_MIC_LEN; tx->u.tx.control->iv_len = CCMP_HDR_LEN; ieee80211_tx_set_iswep(tx); - if (!tx->key->force_sw_encrypt && + if (!(tx->key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) && !(tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) { /* hwaccel - with no need for preallocated room for CCMP " * header or MIC fields */ - tx->u.tx.control->key_idx = tx->key->hw_key_idx; + tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx; return TXRX_CONTINUE; } @@ -569,7 +576,7 @@ ieee80211_rx_h_ccmp_decrypt(struct ieee80211_txrx_data *rx) fc = le16_to_cpu(hdr->frame_control); hdrlen = ieee80211_get_hdrlen(fc); - if (!key || key->alg != ALG_CCMP || + if (!key || key->conf.alg != ALG_CCMP || !(rx->fc & IEEE80211_FCTL_PROTECTED) || (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) return TXRX_CONTINUE; @@ -579,7 +586,7 @@ ieee80211_rx_h_ccmp_decrypt(struct ieee80211_txrx_data *rx) return TXRX_DROP; if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && - !key->force_sw_encrypt && + !(key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT) && !(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) return TXRX_CONTINUE; @@ -600,7 +607,7 @@ ieee80211_rx_h_ccmp_decrypt(struct ieee80211_txrx_data *rx) } if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && - !key->force_sw_encrypt) { + !(key->conf.flags & IEEE80211_KEY_FORCE_SW_ENCRYPT)) { /* hwaccel has already decrypted frame and verified MIC */ } else { u8 *scratch, *b_0, *aad;